diff --git a/.spelling b/.spelling index dac3c06a19..759aefec2b 100644 --- a/.spelling +++ b/.spelling @@ -86,6 +86,8 @@ APIService APIServices APIs AWS +SDK +SDKs Akamai Anthos AppRole diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 296ac1f197..ec5a2a8006 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -8,14 +8,13 @@ Route53 to solve DNS01 ACME challenges. It's advised you read the [DNS01 Challenge Provider](./README.md) page first for a more general understanding of how cert-manager handles DNS01 challenges. -> ℹī¸ This guide assumes that your cluster is hosted on Amazon Web Services -> (AWS) and that you already have a hosted zone in Route53. +> ℹī¸ This guide assumes that you already have a hosted zone in Route53. > -> 📖 Read -> [Tutorial: Deploy cert-manager on Amazon Elastic Kubernetes (EKS) and use Let's Encrypt to sign a certificate for an HTTPS website](../../../tutorials/getting-started-aws-letsencrypt/README.md), -> which contains end-to-end instructions for those who are new to cert-manager and AWS. +> 📖 Read the [AWS + LoadBalancer + Let's Encrypt](../../../tutorials/getting-started-aws-letsencrypt/README.md) +> tutorial, which contains end-to-end instructions for those who are new to +> cert-manager and AWS. -## Set up an IAM Role +## Set up an IAM Policy cert-manager needs to be able to add records to Route53 in order to solve the DNS01 challenge. To enable this, create a IAM policy with the following @@ -47,30 +46,407 @@ permissions: } ``` -> Note: The `route53:ListHostedZonesByName` statement can be removed if you +> ℹī¸ The `route53:ListHostedZonesByName` statement can be removed if you > specify the (optional) `hostedZoneID`. You can further tighten the policy by > limiting the hosted zone that cert-manager has access to (e.g. > `arn:aws:route53:::hostedzone/DIKER8JEXAMPLE`). +> +> 📖 Read about [actions supported by Amazon Route 53](https://docs.aws.amazon.com/Route53/latest/APIReference/API_Operations_Amazon_Route_53.html), +> in the [Amazon Route 53 API Reference](https://docs.aws.amazon.com/Route53/latest/APIReference/Welcome.html). +> +> 📖 Learn how [`eksctl` can automatically create the cert-manager IAM policy](https://eksctl.io/usage/iam-policies/#cert-manager-policy), if you use EKS. ## Credentials -You have two options for the set up - either create a user or a role and attach -that policy from above. Using a role is considered best practice because you do -not have to store permanent credentials in a secret. +cert-manager needs an [AWS access key](https://docs.aws.amazon.com/glossary/latest/reference/glos-chap.html#access_key), +to authenticate to the Route53 API. +An access key is defined by AWS as follows: +> **access key**: +> The combination of an access key ID (for example, `AKIAIOSFODNN7EXAMPLE`) and a secret access key (for example, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`). You use access keys to sign API requests that you make to AWS. + +You have two options: +1. (Best Practice) Use an [IAM Role with temporary security credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#bp-workloads-use-roles). +2. Use an [IAM User with a long-term access key](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html). + +Using an IAM Role with temporary security credentials is considered best practice because: +1. You do not have to store the long-term access key (e.g. in a Secret) +2. You don't have to manage [access key rotation](https://docs.aws.amazon.com/glossary/latest/reference/glos-chap.html#keyrotate). + +Using an [IAM User with long-term access key](#iam-user-with-long-term-access-key) is a reasonable choice if cert-manager +is deployed outside AWS but the DNS zone is on Route53. + +cert-manager supports multiple ways to get the access key and these can be categorized as either "ambient" or "non-ambient". + +### Ambient Credentials + +Ambient credentials are credentials which are made available in the cert-manager controller Pod by one of the following mechanisms: +- [**EKS Pod Identity**](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html):
+ where cert-manager gets credentials from an [EKS Auth API which runs on every Kubernetes node](https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html). +- [**EKS IAM Roles for Service Accounts (IRSA)**](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html):
+ where cert-manager uses a Kubernetes ServiceAccount token which is [mounted into the cert-manager controller Pod](https://docs.aws.amazon.com/eks/latest/userguide/pod-configuration.html). +- [**EC2 Instance Metadata Service (IMDS)**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-security-credentials.html):
+ where cert-manager gets credentials from the `iam/security-credentials/` endpoint of IMDS. +- [**Environment variables**](https://docs.aws.amazon.com/sdkref/latest/guide/environment-variables.html):
+ where cert-manager loads credentials from `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables + in the cert-manager controller Pod, if those variables are present. +- [**Shared config and credentials files**](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html):
+ where cert-manager loads credentials from files (`~/.aws/config` and `~/.aws/credentials`) which are mounted into the cert-manager controller Pod. + +The advantage of ambient credentials is that they are easier to set up and +extensively documented by Amazon AWS. +The disadvantage of ambient credentials is that they are globally available to +all ClusterIssuer and all Issuer resources, which means that in a multi-tenant +environment, any tenant who has permission to create Issuer or ClusterIssuer may +use the ambient credentials and gain the permissions granted to that account. + +> 📖 Read [AWS SDKs and Tools standardized credential providers](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html) +> to learn how cert-manager supports all these ambient credential sources. +> +> ⚠ī¸ By default, cert-manager will only use ambient credentials for +> `ClusterIssuer` resources, not `Issuer` resources. +> +> This is to prevent unprivileged users, who have permission to create Issuer +> resources, from issuing certificates using credentials that cert-manager +> incidentally has access to. +> ClusterIssuer resources are cluster scoped (not namespaced) and only platform +> administrators should be granted permission to create them. +> +> ⚠ī¸ It is possible (but not recommended) to enable ambient authentication mechanisms +> for `Issuer` resources, by setting the `--issuer-ambient-credentials` flag on +> the cert-manager controller to true. -cert-manager supports two ways of specifying credentials: +Here is an example of a `ClusterIssuer` for using Route53 ambient credentials: -- explicit by providing an `accessKeyID` or an `accessKeyIDSecretRef`, and a `secretAccessKeySecretRef` -- or implicit (using [metadata - service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) - or [environment variables or credentials - file](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials). +```yaml +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + ... + solvers: + - dns01: + route53: {} +``` -cert-manager also supports specifying a `role` to enable cross-account access -and/or limit the access of cert-manager. Integration with -[`kiam`](https://github.com/uswitch/kiam) and -[`kube2iam`](https://github.com/jtblin/kube2iam) should work out of the box. +> ℹī¸ Regardless of which ambient mechanism you use, the `route53` section is left empty, +> because cert-manager can find the credentials, role, and region by looking for environment variables +> which will be added to the cert-manager Pod. + +#### EKS Pod Identity + +[EKS Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html) is the simplest way to use ambient credentials, +if you deploy cert-manager on EKS. +It is a four step process: +1. [Setup the EKS Pod Identity agent](https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html) in your cluster. +2. [Assign an IAM role to the cert-manager Kubernetes service account](https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html). +3. Restart the cert-manager Deployment + so that the EKS Pod Identity Agent can inject the necessary environment variables into the Pods. +4. Create a `ClusterIssuer` resource: + + ```yaml + apiVersion: cert-manager.io/v1 + kind: ClusterIssuer + metadata: + name: letsencrypt-prod + spec: + acme: + solvers: + - dns01: + route53: {} + ``` + +#### EKS IAM Role for Service Accounts (IRSA) + +[IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) is another way to use ambient credentials, +if you deploy cert-manager on EKS. +It is more complicated than Pod Identity and requires coordination between the Kubernetes cluster administrator and the AWS account manager. +It involves annotating the `cert-manager` ServiceAccount in Kubernetes, and setting up an IAM role, a trust policy and a trust relationship in AWS. +A mutating webhook will automatically setup a mounted service account volume in the cert-manager Pod. + +1. **Create an IAM OIDC provider for your cluster** + + To use IRSA with cert-manager you must first enable the feature for your cluster. + Follow the [official documentation](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html). + +2. **Create a trust relationship** + + In this configuration an IAM role is mapped to the cert-manager `ServiceAccount` allowing it to authenticate with AWS. + The IAM role you map to the `ServiceAccount` will need permissions on any and all Route53 zones cert-manager will be using. + Create a trust relationship by adding the following trust policy to the IAM role: + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "sts:AssumeRoleWithWebIdentity", + "Principal": { + "Federated": "arn:aws:iam:::oidc-provider/oidc.eks..amazonaws.com/id/" + }, + "Condition": { + "StringEquals": { + "oidc.eks..amazonaws.com/id/:sub": "system:serviceaccount::" + } + } + } + ] + } + ``` + + Replace the following: + + - `` with the AWS account ID of the EKS cluster. + - `` with the region where the EKS cluster is located. + - `` with the hash in the EKS API URL; this will be a random 32 character hex string (example: `45DABD88EEE3A227AF0FA468BE4EF0B5`). + - `` with the namespace where cert-manager is running. + - `` with the name of the `ServiceAccount` object created by cert-manager. + + + > ℹī¸ If you're following the Cross Account example, this trust policy is attached to the cert-manager role in Account X with ARN `arn:aws:iam::XXXXXXXXXXX:role/cert-manager`. + > The permissions policy is the same as above. + +3. **Annotate the cert-manager `ServiceAccount`** + + ```yaml + apiVersion: v1 + kind: ServiceAccount + metadata: + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager + ``` + + The cert-manager Helm chart provides a variable for injecting annotations into cert-manager's `ServiceAccount` like so: + + ```yaml + serviceAccount: + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager + ``` + + > ℹī¸ If you're following the Cross Account example, modify the `ClusterIssuer` with the role from Account Y. + +4. **(optional) Update file system permissions** + + > đŸ“ĸ **Please help us improve this documentation** + > + > The reason for this optional step is that on EKS Fargate and on some + > older versions of EKS you may observe errors such as: + > - `unable to read file at /var/run/secrets/eks.amazonaws.com/serviceaccount/token` + > - `open /var/run/secrets/eks.amazonaws.com/serviceaccount/token: permission denied` + > + > In this case, you can change the user and group of the cert-manager process + > so that it is able to read the mounted ServiceAccount token. + > + > Read [`cert-manager/website#697`: IRSA Needs `runAsUser: 1001`](https://github.com/cert-manager/website/issues/697) + > and tell us whether this step is still necessary or obsolete. + + You may also need to modify the cert-manager `Deployment` with a different user and group, so the `ServiceAccount` token can be read. + + ```yaml + spec: + template: + spec: + securityContext: + fsGroup: 1001 + runAsUser: 1001 + ``` + + The cert-manager Helm chart provides a variable for modifying cert-manager's `Deployment` like so: + + ```yaml + securityContext: + fsGroup: 1001 + runAsUser: 1001 + ``` + +5. **Restart the cert-manager Deployment** + + Restart the cert-manager Deployment, so that the webhook can inject the + necessary `volume`, `volumemount`, and environment variables into the Pods. + +6. **Create a `ClusterIssuer` resource** + + ```yaml + apiVersion: cert-manager.io/v1 + kind: ClusterIssuer + metadata: + name: letsencrypt-prod + spec: + acme: + solvers: + - dns01: + route53: {} + ``` + +### Non-ambient Credentials + +Non-ambient credentials are credentials which are explicitly configured on the Issuer or ClusterIssuer resource. +For example: +- **Access key Secret reference**:
+ where cert-manager loads a long-term access key from a Kubernetes Secret resource. +- **ServiceAccount reference**:
+ where cert-manager gets a ServiceAccount token (signed JWT) from the Kubernetes API server, + and uses the STS AssumeRoleWithWebIdentity endpoint to exchange it for temporary AWS credentials. + +The advantage of non-ambient credentials is that cert-manager can perform Route53 operations in a multi-tenant environment. +Each tenant can be granted permission to create and update Issuer resources in their namespace and they can provide their own AWS credentials in their namespace. + +#### IAM Role with dedicated Kubernetes ServiceAccount + +> 📖 Read the [AWS + LoadBalancer + Let's Encrypt tutorial](../../../tutorials/getting-started-aws-letsencrypt/README.md) +> to learn how to deploy cert-manager on EKS and use this authentication mechanism. + +In this configuration you can reference your own `ServiceAccounts` in your `Issuer` or `ClusterIssuer` +and cert-manager will get a ServiceAccount token from the Kubernetes API which it will send to STS in exchange for AWS temporary credentials. + +The advantages of this mechanism are: +1. Each Issuer can reference a different `ServiceAccount`, which means you can lock down the permissions, such that each `ServiceAccount` is mapped to an IAM role that only has permission to update the zones it needs (unlike Pod Identity or IRSA). +2. This mechanism works even when cert-manager is deployed outside AWS. + +Here's how to set it up: + +1. **Create a ServiceAccount** + + In order to reference a `ServiceAccount` it must first exist. + Unlike normal IRSA the `eks.amazonaws.com/role-arn` annotation is not required. + + ```yaml + apiVersion: v1 + kind: ServiceAccount + metadata: + name: + ``` + +2. **Create an IAM role trust policy** + + For every `ServiceAccount` you want to use for AWS authentication you must first set up a trust policy: + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "sts:AssumeRoleWithWebIdentity", + "Principal": { + "Federated": "arn:aws:iam:::oidc-provider/oidc.eks..amazonaws.com/id/" + }, + "Condition": { + "StringEquals": { + "oidc.eks..amazonaws.com/id/:sub": "system:serviceaccount::" + } + } + } + ] + } + ``` + + Replace the following: + + - `` with the AWS account ID of the EKS cluster. + - `` with the region where the EKS cluster is located. + - `` with the hash in the EKS API URL; this will be a random 32 character hex string (example: `45DABD88EEE3A227AF0FA468BE4EF0B5`). + - `` with the namespace of the `ServiceAccount` object. + - `` with the name of the `ServiceAccount` object. + +3. **Create an RBAC Role and RoleBinding** + + In order to allow cert-manager to issue a token using your `ServiceAccount` you must deploy some RBAC to the cluster: + + ```yaml + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: -tokenrequest + namespace: + rules: + - apiGroups: [''] + resources: ['serviceaccounts/token'] + resourceNames: [''] + verbs: ['create'] + --- + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: cert-manager--tokenrequest + namespace: + subjects: + - kind: ServiceAccount + name: + namespace: + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: -tokenrequest + ``` + + Replace the following: + + - `` name of the `ServiceAccount` object. + - `` namespace of the `ServiceAccount` object. + - `` name of cert-managers `ServiceAccount` object, as created during cert-manager installation. + - `` namespace that cert-manager is deployed into. + +4. **Create an Issuer or ClusterIssuer** + + You should be ready at this point to configure an Issuer to use the new `ServiceAccount`. + You can see example config for this below: + + ```yaml + apiVersion: cert-manager.io/v1 + kind: Issuer + metadata: + name: example + spec: + acme: + ... + solvers: + - dns01: + route53: + region: us-east-1 + role: # This must be set so cert-manager what role to attempt to authenticate with + auth: + kubernetes: + serviceAccountRef: + name: # The name of the service account created + ``` + +#### IAM User with long-term access key + +In this mechanism, cert-manager will load the credentials from a Secret resource. +If you use an `Issuer` resource, the Secret must be in the same namespace as the Issuer. +If you use a `ClusterIssuer` resource, the Secret must be in the `cert-manager` namespace +or what ever value is supplied to the `--cluster-resource-namespace` [option of the cert-manager component](../../../cli/controller.md). + +The advantages of this mechanism are that it is simple and it works even when +cert-manager is deployed outside AWS. +Here is an example configuration for a `ClusterIssuer`: + +```yaml +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + ... + solvers: + - dns01: + route53: + region: eu-central-1 + accessKeyIDSecretRef: + name: prod-route53-credentials-secret + key: access-key-id + secretAccessKeySecretRef: + name: prod-route53-credentials-secret + key: secret-access-key + # (optional) you can also assume a role with these credentials + role: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager +``` ## Cross Account Access @@ -138,251 +514,39 @@ And the following trust relationship (Add AWS `Service`s as needed): } ``` -## Creating an Issuer (or `ClusterIssuer`) - -Here is an example configuration for a `ClusterIssuer`: - -```yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod -spec: - acme: - ... - solvers: - - # example: cross-account zone management for example.com - # this solver uses ambient credentials (i.e. inferred from the environment or EC2 Metadata Service) - # to assume a role in a different account - - selector: - dnsZones: - - "example.com" - dns01: - route53: - region: us-east-1 - hostedZoneID: DIKER8JEXAMPLE # optional, see policy above - role: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager - - # this solver handles example.org challenges - # and uses explicit credentials - - selector: - dnsZones: - - "example.org" - dns01: - route53: - region: eu-central-1 - # The AWS access key ID can be specified using the literal accessKeyID parameter - # or retrieved from a secret using the accessKeyIDSecretRef - # If using accessKeyID, omit the accessKeyIDSecretRef parameter and vice-versa - accessKeyID: AKIAIOSFODNN7EXAMPLE - accessKeyIDSecretRef: - name: prod-route53-credentials-secret - key: access-key-id - secretAccessKeySecretRef: - name: prod-route53-credentials-secret - key: secret-access-key - # you can also assume a role with these credentials - role: arn:aws:iam::YYYYYYYYYYYY:role/dns-manager -``` - -Note that, as mentioned above, the pod is using `arn:aws:iam::XXXXXXXXXXX:role/cert-manager` as a credentials source in Account X, but the `ClusterIssuer` ultimately assumes the `arn:aws:iam::YYYYYYYYYYYY:role/dns-manager` role to actually make changes in Route53 zones located in Account Y. - -## EKS IAM Role for Service Accounts (IRSA) - -While [`kiam`](https://github.com/uswitch/kiam) / [`kube2iam`](https://github.com/jtblin/kube2iam) work directly with cert-manager, some special attention is needed for using the [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) feature available on EKS. - -This feature uses Kubernetes `ServiceAccount` tokens to authenticate with AWS using the [API_AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html). - -> **Note**: For using IRSA with cert-manager you must first enable the feature for your cluster. You can do this by -> following the [official documentation(https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html). - -Because `ServiceAccount` tokens are used to authenticate there are two modes of operation, you can either use cert-manager's own `ServiceAccount` to authenticate or you can reference your own `ServiceAccount` within your `Issuer`/`ClusterIssuer` config. Each option is described below. - -### Using the cert-manager ServiceAccount - -In this configuration an IAM role is mapped to the cert-manager `ServiceAccount` allowing it to authenticate with AWS. The IAM role you map to the `ServiceAccount` will need permissions on any and all Route53 zones cert-manager will be using. - -#### IAM role trust policy - -The cert-manager role needs the following trust relationship attached to the role in order to use the IRSA method. Replace the following: - -- `` with the AWS account ID of the EKS cluster. -- `` with the region where the EKS cluster is located. -- `` with the hash in the EKS API URL; this will be a random 32 character hex string (example: `45DABD88EEE3A227AF0FA468BE4EF0B5`) -- `` with the namespace where cert-manager is running. -- `` with the name of the `ServiceAccount` object created by cert-manager. - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": "sts:AssumeRoleWithWebIdentity", - "Principal": { - "Federated": "arn:aws:iam:::oidc-provider/oidc.eks..amazonaws.com/id/" - }, - "Condition": { - "StringEquals": { - "oidc.eks..amazonaws.com/id/:sub": "system:serviceaccount::" - } - } - } - ] -} -``` - -**Note:** If you're following the Cross Account example above, this trust policy is attached to the cert-manager role in Account X with ARN `arn:aws:iam::XXXXXXXXXXX:role/cert-manager`. The permissions policy is the same as above. - -#### Service annotation - -Annotate the `ServiceAccount` created by cert-manager: - -```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager -``` - -You will also need to modify the cert-manager `Deployment` with the correct file system permissions, so the `ServiceAccount` token can be read. - -```yaml -spec: - template: - spec: - securityContext: - fsGroup: 1001 -``` - -The cert-manager Helm chart provides a variable for injecting annotations into cert-manager's `ServiceAccount` and `Deployment` object like so: - -```yaml -serviceAccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager -securityContext: - fsGroup: 1001 -``` - -**Note:** If you're following the Cross Account example above, modify the `ClusterIssuer` in the same way as above with the role from Account Y. +## Region -### Referencing your own ServiceAccount within Issuer/ClusterIssuer config +If you omit the `.spec.acme.solvers.dns01.route53.region` field, cert-manager +will get the region from the `AWS_REGION` and `AWS_DEFAULT_REGION` environment +variables if they are set in the cert-manager controller Pod. -In this configuration you can reference your own `ServiceAccounts` within your `Issuer`/`ClusterIssuer` and cert-manager will issue itself temporary credentials using these `ServiceAccounts`. Because each issuer can reference a different `ServiceAccount` you can lock down permissions much more, with each `ServiceAccount` mapped to an IAM role that only has permission on the zones it needs for that particular issuer. +If you use [ambient credentials](#ambient-credentials), the `AWS_REGION` and +`AWS_DEFAULT_REGION` environment variables have a higher priority, and the +`.spec.acme.solvers.dns01.route53.region` field will only be used if the +environment variables are not set. +The `.spec.acme.solvers.dns01.route53.region` field is ignored if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html), +because an `AWS_REGION` environment variable is added to the cert-manager controller Pod by +the [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent). -#### Creating a ServiceAccount +The `.spec.acme.solvers.dns01.route53.region` field is ignored if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html), +because an `AWS_REGION` environment variable is added to the cert-manager controller Pod by +the [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). -In order to reference a `ServiceAccount` it must first exist. Unlike normal IRSA the `eks.amazonaws.com/role-arn` annotation is not required, however you may wish to set it as a reference. - -```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: - annotation: - eks.amazonaws.com/role-arn: -``` - -#### IAM role trust policy - -For every `ServiceAccount` you want to use for AWS authentication you must first set up a trust policy. Replace the following: - -- `` with the AWS account ID of the EKS cluster. -- `` with the region where the EKS cluster is located. -- `` with the hash in the EKS API URL; this will be a random 32 character hex string (example: `45DABD88EEE3A227AF0FA468BE4EF0B5`) -- `` with the namespace of the `ServiceAccount` object. -- `` with the name of the `ServiceAccount` object. - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": "sts:AssumeRoleWithWebIdentity", - "Principal": { - "Federated": "arn:aws:iam:::oidc-provider/oidc.eks..amazonaws.com/id/" - }, - "Condition": { - "StringEquals": { - "oidc.eks..amazonaws.com/id/:sub": "system:serviceaccount::" - } - } - } - ] -} -``` - -**Note:** If you're following the Cross Account example above, this trust policy is attached to the cert-manager role in Account X with ARN `arn:aws:iam::XXXXXXXXXXX:role/cert-manager`. The permissions policy is the same as above. - -#### RBAC - -In order to allow cert-manager to issue a token using your `ServiceAccount` you must deploy some RBAC to the cluster. Replace the following: - -- `` name of the `ServiceAccount` object. -- `` namespace of the `ServiceAccount` object. -- `` name of cert-managers `ServiceAccount` object, as created during cert-manager installation. -- `` namespace that cert-manager is deployed into. - -```yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: -tokenrequest - namespace: -rules: - - apiGroups: [''] - resources: ['serviceaccounts/token'] - resourceNames: [''] - verbs: ['create'] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: cert-manager--tokenrequest - namespace: -subjects: - - kind: ServiceAccount - name: - namespace: -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: -tokenrequest -``` - -#### Issuer/ClusterIssuer config - -Once you have completed the above you should have: -- An IAM role with permissions required to on the Route53 zone. -- A Kubernetes `ServiceAccount`. -- A trust policy to allow the Kubernetes `ServiceAccount` access to your IAM role. -- RBAC to allow cert-manager to issue a token using the Kubernetes `ServiceAccount`. - -You should be ready at this point to configure an Issuer to use the new `ServiceAccount`. You can see example config for this below: +> ℹī¸ Route53 is a global service and does not have regional endpoints, but the region +> is used as a hint to help compute the correct AWS credential scope and partition +> when it connects to Route53. +> +> 📖 Read [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) and +> [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) +> to learn more. -```yaml -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: example -spec: - acme: - ... - solvers: - - selector: - dnsZones: - - "example.com" - dns01: - route53: - region: us-east-1 - role: # This must be set so cert-manager what role to attempt to authenticate with - auth: - kubernetes: - serviceAccountRef: - name: # The name of the service account created -``` +> ℹī¸ STS is a regional service and cert-manager will use regional STS endpoint URLs +> computed from the `region` field or environment variables. +> STS is used for [IRSA credentials](#eks-iam-role-for-service-accounts-irsa), [dedicated ServiceAccount credentials](#referencing-your-own-serviceaccount-within-in-an-issuer-or-clusterissuer), and [cross account access](#cross-account-access). +> +> 📖 Read [Manage AWS STS in an AWS Region](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) +> to learn about which regions support STS. +> +> 📖 Read [AWS STS Regional endpoints](https://docs.aws.amazon.com/sdkref/latest/guide/feature-sts-regionalized-endpoints.html), +> to learn how to configure the use of regional STS endpoints using environment variables. diff --git a/content/docs/tutorials/getting-started-aws-letsencrypt/README.md b/content/docs/tutorials/getting-started-aws-letsencrypt/README.md index 87110e8d49..5be63770d8 100644 --- a/content/docs/tutorials/getting-started-aws-letsencrypt/README.md +++ b/content/docs/tutorials/getting-started-aws-letsencrypt/README.md @@ -12,8 +12,8 @@ In this tutorial you will learn how to deploy and configure cert-manager on AWS and how to deploy an HTTPS web server and make it available on the Internet. You will learn how to configure cert-manager to get a signed certificate from Let's Encrypt, which will allow clients to connect to your HTTPS website securely. -You will configure cert-manager to use the [Let's Encrypt DNS-01 challenge protocol](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) with AWS Route53 DNS, -using IAM Roles for Service Accounts (IRSA) to authenticate to AWS. +You will configure cert-manager to use the [Let's Encrypt DNS-01 challenge protocol](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) with AWS Route53 DNS. +You will authenticate to Route53 using a [dedicated Kubernetes ServiceAccount token](../../configuration/acme/dns01/route53.md#referencing-your-own-serviceaccount-within-in-an-issuer-or-clusterissuer). # Part 1 @@ -379,7 +379,7 @@ You need to prove to Let's Encrypt that you own the domain name of the certifica This is known as the [DNS-01 challenge type](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge). cert-manager can create that DNS record for you in by using the AWS Route53 API but it needs to authenticate first, -and currently the most secure method of authentication is to use [IAM roles for service accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). +and currently the most secure method of authentication is to use an [IAM Role with dedicated Kubernetes ServiceAccount](../../configuration/acme/dns01/route53.md#iam-role-with-dedicated-kubernetes-serviceaccount). The advantages of this method are that cert-manager will use an ephemeral Kubernetes ServiceAccount Token to authenticate to AWS and the token need not be stored in a Kubernetes Secret. > 📖 Read about [other ways to configure the ACME issuer with AWS Route53 DNS](../../configuration/acme/dns01/route53.md). @@ -425,7 +425,7 @@ aws iam create-policy \ EOF ``` -> ℹī¸ Read the [cert-manager ACME DNS01 Route53 configuration documentation](https://cert-manager.io/docs/configuration/acme/dns01/route53), +> ℹī¸ Read the [cert-manager ACME DNS01 Route53 configuration documentation](../../configuration/acme/dns01/route53.md), > for more details of this IAM policy. ## Create an IAM role and associate it with a Kubernetes service account