This is a Kubernetes controller that synchronize certificate definitions to AWS Certificate Manager. It also take care of creating required DNS entries for certificate validation. To create those DNS entries this controller is using External-DNS.
This controller manages only ACM public certificates that are going to be used for Application Load Balancers via an Ingress resource. For private certificate the suggested approach is to look at aws-privateca-issuer and Cert-Manager.
Here are a general sequence diagram of how the manager operates:
sequenceDiagram
actor user
participant k8s as Kubernetes API Server
participant manager as acm-sync-manager
participant acm as AWS ACM
participant edns as external-dns
participant dns as AWS route 53
user->>k8s: create Ingress resource
loop
manager->>k8s: watch Ingress resources
end
manager->>k8s: create Certificate CRD
loop
manager->>k8s: watch Certificate CRD resources
end
manager->>acm: create ACM certificate
loop
manager->>acm: poll for DNS TXTs records
end
manager->>k8s: create DNSEndpoint resource
loop
edns->>k8s: watch DNSEndpoint resources
end
edns->>dns: create DNS records
loop
manager->>acm: poll to check for issuance
end
manager->>k8s: update Ingress annotation with certificate ARN
To use this controller you will need to install the External-DNS controller with the DNSEndpoint CRD installed and configured as a source. See crd-source for guidance on how to proceed.
The prefered authentication method is with IAM roles for Service Accounts. Alternative authentication methods with this controller are surely possible but not tested at this time.
An example of policy to use that will give required access to ACM:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "acmmanager",
"Action": [
"acm:DescribeCertificate",
"acm:GetCertificate",
"acm:ListTagsForCertificate",
"acm:AddTagsToCertificate",
"acm:RemoveTagsFromCertificate",
"acm:DeleteCertificate"
],
"Effect": "Allow",
"Resource": [
"arn:aws:acm:*:<account_id>:certificate/*"
]
},
{
"Sid": "acmmanagerAllResources",
"Action": [
"acm:ListCertificates",
"acm:RequestCertificate"
],
"Effect": "Allow",
"Resource": [
"*"
]
}
]
}
To install acm-manager using Helm:
helm repo add acm-manager https://vdesjardins.github.io/acm-manager
helm install acm-manager/acm-manager --generate-name
There is two ways you can use this controller: from an Ingress resource or with the Certificate custom resource definition (CRD).
This controller watches Ingress resource to create Certificate CRD automatically if:
- there is the annotation acm-manager.io/enable equals to yes or true
- OR
- the Ingress field spec.ingressClassName equals to alb AND alb.ingress.kubernetes.io/scheme equals to internet-facing. This behavior can be disabled with the startup parameter ingress-auto-detect.
Upon creation of the Ingress resource the controller will retreive entries in the spec.tls section and provision a Certificate CRD to start the ACM certificate request. If the Ingress spec.tls section specifies the secretName field these hosts will not be added to the ACM certificate request.
When the certificate is provisioned successfuly the alb.ingress.kubernetes.io/certificate-arn annotation is set to the ACM certificate ARN on the Ingress ressource.
You can also use the Custom Resource Definition defined by this controller. Here an example:
apiVersion: acm-manager.io/v1alpha1
kind: Certificate
metadata:
name: certificate-sample
spec:
commonName: endpoint-test.acm-manager.kubestack.io
subjectAlternativeNames:
- endpoint-test.acm-manager.kubestack.io
These environment variables need to be set:
- AWS_REGION
- AWS_PROFILE
- OIDC_S3_BUCKET_NAME
- TEST_DOMAIN_NAME
make setup-aws
To create the Kind cluster:
make cluster
You can now run the E2E tests:
make e2etest