0x00 TLNR;
在 AWS EKS 中,通过 Service Account(SA) 来代替使用 Access Key(AK)和 Secret Key(SK)是通过整合 IAM Roles for Service Accounts (IRSA) 来实现的。这种方式允许 EKS Pod 使用关联的 IAM Role 来访问 AWS 资源,而无需在代码中硬编码 AK/SK,从而提高安全性。
0x01 启用 IAM OIDC
通过EKS外部的OIDC 来绑定 sa 和 iam中的权限。 先确认下是否起用:
aws eks describe-cluster --name <your-cluster-name> --query "cluster.identity.oidc.issuer" --output text
没有输出的话,启用:
eksctl utils associate-iam-oidc-provider --cluster <your-cluster-name> --approve
0x02 创建S3桶的策略
1、编写S3 Policy文件
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket-name"
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket-name/*"
}
]
}
2、创建policy
aws iam create-policy --policy-name MyS3AccessPolicy --policy-document file://my-policy.json
正常时反馈:
{
"Policy": {
"PolicyName": "MyS3AccessPolicy",
"PolicyId": "ANP****ULM",
"Arn": "arn:aws:iam::{you_account_id}:policy/MyS3AccessPolicy",
"Path": "/",
"DefaultVersionId": "v1",
"AttachmentCount": 0,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"CreateDate": "2024-11-28T00:49:43Z",
"UpdateDate": "2024-11-28T00:49:43Z"
}
}
0x03 创建IAM Role 并绑定
1、获取OIDC的ARN,返回一个域名URL
aws eks describe-cluster --name <your-cluster-name> --query "cluster.identity.oidc.issuer" --output text
2、编写信任关系文件
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<account-id>:oidc-provider/<oidc-provider-url>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"<oidc-provider-url>:sub": "system:serviceaccount:<namespace>:<service-account-name>"
}
}
}
]
}
3、创建Role, 并绑定
aws iam create-role --role-name MyEKSRole --assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy --role-name MyEKSRole --policy-arn arn:aws:iam::<account-id>:policy/MyS3AccessPolicy
0x04 创建 K8s SA并绑定IAM Role
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: default
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<account-id>:role/MyEKSRole
提交:
kubectl apply -f sa.yaml
0x05 部署一个应用,使用创建的SA
apiVersion: v1
kind: Pod
metadata:
name: awscli
labels:
app: awscli
spec:
serviceAccountName: {sa-name}
containers:
- image: amazon/aws-cli
command:
- "sleep"
- "604800"
imagePullPolicy: IfNotPresent
name: awscli
restartPolicy: Always
0x06 验证
# 确认env配置
kubectl exec -n YOUR_NAMESPACE awscli -- env | grep AWS
# 获取 sts
kubectl exec -it awscli -n YOUR_NAMESPACE -- aws sts get-caller-identity
0x07 Spring Java 依赖
<dependencies>
<!-- IRSA基础依赖 -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>auth</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sdk-core</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sts</artifactId>
</dependency>
<!-- 业务依赖 -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.29.23</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
0x08 Java代码示例
@GetMapping("/get/{objectKey}")
public String demo(@PathVariable("objectKey") String objectKey) {
final S3Client s3client = S3Client.create();
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
.bucket("my-bucket")
.key(objectKey)
.build();
final ResponseBytes<GetObjectResponse> bytes = s3client.getObjectAsBytes(getObjectRequest);
String objectContent = bytes.asUtf8String();
log.info("received: {}", objectKey);
return objectContent;
}
0x09 参考:
JavaSDK:
https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html如何确认 pod 绑定了正确的 sa, 在pod内部执行:
curl http://169.254.169.254/latest/meta-data/iam/info
参考: https://repost.aws/knowledge-center/eks-pods-iam-role-service-accounts