Skip to content

[Feature Request]: Unable to Issue a CA certificate with the desired pathlen constraint value #220

@find-arka

Description

@find-arka

Describe the expected outcome

  • I created a Root CA in AWS Private CA with the template: RootCACertificate/V1
  • Created a Subordinate CA with the help of the same Root CA. Template used for Subordinate: SubordinateCACertificate_PathLen3/V1
  • Verified that the certificate of Subordinate CA has the pathlen:3 constraint i.e.
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:3
  • Next, I created a CA certificate (using Certificate of cert-manager.io/v1). The generated CA certificate has the following constraints-
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0

Expected a CA certificate with pathlen:2

Describe the actual outcome

The generated CA certificate had a pathlen:0 constraint, instead of the expected pathlen:2 constraint.

Is this happening due to this section in pca.go?

	if spec.IsCA {
		return prefix + "acm-pca:::template/SubordinateCACertificate_PathLen0/V1"
	}

Steps to reproduce

  1. Create an EKS Cluster.

  2. Install Cert Manager v1.10.0

# https://cert-manager.io/docs/installation/helm/
CERT_MANAGER_VERSION=v1.10.0
helm repo add jetstack https://charts.jetstack.io
helm repo update

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version ${CERT_MANAGER_VERSION} \
  --set installCRDs=true \
  --wait
  1. Create a Root CA and a Subordinate CA in AWS Private CA
    You could run this script to create a Root CA and a Subordinate CA- https://raw.githubusercontent.com/find-arka/k8s-misc/main/create-ca-hierarchy-aws-pca.sh

With the output from the script, save the Intermediate CA ARN in an environment variable-

export CA_ARN=arn:aws:acm-pca:REDACTED:REDACTED-AC:certificate-authority/REDACTED
  1. Setup an IAM Policy to access the CA
cat <<EOF > AWSPCAIssuerPolicyTest.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "awspcaissuer",
      "Action": [
        "acm-pca:DescribeCertificateAuthority",
        "acm-pca:GetCertificate",
        "acm-pca:IssueCertificate"
      ],
      "Effect": "Allow",
      "Resource": "${CA_ARN}"
    }
  ]
}
EOF

POLICY_ARN=$(aws iam create-policy \
    --policy-name AWSPCAIssuerPolicyTest \
    --policy-document file://AWSPCAIssuerPolicyTest.json \
    --output json | jq -r '.Policy.Arn')

echo "POLICY_ARN = ${POLICY_ARN}"
  1. Setup a k8s Service Account and an associated IAM role to access the subordinate CA.
CURRENT_CLUSTER="Please put your cluster name here"
echo "${POLICY_ARN}"
echo "${REGION}"
echo "${CURRENT_CLUSTER}"

# Currently, we are installing the plugin in the same namespace as cert-manager
export PCA_NAMESPACE=cert-manager
# latest version https://github.com/cert-manager/aws-privateca-issuer/releases
export AWSPCA_ISSUER_TAG=v1.2.2

# Enable the IAM OIDC Provider for the cluster
eksctl utils associate-iam-oidc-provider \
    --cluster=${CURRENT_CLUSTER} \
    --region=${REGION} \
    --approve;

# Create IAM role bound to a service account
eksctl create iamserviceaccount --cluster=${CURRENT_CLUSTER} \
    --region=${REGION} \
    --namespace=${PCA_NAMESPACE} \
    --attach-policy-arn=${POLICY_ARN} \
    --override-existing-serviceaccounts \
    --tags "created-by=${USER},team=${TEAM},purpose=customer-support" \
    --name=aws-pca-issuer \
    --role-name "ServiceAccountRolePrivateCA-${CURRENT_CLUSTER}" \
    --approve;

# Install AWS Private CA Issuer Plugin 
# https://github.com/cert-manager/aws-privateca-issuer/#setup
helm repo add awspca https://cert-manager.github.io/aws-privateca-issuer
helm repo update
helm install aws-pca-issuer awspca/aws-privateca-issuer \
    --namespace ${PCA_NAMESPACE} \
    --set image.tag=${AWSPCA_ISSUER_TAG} \
    --set serviceAccount.create=false \
    --set serviceAccount.name=aws-pca-issuer \
    --kube-context ${CURRENT_CLUSTER} \
    --wait;

# Verify deployment status
kubectl --context ${CURRENT_CLUSTER} -n ${PCA_NAMESPACE} \
    rollout status deploy/aws-pca-issuer-aws-privateca-issuer;
  1. Create the Issuer-
# edit the var if your CA is in a different region
export CA_REGION="YOUR CA REGION"
export CA_ARN="arn:aws:acm-pca:redacted:redacted:certificate-authority/redacted"

cat << EOF | kubectl apply -f -
apiVersion: awspca.cert-manager.io/v1beta1
kind: AWSPCAClusterIssuer
metadata:
  name: my-cluster-issuer
spec:
  arn: ${CA_ARN}
  region: ${CA_REGION}
EOF
  1. Create a Certificate object
cat << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my-internal-ca
spec:
  commonName: my-internal-ca
  dnsNames:
    - "*.internal.my-org.ca"
  isCA: true
  duration: 2160h #90d
  secretName: my-internal-ca-cert-manager
  subject:
    organizations:
    - cluster.local
    - cert-manager
  issuerRef:
    group: awspca.cert-manager.io
    kind: AWSPCAClusterIssuer
    name: my-cluster-issuer
EOF

Verify:

kubectl get Certificate my-internal-ca

Expected output:

NAME             READY   SECRET                        AGE
my-internal-ca   True    my-internal-ca-cert-manager   4s
  1. extract the secret to read the value-
kubectl get secret my-internal-ca-cert-manager -o yaml | yq -r '.data."tls.crt"' | base64 -d > my-internal-ca-cert-manager-tls-crt.pem
kubectl get secret my-internal-ca-cert-manager -o yaml | yq -r '.data."ca.crt"' | base64 -d > my-internal-ca-cert-manager-ca-crt.pem

my-internal-ca-cert-manager-tls-crt.pem has the CA cert chained with the Issuer. Extract the top section from the pem file and copy it to a different file. I named it generated-ca-cert.pem

openssl x509 -in generated-ca-cert.pem -noout -text | grep -A3 Constraint
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Authority Key Identifier:
                5C:F9:5F:9D:CF:86:DD:56:94:64:36:C4:REDACTED
  1. Get the Subordinate cert and verify that the pathlen 3 constraint is present-
ROOT_CAARN="arn:aws:acm-pca:REDACTED:REDACTED:certificate-authority/REDACTED"
SUBORDINATE_CERTARN="arn:aws:acm-pca:REDACTED:REDACTED:certificate-authority/REDACTED/certificate/REDACTED"

aws acm-pca get-certificate \
    --certificate-authority-arn "${ROOT_CAARN}" \
    --certificate-arn "${SUBORDINATE_CERTARN}" \
    --output json | jq -r '.Certificate' > "intermediate-cert-common-purpose.pem"

openssl x509 -in intermediate-cert-common-purpose.pem -noout -text | grep -A3 Constraint
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:3
            X509v3 Authority Key Identifier:
                0B:97:66:22:D3:3A:FF:7D:51:10:2F:46:D1:F8:E8:E9:1D:4E:64:CA

Subordinate CA cert has pathlen:3 but the generated CA cert from that CA cert doesn't have pathlen:2, instead it has pathlen:0

Relevant log output

N/A.
Have already attached the expected output along with the commands in the above section.

Version

Cert Manager -> v1.10.0
aws-privateca-issuer-> v1.2.2
Kubernetes -> 1.22
Amazon EKS platform version -> eks.6

Have you tried the following?

Category

Supported Workflow Broken

Severity

Severity 3

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions