Generate a CSR (Certificate Signing Request)

Run a small API that generates a CSR from request parameters.

Full source

<#
    Run a small API that generates a CSR (certificate signing request).
    POST /certs/csr with JSON body providing subject and key parameters.
    FileName: 6.2-Cert-CSR.ps1
#>
param(
    [int]$Port = 5000,
    [IPAddress]$IPAddress = [IPAddress]::Loopback
)

Initialize-KrRoot -Path $PSScriptRoot

# Configure default logging
New-KrLogger |
    Set-KrLoggerLevel -Value Debug |
    Add-KrSinkConsole |
    Register-KrLogger -Name 'myLogger' -SetAsDefault

New-KrServer -Name "CSR API"
Add-KrEndpoint -Port $Port -IPAddress $IPAddress


Enable-KrConfiguration

# POST /certs/csr
# Body JSON example:
# {
#   "DnsNames": ["example.com", "www.example.com"],
#   "KeyType": "Ecdsa",            # or "Rsa"
#   "KeyLength": 384,               # 2048 for RSA; 256/384/521 for ECDSA
#   "Country": "US",
#   "Org": "Acme Ltd.",
#   "CommonName": "example.com"
# }
Add-KrMapRoute -Verbs Post -Pattern "/certs/csr" -ScriptBlock {
    $body = Get-KrRequestBody
    $dns = @()
    if ($body.DnsNames) {
        if ($body.DnsNames -is [System.Array]) { $dns = $body.DnsNames } else { $dns = @($body.DnsNames) }
    }

    $params = @{}
    if ($dns.Count -gt 0) { $params.DnsNames = $dns }
    if ($body.KeyType) { $params.KeyType = [string]$body.KeyType }
    if ($body.KeyLength) { $params.KeyLength = [int]$body.KeyLength }
    if ($body.Country) { $params.Country = [string]$body.Country }
    if ($body.Org) { $params.Org = [string]$body.Org }
    if ($body.CommonName) { $params.CommonName = [string]$body.CommonName }

    try {
        Write-KrLog -Level Debug -Message "Creating CSR with params: {params}" -Values $params
        $csr = New-KrCertificateRequest @params
        Write-KrLog -Level Debug -Message "CSR created successfully: {csr}" -Values $csr
        Write-KrJsonResponse -StatusCode 200 -InputObject @{ csrPem = $csr.CsrPem; privateKeyPem = $csr.PrivateKeyPem ; publicKeyPem = $csr.PublicKeyPem }
    } catch {
        Write-KrJsonResponse -StatusCode 400 -InputObject @{ error = $_.Exception.Message }
    }
}

Start-KrServer

# Clean up and close all the loggers when the server stops
Close-KrLogger

Step-by-step

  1. Initialize root: Initialize-KrRoot -Path $PSScriptRoot to make relative paths predictable.
  2. Logging: create and register a default console logger at Debug to trace inputs/outputs.
  3. Server: New-KrServer -Name 'CSR API' creates a host instance.
  4. Listener: bind to 127.0.0.1:5000 with Add-KrEndpoint -Port 5000 -IPAddress Loopback.
  5. Enable configuration: commit staged changes with Enable-KrConfiguration.
  6. Apply config: Enable-KrConfiguration commits staged settings.
  7. Map route: Add-KrMapRoute -Verbs Post -Pattern '/certs/csr' handles CSR requests.
  8. Parse input (JSON body):
    • DnsNames: string or array of strings. Normalized to an array.
    • KeyType: Rsa or Ecdsa (string; case-insensitive recommended).
    • KeyLength: integer. Common: 2048 for RSA; 256/384/521 for ECDSA.
    • Country, Org, CommonName: optional subject fields.
  9. Generate CSR: call New-KrCertificateRequest with the assembled parameters. Debug logs capture the request and result objects.
  10. Respond JSON with:
    • csrPem: PEM-encoded CSR
    • privateKeyPem: PEM-encoded private key for the CSR
    • publicKeyPem: PEM-encoded public key derived from the request
  11. Errors: on validation or parameter errors, return HTTP 400 with { error: <message> }.
  12. Start server: Start-KrServer begins processing requests.

Try it

Save the sample locally so it’s easy to run. Copy the contents of pwsh/tutorial/examples/6.2-Cert-CSR.ps1 into a new file in an empty working folder (for example, cert-csr.ps1), then run:

# From your working folder
pwsh .\cert-csr.ps1
curl -X POST http://127.0.0.1:5000/certs/csr -H "Content-Type: application/json" `
    -d '{"DnsNames":["example.com"],"KeyType":"Ecdsa","KeyLength":384,"Country":"US","Org":"Acme Ltd.","CommonName":"example.com"}'

Invoke-RestMethod -Method Post -Uri 'http://127.0.0.1:5000/certs/csr' -ContentType 'application/json' -Body (@{
    DnsNames = @('example.com'); KeyType = 'Ecdsa'; KeyLength = 384; Country = 'US'; Org = 'Acme Ltd.'; CommonName = 'example.com'
} | ConvertTo-Json)

# (Optional) Save returned PEMs
# $resp = Invoke-RestMethod -Method Post -Uri 'http://127.0.0.1:5000/certs/csr' -ContentType 'application/json' -Body (@{
#   DnsNames = @('example.com'); KeyType = 'Ecdsa'; KeyLength = 384; Country = 'US'; Org = 'Acme Ltd.'; CommonName = 'example.com'
# } | ConvertTo-Json)
# $resp.csrPem        | Set-Content -Path './example-com.csr' -NoNewline
# $resp.privateKeyPem | Set-Content -Path './example-com.key' -NoNewline
# $resp.publicKeyPem  | Set-Content -Path './example-com.pub' -NoNewline

Troubleshooting

Symptom Cause Fix
400 Bad Request Missing/invalid input fields Provide required fields; check KeyType/KeyLength validity
Wrong key algorithm Case mismatch in KeyType Use Rsa or Ecdsa (case-insensitive recommended)
Empty PEM fields CSR generation failed Inspect logs; ensure parameters map to New-KrCertificateRequest
Server not reachable Port blocked/in use Use loopback 127.0.0.1:5000 and verify nothing else uses the port

References


Previous / Next

Go back to Self‑Signed or continue to Import / Export / Validate.