Lab Setup – Script – Part3

The third article in this series will continue the Lab Setup Script. This part of the script I wrote will cover these options: mobile device policies, retention tags/policies, enabling archives, OWA policies and configuring APPs. In the next article I will cover more advanced functionality for existing features and also demonstrate lab cleanup for resetting a lab environment.

What’s new
As can be seen from the new menu, there are new functions available:

labsetup03-01

Let’s dive right in to the new features:

Retention Policies
For retention policies I have a basic loop set up so that you can configure multiple Retention Policies and with another loop apply multiple Retention Policy Tags to each policy. There are additional options that can be configured, but this code section will at least allow for basic retention policies to be added to a lab environment in a more programmatic format.

# Menu code
10 {#	Create retention Policies
	create-retentionpolices
}

# Create Retention Policies

function create-retentionpolices {
    $polno = read-host "How many Retention Policies do you want to create"
    $polcounter = 0
    while ($polcounter -lt $polno) {
        $currentpol = $polcounter +1
        $polname = read-host "Specify a name for Rentention Policy number $currentpol"
        $tagno = read-host "How many Retention Tags do you want to create"
        $counter = 0
        $alltags = @()
        while ($counter -lt $tagno) {
            $current = $counter + 1
            $name = read-host "Specify a name for Retention Tag number $current"
            $time = read-host "Specify a time frame to apply the tag (i.e. 60, 90, 120)"
            $RetentionAction = read-host "Specify a retention action (DeleteAndAllowRecovery, PermanentlyDelete, MoveToArchive)"
            if ($retentionaction -eq "MoveToArchive") {
                $type = "all"
            } else {
                $type = read-host "Specify which folders will be affect (All, Inbox, etc.  )"
            }
            $comment = read-host "Specify a comment for the Retention Tag (optional)"
            $alltags += ,($name)
            if ($retentionaction -eq "permanentlyDelete") {
                $archive = $false
            } else {
                $archive = $true
            }
            New-RetentionPolicyTag -Name $name -Type $type -RetentionAction $retentionaction -RetentionEnabled:$archive -AgeLimitForRetention $time -Comment $comment
            $counter++
        }
        new-retentionpolicy -name $polname -RetentionPolicyTagLinks $alltags
        $polcounter++
    }
}

Here is a sample run through this option. Notice I was able to create two entirely different Retention Tags and apply it to one Retention Policy:

labsetup03-02

At this time the options are limited and will expanded in part four or five of this series.

Mobile Device Policies
Mobile device policies contain a large list of options to be configured. For this particular script I have the password section included as it is the most commonly configured, perhaps the only section. The policy is not applied to any users, but simply creates one to be used for testing.

# Menu Coding
15 { # Mobile Devices
            create-mobiledevicepolicy
}

# Create new mobile device policies

function create-mobiledevicepolicy {
    write-host " "
    write-host "For now, this function will " -nonewline
    write-host "only create the password policy portion" -nonewline -ForegroundColor red
    write-host " of the Mobile Device Policy."
    write-host " "
    start-sleep 5
    write-host "The existing Mobile Device Mailbox Policies are:"
    Get-MobileDeviceMailboxPolicy |ft id
    $name = read-host "What is the name of the new Mobile Device Mailbox Policy"
    $IsDefault = read-host "Will this policy be the default policy [y or n]"
    if ($isdefault -eq "y") {
        $isdefault = $true
    } else {
        $isdefault = $false
    }
    $password = read-host "Do you want to create a device password policy [y or n]"
    if ($password -eq "y") {
        $AlphanumericPasswordRequired = read-host "Will alphanumeric passwords be required [y or n]"
        if ($AlphanumericPasswordRequired -eq "y") {
            $AlphanumericPasswordRequired = $true
        }else {
            $AlphanumericPasswordRequired = $false
        }
        $PasswordRecoveryEnabled = read-host "Will password recovery be enabled [y or n]"
        if ($PasswordRecoveryEnabled -eq "y") {
            $PasswordRecoveryEnabled = $true
        }else {
            $PasswordRecoveryEnabled = $false
        }
        $MaxPasswordFailedAttempts = read-host "How many failed password attempts [4 through 16 or the value Unlimited]"
        $MinPasswordLength = read-host "What is the minimum password length [1 through 16 or the value $null]"
        $complex = read-host "Do you want a complex password policy [y or n]"
        $PasswordHistory = read-host "How many passwords for the device pasword history [1, 3, 7?]"
        if ($complex -eq "y") {
            $MinPasswordComplexCharacters = read-host "What will the minumim complex password characters be allowed [valid range is from 1 to 4]"
            New-MobileDeviceMailboxPolicy -name $name -MinPasswordLength $MinPasswordLength -MaxPasswordFailedAttempts $MaxPasswordFailedAttempts -PasswordEnabled $true -AlphanumericPasswordRequired $AlphanumericPasswordRequired -PasswordRecoveryEnabled $PasswordRecoveryEnabled -MinPasswordComplexCharacters $MinPasswordComplexCharacters -IsDefault $isdefault -PasswordHistory $PasswordHistory
        } else {
            New-MobileDeviceMailboxPolicy -name $name -MinPasswordLength $MinPasswordLength -MaxPasswordFailedAttempts $MaxPasswordFailedAttempts -PasswordEnabled $true -AlphanumericPasswordRequired $AlphanumericPasswordRequired -PasswordRecoveryEnabled $PasswordRecoveryEnabled -IsDefault $isdefault -PasswordHistory $PasswordHistory
        }
    }
    if ($password -eq "n") {
        New-MobileDeviceMailboxPolicy -name $name
    }
}

Here is a quick run-through of this option:

labsetup03-03

Again, notice the limited amount of controls. I am concentrating on the password policy for this initial iteration. In the next article in the series I’ll explore some more advanced options.

OWA Policies
OWA Mailbox Policies are also notoriously complex with dozens of configurable options. I’ve only added seven options for this iteration of the script. When the advanced version of the script comes out there will be an attempt to categorize and organize the options to make the building of the policy less complex or at least doable.

# Menu Code
16 { # OWA Policies
            create-OWApolicy
}

# Create an OWA Policy

function create-OWApolicy {
    write-host " "
    write-host "For now, this function will " -nonewline
    write-host "only create a basic version" -nonewline -ForegroundColor red
    write-host " of the OWA Mailbox Policy."
    write-host " "
    start-sleep 5
    write-host "The existing OWA Mailbox Policies are:"
    Get-OWAMailboxPolicy |ft id
    $name = read-host "What is the name of the new OWA Mailbox Policy"
    $IsDefault = read-host "Will this policy be the default policy [y or n]"
    if ($isdefault -eq "y") {$isdefault = $true} else {$isdefault = $false} 
    $AllowOfflineOn = read-host "Do you want to enable OWA offline in this policy [PrivateComputersOnly | NoComputers | AllComputers]"
    $ChangePasswordEnabled = read-host "Would you like their password change opion to appear [y or n]"
    if ($ChangePasswordEnabled -eq "y") {$ChangePasswordEnabled = $true} else {$ChangePasswordEnabled = $false}
    $JunkEmailEnabled = read-host "Enable Junk mail in OWA [y or n]"
    if ($JunkEmailEnabled -eq "y") {$JunkEmailEnabled = $true} else {$JunkEmailEnabled = $false}
    $LinkedInEnabled = read-host "Would you like to enable LinkedIn for OWA [y or n]"
    if ($LinkedInEnabled -eq "y") {$LinkedInEnabled = $true} else {$LinkedInEnabled = $false}
    $PublicFoldersEnable = read-host "Enable Public folders in OWA [y or n]"
    if ($PublicFoldersEnable -eq "y") {$PublicFoldersEnable = $true} else {$PublicFoldersEnable = $false}
    $RulesEnabled = read-host "Enable Rules in OWA [y or n]"
    if ($RulesEnabled -eq "y") {$RulesEnabled = $true} else {$RulesEnabled = $false}
    write-host " "
    write-host "Creating your policy now." -ForegroundColor green
    write-host " "
    if ($isdefault -eq $true) {
        new-OwaMailboxPolicy -name $name
        set-OwaMailboxPolicy -isdefault $isdefault -identity $name -AllowOfflineOn $AllowOfflineOn -ChangePasswordEnabled $ChangePasswordEnabled -JunkEmailEnabled $JunkEmailEnabled -PublicFoldersEnable $PublicFoldersEnable -RulesEnabled $RulesEnabled
    } else {
        new-OwaMailboxPolicy -name $name
        set-OwaMailboxPolicy -identity $name -AllowOfflineOn $AllowOfflineOn -ChangePasswordEnabled $ChangePasswordEnabled -JunkEmailEnabled $JunkEmailEnabled -PublicFoldersEnable $PublicFoldersEnable -RulesEnabled $RulesEnabled
    }
}

Here is a sample run of creating and setting an OWA policy:

labsetup03-04
As you can see, the script will display previous OWA policies so names are not duplicated by accident. Each question also lays out the acceptable responses as well.

Enabling Archives
Archives are basically just another mailbox connected to a users account. In this code I give an option to create a new database (specifying name, log location and database location) or use an existing database. then you can decide who to apply it to (all or random). More advance options will be available in the next iteration of this code.

# Menu coding
17 { # Enabling Archives
        enable-archives
}

# Enable Archives for all or some users

function enable-archives {
    $selection = read-host "Do you want to enable archives for all mailboxes or random mailboxes [a or r]"
    $location = read-host "Would you like to create a new mailbox database for the archive mailboxes [y or n]"
    if ($location -eq "n") {
        $database = read-host "Which database will the archive mailboxes be placed in"
    }
    if ($location -eq "y") {
        $srv = ($server[0]).name
        write-host "The new archive database will bew placed on $srv."
        $directory1 = read-host "Please enter a valid directory to place the database files"
        $directory2 = read-host "Please enter a valid directory to place the log files"
        $archivename = "ArchiveDatabase"
        $edb = $directory1+"\"+$archivename+".edb"
        $log = $directory2+"\"+$archivename
        $server = get-mailboxserver
        new-mailboxdatabase -name $archivename -edbfilepath $edb -logfolderpath $log -server $srv -erroraction silentlycontinue
    }

    # Enable the mailboxes to have archive mailboxes
    
    if ($selection -eq "a") {
        $mailboxes = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).alias
        foreach ($line in $mailboxes) {
            enable-mailbox $line -Archive -ArchiveDatabase $database -erroraction silentlycontinue
        }
            $name = (get-mailbox $alias).displayname
            write-host "An archive mailbox for $name has been created." -foregroundcolor green    
    } else {
        $mbxcount = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).count
        $range =  get-random -minimum 0 -maximum $mbxcount
        $counter = 0
        $mailbox = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).alias
        while ($counter -lt $range) {
                $alias = $mailbox[$counter]
                enable-mailbox $alias -Archive -ArchiveDatabase $database -erroraction silentlycontinue
                $counter++
        }
        
        $name = (get-mailbox $alias).displayname
        write-host "All archive mailboxes have been created." -foregroundcolor green    
    }
} # End function for archive mailboxes

Sample run-through of this option:

labsetup03-07

In the above example I used an existing Archive Database that I had created for testing.

Configure Apps
Lastly, one of the most underutilized sections of Exchange is the Apps section. This code will only install one app from the web, the Message Header Analyzer. The only caveat is that you need to XML file and the URL for the XML file is here for downloading. Make sure you download this in order to get the app to install. I will add more apps to the list later.

# Menu Coding
18 { # Configure Apps
        configure-Apps
}

# Configuring apps forExchange 2013
function configure-Apps {
    $option = read-host "Do you want to configure Apps (1) or add new Apps (2)"

    # Prep Random mailboxes (version 1)
    $mbxcount = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).count
    $range =  get-random -minimum 0 -maximum $mbxcount
    $mailbox = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).alias

    # Create Random User List
    $counter = 0
    $userlist = @()
    while ($counter -lt $range) {
                $alias = $mailbox[$counter]
                $userlist += @($alias)
                $counter++
    }

    if ($option -eq "1") {
        write-host "Currently there are these apps installed in your Exchange Server 2013 environment"
        get-app -OrganizationApp |ft displayname,providedto,userlist -auto
        $app = (get-app -OrganizationApp).appid
        $choice = read-host "Do you want to limit the apps to random users or allow them for all users [r or a]"
        $mailboxes = (get-mailbox | where {$_.RecipientTypeDetails -ne "DiscoveryMailbox"}).alias
        if ($choice -eq "a") {
            $name = (get-mailbox $alias).displayname
            foreach ($line in $mailboxes) {
                foreach ($line in $app) {
                    set-app $line -OrganizationApp $true -enabled $true
                }
            }
            write-host "Apps have been configured for all users." -foregroundcolor green    
        } else {            
            foreach ($line in $app) {
                Set-App $line -organizationapp -ProvidedTo SpecificUsers -UserList $userlist
            }
        }
    } else {
        # Feature to add later will be user inputed apps - only one app for now - Message Header Analyzer
        # $choice2 = read-host "Install apps from this script (1) or choose your own apps (2)"
        # write-host " "
        $choice = read-host "Do you want to limit the apps to random users or allow them for all users [r or a]"
        $Data = get-content -Encoding byte -Path "c:\scripts\manifest.xml" -ReadCount 0
        # foreach ($line in $applist) {
            if ($choice -eq "a") {
                new-app -DefaultStateForUser Enabled -filedata $data -OrganizationApp
            } else {
                new-app -DefaultStateForUser Enabled -filedata $data -OrganizationApp -ProvidedTo SpecificUsers -UserList $userlist
            }
        #}
    }
}

Quick run through of the options that can be configured:

labsetup03-05

Verifying that it worked:

labsetup03-06

Further Reading

Advertisements

5 thoughts on “Lab Setup – Script – Part3

  1. Thank you for your articles.

    I think that good way to improve your script is publish it on GitHub, CodePlex or other public repository.

    After that more people can add function and improve script. You as repository master will have control on main branch of code.

      • But TechNet Wiki is not a tool to colaborate with code, for this the better will be a version control system like GitHub or CodePlex – please see how many feature can be helpfull to manage code, reviews, bugs et. https://github.com/features . As a git client for Windows I can recomend https://code.google.com/p/tortoisegit/ , yes the site is not very helpfull but the tool is.
        Of course colaboration releases can be less “your” but probably will be created faster. Your choice.

        Thanks again for your post.

      • Understood. I’ve heard of both, never used them as I don’t submit too much code for public modification. Might give it a spin for this script. Thanks for the suggestions.

      • Basic git operations (especially with GUI) are not difficult. Git you can use also without publish code (only on local system) – in a repository directory are created special/technical structures which are used for tracking version, etc. – you decide when you submit your version). I’m not developer also but understanding/using git took me less than a hour. You can find a lot tutorials related to Git on web.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s