I'm working on a project where I need to list AWS S3 buckets in Java Spring Boot. Initially, I used secret and access keys passed through application.properties its working for me and the code looked like this:
@GetMapping("service2/getListOfS3Buckets")
public String getListOfS3Buckets() {
AmazonS3 s3Client = AmazonS3ClientBuilder
.standard()
.withRegion(awsRegion)
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKey, awsSecretKey)))
.build();
List<Bucket> buckets = s3Client.listBuckets();
StringBuilder response = new StringBuilder("List of S3 Buckets:\n");
for (Bucket bucket : buckets) {
response.append(bucket.getName()).append("\n");
}
return response.toString();
}
However, I understand that this is not considered best practice, and I'd like to improve it by using an IAM role attached to a service account. I've attached the IAM role to the pod, but when I use the following code, I encounter an internal error:
I created an IAM policy named "my-policy" with the necessary S3 permissions.
I attached this policy to an IAM role named "my-role" using the following AWS CLI commands:
cat >my-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*",
"s3:Describe*",
"s3-object-lambda:Get*",
"s3-object-lambda:List*"
],
"Resource": "*"
}
]
}
EOF
aws iam create-policy --policy-name my-policy --policy-document file://my-policy.json
eksctl create iamserviceaccount --name my-service-account --namespace kube-system --cluster my-cluster --role-name my-role \
--attach-policy-arn arn:aws:iam::111122223333:policy/my-policy --approve
kubectl describe serviceaccount my-service-account -n kube-system
Name: my-service-account
Namespace: kube-system
Labels: app.kubernetes.io/managed-by=eksctl
Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::11111222222:role/my-role
Image pull secrets: <none>
Mountable secrets: <none>
Tokens: <none>
Events: <none>
And this is my code
@GetMapping("service2/getListOfS3Buckets")
public String getListOfS3Buckets() {
AmazonS3 s3Client = AmazonS3ClientBuilder
.standard()
.withRegion(awsRegion) // Specify your desired AWS region here
.withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
.build();
List<Bucket> buckets = s3Client.listBuckets();
StringBuilder response = new StringBuilder("List of S3 Buckets:\n");
for (Bucket bucket : buckets) {
response.append(bucket.getName()).append("\n");
}
return response.toString();
}
I receive an internal error with the following message:
Request processing failed: com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [EnvironmentVariableCredentialsProvider: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)), SystemPropertiesCredentialsProvider: Unable to load AWS credentials from Java system properties (aws.accessKeyId and aws.secretKey), WebIdentityTokenCredentialsProvider: To use assume role profiles the aws-java-sdk-sts module must be on the class path., com.amazonaws.auth.profile.ProfileCredentialsProvider@59639381: profile file cannot be null, com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@39201cc7: Failed to connect to service endpoint:]
I need assistance in resolving this issue and successfully using the IAM role attached to the service account for AWS authentication. Any guidance or suggestions would be greatly appreciated.
Error says that you haven't annotated the service account with proper IAM role.
Steps to resolve this issue:
Please follow the steps(1,2,3) in this document https://repost.aws/knowledge-center/eks-restrict-s3-bucket