Spring boot application can't find aws credentials from any credentials chain - amazon-web-services

I'm trying to migrate Several spring boot services to EKS and they can't retrieve aws credentials from credentials chain and pods are failing with following error: Unable to load credentials from any of the providers in the chain AwsCredentialsProviderChain
These are what I've tried so far:
I'm using Web identity token from AWS STS for credentials retrieval.
#Bean
public AWSCredentialsProvider awsCredentialsProvider() {
if (System.getenv("AWS_WEB_IDENTITY_TOKEN_FILE") != null) {
return WebIdentityTokenCredentialsProvider.builder().build();
}
return new DefaultAWSCredentialsProviderChain();
}
#Bean
public SqsClient sqsClient(AWSCredentialsProvider awsCredentialsProvider) {
return SqsClient
.builder()
.credentialsProvider(() -> (AwsCredentials) awsCredentialsProvider.getCredentials())
.region(Region.EU_WEST_1).build();
}
#Bean
public SnsClient snsClient(AWSCredentialsProvider awsCredentialsProvider) {
return SnsClient
.builder()
.credentialsProvider(() -> (AwsCredentials) awsCredentialsProvider.getCredentials())
.region(Region.EU_WEST_1).build();
}
The services also have aws-java-sdk-sts maven dependency packaged.
IAM role for the services is also fine and AWS_WEB_IDENTITY_TOKEN_FILE is a also automatically created within pod after each Jenkins build based on K8s manifest file.
From pod I can make GET and POST request to SNS and SQS without any problem.

Problem was fixed.
Main issue was conflicting AWS SDK BOM version with individual models. Also previous version of BOM I was using wasn't supporting AWS SDK v2.x .
These are the main take aways from the issue:
AWS SDK authenticate services using credentials provider chain . The default credential provider chain of the AWS SDK for Java 2.x searches for credentials in your environment using a predefined sequence.
1.1 As of AWS SDK for Java 2.x Web identity token from AWS STS is within default provider chain.
1.2 As long as using v2 of the SDK and having the STS dependency makes explicit configuration of Web identity token redundant.
1.3 Make sure candidate service is using AWS SDK v2 as it’ll reduce the configuration code to minimum.
If a candidate service using AWS SDK v1 following configuration should be added as Web identity token isn’t in default provider chain for v1.
#Bean
public AWSCredentialsProvider awsCredentialsProvider() {
if (System.getenv("AWS_WEB_IDENTITY_TOKEN_FILE") != null) {
return WebIdentityTokenCredentialsProvider.builder().build();
}
return new DefaultAWSCredentialsProviderChain();
}
Last but not least try to use try to use latest AWS SDK BOM dependency . (currently all modules have the same version, but this may not always be the case)

You should have roleArn, sessionname and token details in the identity token cred provider build.
Try this
return WebIdentityTokenCredentialsProvider.builder()
.roleArn(System.getenv("AWS_ROLE_ARN"))
.roleSessionName(System.getenv("AWS_ROLE_SESSION_NAME"))
.webIdentityTokenFile(System.getenv("AWS_WEB_IDENTITY_TOKEN_FILE"))
.build();
than just returning as return WebIdentityTokenCredentialsProvider.builder().build();

You can try to create the file:
Windows: C:\Users[username].aws\config
Mac: /Users/[username]/.aws/config
Linux: /home/[username]/.aws/config
and add an AWS credential to it.
Ex:
[default]
aws_access_key_id = key_value
aws_secret_access_key = secret_value

Related

Unable to access AWS account through terraform AWS provider --

I'm facing a issue, status code is:401
"creating ec2 instance: authfailure: aws was not able to validate the provided access credentials │ status code: 401, request id: d103063f-0b26-4b84-9719-886e62b0e2b1"
the instance code:
resource "aws_instance" "test-EC2" {
instance_type = "t2.micro"
ami = "ami-07ffb2f4d65357b42"
}
I have checked the AMI region still not working
any help would be appreciated
I am looking for a way to create and destroy tokens via the management console provided by AWS. I am learning about terraform AWS provider which requires an access key, a secret key and a token.
As stated in the error message :
creating ec2 instance: authfailure: aws was not able to validate the provided access credentials │ status code: 401, request id: d103063f-0b26-4b84-9719-886e62b0e2b1".
It is clear that terraform is not able to authenticate itself using terraform AWS-provider.
You have to have a provider block in your terraform configuration to use one of the supported ways to get authenticated.
provider "aws" {
region = var.aws_region
}
In general, the following are the ways to get authenticated to AWS via the AWS-terraform provider.
Parameters in the provider configuration
Environment variables
Shared credentials files
Shared configuration files
Container credentials
Instance profile credentials and region
For more details, please take a look at: https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration
By default, if you are already programmatically signed in to your AWS account AWS-terraform provider will use those credentials.
For example:
If you are using aws_access_key_id and aws_secret_access_key to authenticate yourself then you might have a profile for these credentials. you can check this info in your $HOME/.aws/credentials config file.
export the profile using the below command and you are good to go.
export AWS_PROFILE="name_of_profile_using_secrets"
If you have a SSO user for authentication
Then you might have a sso profile available in $HOME/.aws/config In that case you need to sign in with the respective aws sso profile using the below command
aws sso login --profile <sso_profile_name>
If you don't have a SSO profile yet you can also configure it using the below commands and then export it.
aws configure sso
[....] # configure your SSO
export AWS_PROFILE=<your_sso_profile>
Do you have an aws provider defined in your terraform configuration?
provider "aws" {
region = var.aws_region
profile = var.aws_profile
}
if you are running this locally, please have an IAM user profile set (use aws configure) and export that profile in your current session.
aws configure --profile xxx
export AWS_PROFILE=xxx
once you have the profile set, this should work.
If you are running this deployment in any pipleine like Github Action, you could also make use of OpenId connect to avoid any accesskey and secretkey.
Please find the detailed setup for OpenId connect here.

Connect to AWS without using static credentials

I am using aws-go sdk
using static creds I am able to connect using
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(awsAccesstKey, awsSecretKey, "")),
is there anyway using nodeIAM role, by which we can connect to AWS?
The documentation explains how to configure the SDK, including credentials:
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Fatalf("failed to load configuration, %v", err)
}
From the link above:
When you initialize an aws.Config instance using
config.LoadDefaultConfig, the SDK uses its default credential chain to
find AWS credentials. This default credential chain looks for
credentials in the following order:
Environment variables.
Static Credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN)
Web Identity Token (AWS_WEB_IDENTITY_TOKEN_FILE)
Shared configuration files.
SDK defaults to credentials file under .aws folder that is placed in the home folder on your computer.
SDK defaults to config file under .aws folder that is placed in the home folder on your computer.
If your application uses an ECS task definition or RunTask API operation, IAM role for tasks.
If your application is running on an Amazon EC2 instance, IAM role for Amazon EC2.
The SDK detects and uses the built-in providers automatically, without
requiring manual configurations. For example, if you use IAM roles for
Amazon EC2 instances, your applications automatically use the
instance’s credentials. You don’t need to manually configure
credentials in your application.

Springboot with AWS SNS

Actually Iam trying to set email subscription to SNS topic in AWS through springboot and publish the message to SNS topic. But facing issue in configuring the AWS access key and secret key. Do I need to create a separate IAM user for accessing SNS or it is fine to have a IAM user already created with administrator access to SNS topic. Below is the configuration file I created.
#Configuration
public class AmazonSNSConfiguration {
#Bean
#Primary
public AmazonSNSClient amazonSNSClient() {
return (AmazonSNSClient) AmazonSNSClientBuilder
.standard()
.withRegion(Regions.US_EAST_1)
.withCredentials(
new AWSStaticCredentialsProvider(
new BasicAWSCredentials(
"**********",
"***********"
)
)
)
.build();
}
}
When working with Spring BOOT and the Java SNS V2 API, you can create an IAM role that has a policy to use SNS.
Also, there is no reason to Hard Code the key creds in the Java code. You can create an SNSClient object like this:
Region region = Region.US_WEST_2;
SnsClient snsClient = SnsClient.builder()
.region(region)
.build();
This code assumes you have set the creds in a file named credentials located in .aws. See this doc (under heading Configure credentials) for more information:
Get started with the AWS SDK for Java 2.x
Here is an AWS developer tutorial that steps you through How To create a Spring BOOT app that uses the SNS service to create a Sub/Pub app:
Creating a Publish/Subscription Spring Boot Application

Reading aws config and credentials from resources folder using aws java sdk version 2

I have moved my aws credentials from ~/.aws/credentials to resources folder of maven project . the folder structure looks like this
resources/aws/
->config
->credentials
I am using aws java sdk version 2+ . How can i read the values from resources folder to get region, access keys , create bucket and perform operations.
You should not place credentials files in resources directory. AWS Java SDK supports credential files in ~/.aws out-of-the box:
The following list shows the supported credential retrieval techniques:
Java system properties–aws.accessKeyId and aws.secretAccessKey. The AWS SDK for Java uses the SystemPropertyCredentialsProvider to load these credentials.
Environment variables–AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. The AWS SDK for Java uses the EnvironmentVariableCredentialsProvider class to load these credentials.
The default credential profiles file– The specific location of this file can vary per platform, but is typically located at ~/.aws/credentials. This file is shared by many of the AWS SDKs and by the AWS CLI. The AWS SDK for Java uses the ProfileCredentialsProvider to load these credentials.
You can create a credentials file by using the aws configure command provided by the AWS CLI. You can also create it by editing the file with a text editor. For information about the credentials file format, see AWS Credentials File Format.
Amazon ECS container credentials– This is loaded from Amazon ECS if the environment variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set. The AWS SDK for Java uses the ContainerCredentialsProvider to load these credentials.
Instance profile credentials– This is used on Amazon EC2 instances, and delivered through the Amazon EC2 metadata service. The AWS SDK for Java uses the InstanceProfileCredentialsProvider to load these credentials.
So, either use ProfileCredentialsProvider or pass the credentials via system properties or environment variables and use SystemPropertyCredentialsProvider / EnvironmentVariableCredentialsProvider.
AWS Java SDK v2 does not support getting credentials from the resource folder (classpath) directly.
As an alternative, you can put AWS credentials in a properties file in the resource folder:
[[project]/src/test/resources/aws-credentials.properties:
aws_access_key_id = xxx
aws_secret_access_key = xxx
Spring config:
<util:properties id="awsCredentialFile"
location="classpath:aws-credentials.properties"/>
and your code:
#Resource(name = "awsCredentialFile")
public void setProperties(Properties properties) {
this.accessKey = properties.getProperty("aws_access_key_id");
this.secretKey = properties.getProperty("aws_secret_access_key");
}
StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey));
S3Client s3 = S3Client.builder()
.credentialsProvider(credentialsProvider)
.build();

AWS Amplify graphql client IAM setup

I'm using the Amplify graphql client in my project. After custom auth I have the Access Key ID and Secret Access Key.
I need to provide these to the Amplify configuration but I can find no documentation whatsoever about it. The closest documentation I've seen is :
const myAppConfig = {
// ...
'aws_appsync_graphqlEndpoint': 'https://xxxxxx.appsync-api.us-east-1.amazonaws.com/graphql',
'aws_appsync_region': 'us-east-1',
'aws_appsync_authenticationType': 'AWS_IAM',
// ...
}
Amplify.configure(myAppConfig);
But it does not specify where should the credentials be entered.
They are specified for the AWS Appsync SDK but not the graphql client.
Any assistance or insights are greatly appreciated.
Thanks
I resolved it by using AWS.config
import AWS from "aws-sdk";
AWS.config.credentials = new AWS.Credentials(your credentials here)
Amplify.configure then works fine