# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. Import-Module (Join-Path -Path $PSScriptRoot 'certificateCommon.psm1') -Force Describe "CmsMessage cmdlets and Get-PfxCertificate basic tests" -Tags "CI" { BeforeAll { $certLocation = New-GoodCertificate $certLocation | Should -Not -BeNullOrEmpty | Out-Null $protectedCertLocation = New-ProtectedCertificate $protectedCertLocation | Should -Not -BeNullOrEmpty | Out-Null } It "Verify Get-PfxCertificate -FilePath" { $cert = Get-PfxCertificate -FilePath $certLocation $cert.Subject | Should -Be "CN=MyDataEnciphermentCert" } It "Verify Get-PfxCertificate -LiteralPath" { $cert = Get-PfxCertificate -LiteralPath $certLocation $cert.Subject | Should -Be "CN=MyDataEnciphermentCert" } It "Verify Get-PfxCertificate positional argument" { $cert = Get-PfxCertificate $certLocation $cert.Subject | Should -Be "CN=MyDataEnciphermentCert" } It "Verify Get-PfxCertificate right password" { $password = Get-CertificatePassword $cert = Get-PfxCertificate $protectedCertLocation -Password $password $cert.Subject | Should -Be "CN=localhost" } It "Verify Get-PfxCertificate wrong password" { #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Test secret.")] $pass = ConvertTo-SecureString "wrongpass" -AsPlainText -Force { Get-PfxCertificate $protectedCertLocation -Password $pass -ErrorAction Stop } | Should -Throw -ErrorId "GetPfxCertificateUnknownCryptoError,Microsoft.PowerShell.Commands.GetPfxCertificateCommand" } It "Verify CMS message recipient resolution by path" -Skip:(!$IsWindows) { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] $certLocation $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors) $recipient.Certificates.Count | Should -Be 1 $recipient.Certificates[0].Subject | Should -Match 'CN=MyDataEnciphermentCert' } It "Verify CMS message recipient resolution by cert" -Skip:(!$IsWindows) { $errors = $null $cert = Get-PfxCertificate $certLocation $recipient = [System.Management.Automation.CmsMessageRecipient] $cert $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors) $recipient.Certificates.Count | Should -Be 1 $recipient.Certificates[0].Subject | Should -Match 'CN=MyDataEnciphermentCert' } It "Verify a CMS message can be protected / unprotected" -Skip:(!$IsWindows) { $protected = "Hello World","How are you?" | Protect-CmsMessage -To $certLocation $protected.IndexOf("-----BEGIN CMS-----") | Should -Be 0 $message = $protected | Get-CmsMessage $message.Recipients.Count | Should -Be 1 $message.Recipients[0].IssuerName | Should -Be "CN=MyDataEnciphermentCert" $expected = "Hello World" + [System.Environment]::NewLine + "How are you?" $decrypted = $message | Unprotect-CmsMessage -To $certLocation $decrypted | Should -Be $expected $decrypted = $protected | Unprotect-CmsMessage -To $certLocation $decrypted | Should -Be $expected } } Describe "CmsMessage cmdlets thorough tests" -Tags "Feature" { BeforeAll{ if($IsWindows) { Install-TestCertificates } else { # Skip for non-Windows platforms $defaultParamValues = $PSDefaultParameterValues.Clone() $PSDefaultParameterValues = @{ "it:skip" = $true } } } AfterAll { if($IsWindows) { Remove-TestCertificates } else { $global:PSdefaultParameterValues = $defaultParamValues } } It "Verify message recipient resolution by Base64Cert" { $certContent = " -----BEGIN CERTIFICATE----- MIIDXTCCAkWgAwIBAgIQRTsRwsx0LZBHrx9z5Dag2zANBgkqhkiG9w0BAQUFADAh MR8wHQYDVQQDDBZNeURhdGFFbmNpcGhlcm1lbnRDZXJ0MCAXDTE0MDcyNTIyMjkz OVoYDzMwMTQwNzI1MjIzOTM5WjAhMR8wHQYDVQQDDBZNeURhdGFFbmNpcGhlcm1l bnRDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3SuShUvnRqn tYOIouJdP3wPZ5rtDi2KYPurpngGNZjM0EGDTrnhmEAI8DL4Kp6n/zz1mYVoX73+ 6uCpZX/13VDXg1neebJ261XpBX6FzxtclIQr8ywdUtrEgCnUAhgqgvO1Wwm4ogNR tWGCGkmlnqyaoV1j/V4KSn4WvKqSUIOZm0umGCTtNAJ6VtdpYO+uxxnRAapPUCY+ qQ7DFzTUECIo1lMlBcuMiXj6NSFr4/D7ltkZ27jCdsZmzI7ZvRnDlfSYTPQnAO/E 0uYn9uyKY/xfngWkUX/pe+j+10Lm1ypbASrj2Ezgf0KeZRXBwqKUOLhKheEmBJ18 rLV27qwHeQIDAQABo4GOMIGLMA4GA1UdDwEB/wQEAwIEMDAUBgNVHSUEDTALBgkr BgEEAYI3UAEwRAYJKoZIhvcNAQkPBDcwNTAOBggqhkiG9w0DAgICAIAwDgYIKoZI hvcNAwQCAgCAMAcGBSsOAwIHMAoGCCqGSIb3DQMHMB0GA1UdDgQWBBRIyIzwInLJ 3B+FajVUFMACf1hrxjANBgkqhkiG9w0BAQUFAAOCAQEAfFt4rmUmWfCbbwi2mCrZ Osq0lfVNUiZ+iLlEKga4VAI3sJZRtErnVM70eXUt7XpRaOdIfxjuXFpsgc37KyLi ByCORLuRC0itZVs3aba48opfMDXivxBy0ngqCPPLQsyaN9K7WnpvYV1QxiudYwwU 8U5rFmzlwNLvc3XiyoGWaVZluk2DIJawQ5QYAU9/NMBBCbPHjTG7k0l4cpcEC+Ex od3RlO6/MOYuK2WB4VTxKsV80EdA3ljlu7Td8P4movnrbB4rG4wpCpk05eREkg/5 Y54Ilo9m5OSAWtdx4yfS779eebLgUs3P+dk6EKwovXMokVveZA8cenIp3QkqSpeT cQ== -----END CERTIFICATE----- " $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] $certContent $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors) $recipient.Certificates.Count | Should -Be 1 $recipient.Certificates[0].Subject | Should -Match 'CN=MyDataEnciphermentCert' } It "Verify wildcarded recipient resolution by path [Decryption]" { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] ((Get-GoodCertificateLocation) + "*") $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors) # Should have resolved single cert $recipient.Certificates.Count | Should -Be 1 } It "Verify wildcarded recipient resolution by path [Encryption]" { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] ((Get-GoodCertificateLocation) + "*") $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors) $recipient.Certificates.Count | Should -Be 1 } It "Verify resolution by directory" { $protectedEventLoggingCertPath = Join-Path $TestDrive ProtectedEventLoggingDir $null = New-Item -ItemType Directory $protectedEventLoggingCertPath -Force Copy-Item (Get-GoodCertificateLocation) $protectedEventLoggingCertPath Copy-Item (Get-GoodCertificateLocation) (Join-Path $protectedEventLoggingCertPath "SecondCert.pfx") Copy-Item (Get-GoodCertificateLocation) (Join-Path $protectedEventLoggingCertPath "ThirdCert.pfx") $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] $protectedEventLoggingCertPath $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors) $recipient.Certificates.Count | Should -Be 1 } It "Verify resolution by thumbprint" { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] (Get-GoodCertificateObject).Thumbprint $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors) # "Should have certs from thumbprint in 'My' store" $recipient.Certificates.Count | Should -Be 1 $recipient.Certificates[0].Thumbprint | Should -Be (Get-GoodCertificateObject).Thumbprint } It "Verify resolution by subject name" { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] (Get-GoodCertificateObject).Subject $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors) $recipient.Certificates.Count | Should -Be 1 $recipient.Certificates[0].Thumbprint | Should -Be (Get-GoodCertificateObject).Thumbprint } It "Verify error when no cert found in encryption for encryption" { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] "SomeCertificateThatDoesNotExist*" $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors) $errors.Count | Should -Be 1 $errors[0].FullyQualifiedErrorId | Should -Be "NoCertificateFound" } It "Verify error when encrypting to non-wildcarded identifier for decryption" { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] "SomeCertificateThatDoesNotExist" $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors) $errors.Count | Should -Be 1 $errors[0].FullyQualifiedErrorId | Should -Be "NoCertificateFound" } It "Verify error when encrypting to wrong cert" { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] (Get-BadCertificateObject).Thumbprint $recipient.Resolve($ExecutionContext.SessionState, "Encryption", [ref] $errors) $errors.Count | Should -Be 1 $errors[0].FullyQualifiedErrorId | Should -Be "CertificateCannotBeUsedForEncryption" } It "Verify no error when encrypting to wildcarded identifier for decryption" { $errors = $null $recipient = [System.Management.Automation.CmsMessageRecipient] "SomeCertificateThatDoesNotExist*" $recipient.Resolve($ExecutionContext.SessionState, "Decryption", [ref] $errors) $errors | Should -Be $null $recipient.Certificates.Count | Should -Be 0 } It "Verify Protect-CmsMessage emits recipient errors" { { "Hello World" | Protect-CmsMessage -To "SomeThumbprintThatDoesNotExist" -ErrorAction Stop } | Should -Throw -ErrorId "NoCertificateFound,Microsoft.PowerShell.Commands.ProtectCmsMessageCommand" } It "Verify CmsMessage cmdlets works with paths" { try { $randomNum = Get-Random -Minimum 1000 -Maximum 9999 $tempPath = Join-Path $TestDrive "$randomNum-Path-Test-File" $encryptedPath = $tempPath + ".encrypted.txt" "Hello World","How are you?" | Set-Content $tempPath Protect-CmsMessage -Path $tempPath -To (Get-GoodCertificateLocation) -OutFile $encryptedPath $message = Get-CmsMessage -LiteralPath $encryptedPath $message.Recipients.Count | Should -Be 1 $message.Recipients[0].IssuerName | Should -Be "CN=MyDataEnciphermentCert" $expected = "Hello World" + [System.Environment]::NewLine + "How are you?" + [System.Environment]::NewLine $decrypted = $message | Unprotect-CmsMessage -To (Get-GoodCertificateLocation) $decrypted | Should -Be $expected $decrypted = Unprotect-CmsMessage -Path $encryptedPath -To (Get-GoodCertificateLocation) $decrypted | Should -Be $expected } finally { Remove-Item $tempPath, $encryptedPath -Force -ErrorAction SilentlyContinue } } It "Verify Unprotect-CmsMessage works with local store" { try { $randomNum = Get-Random -Minimum 1000 -Maximum 9999 $tempPath = Join-Path $TestDrive "$randomNum-Path-Test-File" "Hello World" | Protect-CmsMessage -To (Get-GoodCertificateLocation) -OutFile $tempPath # Decrypt using $importedCert in the Cert store $decrypted = Unprotect-CmsMessage -Path $tempPath $decrypted | Should -Be "Hello World" } finally { Remove-Item $tempPath -Force -ErrorAction SilentlyContinue } } It "Verify Unprotect-CmsMessage emits recipient errors" { { "" | Unprotect-CmsMessage -To "SomeThumbprintThatDoesNotExist" -IncludeContext -ErrorAction Stop } | Should -Throw -ErrorId "NoCertificateFound,Microsoft.PowerShell.Commands.UnprotectCmsMessageCommand" } It "Verify failure to extract Ascii armor generates an error [Unprotect-CmsMessage]" { { "Hello World" | Unprotect-CmsMessage -ErrorAction Stop } | Should -Throw -ErrorId "InputContainedNoEncryptedContentIncludeContext,Microsoft.PowerShell.Commands.UnprotectCmsMessageCommand" } It "Verify failure to extract Ascii armor generates an error [Get-CmsMessage]" { { "Hello World" | Get-CmsMessage -ErrorAction Stop } | Should -Throw -ErrorId "InputContainedNoEncryptedContent,Microsoft.PowerShell.Commands.GetCmsMessageCommand" } It "Verify 'Unprotect-CmsMessage -IncludeContext' with no encrypted input" { # Should have round-tripped content $result = "Hello World" | Unprotect-CmsMessage -IncludeContext $result | Should -Be "Hello World" } It "Verify Unprotect-CmsMessage lets you include context" { $protected = "Hello World" | Protect-CmsMessage -To (Get-GoodCertificateLocation) $adjustedProtected = "Pre content" + [System.Environment]::NewLine + $protected + [System.Environment]::NewLine + "Post content" $decryptedNoContext = $adjustedProtected | Unprotect-CmsMessage -To (Get-GoodCertificateLocation) $decryptedWithContext = $adjustedProtected | Unprotect-CmsMessage -To (Get-GoodCertificateLocation) -IncludeContext $decryptedNoContext | Should -Be "Hello World" $expected = "Pre content" + [System.Environment]::NewLine + "Hello World" + [System.Environment]::NewLine + "Post content" $decryptedWithContext | Should -Be $expected } It "Verify Unprotect-CmsMessage treats event logs as a first class citizen" { $protected = "Encrypted Message1","Encrypted Message2" | Protect-CmsMessage -To (Get-GoodCertificateLocation) $virtualEventLog = Get-WinEvent Microsoft-Windows-PowerShell/Operational -MaxEvents 1 $savedId = $virtualEventLog.Id $virtualEventLog.Message = $protected $expected = "Encrypted Message1" + [System.Environment]::NewLine + "Encrypted Message2" $decrypted = $virtualEventLog | Unprotect-CmsMessage -To (Get-GoodCertificateLocation) $decrypted | Should -Be $expected $processed = $virtualEventLog | Unprotect-CmsMessage -To (Get-GoodCertificateLocation) -IncludeContext $processed.Id | Should -Be $savedId $processed.Message | Should -Be $expected } # Pending due to #3847 It "Verify -DocumentEncryptionCert parameter works" -Pending { $foundCerts = Get-ChildItem Cert:\CurrentUser -Recurse -DocumentEncryptionCert # Validate they all match the EKU $correctMatching = $foundCerts | Where-Object { ($_.EnhancedKeyUsageList.Count -gt 0) -and ($_.EnhancedKeyUsageList[0].ObjectId -eq '1.3.6.1.4.1.311.80.1') } # "All Document Encryption Cert should have had correct EKU" @($foundCerts).Count | Should -Be @($correctMatching).Count } It "Verify protect message using OutString" { $protected = Get-Process -Id $PID | Protect-CmsMessage -To (Get-GoodCertificateLocation) $decrypted = $protected | Unprotect-CmsMessage -To (Get-GoodCertificateLocation) # Should have had PID in output $decrypted | Should -Match $PID } }