public/New-AxisCertificateAuthority.ps1
|
<# .SYNOPSIS Adds (or replaces) a certificate authority definition in the AxisPowershell configuration. .DESCRIPTION Certificate authorities are the issuers used by Request-AxisCertificate, Invoke-AxisCertificateDeployment and the provisioning job. Four types are supported: - WindowsCA : Microsoft AD CS, reached through the ICertRequest2/ICertAdmin2 COM interfaces (Windows only). - Dogtag : Dogtag PKI / FreeIPA; enrollment through its EST subsystem, revocation through the CA REST API. - EST : any RFC 7030 EST server (OpenXPKI, EJBCA, ...). EST has no revocation; supply -RevokeCommand if needed. - Command : any command line CA such as 'openssl ca', run locally or over SSH. A template (AD CS template name, EST label, or a token in your command) is always required so the CA controls the certificate profile. Passwords and tokens are never written to the configuration file: they are stored in the Windows Credential Manager under 'AxisPowershell-CA-<Name>'. The authority is tested before it is saved unless -SkipTest is given. .PARAMETER Name Short name used to refer to this authority, e.g. "CorpCA". .PARAMETER Template WindowsCA: certificate template name. Dogtag/EST: EST label (may be empty string if the server has none). Command: free text available as {Template} in the command. .PARAMETER CAConfig WindowsCA only. The CA config string "host\CA Name" as shown by certutil -dump. .PARAMETER Server Dogtag/EST: base URL of the server, e.g. https://pki.example.com:8443. .PARAMETER Credential Dogtag/EST: HTTP Basic credential for enrollment (and Dogtag agent revocation unless -RevokeCredential is given). .PARAMETER RevokeCredential Dogtag: separate agent credential for revocation. .PARAMETER ClientCertThumbprint Dogtag/EST: thumbprint of a client certificate in Cert:\CurrentUser\My for mutual TLS instead of Basic auth. .PARAMETER CAThumbprint Dogtag/EST: pin the CA certificate returned by /cacerts to this thumbprint. .PARAMETER SkipCertificateCheck Dogtag/EST: do not validate the server's TLS certificate. .PARAMETER SignCommand Command: command template. Tokens: {CsrFile} {CertFile} {Device} {Subject} {Template}. .PARAMETER RevokeCommand Command/EST: command template for revocation. Tokens: {Serial} {Reason}. .PARAMETER TestCommand Command: optional command run by the connectivity test. .PARAMETER SshHost Command: run the commands on this host over SSH (uses ssh/scp from the PATH). .PARAMETER SshUser Command: SSH user name. .PARAMETER SshKeyFile Command: SSH private key file passed to ssh -i. .PARAMETER KeyTypes Key algorithms this CA/template accepts, e.g. RSA-2048,RSA-4096 for an RSA-only AD CS template. The camera's strongest key type within this list is used. Default: any. .PARAMETER TimeoutSec How long to wait for issuance (pending approvals, slow commands). Default 300. .PARAMETER Default Make this the default authority for Request-AxisCertificate and provisioning. .PARAMETER SkipTest Save without running the connectivity test. .EXAMPLE New-AxisCertificateAuthority -Name CorpCA -Type WindowsCA -CAConfig "pki01.example.com\Example Issuing CA" -Template AxisCamera -Default .EXAMPLE New-AxisCertificateAuthority -Name Dogtag -Type Dogtag -Server https://pki.example.com:8443 -Template cameras -Credential (Get-Credential) .EXAMPLE New-AxisCertificateAuthority -Name LabCA -Type Command -Template server_cert -SshHost ca.lab -SshUser ca -SignCommand 'openssl ca -batch -config /etc/pki/ca/openssl.cnf -extensions {Template} -in {CsrFile} -out {CertFile}' -RevokeCommand 'openssl ca -config /etc/pki/ca/openssl.cnf -revoke /etc/pki/ca/newcerts/{Serial}.pem -crl_reason {Reason}' #> function New-AxisCertificateAuthority { [cmdletbinding(DefaultParameterSetName='WindowsCA')] Param( [Parameter(Mandatory)] [ValidatePattern('^[A-Za-z0-9_-]+$')] [String]$Name, [Parameter(Mandatory)] [ValidateSet("WindowsCA","Dogtag","EST","Command")] [String]$Type, [Parameter(Mandatory)] [AllowEmptyString()] [String]$Template, [Parameter()] [String]$CAConfig, [Parameter()] [String]$Server, [Parameter()] [PSCredential]$Credential, [Parameter()] [PSCredential]$RevokeCredential, [Parameter()] [String]$ClientCertThumbprint, [Parameter()] [String]$CAThumbprint, [Parameter()] [Switch]$SkipCertificateCheck, [Parameter()] [String]$SignCommand, [Parameter()] [String]$RevokeCommand, [Parameter()] [String]$TestCommand, [Parameter()] [String]$SshHost, [Parameter()] [String]$SshUser, [Parameter()] [String]$SshKeyFile, [Parameter()] [ValidateSet("NIST-P384","NIST-P256","RSA-4096","RSA-3072","RSA-2048")] [String[]]$KeyTypes, [Parameter()] [Int]$TimeoutSec=300, [Parameter()] [Switch]$Default, [Parameter()] [Switch]$SkipTest ) $Authority = @{ Type = $Type Template = $Template TimeoutSec = $TimeoutSec } if($KeyTypes) { #The CA template may only sign some algorithms (an RSA-only AD CS template, for example) $Authority.Add("KeyTypes",@($KeyTypes)) } switch($Type) { "WindowsCA" { if(!$CAConfig) { Throw "WindowsCA requires -CAConfig 'host\CA Name'" } $Authority.Add("CAConfig",$CAConfig) $Authority.Add("PollSeconds",5) } { $_ -in "Dogtag","EST" } { if(!$Server) { Throw "$Type requires -Server 'https://host:port'" } if(!$Credential -and !$ClientCertThumbprint) { Throw "$Type requires -Credential or -ClientCertThumbprint" } $Authority.Add("Server",$Server.TrimEnd('/')) $Authority.Add("Label",$Template) $Authority.Add("SkipCertificateCheck",[bool]$SkipCertificateCheck) if($ClientCertThumbprint) { $Authority.Add("ClientCertThumbprint",$ClientCertThumbprint) } if($CAThumbprint) { $Authority.Add("CAThumbprint",$CAThumbprint) } if($Credential) { $Authority.Add("CredentialTarget","AxisPowershell-CA-$Name") } if($RevokeCredential) { $Authority.Add("RevokeCredentialTarget","AxisPowershell-CA-$Name-Revoke") } if($Type -eq "EST" -and $RevokeCommand) { $Authority.Add("RevokeCommand",$RevokeCommand) } } "Command" { if(!$SignCommand) { Throw "Command requires -SignCommand" } $Authority.Add("SignCommand",$SignCommand) if($RevokeCommand) { $Authority.Add("RevokeCommand",$RevokeCommand) } if($TestCommand) { $Authority.Add("TestCommand",$TestCommand) } if($SshHost) { $Authority.Add("SshHost",$SshHost) if($SshUser) { $Authority.Add("SshUser",$SshUser) } if($SshKeyFile) { $Authority.Add("SshKeyFile",$SshKeyFile) } } } } #Secrets go to the credential vault, never to config.json if($Credential) { $Param = @{ Target = $Authority.CredentialTarget Persist = 'Enterprise' Credentials = $Credential } $null = New-StoredCredential @Param } if($RevokeCredential) { $Param = @{ Target = $Authority.RevokeCredentialTarget Persist = 'Enterprise' Credentials = $RevokeCredential } $null = New-StoredCredential @Param } if(!$SkipTest) { $TestAuthority = $Authority.Clone() $TestAuthority.Add("Name",$Name) $Result = & "Test-AxisCertificateAuthority$Type" -Authority $TestAuthority if(!$Result.Reachable) { Throw "Certificate authority test failed: $($Result.Message). Use -SkipTest to save anyway." } Write-Verbose "Authority test: $($Result.Message)" } $Config.CertificateAuthorities[$Name] = $Authority if($Default -or !$Config.Certificate.DefaultAuthority) { $Config.Certificate.DefaultAuthority = $Name } Write-ModuleConfiguration return Get-AxisPSCertificateAuthority -Name $Name } |