diff --git a/CHANGELOG.md b/CHANGELOG.md index e142eeb2..dab04570 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ For older change log history see the [historic changelog](HISTORIC_CHANGELOG.md) - Fixing xExchSendConnector ExtendedRight functionality by moving the test function to the helper module and setting explicit Deny permissions, instead of removing the marked as 'Deny' entries. + - Added AD Permissions parameter for xExchReceiveConnector. ## [1.31.0] - 2020-01-27 diff --git a/README.md b/README.md index 68891ee5..96db3652 100644 --- a/README.md +++ b/README.md @@ -1574,55 +1574,97 @@ parameters. "Domain Users"="Ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-Bypass-Anti-Spam"} * **ExtendedRightDenyEntries**: Similar as ExtendedRightAllowEntries, but to make sure the defined permission is not set -* **AdvertiseClientSettings** -* **AuthMechanism** -* **Banner** -* **BareLinefeedRejectionEnabled** -* **BinaryMimeEnabled** -* **Bindings** -* **ChunkingEnabled** -* **Comment** -* **ConnectionInactivityTimeout** -* **ConnectionTimeout** -* **DefaultDomain** -* **DeliveryStatusNotificationEnabled** -* **DomainController** -* **DomainSecureEnabled** -* **EightBitMimeEnabled** -* **EnableAuthGSSAPI** -* **Enabled** -* **EnhancedStatusCodesEnabled** -* **ExtendedProtectionPolicy** -* **Fqdn** -* **LongAddressesEnabled** -* **MaxAcknowledgementDelay** -* **MaxHeaderSize** -* **MaxHopCount** -* **MaxInboundConnection** -* **MaxInboundConnectionPercentagePerSource** -* **MaxInboundConnectionPerSource** -* **MaxLocalHopCount** -* **MaxLogonFailures** -* **MaxMessageSize** -* **MaxProtocolErrors** -* **MaxRecipientsPerMessage** -* **MessageRateLimit** -* **MessageRateSource** -* **OrarEnabled** -* **PermissionGroups** -* **PipeliningEnabled** -* **ProtocolLoggingLevel** -* **RemoteIPRanges** -* **RequireEHLODomain** -* **RequireTLS** -* **ServiceDiscoveryFqdn** -* **SizeEnabled** -* **SuppressXAnonymousTls** -* **TarpitInterval** -* **TlsCertificateName** -* **TlsDomainCapabilities** -* **TransportRole** -* **Usage** +* **AdvertiseClientSettings**: Specifies whether the SMTP server name,port number, +and authentication settings for the Receive connector are displayed to users in +the options of Outlook on the web. +* **AuthMechanism**: Specifies the advertised and accepted authentication +mechanisms for the Receive connector. +* **AuthTarpitInterval**: Specifies the period of time to delay responses to +failed authentication attempts from remote servers. +* **Banner**: Specifies a custom SMTP 220 banner that's displayed to remote +messaging servers. +* **BareLinefeedRejectionEnabled**: Specifies whether this Receive connector +rejects messages that contain line feed +* **BinaryMimeEnabled**: Specifies whether the BINARYMIME Extended SMTP extension +is enabled or disabled. +* **Bindings**: Specifies the local IP address and TCP port number that's used +by the Receive connector. +* **ChunkingEnabled**: Specifies whether the CHUNKING Extended SMTP extension +is enabled or disabled. +* **Comment**: Specifies an optional comment. +* **ConnectionInactivityTimeout**: Specifies the maximum amount of idle time +before a connection to the Receive connector is closed. +* **ConnectionTimeout**: Specifies the maximum time that the connection to the +Receive connector can remain open +* **DefaultDomain**: Specifies the default accepted domain to use for the +Exchange organization. +* **DeliveryStatusNotificationEnabled**: Specifies whether the DSN +* **DomainController**: Specifies the domain controller that's used by this +cmdlet to read data from or write data to Active Directory. +* **DomainSecureEnabled**: Specifies whether to enable or disable mutual +Transport Layer Security +* **EightBitMimeEnabled**: Specifies whether the 8BITMIME Extended SMTP extension +is enabled or disabled. +* **EnableAuthGSSAPI**: enables or disables Kerberos when Integrated Windows +authentication is available on the Receive connector. +* **Enabled**: Specifies whether to enable or disable the Receive connector. +* **EnhancedStatusCodesEnabled**: Specifies whether the ENHANCEDSTATUSCODES +Extended SMTP extension is enabled or disabled. +* **ExtendedRightAllowEntries**: Additional allow permissions. +* **ExtendedRightDenyEntries**: Additional denz permissions. +* **ExtendedProtectionPolicy**: Specifies how you want to use Extended Protection +for Authentication on the Receive connector. +* **Fqdn**: Specifies the destination FQDN that's shown to connected messaging servers. +* **LongAddressesEnabled**: Specifies whether the Receive connector accepts long +X.400 email addresses. +* **MaxAcknowledgementDelay**: Specifies the period the transport server delays +acknowledgement when receiving messages from a host that doesn't support shadow redundancy. +* **MaxHeaderSize**: Specifies the maximum size of the SMTP message header before +the Receive connector closes the connection. +* **MaxHopCount**: Specifies the maximum number of hops that a message can take +before the message is rejected by the Receive connector. +* **MaxInboundConnection**: Specifies the maximum number of inbound connections +that this Receive connector serves at the same time. +* **MaxInboundConnectionPercentagePerSource**: Specifies the maximum number of +connections that this Receive connector serves at the same time from a single IP +address. +* **MaxInboundConnectionPerSource**: Specifies the maximum number of connections +that a Receive connector serves at the same time from a single IP address +* **MaxLocalHopCount**: Specifies the maximum number of local hops that a message +can take before the message is rejected by the Receive connector. +* **MaxLogonFailures**: pecifies the number of logon failures that the Receive +connector retries before it closes the connection. +* **MaxMessageSize**: Specifies the maximum size of a message that's allowed +through the Receive connector. +* **MaxProtocolErrors**: Specifies the maximum number of SMTP protocol errors +that the Receive connector accepts before closing the connection. +* **MaxRecipientsPerMessage**: Specifies the maximum number of recipients per +message that the Receive connector accepts before closing the connection. +* **MessageRateLimit**: Specifies the maximum number of messages that can be +sent by a single client IP address per minute. +* **MessageRateSource**: Specifies how the message submission rate is calculated. +* **OrarEnabled**: enables or disables Originator Requested Alternate Recipient +* **PermissionGroups**: Specifies the well +* **PipeliningEnabled**: Specifies whether the PIPELINING Extended SMTP +extension is enabled or disabled. +* **ProtocolLoggingLevel**: pecifies whether to enable or disable protocol logging. +* **RemoteIPRanges**: Specifies the remote IP addresses that the Receive +connector accepts messages from. +* **RequireEHLODomain**: Specifies whether the client must provide a domain name +in the EHLO handshake after the SMTP connection is established. +* **RequireTLS**: Specifies whether to require TLS transmission for inbound messages. +* **SizeEnabled**: Specifies how the SIZE Extended SMTP extension is used on the +Receive connector. +* **SuppressXAnonymousTls**: Specifies whether the X +* **TarpitInterval**: Specifies the period of time to delay an SMTP response to +a remote server that may be abusing the connection. +* **TlsCertificateName**: Specifies the X.509 certificate to use for TLS encryption. +* **TlsDomainCapabilities**: Specifies the capabilities that the Receive connector +makes available to specific hosts outside of the organization. +* **TransportRole**: Specifies the transport service on the Mailbox server where +the Receive connector is created. +* **Usage**: Specifies the default permission groups and authentication methods +that are assigned to the Receive connector. ### xExchRemoteDomain diff --git a/source/DSCResources/MSFT_xExchAcceptedDomain/MSFT_xExchAcceptedDomain.psm1 b/source/DSCResources/MSFT_xExchAcceptedDomain/MSFT_xExchAcceptedDomain.psm1 index 71123b5d..c6528308 100644 --- a/source/DSCResources/MSFT_xExchAcceptedDomain/MSFT_xExchAcceptedDomain.psm1 +++ b/source/DSCResources/MSFT_xExchAcceptedDomain/MSFT_xExchAcceptedDomain.psm1 @@ -141,6 +141,8 @@ function Set-TargetResource 'Identity' = $DomainName } -Verbose:$VerbosePreference + $acceptedDomain = Get-TargetResource -DomainName $DomainName -Credential $Credential + # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad '*-AcceptedDomain' -Verbose:$VerbosePreference @@ -148,8 +150,6 @@ function Set-TargetResource Set-EmptyStringParamsToNull -PSBoundParametersIn $PSBoundParameters Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove Credential, Ensure - $acceptedDomain = Get-TargetResource -DomainName $DomainName -Credential $Credential - if ($acceptedDomain['Ensure'] -eq 'Present') { if ($Ensure -eq 'Absent') diff --git a/source/DSCResources/MSFT_xExchAddressList/MSFT_xExchAddressList.psm1 b/source/DSCResources/MSFT_xExchAddressList/MSFT_xExchAddressList.psm1 index 0443f8dd..0e97369b 100644 --- a/source/DSCResources/MSFT_xExchAddressList/MSFT_xExchAddressList.psm1 +++ b/source/DSCResources/MSFT_xExchAddressList/MSFT_xExchAddressList.psm1 @@ -307,9 +307,6 @@ function Set-TargetResource 'Identity' = $Name } -Verbose:$VerbosePreference - # Establish remote PowerShell session - Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad '*-AddressList' -Verbose:$VerbosePreference - if ($PSBoundParameters.ContainsKey('RecipientFilter') -and ($PSBoundParameters.ContainsKey('IncludedRecipients') -or $PSBoundParameters.Keys -contains 'Condit')) @@ -323,6 +320,9 @@ function Set-TargetResource $addressList = Get-TargetResource -Name $Name -Credential $Credential + # Establish remote PowerShell session + Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad '*-AddressList' -Verbose:$VerbosePreference + if ($addressList['Ensure'] -eq 'Present') { if ($Ensure -eq 'Absent') diff --git a/source/DSCResources/MSFT_xExchReceiveConnector/MSFT_xExchReceiveConnector.psm1 b/source/DSCResources/MSFT_xExchReceiveConnector/MSFT_xExchReceiveConnector.psm1 index 899025dd..7540bd91 100644 --- a/source/DSCResources/MSFT_xExchReceiveConnector/MSFT_xExchReceiveConnector.psm1 +++ b/source/DSCResources/MSFT_xExchReceiveConnector/MSFT_xExchReceiveConnector.psm1 @@ -1,3 +1,13 @@ +<# + .SYNOPSIS + Gets the resource + .PARAMETER Identity + Identity of the Receive Connector. Needs to be in format SERVERNAME\CONNECTORNAME (no quotes) + .PARAMETER Credential + Credentials used to establish a remote PowerShell session to Exchange. + .PARAMETER Ensure + Whether the connector should be present or not. +#> function Get-TargetResource { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "")] @@ -17,217 +27,7 @@ function Get-TargetResource [Parameter(Mandatory = $true)] [ValidateSet('Present', 'Absent')] [System.String] - $Ensure, - - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] - $ExtendedRightAllowEntries = @(), - - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] - $ExtendedRightDenyEntries = @(), - - [Parameter()] - [System.Boolean] - $AdvertiseClientSettings, - - [Parameter()] - [System.String[]] - $AuthMechanism, - - [Parameter()] - [System.String] - $Banner, - - [Parameter()] - [System.Boolean] - $BareLinefeedRejectionEnabled, - - [Parameter()] - [System.Boolean] - $BinaryMimeEnabled, - - [Parameter()] - [System.String[]] - $Bindings, - - [Parameter()] - [System.Boolean] - $ChunkingEnabled, - - [Parameter()] - [System.String] - $Comment, - - [Parameter()] - [System.String] - $ConnectionInactivityTimeout, - - [Parameter()] - [System.String] - $ConnectionTimeout, - - [Parameter()] - [System.String] - $DefaultDomain, - - [Parameter()] - [System.String] - $DomainController, - - [Parameter()] - [System.Boolean] - $DeliveryStatusNotificationEnabled, - - [Parameter()] - [System.Boolean] - $DomainSecureEnabled, - - [Parameter()] - [System.Boolean] - $EightBitMimeEnabled, - - [Parameter()] - [System.Boolean] - $EnableAuthGSSAPI, - - [Parameter()] - [System.Boolean] - $Enabled, - - [Parameter()] - [System.Boolean] - $EnhancedStatusCodesEnabled, - - [Parameter()] - [ValidateSet('None', 'Allow', 'Require')] - [System.String] - $ExtendedProtectionPolicy, - - [Parameter()] - [System.String] - $Fqdn, - - [Parameter()] - [System.Boolean] - $LongAddressesEnabled, - - [Parameter()] - [System.String] - $MaxAcknowledgementDelay, - - [Parameter()] - [System.String] - $MaxHeaderSize, - - [Parameter()] - [System.Int32] - $MaxHopCount, - - [Parameter()] - [System.String] - $MaxInboundConnection, - - [Parameter()] - [System.Int32] - $MaxInboundConnectionPercentagePerSource, - - [Parameter()] - [System.String] - $MaxInboundConnectionPerSource, - - [Parameter()] - [System.Int32] - $MaxLocalHopCount, - - [Parameter()] - [System.Int32] - $MaxLogonFailures, - - [Parameter()] - [System.String] - $MaxMessageSize, - - [Parameter()] - [System.String] - $MaxProtocolErrors, - - [Parameter()] - [System.Int32] - $MaxRecipientsPerMessage, - - [Parameter()] - [System.String] - $MessageRateLimit, - - [Parameter()] - [ValidateSet('None', 'IPAddress', 'User', 'All')] - [System.String] - $MessageRateSource, - - [Parameter()] - [System.Boolean] - $OrarEnabled, - - [Parameter()] - [System.String[]] - $PermissionGroups, - - [Parameter()] - [System.Boolean] - $PipeliningEnabled, - - [Parameter()] - [ValidateSet('None', 'Verbose')] - [System.String] - $ProtocolLoggingLevel, - - [Parameter()] - [System.String[]] - $RemoteIPRanges, - - [Parameter()] - [System.Boolean] - $RequireEHLODomain, - - [Parameter()] - [System.Boolean] - $RequireTLS, - - [Parameter()] - [System.String] - $ServiceDiscoveryFqdn, - - [Parameter()] - [ValidateSet('Enabled', 'Disabled', 'EnabledWithoutValue')] - [System.String] - $SizeEnabled, - - [Parameter()] - [System.Boolean] - $SuppressXAnonymousTls, - - [Parameter()] - [System.String] - $TarpitInterval, - - [Parameter()] - [System.String] - $TlsCertificateName, - - [Parameter()] - [System.String[]] - $TlsDomainCapabilities, - - [Parameter()] - [ValidateSet('FrontendTransport', 'HubTransport')] - [System.String] - $TransportRole, - - [Parameter()] - [ValidateSet('Client', 'Internal', 'Internet', 'Partner', 'Custom')] - [System.String] - $Usage + $Ensure ) Assert-IdentityIsValid -Identity $Identity @@ -237,15 +37,18 @@ function Get-TargetResource } -Verbose:$VerbosePreference # Establish remote PowerShell session - Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad 'Get-ReceiveConnector' -Verbose:$VerbosePreference + Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad 'Get-ReceiveConnector', 'Get-ADPermission' -Verbose:$VerbosePreference - $connector = Get-ReceiveConnectorInternal @PSBoundParameters + $connector = Get-ReceiveConnector -Identity $Identity -ErrorAction SilentlyContinue if ($null -ne $connector) { + $adPermissions = Get-ADExtendedPermissions -Identity $Identity.Split('\')[1] + $returnValue = @{ Identity = [System.String] $Identity AdvertiseClientSettings = [System.Boolean] $connector.AdvertiseClientSettings + AuthTarpitInterval = [System.String] $connector.AuthTarpitInterval AuthMechanism = [System.String[]] $connector.AuthMechanism.ToString().Split(',').Trim() Banner = [System.String] $connector.Banner BareLinefeedRejectionEnabled = [System.Boolean] $connector.BareLinefeedRejectionEnabled @@ -263,8 +66,8 @@ function Get-TargetResource Enabled = [System.Boolean] $connector.Enabled EnhancedStatusCodesEnabled = [System.Boolean] $connector.EnhancedStatusCodesEnabled ExtendedProtectionPolicy = [System.String] $connector.ExtendedProtectionPolicy - ExtendedRightAllowEntries = [Microsoft.Management.Infrastructure.CimInstance[]] $ExtendedRightAllowEntries - ExtendedRightDenyEntries = [Microsoft.Management.Infrastructure.CimInstance[]] $ExtendedRightDenyEntries + ExtendedRightAllowEntries = [Microsoft.Management.Infrastructure.CimInstance[]] $adPermissions['ExtendedRightAllowEntries'] + ExtendedRightDenyEntries = [Microsoft.Management.Infrastructure.CimInstance[]] $adPermissions['ExtendedRightDenyEntries'] Fqdn = [System.String] $connector.Fqdn LongAddressesEnabled = [System.Boolean] $connector.LongAddressesEnabled MaxAcknowledgementDelay = [System.String] $connector.MaxAcknowledgementDelay @@ -294,12 +97,133 @@ function Get-TargetResource TlsCertificateName = [System.String] $connector.TlsCertificateName TlsDomainCapabilities = [System.String[]] $connector.TlsDomainCapabilities TransportRole = [System.String] $connector.TransportRole + Usage = [System.String[]] $connector.Usage + Ensure = 'Present' + } + } + else + { + $returnValue = @{ + Ensure = 'Absent' } } $returnValue } +<# + .SYNOPSIS + Sets the resource + .PARAMETER Identity + Identity of the Receive Connector. Needs to be in format SERVERNAME\CONNECTORNAME (no quotes) + .PARAMETER Credential + Credentials used to establish a remote PowerShell session to Exchange. + .PARAMETER Ensure + Whether the connector should be present or not. + .PARAMETER AdvertiseClientSettings + Specifies whether the SMTP server name,port number, and authentication settings for the Receive connector + are displayed to users in the options of Outlook on the web. + .PARAMETER AuthMechanism + Specifies the advertised and accepted authentication mechanisms for the Receive connector. + .PARAMETER AuthTarpitInterval + Specifies the period of time to delay responses to failed authentication attempts from remote servers. + .PARAMETER Banner + Specifies a custom SMTP 220 banner that's displayed to remote messaging servers. + .PARAMETER BareLinefeedRejectionEnabled + Specifies whether this Receive connector rejects messages that contain line feed + .PARAMETER BinaryMimeEnabled + Specifies whether the BINARYMIME Extended SMTP extension is enabled or disabled. + .PARAMETER Bindings + Specifies the local IP address and TCP port number that's used by the Receive connector. + .PARAMETER ChunkingEnabled + Specifies whether the CHUNKING Extended SMTP extension is enabled or disabled. + .PARAMETER Comment + Specifies an optional comment. + .PARAMETER ConnectionInactivityTimeout + Specifies the maximum amount of idle time before a connection to the Receive connector is closed. + .PARAMETER ConnectionTimeout + Specifies the maximum time that the connection to the Receive connector can remain open + .PARAMETER DefaultDomain + Specifies the default accepted domain to use for the Exchange organization. + .PARAMETER DeliveryStatusNotificationEnabled + Specifies whether the DSN + .PARAMETER DomainController + Specifies the domain controller that's used by this cmdlet to read data from or write data to Active Directory. + .PARAMETER DomainSecureEnabled + Specifies whether to enable or disable mutual Transport Layer Security + .PARAMETER EightBitMimeEnabled + Specifies whether the 8BITMIME Extended SMTP extension is enabled or disabled. + .PARAMETER EnableAuthGSSAPI + enables or disables Kerberos when Integrated Windows authentication is available on the Receive connector. + .PARAMETER Enabled + Specifies whether to enable or disable the Receive connector. + .PARAMETER EnhancedStatusCodesEnabled + Specifies whether the ENHANCEDSTATUSCODES Extended SMTP extension is enabled or disabled. + .PARAMETER ExtendedRightAllowEntries + Additional allow permissions. + .PARAMETER ExtendedRightDenyEntries + Additional denz permissions. + .PARAMETER ExtendedProtectionPolicy + Specifies how you want to use Extended Protection for Authentication on the Receive connector. + .PARAMETER Fqdn + Specifies the destination FQDN that's shown to connected messaging servers. + .PARAMETER LongAddressesEnabled + Specifies whether the Receive connector accepts long X.400 email addresses. + .PARAMETER MaxAcknowledgementDelay + Specifies the period the transport server delays acknowledgement when receiving messages from a host that doesn't support shadow redundancy. + .PARAMETER MaxHeaderSize + Specifies the maximum size of the SMTP message header before the Receive connector closes the connection. + .PARAMETER MaxHopCount + Specifies the maximum number of hops that a message can take before the message is rejected by the Receive connector. + .PARAMETER MaxInboundConnection + Specifies the maximum number of inbound connections that this Receive connector serves at the same time. + .PARAMETER MaxInboundConnectionPercentagePerSource + Specifies the maximum number of connections that this Receive connector serves at the same time from a single IP address. + .PARAMETER MaxInboundConnectionPerSource + Specifies the maximum number of connections that a Receive connector serves at the same time from a single IP address + .PARAMETER MaxLocalHopCount + Specifies the maximum number of local hops that a message can take before the message is rejected by the Receive connector. + .PARAMETER MaxLogonFailures + pecifies the number of logon failures that the Receive connector retries before it closes the connection. + .PARAMETER MaxMessageSize + Specifies the maximum size of a message that's allowed through the Receive connector. + .PARAMETER MaxProtocolErrors + Specifies the maximum number of SMTP protocol errors that the Receive connector accepts before closing the connection. + .PARAMETER MaxRecipientsPerMessage + Specifies the maximum number of recipients per message that the Receive connector accepts before closing the connection. + .PARAMETER MessageRateLimit + Specifies the maximum number of messages that can be sent by a single client IP address per minute. + .PARAMETER MessageRateSource + Specifies how the message submission rate is calculated. + .PARAMETER OrarEnabled + enables or disables Originator Requested Alternate Recipient + .PARAMETER PermissionGroups + Specifies the well + .PARAMETER PipeliningEnabled + Specifies whether the PIPELINING Extended SMTP extension is enabled or disabled. + .PARAMETER ProtocolLoggingLevel + pecifies whether to enable or disable protocol logging. + .PARAMETER RemoteIPRanges + Specifies the remote IP addresses that the Receive connector accepts messages from. + .PARAMETER RequireEHLODomain + Specifies whether the client must provide a domain name in the EHLO handshake after the SMTP connection is established. + .PARAMETER RequireTLS + Specifies whether to require TLS transmission for inbound messages. + .PARAMETER SizeEnabled + Specifies how the SIZE Extended SMTP extension is used on the Receive connector. + .PARAMETER SuppressXAnonymousTls + Specifies whether the X + .PARAMETER TarpitInterval + Specifies the period of time to delay an SMTP response to a remote server that may be abusing the connection. + .PARAMETER TlsCertificateName + Specifies the X.509 certificate to use for TLS encryption. + .PARAMETER TlsDomainCapabilities + Specifies the capabilities that the Receive connector makes available to specific hosts outside of the organization. + .PARAMETER TransportRole + Specifies the transport service on the Mailbox server where the Receive connector is created. + .PARAMETER Usage + Specifies the default permission groups and authentication methods that are assigned to the Receive connector. +#> function Set-TargetResource { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "")] @@ -332,8 +256,13 @@ function Set-TargetResource [System.Boolean] $AdvertiseClientSettings, + [Parameter()] + [System.String] + $AuthTarpitInterval, + [Parameter()] [System.String[]] + [ValidateSet('None', 'Tls', 'Integrated', 'BasicAuth', 'BasicAuthRequireTLS', 'ExchangeServer', 'ExternalAuthoritative')] $AuthMechanism, [Parameter()] @@ -471,6 +400,7 @@ function Set-TargetResource $OrarEnabled, [Parameter()] + [ValidateSet('None', 'AnonymousUsers', 'ExchangeUsers', 'ExchangeServers', 'ExchangeLegacyServers', 'Partners', 'Custom')] [System.String[]] $PermissionGroups, @@ -537,16 +467,17 @@ function Set-TargetResource 'Identity' = $Identity } -Verbose:$VerbosePreference + $connector = Get-TargetResource -Identity $Identity -Credential $Credential -Ensure $Ensure + # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad '*ReceiveConnector', '*ADPermission' -Verbose:$VerbosePreference - $connector = Get-ReceiveConnectorInternal @PSBoundParameters - if ($Ensure -eq 'Absent') { - if ($null -ne $connector) + if ($connector['Ensure'] -eq 'Present') { Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToKeep 'Identity', 'DomainController' + Write-Verbose -Message 'Removing the receive connector.' Remove-ReceiveConnector @PSBoundParameters -Confirm:$false } @@ -554,49 +485,57 @@ function Set-TargetResource else { # Remove Credential and Ensure so we don't pass it into the next command - Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove 'Credential', 'Ensure' + Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove 'Credential', 'Ensure', 'ExtendedRightAllowEntries', 'ExtendedRightDenyEntries' Set-EmptyStringParamsToNull -PSBoundParametersIn $PSBoundParameters # We need to create the new connector - if ($null -eq $connector) + if ($connector['Ensure'] -eq 'Absent') { # Create a copy of the original parameters - $originalPSBoundParameters = @{} + $PSBoundParameters + $originalPSBoundParameters = @{ } + $PSBoundParameters # The following aren't valid for New-ReceiveConnector - Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove 'Identity', 'BareLinefeedRejectionEnabled', 'ExtendedRightAllowEntries', 'ExtendedRightDenyEntries' + Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove 'Identity', 'BareLinefeedRejectionEnabled' # Parse out the server name and connector name from the given Identity - $serverName = $Identity.Substring(0, $Identity.IndexOf('\')) - $connectorName = $Identity.Substring($Identity.IndexOf('\') + 1) + $serverName, $connectorName = $Identity.Split('\') # Add in server and name parameters Add-ToPSBoundParametersFromHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToAdd @{ 'Server' = $serverName - 'Name' = $connectorName + 'Name' = $connectorName } + Write-Verbose -Message 'Creating the receive connector.' + # Create the connector - $connector = New-ReceiveConnector @PSBoundParameters + New-ReceiveConnector @PSBoundParameters - # Ensure the connector exists, and if so, set us up so we can run Set-ReceiveConnector next - if ($null -ne $connector) - { - # Remove the two props we added - Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove 'Server', 'Name' + # Add original props back + Add-ToPSBoundParametersFromHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToAdd $originalPSBoundParameters - # Add original props back - Add-ToPSBoundParametersFromHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToAdd $originalPSBoundParameters - } - else + # Remove the two props we added + Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove 'Server', 'Name', 'Usage' + + Write-Verbose -Message 'Setting the receive connector properties.' + + Set-ReceiveConnector @PSBoundParameters + + if ($ExtendedRightAllowEntries -or $ExtendedRightDenyEntries) { - throw 'Failed to create new Receive Connector.' + $splat = @{ + ExtendedRightAllowEntries = $ExtendedRightAllowEntries + ExtendedRightDenyEntries = $ExtendedRightDenyEntries + DomainController = $DomainController + Identity = $Identity.Split('\')[1] + NewObject = $true + } + + Set-ADExtendedPermissions @splat -Verbose:$VerbosePreference } } - - # The connector already exists, so use Set-ReceiveConnector - if ($null -ne $connector) + else { # Usage is not a valid command for Set-ReceiveConnector Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove 'Usage', 'ExtendedRightAllowEntries', 'ExtendedRightDenyEntries' @@ -604,31 +543,135 @@ function Set-TargetResource Set-ReceiveConnector @PSBoundParameters # set AD permissions - if ($ExtendedRightAllowEntries) + if ($ExtendedRightAllowEntries -or $ExtendedRightDenyEntries) { - foreach ($ExtendedRightAllowEntry in $ExtendedRightAllowEntries) - { - foreach ($Value in $($ExtendedRightAllowEntry.Value.Split(','))) - { - $connector | Add-ADPermission -User $ExtendedRightAllowEntry.Key -ExtendedRights $Value - } + $splat = @{ + ExtendedRightAllowEntries = $ExtendedRightAllowEntries + ExtendedRightDenyEntries = $ExtendedRightDenyEntries + DomainController = $DomainController + Identity = $Identity.Split('\')[1] + NewObject = $false } - } - if ($ExtendedRightDenyEntries) - { - foreach ($ExtendedRightDenyEntry in $ExtendedRightDenyEntries) - { - foreach ($Value in $($ExtendedRightDenyEntry.Value.Split(','))) - { - $connector | Remove-ADPermission -User $ExtendedRightDenyEntry.Key -ExtendedRights $Value -Confirm:$false - } - } + Set-ADExtendedPermissions @splat -Verbose:$VerbosePreference } } } } +<# + .SYNOPSIS + Tests the resource + .PARAMETER Identity + Identity of the Receive Connector. Needs to be in format SERVERNAME\CONNECTORNAME (no quotes) + .PARAMETER Credential + Credentials used to establish a remote PowerShell session to Exchange. + .PARAMETER Ensure + Whether the connector should be present or not. + .PARAMETER AdvertiseClientSettings + Specifies whether the SMTP server name,port number, and authentication settings for the Receive connector + are displayed to users in the options of Outlook on the web. + .PARAMETER AuthMechanism + Specifies the advertised and accepted authentication mechanisms for the Receive connector. + .PARAMETER AuthTarpitInterval + Specifies the period of time to delay responses to failed authentication attempts from remote servers. + .PARAMETER Banner + Specifies a custom SMTP 220 banner that's displayed to remote messaging servers. + .PARAMETER BareLinefeedRejectionEnabled + Specifies whether this Receive connector rejects messages that contain line feed + .PARAMETER BinaryMimeEnabled + Specifies whether the BINARYMIME Extended SMTP extension is enabled or disabled. + .PARAMETER Bindings + Specifies the local IP address and TCP port number that's used by the Receive connector. + .PARAMETER ChunkingEnabled + Specifies whether the CHUNKING Extended SMTP extension is enabled or disabled. + .PARAMETER Comment + Specifies an optional comment. + .PARAMETER ConnectionInactivityTimeout + Specifies the maximum amount of idle time before a connection to the Receive connector is closed. + .PARAMETER ConnectionTimeout + Specifies the maximum time that the connection to the Receive connector can remain open + .PARAMETER DefaultDomain + Specifies the default accepted domain to use for the Exchange organization. + .PARAMETER DeliveryStatusNotificationEnabled + Specifies whether the DSN + .PARAMETER DomainController + Specifies the domain controller that's used by this cmdlet to read data from or write data to Active Directory. + .PARAMETER DomainSecureEnabled + Specifies whether to enable or disable mutual Transport Layer Security + .PARAMETER EightBitMimeEnabled + Specifies whether the 8BITMIME Extended SMTP extension is enabled or disabled. + .PARAMETER EnableAuthGSSAPI + enables or disables Kerberos when Integrated Windows authentication is available on the Receive connector. + .PARAMETER Enabled + Specifies whether to enable or disable the Receive connector. + .PARAMETER EnhancedStatusCodesEnabled + Specifies whether the ENHANCEDSTATUSCODES Extended SMTP extension is enabled or disabled. + .PARAMETER ExtendedRightAllowEntries + Additional allow permissions. + .PARAMETER ExtendedRightDenyEntries + Additional deny permissions. + .PARAMETER ExtendedProtectionPolicy + Specifies how you want to use Extended Protection for Authentication on the Receive connector. + .PARAMETER Fqdn + Specifies the destination FQDN that's shown to connected messaging servers. + .PARAMETER LongAddressesEnabled + Specifies whether the Receive connector accepts long X.400 email addresses. + .PARAMETER MaxAcknowledgementDelay + Specifies the period the transport server delays acknowledgement when receiving messages from a host that doesn't support shadow redundancy. + .PARAMETER MaxHeaderSize + Specifies the maximum size of the SMTP message header before the Receive connector closes the connection. + .PARAMETER MaxHopCount + Specifies the maximum number of hops that a message can take before the message is rejected by the Receive connector. + .PARAMETER MaxInboundConnection + Specifies the maximum number of inbound connections that this Receive connector serves at the same time. + .PARAMETER MaxInboundConnectionPercentagePerSource + Specifies the maximum number of connections that this Receive connector serves at the same time from a single IP address. + .PARAMETER MaxInboundConnectionPerSource + Specifies the maximum number of connections that a Receive connector serves at the same time from a single IP address + .PARAMETER MaxLocalHopCount + Specifies the maximum number of local hops that a message can take before the message is rejected by the Receive connector. + .PARAMETER MaxLogonFailures + pecifies the number of logon failures that the Receive connector retries before it closes the connection. + .PARAMETER MaxMessageSize + Specifies the maximum size of a message that's allowed through the Receive connector. + .PARAMETER MaxProtocolErrors + Specifies the maximum number of SMTP protocol errors that the Receive connector accepts before closing the connection. + .PARAMETER MaxRecipientsPerMessage + Specifies the maximum number of recipients per message that the Receive connector accepts before closing the connection. + .PARAMETER MessageRateLimit + Specifies the maximum number of messages that can be sent by a single client IP address per minute. + .PARAMETER MessageRateSource + Specifies how the message submission rate is calculated. + .PARAMETER OrarEnabled + enables or disables Originator Requested Alternate Recipient + .PARAMETER PermissionGroups + Specifies the well + .PARAMETER PipeliningEnabled + Specifies whether the PIPELINING Extended SMTP extension is enabled or disabled. + .PARAMETER ProtocolLoggingLevel + pecifies whether to enable or disable protocol logging. + .PARAMETER RemoteIPRanges + Specifies the remote IP addresses that the Receive connector accepts messages from. + .PARAMETER RequireEHLODomain + Specifies whether the client must provide a domain name in the EHLO handshake after the SMTP connection is established. + .PARAMETER RequireTLS + Specifies whether to require TLS transmission for inbound messages. + .PARAMETER SizeEnabled + Specifies how the SIZE Extended SMTP extension is used on the Receive connector. + .PARAMETER SuppressXAnonymousTls + Specifies whether the X + .PARAMETER TarpitInterval + Specifies the period of time to delay an SMTP response to a remote server that may be abusing the connection. + .PARAMETER TlsCertificateName + Specifies the X.509 certificate to use for TLS encryption. + .PARAMETER TlsDomainCapabilities + Specifies the capabilities that the Receive connector makes available to specific hosts outside of the organization. + .PARAMETER TransportRole + Specifies the transport service on the Mailbox server where the Receive connector is created. + .PARAMETER Usage + Specifies the default permission groups and authentication methods that are assigned to the Receive connector. +#> function Test-TargetResource { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "")] @@ -662,8 +705,13 @@ function Test-TargetResource [System.Boolean] $AdvertiseClientSettings, + [Parameter()] + [System.String] + $AuthTarpitInterval, + [Parameter()] [System.String[]] + [ValidateSet('None', 'Tls', 'Integrated', 'BasicAuth', 'BasicAuthRequireTLS', 'ExchangeServer', 'ExternalAuthoritative')] $AuthMechanism, [Parameter()] @@ -801,6 +849,7 @@ function Test-TargetResource $OrarEnabled, [Parameter()] + [ValidateSet('None', 'AnonymousUsers', 'ExchangeUsers', 'ExchangeServers', 'ExchangeLegacyServers', 'Partners', 'Custom')] [System.String[]] $PermissionGroups, @@ -867,20 +916,14 @@ function Test-TargetResource 'Identity' = $Identity } -Verbose:$VerbosePreference + $connector = Get-TargetResource -Identity $Identity -Credential $Credential -Ensure $Ensure + # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad 'Get-ReceiveConnector', 'Get-ADPermission' -Verbose:$VerbosePreference - $connector = Get-ReceiveConnectorInternal @PSBoundParameters - - # get AD permissions if necessary - if (($ExtendedRightAllowEntries) -or ($ExtendedRightDenyEntries)) - { - $ADPermissions = $connector | Get-ADPermission | Where-Object {$_.IsInherited -eq $false} - } - $testResults = $true - if ($null -eq $connector) + if ($connector['Ensure'] -eq 'Absent') { if ($Ensure -eq 'Present') { @@ -897,17 +940,43 @@ function Test-TargetResource } else { - # remove "Custom" from PermissionGroups - $connector.PermissionGroups = ($connector.PermissionGroups -split ',' ) -notmatch 'Custom' -join ',' - - if (!(Test-ExchangeSetting -Name 'AdvertiseClientSettings' -Type 'Boolean' -ExpectedValue $AdvertiseClientSettings -ActualValue $connector.AdvertiseClientSettings -PSBoundParametersIn $PSBoundParameters -Verbose:$VerbosePreference)) - { - $testResults = $false - } - - if (!(Test-ExchangeSetting -Name 'AuthMechanism' -Type 'Array' -ExpectedValue $AuthMechanism -ActualValue (Convert-StringToArray -StringIn "$($connector.AuthMechanism)" -Separator ',') -PSBoundParametersIn $PSBoundParameters -Verbose:$VerbosePreference)) + # Get AD permissions if necessary + if (($ExtendedRightAllowEntries) -or ($ExtendedRightDenyEntries)) { - $testResults = $false + if ($PSBoundParameters.ContainsKey('DomainController')) + { + $adPermissions = Get-ADPermission -Identity $Identity.Split('\')[1] -DomainController $DomainController | Where-Object { $_.IsInherited -eq $false } + } + else + { + $adPermissions = Get-ADPermission -Identity $Identity.Split('\')[1] | Where-Object { $_.IsInherited -eq $false } + } + + $splat = @{ + ExtendedRightAllowEntries = $ExtendedRightAllowEntries + ExtendedRightDenyEntries = $ExtendedRightDenyEntries + ADPermissions = $adPermissions + } + + $testResults = Test-ExtendedRights @splat -Verbose:$VerbosePreference + } + + # remove "Custom" from PermissionGroups + $connector.PermissionGroups = ($connector.PermissionGroups -split ',' ) -notmatch 'Custom' -join ',' + + if (!(Test-ExchangeSetting -Name 'AdvertiseClientSettings' -Type 'Boolean' -ExpectedValue $AdvertiseClientSettings -ActualValue $connector.AdvertiseClientSettings -PSBoundParametersIn $PSBoundParameters -Verbose:$VerbosePreference)) + { + $testResults = $false + } + + if (!(Test-ExchangeSetting -Name 'AuthMechanism' -Type 'Array' -ExpectedValue $AuthMechanism -ActualValue (Convert-StringToArray -StringIn "$($connector.AuthMechanism)" -Verbose:$VerbosePreference) -PSBoundParametersIn $PSBoundParameters -Verbose:$VerbosePreference)) + { + $testResults = $false + } + + if (!(Test-ExchangeSetting -Name 'AuthTarpitInterval' -Type 'Timespan' -ExpectedValue $AuthTarpitInterval -ActualValue $connector.AuthTarpitInterval -PSBoundParametersIn $PSBoundParameters -Verbose:$VerbosePreference)) + { + $testResults = $false } if (!(Test-ExchangeSetting -Name 'Banner' -Type 'String' -ExpectedValue $Banner -ActualValue $connector.Banner -PSBoundParametersIn $PSBoundParameters -Verbose:$VerbosePreference)) @@ -1134,273 +1203,12 @@ function Test-TargetResource { $testResults = $false } - - # check AD permissions if necessary - if ($ExtendedRightAllowEntries) - { - if (!(Test-ExtendedRightsPresent -ADPermissions $ADPermissions -ExtendedRights $ExtendedRightAllowEntries -ShouldbeTrue:$True -Verbose:$VerbosePreference)) - { - $testResults = $false - } - } - - if ($ExtendedRightDenyEntries) - { - if (Test-ExtendedRightsPresent -ADPermissions $ADPermissions -ExtendedRights $ExtendedRightDenyEntries -ShouldbeTrue:$false -Verbose:$VerbosePreference) - { - $testResults = $false - } - } } } return $testResults } -# Runs Get-ReceiveConnector, only specifying Identity, ErrorAction, and optionally DomainController -function Get-ReceiveConnectorInternal -{ - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $Identity, - - [Parameter(Mandatory = $true)] - [System.Management.Automation.PSCredential] - [System.Management.Automation.Credential()] - $Credential, - - [Parameter(Mandatory = $true)] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure, - - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] - $ExtendedRightAllowEntries, - - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] - $ExtendedRightDenyEntries, - - [Parameter()] - [System.Boolean] - $AdvertiseClientSettings, - - [Parameter()] - [System.String[]] - $AuthMechanism, - - [Parameter()] - [System.String] - $Banner, - - [Parameter()] - [System.Boolean] - $BareLinefeedRejectionEnabled, - - [Parameter()] - [System.Boolean] - $BinaryMimeEnabled, - - [Parameter()] - [System.String[]] - $Bindings, - - [Parameter()] - [System.Boolean] - $ChunkingEnabled, - - [Parameter()] - [System.String] - $Comment, - - [Parameter()] - [System.String] - $ConnectionInactivityTimeout, - - [Parameter()] - [System.String] - $ConnectionTimeout, - - [Parameter()] - [System.String] - $DefaultDomain, - - [Parameter()] - [System.String] - $DomainController, - - [Parameter()] - [System.Boolean] - $DeliveryStatusNotificationEnabled, - - [Parameter()] - [System.Boolean] - $DomainSecureEnabled, - - [Parameter()] - [System.Boolean] - $EightBitMimeEnabled, - - [Parameter()] - [System.Boolean] - $EnableAuthGSSAPI, - - [Parameter()] - [System.Boolean] - $Enabled, - - [Parameter()] - [System.Boolean] - $EnhancedStatusCodesEnabled, - - [Parameter()] - [ValidateSet('None', 'Allow', 'Require')] - [System.String] - $ExtendedProtectionPolicy, - - [Parameter()] - [System.String] - $Fqdn, - - [Parameter()] - [System.Boolean] - $LongAddressesEnabled, - - [Parameter()] - [System.String] - $MaxAcknowledgementDelay, - - [Parameter()] - [System.String] - $MaxHeaderSize, - - [Parameter()] - [System.Int32] - $MaxHopCount, - - [Parameter()] - [System.String] - $MaxInboundConnection, - - [Parameter()] - [System.Int32] - $MaxInboundConnectionPercentagePerSource, - - [Parameter()] - [System.String] - $MaxInboundConnectionPerSource, - - [Parameter()] - [System.Int32] - $MaxLocalHopCount, - - [Parameter()] - [System.Int32] - $MaxLogonFailures, - - [Parameter()] - [System.String] - $MaxMessageSize, - - [Parameter()] - [System.String] - $MaxProtocolErrors, - - [Parameter()] - [System.Int32] - $MaxRecipientsPerMessage, - - [Parameter()] - [System.String] - $MessageRateLimit, - - [Parameter()] - [ValidateSet('None', 'IPAddress', 'User', 'All')] - [System.String] - $MessageRateSource, - - [Parameter()] - [System.Boolean] - $OrarEnabled, - - [Parameter()] - [System.String[]] - $PermissionGroups, - - [Parameter()] - [System.Boolean] - $PipeliningEnabled, - - [Parameter()] - [ValidateSet('None', 'Verbose')] - [System.String] - $ProtocolLoggingLevel, - - [Parameter()] - [System.String[]] - $RemoteIPRanges, - - [Parameter()] - [System.Boolean] - $RequireEHLODomain, - - [Parameter()] - [System.Boolean] - $RequireTLS, - - [Parameter()] - [System.String] - $ServiceDiscoveryFqdn, - - [Parameter()] - [ValidateSet('Enabled', 'Disabled', 'EnabledWithoutValue')] - [System.String] - $SizeEnabled, - - [Parameter()] - [System.Boolean] - $SuppressXAnonymousTls, - - [Parameter()] - [System.String] - $TarpitInterval, - - [Parameter()] - [System.String] - $TlsCertificateName, - - [Parameter()] - [System.String[]] - $TlsDomainCapabilities, - - [Parameter()] - [ValidateSet('FrontendTransport', 'HubTransport')] - [System.String] - $TransportRole, - - [Parameter()] - [ValidateSet('Client', 'Internal', 'Internet', 'Partner', 'Custom')] - [System.String] - $Usage - ) - - $getParams = @{ - Server = $env:COMPUTERNAME - ErrorAction = 'SilentlyContinue' - } - - if ($PSBoundParameters.ContainsKey('DomainController') -and ![String]::IsNullOrEmpty($PSBoundParameters['DomainController'])) - { - $getParams.Add('DomainController', $PSBoundParameters['DomainController']) - } - - return (Get-ReceiveConnector @getParams | Where-Object -FilterScript {$_.Identity -like $PSBoundParameters['Identity']}) -} - # Ensure that a connector Identity is in the proper form function Assert-IdentityIsValid { @@ -1417,58 +1225,4 @@ function Assert-IdentityIsValid } } -# check a connector for specific extended rights -function Test-ExtendedRightsPresent -{ - [cmdletbinding()] - [OutputType([System.Boolean])] - param - ( - [Parameter()] - $ADPermissions, - - [Parameter()] - [Microsoft.Management.Infrastructure.CimInstance[]] - $ExtendedRights, - - [Parameter()] - [System.Boolean] - $ShouldbeTrue - ) - - $returnvalue = $false - - foreach ($Right in $ExtendedRights) - { - foreach ($Value in $($Right.Value.Split(','))) - { - if ($null -ne ($ADPermissions | Where-Object {($_.User.RawIdentity -eq $Right.Key) -and ($_.ExtendedRights.RawIdentity -eq $Value)})) - { - $returnvalue = $true - - if (!($ShouldbeTrue)) - { - Write-Verbose -Message 'Should report exist!' - Write-InvalidSettingVerbose -SettingName 'ExtendedRight' -ExpectedValue "User:$($Right.Key) Value:$Value" -ActualValue 'Present' -Verbose:$VerbosePreference - return $returnvalue - exit - } - } - else - { - $returnvalue = $false - - if ($ShouldbeTrue) - { - Write-InvalidSettingVerbose -SettingName 'ExtendedRight' -ExpectedValue "User:$($Right.Key) Value:$Value" -ActualValue 'Absent' -Verbose:$VerbosePreference - return $returnvalue - exit - } - } - } - } - - return $returnvalue -} - Export-ModuleMember -Function *-TargetResource diff --git a/source/DSCResources/MSFT_xExchReceiveConnector/MSFT_xExchReceiveConnector.schema.mof b/source/DSCResources/MSFT_xExchReceiveConnector/MSFT_xExchReceiveConnector.schema.mof index 6e0f4c20..ebc3014e 100644 --- a/source/DSCResources/MSFT_xExchReceiveConnector/MSFT_xExchReceiveConnector.schema.mof +++ b/source/DSCResources/MSFT_xExchReceiveConnector/MSFT_xExchReceiveConnector.schema.mof @@ -1,63 +1,61 @@ -[ClassVersion("1.0.0.0"), FriendlyName("xExchReceiveConnector")] +[ClassVersion("1.0.0.0."), FriendlyName("xExchReceiveConnector")] class MSFT_xExchReceiveConnector : OMI_BaseResource { - [Key] String Identity; //Identity of the Receive Connector. Needs to be in format 'SERVERNAME\CONNECTORNAME' (no quotes) - [Required, EmbeddedInstance("MSFT_Credential")] String Credential; //Credentials used to establish a remote PowerShell session to Exchange - [Required, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; //Whether the connector should be present or not - - //Remaining properties correspond directly to Set-ReceiveConnector parameters - //http://technet.microsoft.com/en-us/library/bb125140(v=exchg.150).aspx - [Write] Boolean AdvertiseClientSettings; - [Write] String AuthMechanism[]; - [Write] String Banner; - [Write] Boolean BareLinefeedRejectionEnabled; - [Write] Boolean BinaryMimeEnabled; - [Write] String Bindings[]; - [Write] Boolean ChunkingEnabled; - [Write] String Comment; - [Write] String ConnectionInactivityTimeout; - [Write] String ConnectionTimeout; - [Write] String DefaultDomain; - [Write] Boolean DeliveryStatusNotificationEnabled; - [Write] String DomainController; - [Write] Boolean DomainSecureEnabled; - [Write] Boolean EightBitMimeEnabled; - [Write] Boolean EnableAuthGSSAPI; - [Write] Boolean Enabled; - [Write] Boolean EnhancedStatusCodesEnabled; - [Write, EmbeddedInstance("MSFT_KeyValuePair")] String ExtendedRightAllowEntries[]; - [Write, EmbeddedInstance("MSFT_KeyValuePair")] String ExtendedRightDenyEntries[]; - [Write, ValueMap{"None","Allow","Require"}, Values{"None","Allow","Require"}] String ExtendedProtectionPolicy; - [Write] String Fqdn; - [Write] Boolean LongAddressesEnabled; - [Write] String MaxAcknowledgementDelay; - [Write] String MaxHeaderSize; - [Write] Sint32 MaxHopCount; - [Write] String MaxInboundConnection; - [Write] Sint32 MaxInboundConnectionPercentagePerSource; - [Write] String MaxInboundConnectionPerSource; - [Write] Sint32 MaxLocalHopCount; - [Write] Sint32 MaxLogonFailures; - [Write] String MaxMessageSize; - [Write] String MaxProtocolErrors; - [Write] Sint32 MaxRecipientsPerMessage; - [Write] String MessageRateLimit; - [Write, ValueMap{"None","IPAddress","User","All"}, Values{"None","IPAddress","User","All"}] String MessageRateSource; - [Write] Boolean OrarEnabled; - [Write] String PermissionGroups[]; - [Write] Boolean PipeliningEnabled; - [Write, ValueMap{"None","Verbose"}, Values{"None","Verbose"}] String ProtocolLoggingLevel; - [Write] String RemoteIPRanges[]; - [Write] Boolean RequireEHLODomain; - [Write] Boolean RequireTLS; - [Write] String ServiceDiscoveryFqdn; - [Write, ValueMap{"Enabled","Disabled","EnabledWithoutValue"}, Values{"Enabled","Disabled","EnabledWithoutValue"}] String SizeEnabled; - [Write] Boolean SuppressXAnonymousTls; - [Write] String TarpitInterval; - [Write] String TlsCertificateName; - [Write] String TlsDomainCapabilities[]; - [Write, ValueMap{"FrontendTransport","HubTransport"}, Values{"FrontendTransport","HubTransport"}] String TransportRole; - [Write, ValueMap{"Client","Internal","Internet","Partner","Custom"}, Values{"Client","Internal","Internet","Partner","Custom"}] String Usage; + [Key, Description("Identity of the Receive Connector. Needs to be in format SERVERNAME\\\\CONNECTORNAME (no quotes).")] String Identity; + [Required, Description("Credentials used to establish a remote PowerShell session to Exchange."), EmbeddedInstance("MSFT_Credential")] String Credential; + [Required, Description("Whether the connector should be present or not."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Specifies whether the SMTP server name, port number, and authentication settings for the Receive connector are displayed to users in the options of Outlook on the web.")] Boolean AdvertiseClientSettings; + [Write, Description("Specifies the advertised and accepted authentication mechanisms for the Receive connector."), ValueMap{"None","Tls","Integrated","BasicAuth","BasicAuthRequireTLS","ExchangeServer","ExternalAuthoritative"}, Values{"None","Tls","Integrated","BasicAuth","BasicAuthRequireTLS","ExchangeServer","ExternalAuthoritative"}] String AuthMechanism[]; + [Write, Description("Specifies the period of time to delay responses to failed authentication attempts from remote servers.")] String AuthTarpitInterval; + [Write, Description("Specifies a custom SMTP 220 banner that's displayed to remote messaging servers.")] String Banner; + [Write, Description("Specifies whether this Receive connector rejects messages that contain line feed (LF) characters without immediately preceding carriage return characters (CR) in the SMTP DATA stream.")] Boolean BareLinefeedRejectionEnabled; + [Write, Description("Specifies whether the BINARYMIME Extended SMTP extension is enabled or disabled.")] Boolean BinaryMimeEnabled; + [Write, Description("Specifies the local IP address and TCP port number that's used by the Receive connector.")] String Bindings[]; + [Write, Description("Specifies whether the CHUNKING Extended SMTP extension is enabled or disabled.")] Boolean ChunkingEnabled; + [Write, Description("Specifies an optional comment.")] String Comment; + [Write, Description("Specifies the maximum amount of idle time before a connection to the Receive connector is closed.")] String ConnectionInactivityTimeout; + [Write, Description("Specifies the maximum time that the connection to the Receive connector can remain open, even if the connection is actively transmitting data.")] String ConnectionTimeout; + [Write, Description("Specifies the default accepted domain to use for the Exchange organization.")] String DefaultDomain; + [Write, Description("Specifies whether the DSN (delivery status notification) Extended SMTP extension is enabled or disabled on the Receive connector.")] Boolean DeliveryStatusNotificationEnabled; + [Write, Description("Specifies the domain controller that's used by this cmdlet to read data from or write data to Active Directory.")] String DomainController; + [Write, Description("Specifies whether to enable or disable mutual Transport Layer Security (TLS) authentication.")] Boolean DomainSecureEnabled; + [Write, Description("Specifies whether the 8BITMIME Extended SMTP extension is enabled or disabled.")] Boolean EightBitMimeEnabled; + [Write, Description("enables or disables Kerberos when Integrated Windows authentication is available on the Receive connector.")] Boolean EnableAuthGSSAPI; + [Write, Description("Specifies whether to enable or disable the Receive connector.")] Boolean Enabled; + [Write, Description("Specifies whether the ENHANCEDSTATUSCODES Extended SMTP extension is enabled or disabled.")] Boolean EnhancedStatusCodesEnabled; + [Write, Description("Additional allow permissions."), EmbeddedInstance("MSFT_KeyValuePair")] String ExtendedRightAllowEntries[]; + [Write, Description("Additional denz permissions."), EmbeddedInstance("MSFT_KeyValuePair")] String ExtendedRightDenyEntries[]; + [Write, Description("Specifies how you want to use Extended Protection for Authentication on the Receive connector."), ValueMap{"None","Allow","Require"}, Values{"None","Allow","Require"}] String ExtendedProtectionPolicy; + [Write, Description("Specifies the destination FQDN that's shown to connected messaging servers.")] String Fqdn; + [Write, Description("Specifies whether the Receive connector accepts long X.400 email addresses.")] Boolean LongAddressesEnabled; + [Write, Description("Specifies the period the transport server delays acknowledgement when receiving messages from a host that doesn't support shadow redundancy.")] String MaxAcknowledgementDelay; + [Write, Description("Specifies the maximum size of the SMTP message header before the Receive connector closes the connection.")] String MaxHeaderSize; + [Write, Description("Specifies the maximum number of hops that a message can take before the message is rejected by the Receive connector.")] Sint32 MaxHopCount; + [Write, Description("Specifies the maximum number of inbound connections that this Receive connector serves at the same time.")] String MaxInboundConnection; + [Write, Description("Specifies the maximum number of connections that this Receive connector serves at the same time from a single IP address.")] Sint32 MaxInboundConnectionPercentagePerSource; + [Write, Description("Specifies the maximum number of connections that a Receive connector serves at the same time from a single IP address, expressed as the percentage of available remaining connections on a Receive connector.")] String MaxInboundConnectionPerSource; + [Write, Description("Specifies the maximum number of local hops that a message can take before the message is rejected by the Receive connector.")] Sint32 MaxLocalHopCount; + [Write, Description("pecifies the number of logon failures that the Receive connector retries before it closes the connection.")] Sint32 MaxLogonFailures; + [Write, Description("Specifies the maximum size of a message that's allowed through the Receive connector.")] String MaxMessageSize; + [Write, Description("Specifies the maximum number of SMTP protocol errors that the Receive connector accepts before closing the connection.")] String MaxProtocolErrors; + [Write, Description("Specifies the maximum number of recipients per message that the Receive connector accepts before closing the connection.")] Sint32 MaxRecipientsPerMessage; + [Write, Description("Specifies the maximum number of messages that can be sent by a single client IP address per minute.")] String MessageRateLimit; + [Write, Description("Specifies how the message submission rate is calculated."), ValueMap{"None","IPAddress","User","All"}, Values{"None","IPAddress","User","All"}] String MessageRateSource; + [Write, Description("enables or disables Originator Requested Alternate Recipient (ORAR) on the Receive connector.")] Boolean OrarEnabled; + [Write, Description("Specifies the well-known security principals who are authorized to use the Receive connector and the permissions that are assigned to them."), ValueMap{"None","AnonymousUsers","ExchangeUsers","ExchangeServers","ExchangeLegacyServers","Partners","Custom"}, Values{"None","AnonymousUsers","ExchangeUsers","ExchangeServers","ExchangeLegacyServers","Partners","Custom"}] String PermissionGroups[]; + [Write, Description("Specifies whether the PIPELINING Extended SMTP extension is enabled or disabled.")] Boolean PipeliningEnabled; + [Write, Description("pecifies whether to enable or disable protocol logging."), ValueMap{"None","Verbose"}, Values{"None","Verbose"}] String ProtocolLoggingLevel; + [Write, Description("Specifies the remote IP addresses that the Receive connector accepts messages from.")] String RemoteIPRanges[]; + [Write, Description("Specifies whether the client must provide a domain name in the EHLO handshake after the SMTP connection is established.")] Boolean RequireEHLODomain; + [Write, Description("Specifies whether to require TLS transmission for inbound messages.")] Boolean RequireTLS; + [Write, Description("Specifies the service discovery fully-qualified domain name (FQDN)")] String ServiceDiscoveryFqdn; + [Write, Description("Specifies how the SIZE Extended SMTP extension is used on the Receive connector."), ValueMap{"Enabled","Disabled","EnabledWithoutValue"}, Values{"Enabled","Disabled","EnabledWithoutValue"}] String SizeEnabled; + [Write, Description("Specifies whether the X-ANONYMOUSTLS Extended SMTP extension is enabled or disabled.")] Boolean SuppressXAnonymousTls; + [Write, Description("Specifies the period of time to delay an SMTP response to a remote server that may be abusing the connection.")] String TarpitInterval; + [Write, Description("Specifies the X.509 certificate to use for TLS encryption.")] String TlsCertificateName; + [Write, Description("Specifies the capabilities that the Receive connector makes available to specific hosts outside of the organization.")] String TlsDomainCapabilities[]; + [Write, Description("Specifies the transport service on the Mailbox server where the Receive connector is created."), ValueMap{"FrontendTransport","HubTransport"}, Values{"FrontendTransport","HubTransport"}] String TransportRole; + [Write, Description("Specifies the default permission groups and authentication methods that are assigned to the Receive connector."), ValueMap{"Client","Internal","Internet","Partner","Custom"}, Values{"Client","Internal","Internet","Partner","Custom"}] String Usage; }; diff --git a/source/DSCResources/MSFT_xExchRemoteDomain/MSFT_xExchRemoteDomain.psm1 b/source/DSCResources/MSFT_xExchRemoteDomain/MSFT_xExchRemoteDomain.psm1 index e90d413c..61dce68c 100644 --- a/source/DSCResources/MSFT_xExchRemoteDomain/MSFT_xExchRemoteDomain.psm1 +++ b/source/DSCResources/MSFT_xExchRemoteDomain/MSFT_xExchRemoteDomain.psm1 @@ -208,6 +208,8 @@ function Set-TargetResource 'Identity' = $DomainName } -Verbose:$VerbosePreference + $remoteDomain = Get-TargetResource -DomainName $DomainName -Credential $Credential + # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad '*-RemoteDomain' -Verbose:$VerbosePreference @@ -215,8 +217,6 @@ function Set-TargetResource Set-EmptyStringParamsToNull -PSBoundParametersIn $PSBoundParameters Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToRemove Credential, Ensure, 'Default' - $remoteDomain = Get-TargetResource -DomainName $DomainName -Credential $Credential - if ($remoteDomain['Ensure'] -eq 'Present') { if ($Ensure -eq 'Absent') diff --git a/source/DSCResources/MSFT_xExchSendConnector/MSFT_xExchSendConnector.psm1 b/source/DSCResources/MSFT_xExchSendConnector/MSFT_xExchSendConnector.psm1 index d4fbc4ef..909d3eb1 100644 --- a/source/DSCResources/MSFT_xExchSendConnector/MSFT_xExchSendConnector.psm1 +++ b/source/DSCResources/MSFT_xExchSendConnector/MSFT_xExchSendConnector.psm1 @@ -34,7 +34,7 @@ function Get-TargetResource } -Verbose:$VerbosePreference # Establish remote PowerShell session - Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad 'Get-SendConnector' -Verbose:$VerbosePreference + Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad 'Get-SendConnector', 'Get-ADPermission' -Verbose:$VerbosePreference $connector = Get-SendConnector -ErrorAction SilentlyContinue | Where-Object -Property 'Identity' -eq $Name @@ -327,11 +327,11 @@ function Set-TargetResource 'Identity' = $Name } -Verbose:$VerbosePreference + $connector = Get-TargetResource -Name $Name -Credential $Credential -AddressSpaces $AddressSpaces + # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad '*SendConnector', '*ADPermission' -Verbose:$VerbosePreference - $connector = Get-TargetResource -Name $Name -Credential $Credential -AddressSpaces $AddressSpaces - if ($Ensure -eq 'Absent') { Write-Verbose -Message "Removing send connector $Name." @@ -687,11 +687,11 @@ function Test-TargetResource 'Identity' = $Name } -Verbose:$VerbosePreference + $connector = Get-TargetResource -Name $Name -Credential $Credential -AddressSpaces $AddressSpaces + # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad 'Get-SendConnector', 'Get-ADPermission' -Verbose:$VerbosePreference - $connector = Get-TargetResource -Name $Name -Credential $Credential -AddressSpaces $AddressSpaces - $testResults = $true if ($connector['Ensure'] -eq 'Absent') diff --git a/source/Modules/xExchangeHelper/xExchangeHelper.psd1 b/source/Modules/xExchangeHelper/xExchangeHelper.psd1 index f156b6e3..19d82d8e 100644 --- a/source/Modules/xExchangeHelper/xExchangeHelper.psd1 +++ b/source/Modules/xExchangeHelper/xExchangeHelper.psd1 @@ -125,7 +125,8 @@ 'Set-DSCMachineStatus', 'Test-ExtendedRightsPresent', 'Test-ExtendedRights', - 'Get-ADExtendedPermissions' + 'Get-ADExtendedPermissions', + 'Set-ADExtendedPermissions' ) # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. diff --git a/source/Modules/xExchangeHelper/xExchangeHelper.psm1 b/source/Modules/xExchangeHelper/xExchangeHelper.psm1 index 41df3ca2..3272755b 100644 --- a/source/Modules/xExchangeHelper/xExchangeHelper.psm1 +++ b/source/Modules/xExchangeHelper/xExchangeHelper.psm1 @@ -1,5 +1,5 @@ $script:DSCExchangeModuleName = 'DSCExchangeModule' -$script:DSCExchangeModulePath = "$env:Temp\DSCExchangeModuleName" +$script:DSCExchangeModulePath = "$env:Temp\DSCExchangeModule" <# .SYNOPSIS @@ -2619,7 +2619,7 @@ function Test-ExtendedRightsPresent { foreach ($Value in $($Right.Value.Split(','))) { - $permissionsFound = $ADPermissions | Where-Object { ($_.User.RawIdentity -eq $Right.Key) -and ($_.ExtendedRights.RawIdentity -eq $Value) } + $permissionsFound = $ADPermissions | Where-Object { ($_.User.RawIdentity -like "*$($Right.Key)*" -and ($_.ExtendedRights.RawIdentity -like "*$Value*")) } if ($null -ne $permissionsFound) { if ($Deny -eq $true -and $permissionsFound.Deny -eq $false -or @@ -2781,4 +2781,94 @@ return @{ } } +<# + .SYNOPSIS + Set AD extendend permissions on an Exchange object. + .DESCRIPTION + Set AD extendend permissions on an Exchange object. + .PARAMETER ExtendedRightAllowEntries + Additional allow permissions. + .PARAMETER ExtendedRightDenyEntries + Additional deny permissions. + .PARAMETER DomainController + Specifies the domain controller that's used by this cmdlet to read data from or write data to Active Directory. + .PARAMETER NewObject + Specfies whether the object was just created by Set-TargetRessource +#> +function Set-ADExtendedPermissions +{ + [CmdletBinding()] + param ( + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ExtendedRightAllowEntries = @(), + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $ExtendedRightDenyEntries = @(), + + [Parameter()] + [System.String] + $DomainController, + + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter(Mandatory = $true)] + [System.Management.Automation.SwitchParameter] + $NewObject + ) + + if ($NewObject -and (-not $DomainController)) + { + $adObject = Get-ADPermission -Identity $Identity -ErrorAction SilentlyContinue + $itt = 0 + + while ($null -eq $adObject -and $itt -le 3) + { + Write-Verbose -Message 'Extended AD permissions were specified and the new connector is still not found in AD. Sleeping for 30 seconds.' + Start-Sleep -Seconds 30 + $itt++ + $adObject = Get-ADPermission -Identity $Identity -ErrorAction SilentlyContinue + } + + if ($null -eq $adObject) + { + throw "The AD Object $Identity was not found after 2 minutes of wait time. Please check AD replication!" + } + } + if ($DomainController) + { + Write-Verbose -Message 'Setting domain controller as default parameter.' + $PSDefaultParameterValues = @{ + 'Add-ADPermission:DomainController' = $DomainController + } + } + if ($ExtendedRightAllowEntries) + { + Write-Verbose -Message "Setting ExtendedRightAllowEntries for AD Object: $Identity." + + foreach ($ExtendedRightAllowEntry in $ExtendedRightAllowEntries) + { + foreach ($Value in $($ExtendedRightAllowEntry.Value.Split(','))) + { + Add-ADPermission -Identity $Identity -User $ExtendedRightAllowEntry.Key -ExtendedRights $Value + } + } + } + if ($ExtendedRightDenyEntries) + { + Write-Verbose -Message "Setting ExtendedRightDenyEntries AD Object: $Identity." + + foreach ($ExtendedRightDenyEntry in $ExtendedRightDenyEntries) + { + foreach ($Value in $($ExtendedRightDenyEntry.Value.Split(','))) + { + Add-ADPermission -Identity $Identity -User $ExtendedRightDenyEntry.Key -ExtendedRights $Value -Deny -Confirm:$false + } + } + } +} + Export-ModuleMember -Function * diff --git a/source/xExchange.psd1 b/source/xExchange.psd1 index 0739525b..4dab2175 100644 --- a/source/xExchange.psd1 +++ b/source/xExchange.psd1 @@ -80,7 +80,8 @@ 'Set-DSCMachineStatus', 'Test-ExtendedRightsPresent', 'Test-ExtendedRights', - 'Get-ADExtendedPermissions' + 'Get-ADExtendedPermissions', + 'Set-ADExtendedPermissions' ) # Cmdlets to export from this module diff --git a/tests/Integration/MSFT_xExchMailboxDatabase.Integration.Tests.ps1 b/tests/Integration/MSFT_xExchMailboxDatabase.Integration.Tests.ps1 index 3b40a73a..a0a269e3 100644 --- a/tests/Integration/MSFT_xExchMailboxDatabase.Integration.Tests.ps1 +++ b/tests/Integration/MSFT_xExchMailboxDatabase.Integration.Tests.ps1 @@ -58,7 +58,7 @@ if ($exchangeInstalled) # Get required credentials to use for the test $shellCredentials = Get-TestCredential - Get-RemoteExchangeSession -Credential $shellCredentials -CommandsToLoad '*-MailboxDatabase', '*-Mailbox', '*-Recipient', 'Get-AcceptedDomain' + Get-RemoteExchangeSession -Credential $shellCredentials -CommandsToLoad '*-MailboxDatabase', '*-Mailbox', '*-Recipient', 'Get-AcceptedDomain', '*-OfflineAddressBook' -Verbose $TestDBName = 'Mailbox Database Test 123' diff --git a/tests/Integration/MSFT_xExchOabVirtualDirectory.Integration.Tests.ps1 b/tests/Integration/MSFT_xExchOabVirtualDirectory.Integration.Tests.ps1 index 3670b7d0..8d29a038 100644 --- a/tests/Integration/MSFT_xExchOabVirtualDirectory.Integration.Tests.ps1 +++ b/tests/Integration/MSFT_xExchOabVirtualDirectory.Integration.Tests.ps1 @@ -31,6 +31,7 @@ if ($exchangeInstalled) $serverFqdn = [System.Net.Dns]::GetHostByName($env:COMPUTERNAME).HostName } + Get-RemoteExchangeSession -Credential $ShellCredentials -CommandsToLoad '*-OfflineAddressBook' # Get the test OAB $testOabName = Get-TestOfflineAddressBook -ShellCredentials $shellCredentials diff --git a/tests/Integration/MSFT_xExchReceiveConnector.Integration.Tests.ps1 b/tests/Integration/MSFT_xExchReceiveConnector.Integration.Tests.ps1 index ff714447..113f6a02 100644 --- a/tests/Integration/MSFT_xExchReceiveConnector.Integration.Tests.ps1 +++ b/tests/Integration/MSFT_xExchReceiveConnector.Integration.Tests.ps1 @@ -29,141 +29,152 @@ if ($exchangeInstalled) # Set configuration with default values $extendedRightAllowEntries = $(New-CimInstance -ClassName MSFT_KeyValuePair -Namespace root/microsoft/Windows/DesiredStateConfiguration -ClientOnly -Property @{ - Key = 'NT AUTHORITY\ANONYMOUS LOGON'; ` - Value = 'Ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-Bypass-Anti-Spam'}) + Key = 'NT AUTHORITY\ANONYMOUS LOGON' + Value = 'Ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-Bypass-Anti-Spam' + } + ) $testParams = @{ - Identity = "$($env:computername)\AnonymousRelay $($env:computername)" - Credential = $shellCredentials - Ensure = 'Present' - ExtendedRightAllowEntries = $extendedRightAllowEntries - AdvertiseClientSettings = $false - AuthMechanism = 'Tls', 'ExternalAuthoritative' - Banner = '220 Pester' - BareLinefeedRejectionEnabled = $false - BinaryMimeEnabled = $true - Bindings = '192.168.0.100:25' - ChunkingEnabled = $true - Comment = 'Connector for relaying' - ConnectionInactivityTimeout = '00:05:00' - ConnectionTimeout = '00:10:00' - DefaultDomain = '' - DeliveryStatusNotificationEnabled = $true - DomainSecureEnabled = $false - EightBitMimeEnabled = $true - EnableAuthGSSAPI = $false - Enabled = $true - EnhancedStatusCodesEnabled = $true - ExtendedProtectionPolicy = 'none' - Fqdn = "$($env:computername).pester.com" - LongAddressesEnabled = $false - MaxAcknowledgementDelay = '00:00:00' - MaxHeaderSize = '128KB' - MaxHopCount = '60' - MaxInboundConnection = '5000' - MaxInboundConnectionPercentagePerSource = '100' - MaxInboundConnectionPerSource = '50' - MaxLocalHopCount = '12' - MaxLogonFailures = '3' - MaxMessageSize = '35MB' - MaxProtocolErrors = '5' - MaxRecipientsPerMessage = '5000' - MessageRateLimit = 'Unlimited' - MessageRateSource = 'IPAddress' - OrarEnabled = $false - PermissionGroups = 'AnonymousUsers', 'ExchangeServers' - PipeliningEnabled = $true - ProtocolLoggingLevel = 'Verbose' - RemoteIPRanges = '192.16.7.99' - RequireEHLODomain = $false - RequireTLS = $false - ServiceDiscoveryFqdn = '' - SizeEnabled = 'EnabledwithoutValue' - SuppressXAnonymousTls = $false - TarpitInterval = '00:00:00' - TlsCertificateName = $null - TlsDomainCapabilities = 'contoso.com:AcceptOorgProtocol' - TransportRole = 'FrontendTransport' - Usage = 'Custom' + Identity = "$($env:computername)\AnonymousRelay $($env:computername)" + Credential = $shellCredentials + Ensure = 'Present' + ExtendedRightAllowEntries = $extendedRightAllowEntries + AdvertiseClientSettings = $false + AuthMechanism = 'Tls', 'ExternalAuthoritative' + Banner = '220 Pester' + BareLinefeedRejectionEnabled = $false + BinaryMimeEnabled = $true + Bindings = '192.168.0.100:25' + ChunkingEnabled = $true + Comment = 'Connector for relaying' + ConnectionInactivityTimeout = '00:05:00' + ConnectionTimeout = '00:10:00' + DefaultDomain = '' + DeliveryStatusNotificationEnabled = $true + DomainSecureEnabled = $false + EightBitMimeEnabled = $true + EnableAuthGSSAPI = $false + Enabled = $true + EnhancedStatusCodesEnabled = $true + ExtendedProtectionPolicy = 'none' + Fqdn = "$($env:computername).pester.com" + LongAddressesEnabled = $false + MaxAcknowledgementDelay = '00:00:00' + MaxHeaderSize = '128KB' + MaxHopCount = '60' + MaxInboundConnection = '5000' + MaxInboundConnectionPercentagePerSource = '100' + MaxInboundConnectionPerSource = '50' + MaxLocalHopCount = '12' + MaxLogonFailures = '3' + MaxMessageSize = '35MB' + MaxProtocolErrors = '5' + MaxRecipientsPerMessage = '5000' + MessageRateLimit = 'Unlimited' + MessageRateSource = 'IPAddress' + OrarEnabled = $false + PermissionGroups = 'AnonymousUsers', 'ExchangeServers' + PipeliningEnabled = $true + ProtocolLoggingLevel = 'Verbose' + RemoteIPRanges = '192.16.7.99' + RequireEHLODomain = $false + RequireTLS = $false + ServiceDiscoveryFqdn = '' + SizeEnabled = 'EnabledwithoutValue' + SuppressXAnonymousTls = $false + TarpitInterval = '00:00:00' + TlsCertificateName = $null + TlsDomainCapabilities = 'contoso.com:AcceptOorgProtocol' + TransportRole = 'FrontendTransport' + Usage = 'Custom' + } + + $getParams = @{ + Identity = "$($env:computername)\AnonymousRelay $($env:computername)" + Credential = $shellCredentials + Ensure = 'Present' } $expectedGetResults = @{ - ExtendedRightAllowEntries = $extendedRightAllowEntries - AdvertiseClientSettings = $false - AuthMechanism = 'Tls', 'ExternalAuthoritative' - Banner = '220 Pester' - BareLinefeedRejectionEnabled = $false - BinaryMimeEnabled = $true - Bindings = '192.168.0.100:25' - ChunkingEnabled = $true - Comment = 'Connector for relaying' - ConnectionInactivityTimeout = '00:05:00' - ConnectionTimeout = '00:10:00' - DefaultDomain = '' - # DomainController = '' - DeliveryStatusNotificationEnabled = $true - DomainSecureEnabled = $false - EightBitMimeEnabled = $true - EnableAuthGSSAPI = $false - Enabled = $true - EnhancedStatusCodesEnabled = $true - ExtendedProtectionPolicy = 'none' - Fqdn = "$($env:computername).pester.com" - LongAddressesEnabled = $false - MaxAcknowledgementDelay = '00:00:00' - MaxHeaderSize = '128 KB (131,072 bytes)' - MaxHopCount = '60' - MaxInboundConnection = '5000' - MaxInboundConnectionPercentagePerSource = '100' - MaxInboundConnectionPerSource = '50' - MaxLocalHopCount = '12' - MaxLogonFailures = '3' - MaxMessageSize = '35 MB (36,700,160 bytes)' - MaxProtocolErrors = '5' - MaxRecipientsPerMessage = '5000' - MessageRateLimit = 'Unlimited' - MessageRateSource = 'IPAddress' - OrarEnabled = $false - PermissionGroups = [System.String[]] @('AnonymousUsers', 'ExchangeServers', 'Custom') - PipeliningEnabled = $true - ProtocolLoggingLevel = 'Verbose' - RemoteIPRanges = '192.16.7.99' - RequireEHLODomain = $false - RequireTLS = $false - ServiceDiscoveryFqdn = '' - SizeEnabled = 'EnabledwithoutValue' - SuppressXAnonymousTls = $false - TarpitInterval = '00:00:00' - TlsCertificateName = '' - TlsDomainCapabilities = 'contoso.com:AcceptOorgProtocol' - TransportRole = 'FrontendTransport' + ExtendedRightAllowEntries = $extendedRightAllowEntries + AdvertiseClientSettings = $false + AuthMechanism = 'Tls', 'ExternalAuthoritative' + Banner = '220 Pester' + BareLinefeedRejectionEnabled = $false + BinaryMimeEnabled = $true + Bindings = '192.168.0.100:25' + ChunkingEnabled = $true + Comment = 'Connector for relaying' + ConnectionInactivityTimeout = '00:05:00' + ConnectionTimeout = '00:10:00' + DefaultDomain = '' + # DomainController = '' + DeliveryStatusNotificationEnabled = $true + DomainSecureEnabled = $false + EightBitMimeEnabled = $true + EnableAuthGSSAPI = $false + Enabled = $true + EnhancedStatusCodesEnabled = $true + ExtendedProtectionPolicy = 'none' + Fqdn = "$($env:computername).pester.com" + LongAddressesEnabled = $false + MaxAcknowledgementDelay = '00:00:00' + MaxHeaderSize = '128 KB (131,072 bytes)' + MaxHopCount = '60' + MaxInboundConnection = '5000' + MaxInboundConnectionPercentagePerSource = '100' + MaxInboundConnectionPerSource = '50' + MaxLocalHopCount = '12' + MaxLogonFailures = '3' + MaxMessageSize = '35 MB (36,700,160 bytes)' + MaxProtocolErrors = '5' + MaxRecipientsPerMessage = '5000' + MessageRateLimit = 'Unlimited' + MessageRateSource = 'IPAddress' + OrarEnabled = $false + PermissionGroups = [System.String[]] @('AnonymousUsers', 'ExchangeServers', 'Custom') + PipeliningEnabled = $true + ProtocolLoggingLevel = 'Verbose' + RemoteIPRanges = '192.16.7.99' + RequireEHLODomain = $false + RequireTLS = $false + ServiceDiscoveryFqdn = '' + SizeEnabled = 'EnabledwithoutValue' + SuppressXAnonymousTls = $false + TarpitInterval = '00:00:00' + TlsCertificateName = '' + TlsDomainCapabilities = 'contoso.com:AcceptOorgProtocol' + TransportRole = 'FrontendTransport' } - Test-TargetResourceFunctionality -Params $testParams -ContextLabel 'Create Receive Connector' -ExpectedGetResults $expectedGetResults + Test-TargetResourceFunctionality -Params $testParams -GetParams $getParams -ContextLabel 'Create Receive Connector' -ExpectedGetResults $expectedGetResults # Modify configuration $extendedRightDenyEntries = $(New-CimInstance -ClassName MSFT_KeyValuePair -Namespace root/microsoft/Windows/DesiredStateConfiguration ` - -Property @{Key = 'Domain Users'; Value = 'ms-Exch-Bypass-Anti-Spam'} -ClientOnly) + -Property @{Key = "$($env:USERDOMAIN)\Domain Users"; Value = 'ms-Exch-Bypass-Anti-Spam' } -ClientOnly) $testParams.ExtendedRightDenyEntries = $extendedRightDenyEntries $expectedGetResults.ExtendedRightDenyEntries = $extendedRightDenyEntries - Test-TargetResourceFunctionality -Params $testParams -ContextLabel 'Modify Receive Connector' -ExpectedGetResults $expectedGetResults + Test-TargetResourceFunctionality -Params $testParams -GetParams $getParams -ContextLabel 'Modify Receive Connector' -ExpectedGetResults $expectedGetResults # Modify configuration $testParams.Ensure = 'Absent' - $expectedGetResults = $null + $getParams.Ensure = 'Absent' + $expectedGetResults = @{ + Ensure = 'Absent' + } - Test-TargetResourceFunctionality -Params $testParams -ContextLabel 'Remove Receive Connector' -ExpectedGetResults $expectedGetResults + Test-TargetResourceFunctionality -Params $testParams -GetParams $getParams -ContextLabel 'Remove Receive Connector' -ExpectedGetResults $expectedGetResults # Try to remove the same receive connector again. This should not cause any errors. $testStartTime = [DateTime]::Now - Test-TargetResourceFunctionality -Params $testParams -ContextLabel 'Attempt Removal of Already Removed Receive Connector' -ExpectedGetResults $expectedGetResults + Test-TargetResourceFunctionality -Params $testParams -GetParams $getParams -ContextLabel 'Attempt Removal of Already Removed Receive Connector' -ExpectedGetResults $expectedGetResults Context 'When Get-ReceiveConnector is called and the connector is absent' { It 'Should not cause an error to be logged in the event log' { Get-EventLog -LogName 'MSExchange Management' -After $testStartTime -ErrorAction SilentlyContinue | ` - Where-Object -FilterScript {$_.Message -like '*Cmdlet failed. Cmdlet Get-ReceiveConnector, parameters -Identity*'} |` + Where-Object -FilterScript { $_.Message -like '*Cmdlet failed. Cmdlet Get-ReceiveConnector, parameters -Identity*' } |` Should -Be $null } } diff --git a/tests/TestHelpers/xExchangeTestHelper.psm1 b/tests/TestHelpers/xExchangeTestHelper.psm1 index 4f47994f..4dfaded4 100644 --- a/tests/TestHelpers/xExchangeTestHelper.psm1 +++ b/tests/TestHelpers/xExchangeTestHelper.psm1 @@ -298,8 +298,6 @@ function Get-TestOfflineAddressBook [System.String] $testOabName = 'Offline Address Book (DSC Test)' - Get-RemoteExchangeSession -Credential $ShellCredentials -CommandsToLoad '*-OfflineAddressBook' - if ($null -eq (Get-OfflineAddressBook -Identity $testOabName -ErrorAction SilentlyContinue)) { Write-Verbose -Message "Test OAB does not exist. Creating OAB with name '$testOabName'." diff --git a/tests/Unit/MSFT_xExchAddressList.tests.ps1 b/tests/Unit/MSFT_xExchAddressList.tests.ps1 index f61d6734..b78e01bf 100644 --- a/tests/Unit/MSFT_xExchAddressList.tests.ps1 +++ b/tests/Unit/MSFT_xExchAddressList.tests.ps1 @@ -104,28 +104,13 @@ try } Describe 'MSFT_xExchAddressList.tests\Set-TargetResource' -Tag 'Set' { - BeforeAll { - Mock -CommandName Write-FunctionEntry -Verifiable - Mock -CommandName Get-RemoteExchangeSession -Verifiable - } + Mock -CommandName Write-FunctionEntry -Verifiable + Mock -CommandName Get-RemoteExchangeSession -Verifiable AfterEach { Assert-VerifiableMock } - Context 'Customized filters and precanned filters are used simultaneously' { - It 'Should throw' { - $setTargetResourceParams = @{ - Name = 'MyCustomAddressList' - Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'fakeuser', (New-Object -TypeName System.Security.SecureString) - RecipientFilter = "(RecipientType -eq 'UserMailbox')" - IncludedRecipients = 'MailUsers' - } - - { Set-TargetResource @setTargetResourceParams } | Should -Throw - } - } - Context 'Address list is present' { Mock -CommandName 'Get-TargetResource' -MockWith { return @{ @@ -203,6 +188,27 @@ try } } + Describe 'MSFT_xExchAddressList.tests\Set-TargetResource - wrong filters' -Tag 'Set' { + Context 'Customized filters and precanned filters are used simultaneously' { + Mock -CommandName Write-FunctionEntry -Verifiable + + It 'Should throw' { + $setTargetResourceParams = @{ + Name = 'MyCustomAddressList' + Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'fakeuser', (New-Object -TypeName System.Security.SecureString) + RecipientFilter = "(RecipientType -eq 'UserMailbox')" + IncludedRecipients = 'MailUsers' + } + + Mock -CommandName Get-RemoteExchangeSession + + { Set-TargetResource @setTargetResourceParams } | Should -Throw + } + + Assert-VerifiableMock + } + } + Describe 'MSFT_xExchAddressList.tests\Test-TargetResource' -Tag 'Test' { BeforeAll { Mock -CommandName Write-FunctionEntry -Verifiable diff --git a/tests/Unit/MSFT_xExchReceiveConnector.tests.ps1 b/tests/Unit/MSFT_xExchReceiveConnector.tests.ps1 index afb5ccae..c119fdcb 100644 --- a/tests/Unit/MSFT_xExchReceiveConnector.tests.ps1 +++ b/tests/Unit/MSFT_xExchReceiveConnector.tests.ps1 @@ -15,13 +15,60 @@ function Invoke-TestCleanup try { InModuleScope $script:DSCResourceName { + function Add-ADPermission + { + param( + $Identity, + $User, + $ExtendedRights, + [Switch] + $Deny + ) + } + function Get-ADPermission + { + param( + $Identity + ) + } + function Get-ReceiveConnector + { + param () + } + function Set-ReceiveConnector + { + param ( + $Identity + ) + } + function Set-ADExtendedPermissions + { + param ( + $ExtendedRightAllowEntries, + $ExtendedRightDenyEntries, + $Identity, + $NewObject + ) + } + function New-ReceiveConnector + { + param ( + $Name + ) + } + function Remove-ReceiveConnector + { + param ( + $Identity + ) + } Describe 'MSFT_xExchReceiveConnector\Get-TargetResource' -Tag 'Get' { AfterEach { Assert-VerifiableMock } $getTargetResourceParams = @{ - Identity = 'ReceiveConnector' + Identity = 'Server1\ReceiveConnector' Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'fakeuser', (New-Object -TypeName System.Security.SecureString) Ensure = 'Present' } @@ -48,6 +95,7 @@ try ExtendedRightAllowEntries = [Microsoft.Management.Infrastructure.CimInstance[]] @() ExtendedRightDenyEntries = [Microsoft.Management.Infrastructure.CimInstance[]] @() Fqdn = [System.String] '' + Identity = [System.String] 'Server1\ReceiveConnector' LongAddressesEnabled = [System.Boolean] $false MaxAcknowledgementDelay = [System.String] '' MaxHeaderSize = [System.String] '' @@ -79,12 +127,370 @@ try } Context 'When Get-TargetResource is called' { - Mock -CommandName Assert-IdentityIsValid -Verifiable Mock -CommandName Write-FunctionEntry -Verifiable Mock -CommandName Get-RemoteExchangeSession -Verifiable - Mock -CommandName Get-ReceiveConnectorInternal -Verifiable -MockWith { return $getReceiveConnectorStandardOutput } + Mock -CommandName Get-ReceiveConnector -Verifiable -MockWith { return $getReceiveConnectorStandardOutput } + Mock -CommandName Get-ADPermission -ModuleName 'xExchangeHelper' Test-CommonGetTargetResourceFunctionality -GetTargetResourceParams $getTargetResourceParams + $results = Get-TargetResource @getTargetResourceParams + $results['Ensure'] | Should -Be 'Present' + } + Context 'When receive connector does not exists' { + It 'Should return Absent' { + Mock -CommandName Write-FunctionEntry -Verifiable + Mock -CommandName Get-RemoteExchangeSession -Verifiable + Mock -CommandName Get-ReceiveConnector -Verifiable + + $results = Get-TargetResource @getTargetResourceParams + $results['Ensure'] | Should -Be 'Absent' + } + } + Context 'When the identity is not correct' { + It 'Should throw an exception' { + $getTargetResourceParamsWrong = @{ } + $getTargetResourceParams + $getTargetResourceParamsWrong['Identity'] = 'WrongIdentity' + + { Get-TargetResource @getTargetResourceParamsWrong } | Should -Throw "Identity must be in the format: 'SERVERNAME\Connector Name' (No quotes)" + } + } + } + Describe 'MSFT_xExchReceiveConnector\Set-TargetResource' -Tag 'Set' { + AfterEach { + Assert-VerifiableMock + } + + Mock -CommandName Write-FunctionEntry -Verifiable + Mock -CommandName Get-RemoteExchangeSession -Verifiable + + $setTargetResourceParams = @{ + Identity = 'Server1\ReceiveConnector' + Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'fakeuser', (New-Object -TypeName System.Security.SecureString) + Ensure = 'Present' + DomainSecureEnabled = $false + ConnectionTimeout = '00:30:30' + } + + Context 'When the receive connector is present' { + Mock -CommandName Get-TargetResource -Verifiable -MockWith { return @{ + Ensure = 'Present' + } + } + + It 'Should remove the connector when Absent is specified' { + + $setTargetResourceParamsAbsent = @{ } + $setTargetResourceParams + $setTargetResourceParamsAbsent['Ensure'] = 'Absent' + + Mock -CommandName Remove-ReceiveConnector -ParameterFilter { $Identity -eq 'Server1\ReceiveConnector' } -Verifiable + + Set-TargetResource @setTargetResourceParamsAbsent + } + It 'Should set the connector properites' { + Mock -CommandName Set-ReceiveConnector -ParameterFilter { $Identity -eq 'Server1\ReceiveConnector' } -Verifiable + + Set-TargetResource @setTargetResourceParams + } + It 'Should set the allow Permissions when specified' { + $setTargetResourcePermissions = @{ } + $setTargetResourceParams + $setTargetResourcePermissions['ExtendedRightAllowEntries'] = New-CimInstance -ClassName MSFT_KeyValuePair -Property @{ + key = 'User1Allow' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + + Mock -CommandName 'Set-ADExtendedPermissions' -Verifiable -ParameterFilter { + $Identity -eq 'ReceiveConnector' -and + $NewObject -eq $false -and + $ExtendedRightAllowEntries.Key -eq 'User1Allow' + } + + Set-TargetResource @setTargetResourcePermissions + } + It 'Should set the deny Permissions when specified' { + $setTargetResourcePermissions = @{ } + $setTargetResourceParams + $setTargetResourcePermissions['ExtendedRightDenyEntries'] = New-CimInstance -ClassName MSFT_KeyValuePair -Property @{ + key = 'User2Deny' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + + Mock -CommandName 'Set-ADExtendedPermissions' -Verifiable -ParameterFilter { + $Identity -eq 'ReceiveConnector' -and + $NewObject -eq $false -and + $ExtendedRightDenyEntries.Key -eq 'User2Deny' + } + + Set-TargetResource @setTargetResourcePermissions + } + } + Context 'When the receive connector is not present' { + Mock -CommandName Get-TargetResource -MockWith { + return @{ + Ensure = 'Absent' + } + } -Verifiable + + It 'Should create the receive connector' { + Mock -CommandName New-ReceiveConnector -ParameterFilter { $Name -eq 'ReceiveConnector' } -Verifiable + Mock -CommandName Set-ReceiveConnector -ParameterFilter { $Identity -eq 'Server1\ReceiveConnector' } -Verifiable + + Set-TargetResource @setTargetResourceParams + } + + Context 'When permissions are specified' { + Mock -CommandName New-ReceiveConnector -ParameterFilter { $Name -eq 'ReceiveConnector' } -Verifiable + Mock -CommandName Set-ReceiveConnector -ParameterFilter { $Identity -eq 'Server1\ReceiveConnector' } -Verifiable + + It 'Should set the allow Permissions when specified' { + $setTargetResourcePermissions = @{ } + $setTargetResourceParams + $setTargetResourcePermissions['ExtendedRightAllowEntries'] = New-CimInstance -ClassName MSFT_KeyValuePair -Property @{ + key = 'User1Allow' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + + Mock -CommandName 'Set-ADExtendedPermissions' -Verifiable -ParameterFilter { + $Identity -eq 'ReceiveConnector' -and + $NewObject -eq $true -and + $ExtendedRightAllowEntries.Key -eq 'User1Allow' + } + + Set-TargetResource @setTargetResourcePermissions + } + It 'Should set the deny Permissions when specified' { + $setTargetResourcePermissions = @{ } + $setTargetResourceParams + $setTargetResourcePermissions['ExtendedRightDenyEntries'] = New-CimInstance -ClassName MSFT_KeyValuePair -Property @{ + key = 'User2Deny' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + + Mock -CommandName 'Set-ADExtendedPermissions' -Verifiable -ParameterFilter { + $Identity -eq 'ReceiveConnector' -and + $NewObject -eq $true -and + $ExtendedRightDenyEntries.Key -eq 'User2Deny' + } + + Set-TargetResource @setTargetResourcePermissions + } + } + } + Context 'When the identity is not correct' { + It 'Should throw an exception' { + $setTargetResourceParamsWrong = @{ } + $setTargetResourceParams + $setTargetResourceParamsWrong['Identity'] = 'WrongIdentity' + + { Set-TargetResource @setTargetResourceParamsWrong } | Should -Throw "Identity must be in the format: 'SERVERNAME\Connector Name' (No quotes)" + } + } + } + Describe 'MSFT_xExchReceiveConnector\Test-TargetResource' -Tag 'Test' { + AfterEach { + Assert-VerifiableMock + } + + Mock -CommandName Write-FunctionEntry -Verifiable + Mock -CommandName Get-RemoteExchangeSession -Verifiable + + $testTargetResourceParams = @{ + Identity = 'Server1\ReceiveConnector' + Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'fakeuser', (New-Object -TypeName System.Security.SecureString) + Ensure = 'Present' + DomainSecureEnabled = $false + MaxHopCount = 1 + } + + Context 'When the receive connector is present' { + $getTargetRessourceOutput = @{ + AdvertiseClientSettings = [System.Boolean] $false + AuthMechanism = [System.String[]] @() + Banner = [System.String] '' + BareLinefeedRejectionEnabled = [System.Boolean] $false + BinaryMimeEnabled = [System.Boolean] $false + Bindings = [System.String[]] @() + ChunkingEnabled = [System.Boolean] $false + Comment = [System.String] '' + ConnectionInactivityTimeout = [System.String] '' + ConnectionTimeout = [System.String] '00:30:30' + DefaultDomain = [System.String] '' + DeliveryStatusNotificationEnabled = [System.Boolean] $false + DomainSecureEnabled = [System.Boolean] $false + EightBitMimeEnabled = [System.Boolean] $false + EnableAuthGSSAPI = [System.Boolean] $false + Enabled = [System.Boolean] $false + EnhancedStatusCodesEnabled = [System.Boolean] $false + ExtendedProtectionPolicy = [System.String] '' + ExtendedRightAllowEntries = [Microsoft.Management.Infrastructure.CimInstance[]] @() + ExtendedRightDenyEntries = [Microsoft.Management.Infrastructure.CimInstance[]] @() + Fqdn = [System.String] '' + Identity = [System.String] 'Server1\ReceiveConnector' + LongAddressesEnabled = [System.Boolean] $false + MaxAcknowledgementDelay = [System.String] '' + MaxHeaderSize = [System.String] '' + MaxHopCount = [System.Int32] 1 + MaxInboundConnection = [System.String] '' + MaxInboundConnectionPercentagePerSource = [System.Int32] 1 + MaxInboundConnectionPerSource = [System.String] '' + MaxLocalHopCount = [System.Int32] 1 + MaxLogonFailures = [System.Int32] 1 + MaxMessageSize = [System.String] '' + MaxProtocolErrors = [System.String] '' + MaxRecipientsPerMessage = [System.Int32] 1 + MessageRateLimit = [System.String] '' + MessageRateSource = [System.String] '' + OrarEnabled = [System.Boolean] $false + PermissionGroups = [System.String[]] @() + PipeliningEnabled = [System.Boolean] $false + ProtocolLoggingLevel = [System.String] '' + RemoteIPRanges = [System.String[]] @() + RequireEHLODomain = [System.Boolean] $false + RequireTLS = [System.Boolean] $false + ServiceDiscoveryFqdn = [System.String] '' + SizeEnabled = [System.String] '' + SuppressXAnonymousTls = [System.Boolean] $false + TarpitInterval = [System.String] '' + TlsCertificateName = [System.String] '' + TlsDomainCapabilities = [System.String[]] @() + TransportRole = [System.String] '' + Ensure = 'Present' + } + + Mock -CommandName Get-TargetResource -Verifiable -MockWith { return $getTargetRessourceOutput } + + It 'Should return false when Absent is specified' { + + $testTargetResourceParamsAbsent = @{ } + $testTargetResourceParams + $testTargetResourceParamsAbsent['Ensure'] = 'Absent' + + Test-TargetResource @testTargetResourceParamsAbsent | Should -Be $false + } + It 'Should return false when property does not match' { + $testTargetResourceParamsNewValues = @{ } + $testTargetResourceParams + $testTargetResourceParamsNewValues['MaxHopCount'] = 2 + $testTargetResourceParamsNewValues['DomainSecureEnabled'] = $true + + Test-TargetResource @testTargetResourceParamsNewValues | Should -Be $false + } + It 'Should return true when properties match' { + Test-TargetResource @testTargetResourceParams | Should -Be $true + } + Context 'When extended permissions are specified' { + $ADPermissions = @() + $permission += [PSCustomObject] @{ + IsInherited = $false + User = [PSCustomObject] @{ + RawIdentity = 'User1Allow' + } + Deny = [System.Management.Automation.SwitchParameter]::new($false) + ExtendedRights = [PSCustomObject] @{ + RawIdentity = 'ms-Exch-SMTP-Accept-Any-Recipient' + } + } + $ADPermissions += $permission + + $permission = [PSCustomObject] @{ + IsInherited = $false + User = [PSCustomObject] @{ + RawIdentity = 'User1Allow' + } + Deny = [System.Management.Automation.SwitchParameter]::new($false) + ExtendedRights = [PSCustomObject] @{ + RawIdentity = 'ms-Exch-SMTP-Accept-Any-Sender' + } + } + $ADPermissions += $permission + + $permission = [PSCustomObject] @{ + IsInherited = $false + User = [PSCustomObject] @{ + RawIdentity = 'User2Deny' + } + Deny = [System.Management.Automation.SwitchParameter]::new($true) + ExtendedRights = [PSCustomObject] @{ + RawIdentity = 'ms-Exch-SMTP-Accept-Any-Recipient' + } + } + $ADPermissions += $permission + + $permission = [PSCustomObject] @{ + IsInherited = $false + User = [PSCustomObject] @{ + RawIdentity = 'User2Deny' + } + Deny = [System.Management.Automation.SwitchParameter]::new($true) + ExtendedRights = [PSCustomObject] @{ + RawIdentity = 'ms-Exch-SMTP-Accept-Any-Sender' + } + } + $ADPermissions += $permission + + Mock -CommandName 'Get-ADPermission' -MockWith { return $ADPermissions } + + Context 'When permissions are not compliant' { + It 'Should return $false when extended permissions do not match' { + $TestTargetResourceParamsFalse = @{ } + $TestTargetResourceParams + $TestTargetResourceParamsFalse['ExtendedRightAllowEntries'] = ( + New-CimInstance -ClassName 'MSFT_KeyValuePair' -Property @{ + key = 'User1Allow' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Authoritative-Domain-Sender' + } -ClientOnly + ) + + Test-TargetResource @TestTargetResourceParamsFalse | Should -Be $false + } + It 'Should return $false when permissions are not present' { + $TestTargetResourceParamsFalse = @{ } + $TestTargetResourceParams + $TestTargetResourceParamsFalse['ExtendedRightAllowEntries'] = ( + New-CimInstance -ClassName 'MSFT_KeyValuePair' -Property @{ + key = 'User1Allow' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + ) + + Mock -CommandName 'Get-ADPermission' -MockWith { return ($ADPermissions | Where-Object -FilterScript { $_.User.RawIdentity -eq 'User2Deny' }) } + Test-TargetResource @TestTargetResourceParamsFalse | Should -Be $false + } + } + Context 'When permissions match' { + It 'Should return $true' { + $TestTargetResourceParamsTrue = @{ } + $TestTargetResourceParams + $TestTargetResourceParamsTrue['ExtendedRightAllowEntries'] = ( + New-CimInstance -ClassName 'MSFT_KeyValuePair' -Property @{ + key = 'User1Allow' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + ) + $TestTargetResourceParamsTrue['ExtendedRightDenyEntries'] = ( + New-CimInstance -ClassName 'MSFT_KeyValuePair' -Property @{ + key = 'User2Deny' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + ) + + Test-TargetResource @TestTargetResourceParamsTrue | Should -Be $true + } + } + } + } + Context 'When the receive connector is not present' { + Mock -CommandName Get-TargetResource -MockWith { return @{ + Ensure = 'Absent' + } + } -Verifiable + + It 'Should return false when Absent is not specified' { + Test-TargetResource @testTargetResourceParams | Should -Be $false + } + It 'Should return true when Absent is specified' { + $testTargetResourceParamsAbsent = @{ } + $testTargetResourceParams + $testTargetResourceParamsAbsent['Ensure'] = 'Absent' + Test-TargetResource @testTargetResourceParamsAbsent | Should -Be $true + } + } + Context 'When the identity is not correct' { + It 'Should throw an exception' { + $testTargetResourceParamsWrong = @{ } + $testTargetResourceParams + $testTargetResourceParamsWrong['Identity'] = 'WrongIdentity' + + { Test-TargetResource @testTargetResourceParamsWrong } | Should -Throw "Identity must be in the format: 'SERVERNAME\Connector Name' (No quotes)" + } } } } diff --git a/tests/Unit/MSFT_xExchSendConnector.tests.ps1 b/tests/Unit/MSFT_xExchSendConnector.tests.ps1 index 67918bde..33a724b8 100644 --- a/tests/Unit/MSFT_xExchSendConnector.tests.ps1 +++ b/tests/Unit/MSFT_xExchSendConnector.tests.ps1 @@ -247,7 +247,7 @@ try $Identity -eq 'MySendConnector' -and $User -eq 'User1Allow' -and ($ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Recipient' -or - $ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Recipient') + $ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Sender') } Set-TargetResource @setTargetResourcePermissions @@ -265,7 +265,7 @@ try $Identity -eq 'MySendConnector' -and $User -eq 'User2Deny' -and ($ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Recipient' -or - $ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Recipient') + $ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Sender') } Set-TargetResource @setTargetResourcePermissions } diff --git a/tests/Unit/xExchangeHelper.tests.ps1 b/tests/Unit/xExchangeHelper.tests.ps1 index 88484f73..f0ca5ced 100644 --- a/tests/Unit/xExchangeHelper.tests.ps1 +++ b/tests/Unit/xExchangeHelper.tests.ps1 @@ -3137,6 +3137,135 @@ try } } } + + Describe 'xExchangeHelper\Set-ADExtendedPermissions' -Tag 'Helper' { + AfterEach { + Assert-VerifiableMock + } + + function Add-ADPermission + { + param( + $Identity, + $User, + $ExtendedRights, + [Switch] + $Deny + ) + } + function Get-ADPermission + { + param( + $Identity + ) + } + + Context 'When it is a new object' { + It 'Should throw when the object is not found' { + Mock -CommandName 'Get-ADPermission' -Verifiable -ParameterFilter { $Identity -eq 'FakeADObject' } + + { Set-ADExtendedPermissions -Identity 'FakeADobject' -NewObject } | Should -Throw "The AD Object FakeADobject was not found after 2 minutes of wait time. Please check AD replication!" + } + It 'Should set the allow Permissions when specified' { + $ExtendedRightAllowEntries = New-CimInstance -ClassName MSFT_KeyValuePair -Property @{ + key = 'User1Allow' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + + Mock -CommandName 'Get-ADPermission' -Verifiable -ParameterFilter { $Identity -eq 'FakeADObject' } -MockWith { + return 'DummyOutput' + } + Mock -CommandName 'Add-ADPermission' -Verifiable -ParameterFilter { + $Identity -eq 'FakeADObject' -and + $User -eq 'User1Allow' -and + ($ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Recipient' -or + $ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Sender') + } + + $splat = @{ + ExtendedRightAllowEntries = $ExtendedRightAllowEntries + Identity = 'FakeADObject' + NewObject = $true + } + + Set-ADExtendedPermissions @splat + } + It 'Should set the deny Permissions when specified' { + $ExtendedRightDenyEntries = New-CimInstance -ClassName MSFT_KeyValuePair -Property @{ + key = 'User2Deny' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + + Mock -CommandName 'Get-ADPermission' -Verifiable -ParameterFilter { $Identity -eq 'FakeADObject' } { + return 'DummyOutput' + } + Mock -CommandName 'Add-ADPermission' -Verifiable -ParameterFilter { + $Identity -eq 'FakeADObject' -and + $User -eq 'User2Deny' -and + $Deny -eq $true -and + ($ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Recipient' -or + $ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Sender') + } + + $splat = @{ + ExtendedRightDenyEntries = $ExtendedRightDenyEntries + Identity = 'FakeADObject' + NewObject = $true + } + + Set-ADExtendedPermissions @splat + } + } + Context 'When it is not a new object' { + It 'Should set the allow Permissions when specified' { + $ExtendedRightAllowEntries = New-CimInstance -ClassName MSFT_KeyValuePair -Property @{ + key = 'User1Allow' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + + Mock -CommandName 'Add-ADPermission' -Verifiable -ParameterFilter { + $Identity -eq 'FakeADObject' -and + $DomainController -eq 'FakeDC.local.com' -and + $User -eq 'User1Allow' -and + ($ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Recipient' -or + $ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Sender') + } + + $splat = @{ + ExtendedRightAllowEntries = $ExtendedRightAllowEntries + DomainController = 'FakeDC.local.com' + Identity = 'FakeADObject' + NewObject = $true + } + + Set-ADExtendedPermissions @splat + } + It 'Should set the deny Permissions when specified' { + $ExtendedRightDenyEntries = New-CimInstance -ClassName MSFT_KeyValuePair -Property @{ + key = 'User2Deny' + value = 'ms-Exch-SMTP-Accept-Any-Recipient,ms-Exch-SMTP-Accept-Any-Sender' + } -ClientOnly + + Mock -CommandName 'Add-ADPermission' -Verifiable -ParameterFilter { + $Identity -eq 'FakeADObject' -and + $DomainController -eq 'FakeDC.local.com' -and + $User -eq 'User2Deny' -and + $Deny -eq $true -and + ($ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Recipient' -or + $ExtendedRights -eq 'ms-Exch-SMTP-Accept-Any-Sender') + } + + $splat = @{ + ExtendedRightDenyEntries = $ExtendedRightDenyEntries + DomainController = 'FakeDC.local.com' + Identity = 'FakeADObject' + NewObject = $true + } + + Set-ADExtendedPermissions @splat + } + } + } } } finally