Sample ACME Metadata PowerShell Scripts

The following PowerShell scripts:

These are starting points to create scripts as per your implementation.

Some variables are exposed in the PowerShell custom extension as shown in Table 15: Variables for PowerShell Custom Extension.

Table 15: Variables for PowerShell Custom Extension

Variable Description
$username The user making the enrollment request. The format of this value will vary depending on the value set for the acmeuniqueclaimtype when the Keyfactor ACME was configured. If the acmeuniqueclaimtype is set to sub, this will be a GUID.
$csr The CSR contents.
$template The certificate template short name configured for use during enrollment for the requesting user.
$identifiers A list of strings representing the identifiers used in the enrollment. This typically includes the requested SAN for the certificate.
$metadata A dictionary of metadata being included in the request. The key is the metadata field name defined in Keyfactor Command.
Sample Simple PowerShell Script

Populate the Email-Contact metadata field with a static email address for all requests and populate the value in Keyfactor Command for the enrolled certificate.

Copy
# Uncomment to output returned values to Keyfactor ACME log file
#Write-Warning $username
#$identifiers | ForEach-Object -Process {Write-Warning $_ }
#Write-Warning $template
#Write-Warning $csr

# Populate the Email-Contact metadata field with a static value
$metadata."Email-Contact" = "john.smith@keyexample.com"
Sample Advanced PowerShell Script

Take the unique username of the user making the request, look it up in Keycloak to find the user’s first name, last name, and email address, and populate metadata fields in Keyfactor Command with these values for the enrolled certificate. Output information about the process to the Keyfactor ACME log.

Copy
# Uncomment to output returned values to Keyfactor ACME log file
#Write-Warning $username
#$identifiers | ForEach-Object -Process {Write-Warning $_ }
#Write-Warning $template
#Write-Warning $csr

# Keyfactor IdP Configuration
$IdPUrl = "https://appsrvr186.keyexample.com:4443"
$Realm = "Keyfactor"
$ClientId = "LimitedAdmin-Client" # Client needs to be able to query for users
$ClientSecret = "MySuperSecretAdminClientSecret"
$UserSub = $username # Populate a variable with the username of the user making the request

# Step 1: Obtain an OAuth token
$Body = @{
    grant_type    = "client_credentials"
    client_id     = $ClientId
    client_secret = $ClientSecret
}

$TokenHeaders = @{
    'Content-Type' = 'application/x-www-form-urlencoded'
}

$TokenResults = Invoke-RestMethod -Method Post -Uri "$IdPUrl/realms/$Realm/protocol/openid-connect/token" -Headers $TokenHeaders -Body $Body

$AccessToken = $TokenResults.access_token

# Step 2: Use the token to make a GET request to Keyfactor IdP to look up user's name and email address
$user = ""
$UserResponse = ""

# Function to Search Keyfactor IdP for a User
Function Get-UserBySub {
    param ($Sub)
    $UserSearchUrl = "$IdPUrl/admin/realms/$Realm/users/$Sub"

    try {
        $UserResponse = Invoke-RestMethod -Uri $UserSearchUrl `
            -Method Get `
            -Headers @{ "Authorization" = "Bearer $AccessToken" }

        if ($UserResponse) {
            Write-Warning "Get-UserBySub Function - User found: $($UserResponse.username) - Email: $($UserResponse.email)"
            return $UserResponse
        } else {
            Write-Warning "Get-UserBySub Function - API returned no data for user $Sub"
        }
    }
    catch {
        Write-Output "Error checking user: $_"
        if ($_.Exception.Response) {
            Write-Warning "Get-UserBySub Function - HTTP Status Code: $($_.Exception.Response.StatusCode)"
            Write-Warning "Get-UserBySub Function - Response Content: $($_.Exception.Response.Content.ReadAsStringAsync().Result)"
        }
    }
    return $null
}

# Get the user information
$User = Get-UserBySub -Sub $UserSub
Write-Warning "Get-UserBySub Function - Email address returned was: $($User.email)"
Write-Warning "Get-UserBySub Function - User name returned was: $($User.firstname) $($User.lastname)"

# Step 3: Populate the metadata AppContactList, AppownerFirstName, and AppOwnerLastName fields with the returned data
# in the enrollment request to Keyfactor Command
$metadata."AppContactList" = $User.email
$metadata."AppOwnerFirstName" = $User.firstname
$metadata."AppOwnerLastName" = $User.lastname