From ccfe3ad939567d352f5c8b5a7c9f28378048fc0d Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Tue, 8 Oct 2024 15:35:48 +0100 Subject: [PATCH 01/13] Fix the heading to say Policy instead of Role Signed-off-by: Richard Wall --- content/docs/configuration/acme/dns01/route53.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 296ac1f197..2996386bf8 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -15,7 +15,7 @@ how cert-manager handles DNS01 challenges. > [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. -## 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 From aa2a29b1bf71fad7c0fda8e69bd6b1dcf482d1d1 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Tue, 8 Oct 2024 15:36:58 +0100 Subject: [PATCH 02/13] Use an info icon to accentuate the note about Policy permissions Signed-off-by: Richard Wall --- content/docs/configuration/acme/dns01/route53.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 2996386bf8..8574b57a3d 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -47,7 +47,7 @@ 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`). From 8d436a115c813c410f7b7e13f6df57fb47951843 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Tue, 8 Oct 2024 15:37:48 +0100 Subject: [PATCH 03/13] Add some further links of interest in the Policy section Signed-off-by: Richard Wall --- content/docs/configuration/acme/dns01/route53.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 8574b57a3d..debea9f371 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -51,6 +51,11 @@ permissions: > 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 From c989f4c06c56ef3008d37bc2d2202fe8dda9881b Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Tue, 8 Oct 2024 16:58:49 +0100 Subject: [PATCH 04/13] Summarize the ways cert-manager can get an access key and explain the difference between ambient and non-ambient credentials Signed-off-by: Richard Wall --- .spelling | 2 + .../docs/configuration/acme/dns01/route53.md | 82 ++++++++++++++++--- 2 files changed, 71 insertions(+), 13 deletions(-) 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 debea9f371..54609dd36a 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -59,24 +59,80 @@ permissions: ## 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 supports two ways of specifying 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). +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. (Legacy) Use an [IAM User and a long-term access key](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html). +2. (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). + +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). + +cert-manager supports multiple ways to get the access key +and these can be categorized as either "ambient" or "non-ambient": + +**Ambient credentials** +are credentials which are made available in the cert-manager controller Pod by one of the following mechanisms: +- [EKS IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + 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). +- [EKS Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + 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). +- [EC2 Instance Metadata Service (IMDS)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-security-credentials.html). + 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) + (`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`). + If those environment variables are present in the cert-manager controller Pod cert-manager will use them.. +- [Shared config and credentials files](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html) + (`~/.aws/config` and `~/.aws/credentials`). + If those files are mounted into the cert-manager controller Pod, cert-manager will use them. + +The advantage of ambient credentials is that they are easier to set up, well +documented, and AWS provides ways to automate the configuration. +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, which uses the AWS SDK for Go V2, supports all these ambient credential sources. + +**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. + +> ⚠ī¸ 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 this authentication mechanism +> for `Issuer` resources, by setting the `--issuer-ambient-credentials` flag on +> the cert-manager controller to true. cert-manager also supports specifying a `role` to enable cross-account access -and/or limit the access of cert-manager. Integration with +or to 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. - ## Cross Account Access Example: Account Y manages Route53 DNS Zones. Now you want cert-manager running in Account X (or many other accounts) to be able to manage records in Route53 zones hosted in Account Y. From d20f3e11373b0555faadfa690f0d4e6e61ae09f9 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Tue, 8 Oct 2024 18:08:12 +0100 Subject: [PATCH 05/13] Re-arrange the IRSA and explicit service account documentation Signed-off-by: Richard Wall --- .../docs/configuration/acme/dns01/route53.md | 392 +++++++++--------- 1 file changed, 207 insertions(+), 185 deletions(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 54609dd36a..0b157348e5 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -76,8 +76,9 @@ Using an IAM Role with temporary security credentials is considered best practic cert-manager supports multiple ways to get the access key and these can be categorized as either "ambient" or "non-ambient": -**Ambient credentials** -are credentials which are made available in the cert-manager controller Pod by one of the following mechanisms: +### Ambient Credentials + +**Ambient credentials** are credentials which are made available in the cert-manager controller Pod by one of the following mechanisms: - [EKS IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). 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). - [EKS Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). @@ -100,19 +101,7 @@ 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, which uses the AWS SDK for Go V2, supports all these ambient credential sources. - -**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. - +> > ⚠ī¸ By default, cert-manager will only use ambient credentials for > `ClusterIssuer` resources, not `Issuer` resources. > @@ -122,86 +111,11 @@ Each tenant can be granted permission to create and update Issuer resources in t > 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 this authentication mechanism +> ⚠ī¸ 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 also supports specifying a `role` to enable cross-account access -or to 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. - -## Cross Account Access - -Example: Account Y manages Route53 DNS Zones. Now you want cert-manager running in Account X (or many other accounts) to be able to manage records in Route53 zones hosted in Account Y. - -First, create a role with the permissions policy above (let's call the role `dns-manager`) -in Account Y, and attach a trust relationship like the one below. - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "AWS": "arn:aws:iam::XXXXXXXXXXX:role/cert-manager" - }, - "Action": "sts:AssumeRole" - } - ] -} -``` - -Bear in mind, that you won't be able to define this policy until `cert-manager` role on account Y is created. If you are setting this up using a configuration language, you may want to define principal as: - -```json -"Principal": { - "AWS": "XXXXXXXXXXX" - } -``` -And restrict it, in a future step, after all the roles are created. - -This allows the role `cert-manager` in Account X to assume the `dns-manager` role in Account Y to manage the Route53 DNS zones in Account Y. For more information visit the [official -documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html). - -Second, create the cert-manager role in Account X; this will be used as a credentials source for the cert-manager pods running in Account X. Attach to the role the following **permissions** policy: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Resource": "arn:aws:iam::YYYYYYYYYYYY:role/dns-manager", - "Action": "sts:AssumeRole" - } - ] -} -``` - -And the following trust relationship (Add AWS `Service`s as needed): - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": "ec2.amazonaws.com" - }, - "Action": "sts:AssumeRole" - } - ] -} -``` - -## Creating an Issuer (or `ClusterIssuer`) - -Here is an example configuration for a `ClusterIssuer`: +Here is an example of a `ClusterIssuer` for using Route53 ambient credentials: ```yaml apiVersion: cert-manager.io/v1 @@ -212,67 +126,35 @@ 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 + - dns01: + route53 {}: ``` -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) +Regardless of which ambient mechanism you use, the `route53` section is left empty, because cert-manager (using the AWS SDK for Go V2) can find the credentials, role, and region by looking for environment variables which will be added to the cert-manager Pod. -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. +#### EKS Pod Identity -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). +If you deploy cert-manager on EKS, [Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html) is the simplest way to use ambient credentials. +It is a three 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, then +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. -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. +#### EKS IAM Role for Service Accounts (IRSA) -### Using the cert-manager ServiceAccount +If you deploy cert-manager on EKS, IAM Roles for Service Accounts (IRSA) is another way to use use ambient credentials. +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, which is configured by default on EKS, will automatically setup a mounted service account volume in the cert-manager Pod. -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. +> ℹī¸ To use 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). -#### IAM role trust policy +1. **Create a trust relationship** -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. +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 { @@ -294,11 +176,19 @@ The cert-manager role needs the following trust relationship attached to the rol } ``` -**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. +Replace the following: -#### Service annotation +- `` 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 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. -Annotate the `ServiceAccount` created by cert-manager: +2. **Annotate the cert-manager `ServiceAccount`** ```yaml apiVersion: v1 @@ -308,7 +198,19 @@ metadata: 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. +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 above, modify the `ClusterIssuer` in the same way as above with the role from Account Y. + +3. **(optional) Update file system permissions** + +You may also need to modify the cert-manager `Deployment` with the correct file system permissions, so the `ServiceAccount` token can be read. ```yaml spec: @@ -318,45 +220,49 @@ spec: fsGroup: 1001 ``` -The cert-manager Helm chart provides a variable for injecting annotations into cert-manager's `ServiceAccount` and `Deployment` object like so: +The cert-manager Helm chart provides a variable for modifying cert-manager's `Deployment` 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. +### 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. -### Referencing your own ServiceAccount within Issuer/ClusterIssuer config +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. -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. +#### Referencing your own ServiceAccount within in an Issuer or ClusterIssuer +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 advantage of this method over IRSA or Pod Identity is that 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 for that particular -#### Creating a ServiceAccount +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, however you may wish to set it as a reference. +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: - annotation: - eks.amazonaws.com/role-arn: ``` -#### IAM role trust policy +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. 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. +For every `ServiceAccount` you want to use for AWS authentication you must first set up a trust policy: ```json { @@ -378,16 +284,17 @@ For every `ServiceAccount` you want to use for AWS authentication you must first } ``` -**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. +Replace the following: -#### RBAC +- `` 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. -In order to allow cert-manager to issue a token using your `ServiceAccount` you must deploy some RBAC to the cluster. Replace the following: +3. **Create an RBAC Role and RoleBinding** -- `` 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. +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 @@ -416,15 +323,17 @@ roleRef: name: -tokenrequest ``` -#### Issuer/ClusterIssuer config +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. -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`. +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: +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 @@ -435,10 +344,7 @@ spec: acme: ... solvers: - - selector: - dnsZones: - - "example.com" - dns01: + - dns01: route53: region: us-east-1 role: # This must be set so cert-manager what role to attempt to authenticate with @@ -447,3 +353,119 @@ spec: serviceAccountRef: name: # The name of the service account created ``` + +## Cross Account Access + +Example: Account Y manages Route53 DNS Zones. Now you want cert-manager running in Account X (or many other accounts) to be able to manage records in Route53 zones hosted in Account Y. + +First, create a role with the permissions policy above (let's call the role `dns-manager`) +in Account Y, and attach a trust relationship like the one below. + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::XXXXXXXXXXX:role/cert-manager" + }, + "Action": "sts:AssumeRole" + } + ] +} +``` + +Bear in mind, that you won't be able to define this policy until `cert-manager` role on account Y is created. If you are setting this up using a configuration language, you may want to define principal as: + +```json +"Principal": { + "AWS": "XXXXXXXXXXX" + } +``` +And restrict it, in a future step, after all the roles are created. + +This allows the role `cert-manager` in Account X to assume the `dns-manager` role in Account Y to manage the Route53 DNS zones in Account Y. For more information visit the [official +documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html). + +Second, create the cert-manager role in Account X; this will be used as a credentials source for the cert-manager pods running in Account X. Attach to the role the following **permissions** policy: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": "arn:aws:iam::YYYYYYYYYYYY:role/dns-manager", + "Action": "sts:AssumeRole" + } + ] +} +``` + +And the following trust relationship (Add AWS `Service`s as needed): + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} +``` + +## 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. From df1b6bf2e624d5d2bce1dd72f1b200dd50b83c5a Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Tue, 8 Oct 2024 19:39:40 +0100 Subject: [PATCH 06/13] Add a section about loading credentials from a Secret Signed-off-by: Richard Wall --- .../docs/configuration/acme/dns01/route53.md | 80 +++++++------------ 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 0b157348e5..65d9028a2b 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -354,6 +354,36 @@ spec: name: # The name of the service account created ``` +#### Referencing a long-term access key within in an Issuer or ClusterIssuer + +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). +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 Example: Account Y manages Route53 DNS Zones. Now you want cert-manager running in Account X (or many other accounts) to be able to manage records in Route53 zones hosted in Account Y. @@ -419,53 +449,3 @@ 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. From 0bf19d3ee589ae0279931ac5da368624685a9d5d Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Tue, 8 Oct 2024 19:50:58 +0100 Subject: [PATCH 07/13] Format the numbered list items Signed-off-by: Richard Wall --- .../docs/configuration/acme/dns01/route53.md | 417 ++++++++++-------- 1 file changed, 228 insertions(+), 189 deletions(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 65d9028a2b..32109bb68d 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -73,24 +73,22 @@ Using an IAM Role with temporary security credentials is considered best practic 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). -cert-manager supports multiple ways to get the access key -and these can be categorized as either "ambient" or "non-ambient": +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 IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). - 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). -- [EKS Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). - 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). -- [EC2 Instance Metadata Service (IMDS)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-security-credentials.html). - 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) - (`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`). - If those environment variables are present in the cert-manager controller Pod cert-manager will use them.. -- [Shared config and credentials files](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html) - (`~/.aws/config` and `~/.aws/credentials`). - If those files are mounted into the cert-manager controller Pod, cert-manager will use them. +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, well documented, and AWS provides ways to automate the configuration. @@ -130,110 +128,151 @@ spec: route53 {}: ``` -Regardless of which ambient mechanism you use, the `route53` section is left empty, because cert-manager (using the AWS SDK for Go V2) can find the credentials, role, and region by looking for environment variables which will be added to the cert-manager Pod. +> ℹī¸ 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 -If you deploy cert-manager on EKS, [Pod Identity](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html) is the simplest way to use ambient credentials. -It is a three 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, then +[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. +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) -If you deploy cert-manager on EKS, IAM Roles for Service Accounts (IRSA) is another way to use use ambient credentials. +IAM Roles for Service Accounts (IRSA) 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, which is configured by default on EKS, will automatically setup a mounted service account volume in the cert-manager Pod. +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. -> ℹī¸ To use 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). - -1. **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 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. - -2. **Annotate the cert-manager `ServiceAccount`** - -```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager -``` +3. **(optional) Update file system permissions** -The cert-manager Helm chart provides a variable for injecting annotations into cert-manager's `ServiceAccount` like so: + You may also need to modify the cert-manager `Deployment` with the correct file system permissions, so the `ServiceAccount` token can be read. -```yaml -serviceAccount: - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXX:role/cert-manager -``` + ```yaml + spec: + template: + spec: + securityContext: + fsGroup: 1001 + ``` -> ℹī¸ If you're following the Cross Account example above, modify the `ClusterIssuer` in the same way as above with the role from Account Y. + The cert-manager Helm chart provides a variable for modifying cert-manager's `Deployment` like so: -3. **(optional) Update file system permissions** + ```yaml + securityContext: + fsGroup: 1001 + ``` -You may also need to modify the cert-manager `Deployment` with the correct file system permissions, so the `ServiceAccount` token can be read. +4. **Restart the cert-manager Deployment** -```yaml -spec: - template: - spec: - securityContext: - fsGroup: 1001 -``` + Restart the cert-manager Deployment, so that the webhook can inject the + necessary `volume`, `volumemount`, and environment variables into the Pods. -The cert-manager Helm chart provides a variable for modifying cert-manager's `Deployment` like so: +5. **Create a `ClusterIssuer` resource** -```yaml -securityContext: - fsGroup: 1001 -``` + ```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. +Non-ambient credentials are credentials which are explicitly configured on the Issuer or ClusterIssuer resource. For example: -- *Access key Secret reference*: +- **Access key Secret reference**:
where cert-manager loads a long-term access key from a Kubernetes Secret resource. -- *ServiceAccount reference*: +- **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. @@ -250,109 +289,109 @@ such that each `ServiceAccount` is mapped to an IAM role that only has permissio 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. + 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: -``` + ```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. + 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. + 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 -``` + 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 + ``` #### Referencing a long-term access key within in an Issuer or ClusterIssuer From b8b1a1c5d8ce23984792a023fa2ff94a0d10afb9 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 9 Oct 2024 06:54:02 +0100 Subject: [PATCH 08/13] Notes about the region field Signed-off-by: Richard Wall --- .../docs/configuration/acme/dns01/route53.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 32109bb68d..e66f2822d1 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -488,3 +488,40 @@ And the following trust relationship (Add AWS `Service`s as needed): ] } ``` + +## Region + +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. + +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). + +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). + +> ℹī¸ 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. + +> ℹī¸ 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. From ae9a9e01482b0c0cb69418eb9791453c2bd11981 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 9 Oct 2024 07:22:27 +0100 Subject: [PATCH 09/13] Cross links with the tutorial Signed-off-by: Richard Wall --- .../docs/configuration/acme/dns01/route53.md | 19 ++++++++++--------- .../getting-started-aws-letsencrypt/README.md | 8 ++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index e66f2822d1..7a66efc74f 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -11,9 +11,9 @@ 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. > -> 📖 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 Policy @@ -90,8 +90,8 @@ Ambient credentials are credentials which are made available in the cert-manager - [**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, well -documented, and AWS provides ways to automate the configuration. +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 @@ -150,10 +150,9 @@ It is a four step process: name: letsencrypt-prod spec: acme: - ... solvers: - dns01: - route53 {}: + route53: {} ``` #### EKS IAM Role for Service Accounts (IRSA) @@ -260,10 +259,9 @@ A mutating webhook will automatically setup a mounted service account volume in name: letsencrypt-prod spec: acme: - ... solvers: - dns01: - route53 {}: + route53: {} ``` ### Non-ambient Credentials @@ -281,6 +279,9 @@ Each tenant can be granted permission to create and update Issuer resources in t #### Referencing your own ServiceAccount within in an Issuer or ClusterIssuer +> 📖 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 advantage of this method over IRSA or Pod Identity is that each Issuer can reference a different `ServiceAccount`, diff --git a/content/docs/tutorials/getting-started-aws-letsencrypt/README.md b/content/docs/tutorials/getting-started-aws-letsencrypt/README.md index 87110e8d49..55ced23bc0 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 a [dedicated Kubernetes ServiceAccount token](../../configuration/acme/dns01/route53.md#referencing-your-own-serviceaccount-within-in-an-issuer-or-clusterissuer). 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 From 71a554d8259a3449dc505e74c1d4c1efc5a21f67 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 9 Oct 2024 09:44:22 +0100 Subject: [PATCH 10/13] Link to the IRSA introduction Signed-off-by: Richard Wall --- content/docs/configuration/acme/dns01/route53.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 7a66efc74f..addeb866ac 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -98,7 +98,7 @@ 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, which uses the AWS SDK for Go V2, supports all these ambient credential sources. +> 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. @@ -157,7 +157,7 @@ It is a four step process: #### EKS IAM Role for Service Accounts (IRSA) -IAM Roles for Service Accounts (IRSA) is another way to use ambient credentials, +[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. From 7c5947f74029f36f7beb4448e25fd5d71af65ded Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 9 Oct 2024 09:46:06 +0100 Subject: [PATCH 11/13] Fix invalid yaml Signed-off-by: Richard Wall --- content/docs/configuration/acme/dns01/route53.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index addeb866ac..0f832db241 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -125,7 +125,7 @@ spec: ... solvers: - dns01: - route53 {}: + route53: {} ``` > ℹī¸ Regardless of which ambient mechanism you use, the `route53` section is left empty, From 2f19d2e9ae6bb3a106964d9a2beb2f9ccf2ec2ab Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 9 Oct 2024 10:10:48 +0100 Subject: [PATCH 12/13] Don't describe IAM User as legacy and explain when it is appropriate to use that Signed-off-by: Richard Wall --- .../docs/configuration/acme/dns01/route53.md | 31 ++++++++++++------- .../getting-started-aws-letsencrypt/README.md | 2 +- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 0f832db241..9a7bba0392 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -8,8 +8,7 @@ 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 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 @@ -66,13 +65,16 @@ An access key is defined by AWS as follows: > 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. (Legacy) Use an [IAM User and a long-term access key](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html). -2. (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). +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 @@ -198,7 +200,7 @@ A mutating webhook will automatically setup a mounted service account volume in - `` 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 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. @@ -277,16 +279,19 @@ For example: 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. -#### Referencing your own ServiceAccount within in an Issuer or ClusterIssuer +#### 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 advantage of this method over IRSA or Pod Identity is that 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 for that particular + +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** @@ -328,7 +333,7 @@ such that each `ServiceAccount` is mapped to an IAM role that only has permissio - `` 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 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. @@ -394,12 +399,16 @@ such that each `ServiceAccount` is mapped to an IAM role that only has permissio name: # The name of the service account created ``` -#### Referencing a long-term access key within in an Issuer or ClusterIssuer +#### 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 diff --git a/content/docs/tutorials/getting-started-aws-letsencrypt/README.md b/content/docs/tutorials/getting-started-aws-letsencrypt/README.md index 55ced23bc0..5be63770d8 100644 --- a/content/docs/tutorials/getting-started-aws-letsencrypt/README.md +++ b/content/docs/tutorials/getting-started-aws-letsencrypt/README.md @@ -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 a [dedicated Kubernetes ServiceAccount token](../../configuration/acme/dns01/route53.md#referencing-your-own-serviceaccount-within-in-an-issuer-or-clusterissuer). +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). From 4d8ddd2e4255ac4e889decb4f593549e3a5cee08 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Thu, 10 Oct 2024 09:48:30 +0100 Subject: [PATCH 13/13] Add runAsUser: 1001 to the IRSA instructions Along with a call for feedback from EKS Fargate users Signed-off-by: Richard Wall --- .../docs/configuration/acme/dns01/route53.md | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/content/docs/configuration/acme/dns01/route53.md b/content/docs/configuration/acme/dns01/route53.md index 9a7bba0392..ec5a2a8006 100644 --- a/content/docs/configuration/acme/dns01/route53.md +++ b/content/docs/configuration/acme/dns01/route53.md @@ -228,9 +228,22 @@ A mutating webhook will automatically setup a mounted service account volume in > ℹī¸ If you're following the Cross Account example, modify the `ClusterIssuer` with the role from Account Y. -3. **(optional) Update file system permissions** - - You may also need to modify the cert-manager `Deployment` with the correct file system permissions, so the `ServiceAccount` token can be read. +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: @@ -238,6 +251,7 @@ A mutating webhook will automatically setup a mounted service account volume in spec: securityContext: fsGroup: 1001 + runAsUser: 1001 ``` The cert-manager Helm chart provides a variable for modifying cert-manager's `Deployment` like so: @@ -245,14 +259,15 @@ A mutating webhook will automatically setup a mounted service account volume in ```yaml securityContext: fsGroup: 1001 + runAsUser: 1001 ``` -4. **Restart the cert-manager Deployment** +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. -5. **Create a `ClusterIssuer` resource** +6. **Create a `ClusterIssuer` resource** ```yaml apiVersion: cert-manager.io/v1