Skip to content

Commit 31efa3d

Browse files
authored
docs(tutorials/aws): document AWS SDK credential provider chain (#6444)
* docs(tutorials/aws): document AWS SDK credential provider chain ExternalDNS resolves AWS credentials via the aws-sdk-go-v2 default credential provider chain (provider/aws/config.go uses config.LoadDefaultConfig), so any credential source the SDK supports works — including AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY env vars, AWS_SHARED_CREDENTIALS_FILE / AWS_CONFIG_FILE, EC2 instance profile, ECS container credentials, and EKS Pod Identity. The tutorial previously documented only three deployment patterns (Node IAM Role, mounted credentials file, IRSA), leaving users to guess that env vars work or dig through Helm chart values. Add a note pointing at the AWS SDK reference for the full chain plus a tip showing the env-var pattern via the Helm chart's env: block, which is the concrete recipe users have been reconstructing from scratch. Refs #5265 * docs(tutorials/aws): clarify which Helm chart the env example targets Be explicit that the env-var example targets the in-tree external-dns Helm chart under charts/external-dns/, since multiple community charts named "external-dns" exist with different value schemas. * docs(aws): streamline AWS credential provider chain documentation following feedback Signed-off-by: Alexander Chernov <alexander@chernov.it> * docs(aws): enhance security guidance for AWS credential methods in documentation Signed-off-by: Alexander Chernov <alexander@chernov.it> * docs(tutorials/aws): fix markdownlint errors in static credentials section The Lint workflow rejected the previous commits with MD004/MD030/MD032/ MD028/MD031/MD022 violations against the static-credentials blockquote. Convert bullet markers from `*` to `-` (MD004) and trim the spacing after markers to one space (MD030). Add the blank-blockquote separator lines before each list inside a blockquote (MD032). Add a non-blockquote separator between the two consecutive `[!TIP]` callouts (MD028). Add the blank line between the closing fence and the next heading (MD031, MD022). Refs: #5265 Signed-off-by: Alexander Chernov <alexander@chernov.it> --------- Signed-off-by: Alexander Chernov <alexander@chernov.it>
1 parent 8d45c1c commit 31efa3d

1 file changed

Lines changed: 56 additions & 2 deletions

File tree

docs/tutorials/aws.md

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ You will need to use the above policy (represented by the `POLICY_ARN` environme
123123
- [Static credentials](#static-credentials)
124124
- [IAM Roles for Service Accounts](#iam-roles-for-service-accounts)
125125

126+
> [!NOTE]
127+
> ExternalDNS resolves AWS credentials through the
128+
> [AWS SDK for Go v2 default credential provider chain](https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/configure-gosdk.html#specifying-credentials).
129+
> Any source supported by the SDK works without additional configuration in ExternalDNS — including environment
130+
> variables, shared config and credentials files, EC2 instance profile / ECS container credentials, and EKS Pod
131+
> Identity. See the AWS SDK reference for the full list and precedence order.
132+
126133
For this tutorial, ExternalDNS will use the environment variable `EXTERNALDNS_NS` to represent the namespace, defaulted to `default`.
127134
Feel free to change this to something else, such `externaldns` or `kube-addons`.
128135
Make sure to edit the `subjects[0].namespace` for the `ClusterRoleBinding` resource when deploying ExternalDNS with RBAC enabled.
@@ -249,9 +256,32 @@ If ExternalDNS is not yet deployed, follow the steps under [Deploy ExternalDNS](
249256

250257
In this method, the policy is attached to an IAM user, and the credentials secrets for the IAM user are then made available using a Kubernetes secret.
251258

252-
This method is not the preferred method as the secrets in the credential file could be copied and used by an unauthorized threat actor.
259+
> [!WARNING]
260+
> **Security Risks with Static Credentials**
261+
>
262+
> - `kubectl describe pod` could expose secrets.
263+
> - Anyone who can `exec` into the container and run `env` can see them.
264+
> - Env vars can leak into logs, crash dumps, or child processes.
265+
> - There is no way to make them visible to a specific user only.
266+
> - They are long-lived, easy to leak, hard to rotate, and easy to accidentally commit or log.
267+
>
268+
> **When to use:**
269+
>
270+
> - Limit usage to non-AWS clusters.
271+
> - Always apply minimal privileges.
272+
> - Acknowledges reality (sometimes it is the only viable option).
273+
>
274+
> **For AWS specifically, the best practice and recommended hierarchy is:**
275+
>
276+
> 1. **IRSA (preferred):** Map an AWS IAM role to a Kubernetes service account; no static credentials in the pod.
277+
> 2. **EKS Pod Identity:** Native EKS alternative to IRSA; associates IAM role with a service account via the Pod Identity Agent.
278+
> 3. **Node IAM Role:** Attach policy to the node instance profile; not recommended beyond tests because all pods on the node inherit the permissions. Tolerated, but not recommended.
279+
> 4. **Mount credentials file:** Minimize privileges and avoid long-lived keys where possible.
280+
> 5. **Environment variables:** Minimize privileges and avoid long-lived keys where possible.
281+
282+
This method is not the preferred method as the secrets in the credential file or environment variables could be copied and used by an unauthorized threat actor.
253283
However, if the Kubernetes cluster is not hosted on AWS, it may be the only method available.
254-
Given this situation, it is important to limit the associated privileges to just minimal required privileges, i.e. read-write access to Route53, and not used a credentials file that has extra privileges beyond what is required.
284+
Given this situation, it is important to limit the associated privileges to just minimal required privileges, i.e. read-write access to Route53, and not use a credentials file that has extra privileges beyond what is required.
255285

256286
#### Create IAM user and attach the policy
257287

@@ -296,6 +326,30 @@ Follow the steps under [Deploy ExternalDNS](#deploy-externaldns) using either RB
296326
> ExternalDNS looks for the hosted zones in all profiles and keeps maintaining a mapping table between zone and profile
297327
> in order to be able to modify the zones in the correct profile.
298328
329+
<!-- markdownlint-disable-line MD028 -->
330+
331+
> [!TIP]
332+
> To pass static credentials as environment variables (e.g. when running outside AWS and
333+
> mounting the credentials file is not convenient), source them from a Kubernetes `Secret`
334+
> and project them into the pod. With the
335+
> [in-tree `external-dns` Helm chart](https://github.com/kubernetes-sigs/external-dns/tree/master/charts/external-dns),
336+
> set the top-level `env` value:
337+
>
338+
> ```yaml
339+
> # values.yaml
340+
> env:
341+
> - name: AWS_ACCESS_KEY_ID
342+
> valueFrom:
343+
> secretKeyRef:
344+
> name: aws-route53-credentials
345+
> key: aws-access-key-id
346+
> - name: AWS_SECRET_ACCESS_KEY
347+
> valueFrom:
348+
> secretKeyRef:
349+
> name: aws-route53-credentials
350+
> key: aws-secret-access-key
351+
> ```
352+
299353
### IAM Roles for Service Accounts
300354
301355
[IRSA](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) ([IAM roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)) allows cluster operators to map AWS IAM Roles to Kubernetes Service Accounts.

0 commit comments

Comments
 (0)