Examples/TestLabGuide.ps1

Configuration TestLabGuide {
<#
    Requires the following custom DSC resources:

        xComputerManagement: https://github.com/PowerShell/xComputerManagement
        xNetworking: https://github.com/PowerShell/xNetworking
        xActiveDirectory: https://github.com/PowerShell/xActiveDirectory
        xSmbShare: https://github.com/PowerShell/xSmbShare
        xDhcpServer: https://github.com/PowerShell/xDhcpServer
        xDnsServer: https://github.com/PowerShell/xDnsServer
#>

    param (
        [Parameter()] [ValidateNotNull()] [PSCredential] $Credential = (Get-Credential -Credential 'Administrator')
    )
    Import-DscResource -Module xComputerManagement, xNetworking, xActiveDirectory;
    Import-DscResource -Module xSmbShare, PSDesiredStateConfiguration;
    Import-DscResource -Module xDHCPServer, xDnsServer;

    node $AllNodes.Where({$true}).NodeName {

        LocalConfigurationManager {

            RebootNodeIfNeeded   = $true;
            AllowModuleOverwrite = $true;
            ConfigurationMode    = 'ApplyOnly';
            CertificateID        = $node.Thumbprint;
        }

        if (-not [System.String]::IsNullOrEmpty($node.IPAddress)) {

            xIPAddress 'PrimaryIPAddress' {

                IPAddress      = $node.IPAddress;
                InterfaceAlias = $node.InterfaceAlias;
                PrefixLength   = $node.PrefixLength;
                AddressFamily  = $node.AddressFamily;
            }

            if (-not [System.String]::IsNullOrEmpty($node.DefaultGateway)) {

                xDefaultGatewayAddress 'PrimaryDefaultGateway' {

                    InterfaceAlias = $node.InterfaceAlias;
                    Address        = $node.DefaultGateway;
                    AddressFamily  = $node.AddressFamily;
                }
            }

            if (-not [System.String]::IsNullOrEmpty($node.DnsServerAddress)) {

                xDnsServerAddress 'PrimaryDNSClient' {

                    Address        = $node.DnsServerAddress;
                    InterfaceAlias = $node.InterfaceAlias;
                    AddressFamily  = $node.AddressFamily;
                }
            }

            if (-not [System.String]::IsNullOrEmpty($node.DnsConnectionSuffix)) {

                xDnsConnectionSuffix 'PrimaryConnectionSuffix' {

                    InterfaceAlias           = $node.InterfaceAlias;
                    ConnectionSpecificSuffix = $node.DnsConnectionSuffix;
                }
            }

        } #end if IPAddress

        xFirewall 'FPS-ICMP4-ERQ-In' {

            Name        = 'FPS-ICMP4-ERQ-In';
            DisplayName = 'File and Printer Sharing (Echo Request - ICMPv4-In)';
            Description = 'Echo request messages are sent as ping requests to other nodes.';
            Direction   = 'Inbound';
            Action      = 'Allow';
            Enabled     = 'True';
            Profile     = 'Any';
        }

        xFirewall 'FPS-ICMP6-ERQ-In' {

            Name        = 'FPS-ICMP6-ERQ-In';
            DisplayName = 'File and Printer Sharing (Echo Request - ICMPv6-In)';
            Description = 'Echo request messages are sent as ping requests to other nodes.';
            Direction   = 'Inbound';
            Action      = 'Allow';
            Enabled     = 'True';
            Profile     = 'Any';
        }
    } #end nodes ALL

    node $AllNodes.Where({$_.Role -in 'DC'}).NodeName {

        ## Flip credential into username@domain.com
        $domainCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ("$($Credential.UserName)@$($node.DomainName)", $Credential.Password);

        xComputer 'Hostname' {

            Name = $node.NodeName;
        }

        ## Hack to fix DependsOn with hypens "bug" :(
        foreach ($feature in @(
                'AD-Domain-Services',
                'GPMC',
                'RSAT-AD-Tools',
                'DHCP',
                'RSAT-DHCP'
            )) {
            WindowsFeature $feature.Replace('-','') {

                Ensure               = 'Present';
                Name                 = $feature;
                IncludeAllSubFeature = $true;
            }
        }

        xADDomain 'ADDomain' {

            DomainName                    = $node.DomainName;
            SafemodeAdministratorPassword = $Credential;
            DomainAdministratorCredential = $Credential;
            DependsOn                     = '[WindowsFeature]ADDomainServices';
        }

        xDhcpServerAuthorization 'DhcpServerAuthorization' {

            Ensure    = 'Present';
            DependsOn = '[WindowsFeature]DHCP','[xADDomain]ADDomain';
        }

        xDhcpServerScope 'DhcpScope10_0_0_0' {

            Name          = 'Corpnet';
            IPStartRange  = '10.0.0.100';
            IPEndRange    = '10.0.0.200';
            SubnetMask    = '255.255.255.0';
            LeaseDuration = '00:08:00';
            State         = 'Active';
            AddressFamily = 'IPv4';
            DependsOn     = '[WindowsFeature]DHCP';
        }

        xDhcpServerOption 'DhcpScope10_0_0_0_Option' {

            ScopeID            = '10.0.0.0';
            DnsDomain          = 'corp.contoso.com';
            DnsServerIPAddress = '10.0.0.1';
            Router             = '10.0.0.2';
            AddressFamily      = 'IPv4';
            DependsOn          = '[xDhcpServerScope]DhcpScope10_0_0_0';
        }

        xADUser User1 {

            DomainName  = $node.DomainName;
            UserName    = 'User1';
            Description = 'Lability Test Lab user';
            Password    = $Credential;
            Ensure      = 'Present';
            DependsOn   = '[xADDomain]ADDomain';
        }

        xADGroup DomainAdmins {

            GroupName        = 'Domain Admins';
            MembersToInclude = 'User1';
            DependsOn        = '[xADUser]User1';
        }

        xADGroup EnterpriseAdmins {

            GroupName        = 'Enterprise Admins';
            GroupScope       = 'Universal';
            MembersToInclude = 'User1';
            DependsOn        = '[xADUser]User1';
        }

    } #end nodes DC

    ## INET1 is on the 'Internet' subnet and not domain-joined
    node $AllNodes.Where({$_.Role -in 'CLIENT','APP','EDGE'}).NodeName {

        ## Flip credential into username@domain.com
        $upn = '{0}@{1}' -f $Credential.UserName, $node.DomainName;
        $domainCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($upn, $Credential.Password);

        xComputer 'DomainMembership' {

            Name       = $node.NodeName;
            DomainName = $node.DomainName;
            Credential = $domainCredential;
        }
    } #end nodes DomainJoined

    node $AllNodes.Where({$_.Role -in 'APP'}).NodeName {

        ## Flip credential into username@domain.com
        $upn = '{0}@{1}' -f $Credential.UserName, $node.DomainName;
        $domainCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($upn, $Credential.Password);

        foreach ($feature in @(
                'Web-Default-Doc',
                'Web-Dir-Browsing',
                'Web-Http-Errors',
                'Web-Static-Content',
                'Web-Http-Logging',
                'Web-Stat-Compression',
                'Web-Filtering',
                'Web-Mgmt-Tools',
                'Web-Mgmt-Console')) {
            WindowsFeature $feature.Replace('-','') {

                Ensure               = 'Present';
                Name                 = $feature;
                IncludeAllSubFeature = $true;
                DependsOn            = '[xComputer]DomainMembership';
            }
        }

        File 'FilesFolder' {

            DestinationPath = 'C:\Files';
            Type            = 'Directory';
        }

        File 'ExampleTxt' {

            DestinationPath = 'C:\Files\Example.txt'
            Type            = 'File';
            Contents        = 'This is a shared file.';
            DependsOn       = '[File]FilesFolder';
        }

        xSmbShare 'FilesShare' {

            Name         = 'Files';
            Path         = 'C:\Files';
            ChangeAccess = 'CORP\User1';
            DependsOn    = '[File]FilesFolder';
            Ensure       = 'Present';
        }
    } #end nodes APP

    node $AllNodes.Where({$_.Role -in 'EDGE'}).NodeName {

        xIPAddress 'SecondaryIPAddress' {
            IPAddress      = $node.SecondaryIPAddress;
            InterfaceAlias = $node.SecondaryInterfaceAlias;
            PrefixLength   = $node.SecondaryPrefixLength;
            AddressFamily  = $node.AddressFamily;
        }

        xDnsServerAddress 'SecondaryDNSClient' {
            Address        = $node.SecondaryDnsServerAddress;
            InterfaceAlias = $node.SecondaryInterfaceAlias;
            AddressFamily  = $node.AddressFamily
        }

        xDnsConnectionSuffix 'SecondarySuffix' {
            InterfaceAlias = $node.SecondaryInterfaceAlias;
            ConnectionSpecificSuffix = $node.SecondaryDnsConnectionSuffix;
        }

    }

    node $AllNodes.Where({$_.Role -in 'INET'}).NodeName {

        foreach ($feature in @(
                'Web-Default-Doc',
                'Web-Dir-Browsing',
                'Web-Http-Errors',
                'Web-Static-Content',
                'Web-Http-Logging',
                'Web-Stat-Compression',
                'Web-Filtering',
                'Web-Mgmt-Tools',
                'Web-Mgmt-Console',
                'DNS',
                'DHCP',
                'RSAT-DNS-Server',
                'RSAT-DHCP')) {
            WindowsFeature $feature.Replace('-','') {

                Ensure               = 'Present';
                Name                 = $feature;
                IncludeAllSubFeature = $true;
            }
        }


        xDhcpServerScope 'DhcpScope137_107_0_0' {

            Name          = 'Corpnet';
            IPStartRange  = '131.107.0.100';
            IPEndRange    = '131.107.0.150';
            SubnetMask    = '255.255.255.0';
            LeaseDuration = '00:08:00';
            State         = 'Active';
            AddressFamily = 'IPv4';
            DependsOn     = '[WindowsFeature]DHCP';
        }

        xDhcpServerOption 'DhcpScope137_107_0_0_Option' {

            ScopeID            = '131.107.0.0';
            DnsDomain          = 'isp.example.com';
            DnsServerIPAddress = '131.107.0.1';
            Router             = '131.107.0.1';
            AddressFamily      = 'IPv4';
            DependsOn          = '[xDhcpServerScope]DhcpScope137_107_0_0';
        }

        File 'NCSI' {

            DestinationPath = 'C:\inetpub\wwwroot\ncsi.txt';
            Type            = 'File';
            Contents        = 'Microsoft NCSI';
            DependsOn       = '[WindowsFeature]WebDefaultDoc';
        }

        xDnsServerPrimaryZone 'isp_example_com' {

            Name      = 'isp.example.com';
            DependsOn = '[WindowsFeature]DNS';
        }

        xDnsRecord 'inet1_isp_example_com' {

            Name      = 'inet1';
            Target    = '131.107.0.1';
            Zone      = 'isp.example.com';
            Type      = 'ARecord';
            DependsOn = '[xDnsServerPrimaryZone]isp_example_com';
        }

        xDnsServerPrimaryZone 'contoso_com' {

            Name      = 'contoso.com';
            DependsOn = '[WindowsFeature]DNS';
        }

        xDnsRecord 'edge1_contoso_com' {

            Name      = 'edge1';
            Target    = '131.107.0.2';
            Zone      = 'contoso.com';
            Type      = 'ARecord';
            DependsOn = '[xDnsServerPrimaryZone]contoso_com';
        }

        xDnsServerPrimaryZone 'msftncsi_com' {

            Name      = 'msftncsi.com';
            DependsOn = '[WindowsFeature]DNS';
        }

        xDnsRecord 'www_msftncsi_com' {

            Name      = 'www';
            Target    = '131.107.0.1';
            Zone      = 'msftncsi.com';
            Type      = 'ARecord';
            DependsOn = '[xDnsServerPrimaryZone]msftncsi_com';
        }

        xDnsRecord 'dns_msftncsi_com' {

            Name      = 'dns';
            Target    = '131.107.255.255';
            Zone      = 'msftncsi.com';
            Type      = 'ARecord';
            DependsOn = '[xDnsServerPrimaryZone]msftncsi_com';
        }

    } #end nodes INET

} #end Configuration Example