gorogoro
gorogoro

Reputation: 330

AWS Java SDK not finding profile when using AWS SSO

I can't reach aws when my login is made using AWS SSO. I login from my computer using:

aws sso login --profile staging

The profile is configured like this:

[profile staging]
sso_start_url = https://som-nice-working-url
sso_region = us-east-1
sso_account_id = 1234
sso_role_name = the-role-name
region = eu-west-1
output = yaml

After doing the login I can access aws through aws cli.

Then I set the varible: AWS_PROFILE=staging But on java I'm getting the following exception:

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: You must specify a value for roleArn and roleSessionName, com.amazonaws.auth.profile.ProfileCredentialsProvider@369a95a5: No AWS profile named 'staging', com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@6d6f6ca9: Failed to connect to service endpoint: ]

I have tryed using the ProfileCredentialsProvider with "staging" but the result is the same.

What CredentialsProvider should I use?

My code is using the DefaultProviderChain:

AWSGlueClient.builder()
            .withRegion("eu-west-1")
            .build()

Thank you.

Upvotes: 29

Views: 36953

Answers (7)

Archmede
Archmede

Reputation: 1842

For a Java application you'll need the SSO Dependency.

As of writing the latest is version 2.16.76

// Gradle example
dependencies {
    
    implementation(platform("software.amazon.awssdk:bom:2.16.76"))
    implementation("software.amazon.awssdk:sso")
    implementation("software.amazon.awssdk:ssooidc")
}

You'll also need to set a default profile in either ~/.aws/configuration or ~/.aws/credentials

More info below:

https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup.html#setup-credentials https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-additional.html#setup-additional-credentials

But, you should also be able to just set the AWS_PROFILE environment variable to your profile and it should just magically work without the SSO dependency.

In your example, specifically:

AWS_PROFILE=staging

Upvotes: 25

parisni
parisni

Reputation: 1152

This is an enhanced answers's @nluk provided. You just need the iam profile name to get the sso profile from the .aws folder and config file.

Add this in the pom:

        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>sso</artifactId>
            <version>2.19.16</version>
        </dependency>

then: you can use sdk2 sso tooling:

import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
import software.amazon.awssdk.auth.credentials.ProfileProviderCredentialsContext;
import software.amazon.awssdk.profiles.ProfileFile;
import software.amazon.awssdk.services.sso.auth.SsoProfileCredentialsProviderFactory;

//....
 String awsProfile = "my-profile-name"
 ProfileFile profileFile = ProfileFile.defaultProfileFile();
    profileFile
        .getSection("profiles", awsProfile)
        .ifPresent(
            profile -> {
              ProfileProviderCredentialsContext profileProvider =
                  ProfileProviderCredentialsContext.builder()
                      .profile(profile)
                      .profileFile(profileFile)
                      .build();
//            cast to get the token
              AwsSessionCredentials awsCredentials =
                  (AwsSessionCredentials)
                      new SsoProfileCredentialsProviderFactory()
                          .create(profileProvider)
                          .resolveCredentials();
// then get the temporary credentials
//            awsCredentials.accessKeyId();
//            awsCredentials.secretAccessKey();
//            awsCredentials.sessionToken();
            });

Upvotes: 1

Gapmeister66
Gapmeister66

Reputation: 894

When using AWS SDK for Java, you could try giving some environment variables to your Java applicatation using values from the cached temporary credentials.

Login using:

aws sso login

Read the cached file:

cat ~/.aws/cli/cache/<generated>.json

Set your environment variables using fields from the cached file:

AWS_ACCESS_KEY_ID=<AccessKeyId>
AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
AWS_SESSION_TOKEN=<SessionToken>

Run your Java application using these environment variables.

Under the hood, the EnvironmentVariableCredentialsProvider class reads these environment variables.

You will need to reset these environment variables every time the session token expires.

Upvotes: 0

nluk
nluk

Reputation: 754

In my case, just adding the aws-sso dependency:

    <dependency>
       <groupId>software.amazon.awssdk</groupId>
       <artifactId>sso</artifactId>
    </dependency>

allows the default credentials providers chain to pick up sso under ProfileCredentialsProvider: Profile credentials provider with sso profile

To work out of the box, it requires from you to have the [default] profile specified. Otherwise, simply using .credentialsProvider(ProfileCredentialsProvider.create("xyz")) also works with [profile xyz].

If all fails, add the credentials provider manually:

  1. Setup your profile file .aws/config
  2. Login with cli aws sso login --profile <your_profile>
  3. A json file is generated in .aws/sso/cache with contents as described here
{
 "startUrl": "https://my-sso-portal.awsapps.com/start",
 "region": "us-east-1",
 "accessToken": "eyJlbmMiOiJBM….",
 "expiresAt": "2020-06-17T10:02:08UTC"
}
  1. Include in your project a dependency to software.amazon.awssdk:sso
  2. Create SsoCredentialsProvider with the data from json file:
CredentialsProvider ssoCredentialsProvider = ((SsoCredentialsProvider.Builder) SsoCredentialsProvider.builder())
.ssoClient(SsoClient.builder().region(<REGION_FROM_JSON>).build())
.refreshRequest( () ->
    GetRoleCredentialsRequest.builder()
      .roleName("<ROLE_FROM_PROFILE>")
      .accountId("<ACCOUNT_ID_FROM_PROFILE>")
      .accessToken("<ACCESS_TOKEN_FROM_JSON>")
      .build()
).build();

Upvotes: 9

Ahmad Abdelghany
Ahmad Abdelghany

Reputation: 13228

Support for SSO Credentials Provider was added to AWS SDK for Java V2 in version 2.15.33 (November 2020). Older versions of the SDK don't work with SSO. (See the Feature Request & the PR)

If you are using maven, make sure the versions of all SDK modules are compatible by specifying the version in the dependencyManagement section as described in the documentation. e.g.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.17.8</version>  <!--Must be 2.15.33 or higher-->
            <type>pom</type>
            <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>dynamodb</artifactId>
    </dependency>
    <dependency>
       <groupId>software.amazon.awssdk</groupId>
       <artifactId>sso</artifactId>
    </dependency>
</dependencies>

Upvotes: 10

tdebroc
tdebroc

Reputation: 1526

Waiting for SDK 2 to integrate SSO, aws-sso-cred-restore is a workaround:

Intall it (with Python 3):

pip3 install aws-sso-cred-restore

Then you can run this (it get a Token available for around 1h, so you should run it every hour to refresh):

aws-sso-cred-restore --profile $YOUR_PROFILE

And you can use again your $YOUR_PROFILE in your Java app.

Upvotes: 1

Milan Gaty&#225;s
Milan Gaty&#225;s

Reputation: 2787

I might be wrong, however IMO there is no way to use AWS SSO within AWS SDK yet based on https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html.

AFAIK AWS SSO is at the moment integrated only into AWS CLI - https://docs.aws.amazon.com/singlesignon/latest/userguide/integrating-aws-cli.html

Upvotes: 1

Related Questions