Public/New-TMConsoleCertificate.ps1
function New-TMConsoleCertificate { param ( ) ## Perform Windows Setup if ($IsWindows) { ## Only admins can create certificates if (-Not (Test-IsAdmin)) { throw 'Creating a certificate requires administrative permission.' } ## Provide naming details for the certificate $SubjectName = $env:COMPUTERNAME ## Create File Path variables $OutFolder = Join-Path -Path $Env:ProgramData -ChildPath "tmconsole" -AdditionalChildPath "certificates" $OutServerKeyPath = Join-Path -Path $OutFolder -ChildPath 'TMConsole.key' $OutCertificatePath = Join-Path -Path $OutFolder -ChildPath 'TMConsole.pem' $TempDERKeyPath = Join-Path -Path $OutFolder -ChildPath 'TMConsole.der' ## Create the Certificates Folder if it's not already present Test-FolderPath -FolderPath $OutFolder ## Remove Existing Certificates Get-ChildItem -Path $OutFolder -Recurse -Force | Remove-Item -Force -Recurse ## Create the Self Signed Certificate $CertSettingsSplat = @{ DnsName = $SubjectName CertStorelocation = 'Cert:\LocalMachine\My' KeyLength = 2048 KeyFriendlyName = $SubjectName KeyAlgorithm = 'RSA' KeyUsageProperty = 'All' Provider = 'Microsoft Enhanced RSA and AES Cryptographic Provider' FriendlyName = $SubjectName HashAlgorithm = 'Sha256' KeyExportPolicy = 'Exportable' Keyspec = 'KeyExchange' NotAfter = (Get-Date).AddYears(2) } try { Write-Verbose "New Cert Settings: $CertSettingsSplat" $TempCert = New-SelfSignedCertificate @CertSettingsSplat $NewCert = Get-ChildItem "Cert:\LocalMachine\My\$($TempCert.Thumbprint)" } catch { throw "Failed to create certificate: $_" } if (-Not $NewCert.PrivateKey) { throw "There was an error creating the TLS Certificate for TMConsole. No Private Key was available for export." } ## Convert the Certificate to an RSA Certificate format to export the Private Key $RSACng = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($NewCert); $RsaPrivateKeyBytesB64 = [Convert]::ToBase64String($RSACng.ExportRsaPrivateKey(), "InsertLineBreaks") ## Create the output string $PrivateKeyString = "-----BEGIN RSA PRIVATE KEY-----`r`n" $PrivateKeyString += $RsaPrivateKeyBytesB64 $PrivateKeyString += "`r`n-----END RSA PRIVATE KEY-----" ## Write the output string to the key file $PrivateKeyString | Set-Content $OutServerKeyPath -Force ## Convert the certificate to get a Public Certificate Export-Certificate -Cert $NewCert -FilePath $TempDERKeyPath -Type CERT -Force | Out-Null certutil -encode $TempDERKeyPath $OutCertificatePath | Out-Null Remove-Item -Path $TempDERKeyPath ## Import this certificate to the user's trusted root certificates try { Import-Certificate -FilePath $OutCertificatePath -CertStoreLocation "cert:\LocalMachine\Root" -Confirm:$False | Out-Null } catch { throw "Unable to import certificate to Local Machine Root store: $_" } } ## Perform Mac Setup if ($IsMacOS) { ## Ensure OpenSSL is installed if (-Not (Test-Path -Path '/usr/bin/openssl')) { throw 'Open SSL is not installed' } ## Get the Hostname as the Cert Subject Name (used throught the script) $SubjectName = ($(&hostname -s)).toLower() ## ## Configure paths ## $CertFolder = Join-Path -Path '/' -ChildPath 'Users' -AdditionalChildPath $env:USER, 'Library', 'Application Support', 'tmconsole', 'certificates' Test-FolderPath -FolderPath $CertFolder $DeviceConfigFile = Join-Path -Path $CertFolder -ChildPath "$SubjectName-openssl.cnf" $AppKeyPath = Join-Path -Path $CertFolder -ChildPath 'TMConsole.key' $AppCertPath = Join-Path -Path $CertFolder -ChildPath 'TMConsole.crt' ## Create a new OpenSSL Config file for this request $OpenSSLConfigLines = @" [req] distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no [req_distinguished_name] C = US ST = MA L = Boston O = TransitionManager OU = TMConsole CN = {hostname} [v3_req] keyUsage = keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = {hostname} DNS.2 = {hostname}.local "@ ## Replace the {hostname} token with the Subject name $DeviceConfigLines = [System.Collections.ArrayList]@() foreach ($OpenSSLConfigLine in $OpenSSLConfigLines) { [void]$DeviceConfigLines.Add(($OpenSSLConfigLine -replace "\{hostname\}", $SubjectName)) } Set-Content -Path $DeviceConfigFile -Value $DeviceConfigLines -Force ## ## Generate a self signed cert, one request command ## ## Construct the OpenSSL command to produce the certificate $CreateSelfSignedCertComamndArgs = @( "req" "-x509" "-new" "-keyout" "$AppKeyPath" "-out" "$AppCertPath" "-nodes" "-days" "1000" "-config" "$DeviceConfigFile" ) ## Generate Certificate Write-Verbose ('Running Command: openssl ' + ($CreateSelfSignedCertComamndArgs -join ', ')) & openssl $CreateSelfSignedCertComamndArgs ## Import the Certificate to the Trusted Root store sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain $AppCertPath } } |