dsccommunity/ExchangeDsc

xExchInstall: Check/Install Prerequisites

Opened this issue · 6 comments

Details

Currently the xExchInstall resource doesn't check for prerequisites for Exchange 2013/2016/2019 and install them if necessary. This is pretty much the only thing that limits this DSC resource module from being a 100% end to end solution for deploying, configuring, and maintaining Exchange 2013/2016/2019.

Suggested solution

Add a prerequisite check for prerequisites i.e. .Net Framework, Visual C++ Redist. 2012 & 2013, UM Runtime, and necessary windows features (RSAT, etc.)

Hi Dana,
The install of prerequisite packages and features can be handled via other DSC resources. See this example that I used to deploy Exchange 2019 on Windows 2019 Server Core using DSC:

$ConfigurationData = @{
    AllNodes = @(
        @{
            NodeName                    = '*'

            <#
                NOTE! THIS IS NOT RECOMMENDED IN PRODUCTION.
                This is added so that AppVeyor automatic tests can pass, otherwise
                the tests will fail on passwords being in plain text and not being
                encrypted. Because it is not possible to have a certificate in
                AppVeyor to encrypt the passwords we need to add the parameter
                'PSDscAllowPlainTextPassword'.
                NOTE! THIS IS NOT RECOMMENDED IN PRODUCTION.
                See:
                http://blogs.msdn.com/b/powershell/archive/2014/01/31/want-to-secure-credentials-in-windows-powershell-desired-state-configuration.aspx
            #>
            PSDscAllowPlainTextPassword = $true
        },

        @{
            NodeName = 'e19core-1'
        }
    )
}

Configuration ExchangeSetup
{
    param
    (
        [Parameter(Mandatory = $true)]
        [System.Management.Automation.PSCredential]
        $ExchangeCredential
    )

    Import-DscResource -ModuleName StorageDsc
    Import-DscResource -ModuleName xExchange
    Import-DscResource -ModuleName WindowsDefender

    Node $AllNodes.NodeName
    {
        File VCREDISTFile
        {
            Ensure          = 'Present'
            SourcePath      = '\\rras-1\Binaries\vcredist_x64.exe'
            DestinationPath = 'c:\Binaries\vcredist_x64.exe'
        }

        Package VCREDIST2013
        {
            Ensure      = 'Present'  # You can also set Ensure to 'Absent'
            Path        = 'c:\Binaries\vcredist_x64.exe'
            Arguments   = '/install /quiet'
            Name        = 'Microsoft Visual C++ 2013 x64'
            ProductId   = '929FBD26-9020-399B-9A7A-751D61F0B942'

            DependsOn   = '[File]VCREDISTFile'
        }

        WindowsFeature ServerMediaFoundation
        {
            Ensure = 'Present'
            Name   = 'Server-Media-Foundation'
        }

        # Note that RSAT-ADDS is only required if Setup will be running PrepareSchema/AD/etc
        WindowsFeature RSATADDS
        {
            Ensure = 'Present'
            Name   = 'RSAT-ADDS'
        }

        File Ex2019File
        {
            Ensure          = 'Present'
            SourcePath      = '\\rras-1\Binaries\ExchangeServer2019-x64.iso'
            DestinationPath = 'c:\Binaries\ExchangeServer2019-x64.iso'
        }

        MountImage ExISO
        {
            ImagePath   = 'c:\Binaries\ExchangeServer2019-x64.iso'
            DriveLetter = 'X'

            DependsOn   = '[File]Ex2019File'
        }

        Package UCMA4
        {
            Ensure      = 'Present'
            Path        = 'X:\UCMARedist\setup.exe'
            Arguments   = '/quiet'
            Name        = 'Microsoft Unified Communications Managed API 4.0, Runtime'
            ProductId   = '41D635FE-4F9D-47F7-8230-9B29D6D42D31'

            DependsOn   = '[MountImage]ExISO','[WindowsFeature]ServerMediaFoundation'
        }

        # Configure AV exclusions per: https://docs.microsoft.com/en-us/Exchange/antispam-and-antimalware/windows-antivirus-software
        WindowsDefender ConfigureExclusions
        {
            IsSingleInstance = 'Yes'
            ExclusionPath    = @(
                'C:\Windows\Cluster'
                'C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB'
                'C:\Program Files\Microsoft\Exchange Server\V15\FIP-FS'
                'C:\Program Files\Microsoft\Exchange Server\V15\Logging'
                'C:\Program Files\Microsoft\Exchange Server\V15\Mailbox'
                'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Data\Adam'
                'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Data\IpFilter'
                'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Data\Queue'
                'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Data\SenderReputation'
                'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Data\Temp'
                'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs'
                'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Pickup'
                'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Replay'
                'C:\Program Files\Microsoft\Exchange Server\V15\UnifiedMessaging\Grammars'
                'C:\Program Files\Microsoft\Exchange Server\V15\UnifiedMessaging\Prompts'
                'C:\Program Files\Microsoft\Exchange Server\V15\UnifiedMessaging\Temp'
                'C:\Program Files\Microsoft\Exchange Server\V15\UnifiedMessaging\Voicemail'
                'C:\Program Files\Microsoft\Exchange Server\V15\Working\OleConverter'
                'C:\inetpub\temp\IIS Temporary Compressed Files'
                'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files'
                'C:\Windows\System32\Inetsrv'
                'C:\Windows\Temp\OICE_*'
            )
            ExclusionProcess = @(
                'ComplianceAuditService.exe'
                'Dsamain.exe'
                'EdgeTransport.exe'
                'fms.exe'
                'hostcontrollerservice.exe'
                'inetinfo.exe'
                'Microsoft.Exchange.AntispamUpdateSvc.exe'
                'Microsoft.Exchange.ContentFilter.Wrapper.exe'
                'Microsoft.Exchange.Diagnostics.Service.exe'
                'Microsoft.Exchange.Directory.TopologyService.exe'
                'Microsoft.Exchange.EdgeCredentialSvc.exe'
                'Microsoft.Exchange.EdgeSyncSvc.exe'
                'Microsoft.Exchange.Imap4.exe'
                'Microsoft.Exchange.Imap4service.exe'
                'Microsoft.Exchange.Notifications.Broker.exe'
                'Microsoft.Exchange.Pop3.exe'
                'Microsoft.Exchange.Pop3service.exe'
                'Microsoft.Exchange.ProtectedServiceHost.exe'
                'Microsoft.Exchange.RPCClientAccess.Service.exe'
                'Microsoft.Exchange.Search.Service.exe'
                'Microsoft.Exchange.Servicehost.exe'
                'Microsoft.Exchange.Store.Service.exe'
                'Microsoft.Exchange.Store.Worker.exe'
                'Microsoft.Exchange.UM.CallRouter.exe'
                'MSExchangeCompliance.exe'
                'MSExchangeDagMgmt.exe'
                'MSExchangeDelivery.exe'
                'MSExchangeFrontendTransport.exe'
                'MSExchangeHMHost.exe'
                'MSExchangeHMWorker.exe'
                'MSExchangeMailboxAssistants.exe'
                'MSExchangeMailboxReplication.exe'
                'MSExchangeRepl.exe'
                'MSExchangeSubmission.exe'
                'MSExchangeTransport.exe'
                'MSExchangeTransportLogSearch.exe'
                'MSExchangeThrottling.exe'
                'Noderunner.exe'
                'OleConverter.exe'
                'ParserServer.exe'
                'Powershell.exe'
                'ScanEngineTest.exe'
                'ScanningProcess.exe'
                'UmService.exe'
                'UmWorkerProcess.exe'
                'UpdateService.exe'
                'W3wp.exe'
                'wsbexchange.exe'
            )
            ExclusionExtension = @(
                '.config'
                '.chk'
                '.edb'
                '.jfm'
                '.jrs'
                '.log'
                '.que'
                '.dsc'
                '.txt'
                '.cfg'
                '.grxml'
                '.lzx'
            )
        }

        xExchInstall InstallExchange
        {
            Path       = 'X:\Setup.exe'
            Arguments  = '/mode:Install /role:Mailbox /IAcceptExchangeServerLicenseTerms /InstallWindowsComponents'
            Credential = $ExchangeCredential

            DependsOn  = '[WindowsDefender]ConfigureExclusions','[MountImage]ExISO','[WindowsFeature]RSATADDS'
        }

        xExchExchangeServer EXServer
        {
            Identity            = $Node.NodeName
            Credential          = $ExchangeCredential
            ProductKey          = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
            AllowServiceRestart = $true

            DependsOn           = '[xExchInstall]InstallExchange'
        }

        #Copy an certificate .PFX that had been previously exported, import it, and enable services on it
        File CopyExchangeCert
        {
            Ensure          = 'Present'
            SourcePath      = "\\rras-1\Binaries\Certificates\ExchangeCert.pfx"
            DestinationPath = 'C:\Binaries\Certificates\ExchangeCert.pfx'
            Credential      = $ExchangeCredential
        }

        xExchExchangeCertificate Certificate
        {
            Thumbprint              = '766358855A7361C6D99D4FB58903AB0833296B2A'
            Credential              = $ExchangeAdminCredential
            Ensure                  = 'Present'
            AllowExtraServices      = $true
            CertCreds               = $ExchangeCertCredential
            CertFilePath            = 'C:\Binaries\Certificates\ExchangeCert.pfx'
            Services                = 'IIS','POP','IMAP','SMTP'
            DependsOn               = '[File]CopyExchangeCert'
        }

        ###CAS specific settings###
        #The following section shows how to configure commonly configured URL's on various virtual directories
        xExchClientAccessServer CAS
        {
            Identity                       = $Node.NodeName
            Credential                     = $ExchangeAdminCredential
            AutoDiscoverServiceInternalUri = "https://$($casSettingsPerSite.InternalNamespace)/autodiscover/autodiscover.xml"
            AutoDiscoverSiteScope          = $casSettingsPerSite.AutoDiscoverSiteScope
        }

        xExchActiveSyncVirtualDirectory ASVdir
        {
            Identity    = "$($Node.NodeName)\Microsoft-Server-ActiveSync (Default Web Site)"
            Credential  = $ExchangeAdminCredential
            ExternalUrl = "https://$($casSettingsAll.ExternalNamespace)/Microsoft-Server-ActiveSync"
            InternalUrl = "https://$($casSettingsPerSite.InternalNamespace)/Microsoft-Server-ActiveSync"
        }

        xExchEcpVirtualDirectory ECPVDir
        {
            Identity    = "$($Node.NodeName)\ecp (Default Web Site)"
            Credential  = $ExchangeAdminCredential
            ExternalUrl = "https://$($casSettingsAll.ExternalNamespace)/ecp"
            InternalUrl = "https://$($casSettingsPerSite.InternalNamespace)/ecp"
        }

        xExchMapiVirtualDirectory MAPIVdir
        {
            Identity                 = "$($Node.NodeName)\mapi (Default Web Site)"
            Credential               = $ExchangeAdminCredential
            ExternalUrl              = "https://$($casSettingsAll.ExternalNamespace)/mapi"
            InternalUrl              = "https://$($casSettingsPerSite.InternalNamespace)/mapi"
            IISAuthenticationMethods = 'Ntlm','OAuth','Negotiate'
        }

        xExchOabVirtualDirectory OABVdir
        {
            Identity    = "$($Node.NodeName)\OAB (Default Web Site)"
            Credential  = $ExchangeAdminCredential
            ExternalUrl = "https://$($casSettingsAll.ExternalNamespace)/oab"
            InternalUrl = "https://$($casSettingsPerSite.InternalNamespace)/oab"
        }

        xExchOutlookAnywhere OAVdir
        {
            Identity                           = "$($Node.NodeName)\Rpc (Default Web Site)"
            Credential                         = $ExchangeAdminCredential
            ExternalClientAuthenticationMethod = 'Negotiate'
            ExternalClientsRequireSSL          = $true
            ExternalHostName                   = $casSettingsAll.ExternalNamespace
            IISAuthenticationMethods           = 'Basic', 'Ntlm', 'Negotiate'
            InternalClientAuthenticationMethod = 'Ntlm'
            InternalClientsRequireSSL          = $true
            InternalHostName                   = $casSettingsPerSite.InternalNamespace
        }
    }
}

This would be the preferred way to install prerequisites when the main Exchange setup.exe does not support downloading them from an external source and then install them.

We should add the configuration in previous comment as an example in the module.

@johlju, I can help with this. To make sure, we need to add the example that @mhendric provided on the DSC module itself of xExchInstall https://github.com/dsccommunity/xExchange/tree/main/source/DSCResources/MSFT_xExchInstall or needs to be added in the examples folder: https://github.com/dsccommunity/xExchange/tree/main/source/Examples?

A new example that shows how to install prerequisites. It could be extended to existing example here https://github.com/dsccommunity/xExchange/blob/main/source/Examples/InstallExchange/InstallExchange.ps1

We should really have the correct folder structure for examples as well, but that can be fixed later.

Hmm, it seems there should be more examples that just extending the one I mentioned above since the example configuration above contain examples for several resources. So we might need to do the correct folder and file structure, see how it is made here: https://github.com/dsccommunity/SqlServerDsc/tree/main/source/Examples/Resources

Having the correct folder and file structure prepares for adding auto-documentation later to this repo (publish to Wiki).

we will work on it. thank you for the feedback