139 lines
6.0 KiB
PowerShell
139 lines
6.0 KiB
PowerShell
param(
|
|
[string]$OutputDirectory = (Join-Path (Split-Path -Parent $PSScriptRoot) "deploy/.control-plane-tls")
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
if ([string]::IsNullOrWhiteSpace($OutputDirectory)) {
|
|
throw "OutputDirectory is required"
|
|
}
|
|
|
|
if (Test-Path -LiteralPath $OutputDirectory) {
|
|
$existing = @(Get-ChildItem -Force -LiteralPath $OutputDirectory)
|
|
if ($existing.Count -gt 0) {
|
|
throw "OutputDirectory must be empty: $OutputDirectory"
|
|
}
|
|
}
|
|
else {
|
|
New-Item -ItemType Directory -Path $OutputDirectory | Out-Null
|
|
}
|
|
|
|
function ConvertTo-Pem {
|
|
param(
|
|
[string]$Label,
|
|
[byte[]]$Bytes
|
|
)
|
|
|
|
$base64 = [Convert]::ToBase64String($Bytes, [Base64FormattingOptions]::InsertLineBreaks)
|
|
return "-----BEGIN $Label-----`n$base64`n-----END $Label-----`n"
|
|
}
|
|
|
|
function Write-PemFile {
|
|
param(
|
|
[string]$Path,
|
|
[string]$Label,
|
|
[byte[]]$Bytes
|
|
)
|
|
|
|
[IO.File]::WriteAllText($Path, (ConvertTo-Pem -Label $Label -Bytes $Bytes), [Text.Encoding]::ASCII)
|
|
}
|
|
|
|
function New-CertificateRequest {
|
|
param(
|
|
[string]$CommonName,
|
|
[System.Security.Cryptography.RSA]$Key,
|
|
[bool]$IsCertificateAuthority,
|
|
[string]$ExtendedKeyUsage,
|
|
[string]$SubjectAlternativeName
|
|
)
|
|
|
|
$request = [System.Security.Cryptography.X509Certificates.CertificateRequest]::new(
|
|
"CN=$CommonName",
|
|
$Key,
|
|
[System.Security.Cryptography.HashAlgorithmName]::SHA256,
|
|
[System.Security.Cryptography.RSASignaturePadding]::Pkcs1
|
|
)
|
|
$request.CertificateExtensions.Add([System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension]::new(
|
|
$IsCertificateAuthority, $false, 0, $true
|
|
))
|
|
if ($IsCertificateAuthority) {
|
|
$request.CertificateExtensions.Add([System.Security.Cryptography.X509Certificates.X509KeyUsageExtension]::new(
|
|
[System.Security.Cryptography.X509Certificates.X509KeyUsageFlags]::KeyCertSign -bor
|
|
[System.Security.Cryptography.X509Certificates.X509KeyUsageFlags]::CrlSign,
|
|
$true
|
|
))
|
|
return $request
|
|
}
|
|
$request.CertificateExtensions.Add([System.Security.Cryptography.X509Certificates.X509KeyUsageExtension]::new(
|
|
[System.Security.Cryptography.X509Certificates.X509KeyUsageFlags]::DigitalSignature -bor
|
|
[System.Security.Cryptography.X509Certificates.X509KeyUsageFlags]::KeyEncipherment,
|
|
$true
|
|
))
|
|
$usage = [System.Security.Cryptography.OidCollection]::new()
|
|
if ($ExtendedKeyUsage -eq "serverAuth") {
|
|
$null = $usage.Add([System.Security.Cryptography.Oid]::new("1.3.6.1.5.5.7.3.1"))
|
|
}
|
|
else {
|
|
$null = $usage.Add([System.Security.Cryptography.Oid]::new("1.3.6.1.5.5.7.3.2"))
|
|
}
|
|
$request.CertificateExtensions.Add([System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]::new($usage, $true))
|
|
$san = [System.Security.Cryptography.X509Certificates.SubjectAlternativeNameBuilder]::new()
|
|
if ($SubjectAlternativeName.StartsWith("DNS:")) {
|
|
$san.AddDnsName($SubjectAlternativeName.Substring(4))
|
|
}
|
|
else {
|
|
$san.AddUri([Uri]$SubjectAlternativeName.Substring(4))
|
|
}
|
|
$request.CertificateExtensions.Add($san.Build())
|
|
return $request
|
|
}
|
|
|
|
function New-LeafCertificate {
|
|
param(
|
|
[string]$Name,
|
|
[string]$CommonName,
|
|
[string]$ExtendedKeyUsage,
|
|
[string]$SubjectAlternativeName
|
|
)
|
|
|
|
$directory = Join-Path $OutputDirectory $Name
|
|
New-Item -ItemType Directory -Path $directory | Out-Null
|
|
$key = [System.Security.Cryptography.RSA]::Create(2048)
|
|
try {
|
|
$request = New-CertificateRequest -CommonName $CommonName -Key $key -IsCertificateAuthority $false -ExtendedKeyUsage $ExtendedKeyUsage -SubjectAlternativeName $SubjectAlternativeName
|
|
$serial = [byte[]]::new(16)
|
|
[System.Security.Cryptography.RandomNumberGenerator]::Fill($serial)
|
|
$certificate = $request.Create($caCertificate, $notBefore, $notAfter, $serial)
|
|
try {
|
|
Write-PemFile -Path (Join-Path $directory "tls.crt") -Label "CERTIFICATE" -Bytes $certificate.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
|
|
Write-PemFile -Path (Join-Path $directory "tls.key") -Label "PRIVATE KEY" -Bytes $key.ExportPkcs8PrivateKey()
|
|
}
|
|
finally {
|
|
$certificate.Dispose()
|
|
}
|
|
}
|
|
finally {
|
|
$key.Dispose()
|
|
}
|
|
Copy-Item -LiteralPath $caCertificatePath -Destination (Join-Path $directory "ca.crt")
|
|
}
|
|
|
|
$notBefore = [DateTimeOffset]::UtcNow.AddMinutes(-5)
|
|
$notAfter = $notBefore.AddDays(7)
|
|
$caKey = [System.Security.Cryptography.RSA]::Create(2048)
|
|
$caRequest = New-CertificateRequest -CommonName "proxy-pool-local-control-plane-ca" -Key $caKey -IsCertificateAuthority $true -ExtendedKeyUsage "" -SubjectAlternativeName ""
|
|
$caCertificate = $caRequest.CreateSelfSigned($notBefore, $notAfter)
|
|
$caCertificatePath = Join-Path $OutputDirectory "ca.crt"
|
|
Write-PemFile -Path $caCertificatePath -Label "CERTIFICATE" -Bytes $caCertificate.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
|
|
Write-PemFile -Path (Join-Path $OutputDirectory "ca.key") -Label "PRIVATE KEY" -Bytes $caKey.ExportPkcs8PrivateKey()
|
|
|
|
New-LeafCertificate -Name "controller" -CommonName "proxy-pool-controller" -ExtendedKeyUsage "serverAuth" -SubjectAlternativeName "DNS:controller"
|
|
New-LeafCertificate -Name "gateway-a" -CommonName "proxy-pool-gateway-a" -ExtendedKeyUsage "clientAuth" -SubjectAlternativeName "URI:spiffe://proxy-pool.local/development/worker/gateway-a"
|
|
New-LeafCertificate -Name "gateway-b" -CommonName "proxy-pool-gateway-b" -ExtendedKeyUsage "clientAuth" -SubjectAlternativeName "URI:spiffe://proxy-pool.local/development/worker/gateway-b"
|
|
New-LeafCertificate -Name "checker-a" -CommonName "proxy-pool-checker-a" -ExtendedKeyUsage "clientAuth" -SubjectAlternativeName "URI:spiffe://proxy-pool.local/development/checker/checker-a"
|
|
|
|
$caCertificate.Dispose()
|
|
$caKey.Dispose()
|
|
|
|
Write-Host "Generated local control-plane certificates in $OutputDirectory"
|