Providers/FreeIPA/Private/New-FreeIPACertificateRequest.ps1
|
function New-FreeIPACertificateRequest { <# .SYNOPSIS Builds a PKCS#10 certificate signing request with in-box .NET, and returns it as PEM .DESCRIPTION The realm's CA signs whatever the seed asks it to, and it asks with a request signed by a key generated here and thrown away: nothing ever needs to use the certificates, only to see them on the entries and in the CA. The request carries the subject the realm demands - the login or the host name as the common name, the realm as the organisation - and the subject alternative names a row asks for, which the realm checks against the principal. System.Security.Cryptography.X509Certificates.CertificateRequest is in .NET Framework 4.7.2 and every .NET Core, so both editions build the request without a module and without openssl. A machine older than that gets a plain error rather than a type resolution failure. .PARAMETER Subject The distinguished name, for example CN=jnino,O=IPA.EXAMPLE.COM. .PARAMETER DnsName DNS names for the subject alternative name extension. .PARAMETER EmailAddress Email addresses for the subject alternative name extension. .PARAMETER KeySize RSA key size. Defaults to 2048. .OUTPUTS System.String. The request as PEM, with the BEGIN and END lines. .EXAMPLE PS> New-FreeIPACertificateRequest -Subject 'CN=zz-test-web01.ipa.example.com,O=IPA.EXAMPLE.COM' -DnsName 'zz-test-web01.ipa.example.com' DESCRIPTION: Builds a request for a service certificate OUTPUT: The PEM text USE CASE: Handed to cert_request by New-FreeIPACertificate .NOTES Author: Jeffrey Stuhr Blog: https://www.techbyjeff.net LinkedIn: https://www.linkedin.com/in/jeffrey-stuhr-034214aa/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Builds a request in memory and changes nothing; the key is discarded before it returns.')] [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Subject, [Parameter()] [string[]]$DnsName = @(), [Parameter()] [string[]]$EmailAddress = @(), [Parameter()] [ValidateSet(2048, 3072, 4096)] [int]$KeySize = 2048 ) if (-not ('System.Security.Cryptography.X509Certificates.CertificateRequest' -as [type])) { throw 'Building a certificate request needs .NET Framework 4.7.2 or later, or PowerShell 7.' } $rsa = [System.Security.Cryptography.RSA]::Create($KeySize) try { $request = [System.Security.Cryptography.X509Certificates.CertificateRequest]::new( $Subject, $rsa, [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) $names = @($DnsName | Where-Object { $_ }) + @($EmailAddress | Where-Object { $_ }) if ($names.Count -gt 0) { $san = [System.Security.Cryptography.X509Certificates.SubjectAlternativeNameBuilder]::new() foreach ($name in @($DnsName | Where-Object { $_ })) { $san.AddDnsName($name) } foreach ($address in @($EmailAddress | Where-Object { $_ })) { $san.AddEmailAddress($address) } $request.CertificateExtensions.Add($san.Build()) } $der = $request.CreateSigningRequest() } finally { $rsa.Dispose() } $body = [Convert]::ToBase64String($der, [Base64FormattingOptions]::InsertLineBreaks) return "-----BEGIN CERTIFICATE REQUEST-----`n$body`n-----END CERTIFICATE REQUEST-----`n" } |