Steps to Reproduce
- Set up GCP Certificate Authority Service with a subordinate (intermediate) CA
- Configure step-ca in RA mode with cloudCAS:
{
"authority": {
"type": "cloudcas",
"certificateAuthority": "projects/my-project/locations/us-central1/caPools/my-pool/certificateAuthorities/my-intermediate-ca",
"config": {
"credentialsFile": "/path/to/gcp-sa-key.json"
},
"provisioners": [
{
"type": "SCEP",
"name": "scep",
"challenge": "secret",
"minimumPublicKeyLength": 2048,
"encryptionAlgorithmIdentifier": 2,
"decrypterCertificate": "-----BEGIN CERTIFICATE-----\n...",
"decrypterKeyPEM": "-----BEGIN RSA PRIVATE KEY-----\n..."
}
]
}
}
- Start step-ca
Your Environment
- OS - macOS (also reproducible on Linux via Helm chart)
step-ca Version - 0.29.0
Expected Behavior
step-ca should start successfully with SCEP provisioner in cloudCAS RA mode, similar to how VaultCAS works after the fix in PR #1803.
Actual Behavior
step-ca panics on startup:
panic: runtime error: index out of range [0] with length 0
goroutine 1 [running]:
github.com/smallstep/certificates/authority.(*Authority).init(0x14000732280)
/path/to/certificates/authority/authority.go:760 +0x...
The panic occurs because a.intermediateX509Certs is empty when initializing the SCEP authority.
In cas/cloudcas/cloudcas.go, the GetCertificateAuthority() function only returns RootCertificate but not IntermediateCertificates:
func (c *CloudCAS) GetCertificateAuthority(req *apiv1.GetCertificateAuthorityRequest) (*apiv1.GetCertificateAuthorityResponse, error) {
// ...
// Last certificate in the chain is the root.
root, err := parseCertificate(resp.PemCaCertificates[len(resp.PemCaCertificates)-1])
if err != nil {
return nil, err
}
return &apiv1.GetCertificateAuthorityResponse{
RootCertificate: root,
// IntermediateCertificates is NOT populated!
}, nil
}
GCP CAS does provide the full certificate chain in PemCaCertificates (verified via gcloud privateca subordinates describe), but cloudCAS doesn't extract the intermediate certificates.
This was fixed for VaultCAS in PR #1803, but cloudCAS was not updated.
Additional Context
Suggested fix would be to update GetCertificateAuthority() in cas/cloudcas/cloudcas.go to parse and return intermediate certificates, similar to what was done for VaultCAS in #1803:
func (c *CloudCAS) GetCertificateAuthority(req *apiv1.GetCertificateAuthorityRequest) (*apiv1.GetCertificateAuthorityResponse, error) {
// ... existing code to get resp ...
// Last certificate in the chain is the root.
root, err := parseCertificate(resp.PemCaCertificates[len(resp.PemCaCertificates)-1])
if err != nil {
return nil, err
}
// Parse intermediate certificates (all except the last/root)
var intermediates []*x509.Certificate
for i := 0; i < len(resp.PemCaCertificates)-1; i++ {
cert, err := parseCertificate(resp.PemCaCertificates[i])
if err != nil {
return nil, err
}
intermediates = append(intermediates, cert)
}
return &apiv1.GetCertificateAuthorityResponse{
RootCertificate: root,
IntermediateCertificates: intermediates,
}, nil
}
Contributing
Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).
Steps to Reproduce
{ "authority": { "type": "cloudcas", "certificateAuthority": "projects/my-project/locations/us-central1/caPools/my-pool/certificateAuthorities/my-intermediate-ca", "config": { "credentialsFile": "/path/to/gcp-sa-key.json" }, "provisioners": [ { "type": "SCEP", "name": "scep", "challenge": "secret", "minimumPublicKeyLength": 2048, "encryptionAlgorithmIdentifier": 2, "decrypterCertificate": "-----BEGIN CERTIFICATE-----\n...", "decrypterKeyPEM": "-----BEGIN RSA PRIVATE KEY-----\n..." } ] } }Your Environment
step-caVersion - 0.29.0Expected Behavior
step-ca should start successfully with SCEP provisioner in cloudCAS RA mode, similar to how VaultCAS works after the fix in PR #1803.
Actual Behavior
step-ca panics on startup:
The panic occurs because
a.intermediateX509Certsis empty when initializing the SCEP authority.In
cas/cloudcas/cloudcas.go, theGetCertificateAuthority()function only returnsRootCertificatebut notIntermediateCertificates:GCP CAS does provide the full certificate chain in
PemCaCertificates(verified viagcloud privateca subordinates describe), but cloudCAS doesn't extract the intermediate certificates.This was fixed for VaultCAS in PR #1803, but cloudCAS was not updated.
Additional Context
Suggested fix would be to update
GetCertificateAuthority()incas/cloudcas/cloudcas.goto parse and return intermediate certificates, similar to what was done for VaultCAS in #1803:Contributing
Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).