Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible fix for aws profile assumeRole from ec2InstanceRole issues: #3038

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,7 @@ public boolean isRoleBasedProfile() {
public boolean isProcessBasedProfile() {
return getCredentialProcess() != null;
}
public String getCredentialSource() {
return getPropertyValue(ProfileKeyConstants.CREDENTIAL_SOURCE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.amazonaws.auth.profile.internal;

import com.amazonaws.annotation.SdkInternalApi;

@SdkInternalApi
public enum CredentialSourceType {
EC2_INSTANCE_METADATA,
ECS_CONTAINER,
ENVIRONMENT;

public static CredentialSourceType parse(String value) {
if (value.equalsIgnoreCase("Ec2InstanceMetadata")) {
return EC2_INSTANCE_METADATA;
} else if (value.equalsIgnoreCase("EcsContainer")) {
return ECS_CONTAINER;
} else if (value.equalsIgnoreCase("Environment")) {
return ENVIRONMENT;
}

throw new IllegalArgumentException(String.format("%s is not a valid credential_source", value));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,9 @@ public class ProfileKeyConstants {
* Absolute path to a JWT file containing a web identity token.
*/
public static final String WEB_IDENTITY_TOKEN = "web_identity_token_file";

/**
* A source to obtain credentials from.
*/
public static final String CREDENTIAL_SOURCE = "credential_source";
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,68 +14,110 @@
*/
package com.amazonaws.auth.profile.internal;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.amazonaws.SdkClientException;
import com.amazonaws.annotation.Immutable;
import com.amazonaws.annotation.SdkInternalApi;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSCredentialsProviderChain;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.auth.ContainerCredentialsProvider;
import com.amazonaws.auth.EnvironmentVariableCredentialsProvider;
import com.amazonaws.auth.InstanceProfileCredentialsProvider;
import com.amazonaws.auth.SystemPropertiesCredentialsProvider;
import com.amazonaws.internal.StaticCredentialsProvider;
import com.amazonaws.util.StringUtils;

/**
* Serves credentials defined in a {@link BasicProfile}. Does validation that both access key and
* secret key exists and are non empty.
* Serves credentials defined in a {@link BasicProfile}. Does validation that
* both access key and secret key exists and are non empty.
*/
@SdkInternalApi
@Immutable
public class ProfileStaticCredentialsProvider implements AWSCredentialsProvider {

private final BasicProfile profile;
private final AWSCredentialsProvider credentialsProvider;
private final BasicProfile profile;
private final AWSCredentialsProvider credentialsProvider;

public ProfileStaticCredentialsProvider(BasicProfile profile) {
this.profile = profile;
this.credentialsProvider = new StaticCredentialsProvider(fromStaticCredentials());
}

/**
* The raw properties in this profile.
*/
private final Map<String, String> properties;

@Override
public AWSCredentials getCredentials() {
return credentialsProvider.getCredentials();
}
public ProfileStaticCredentialsProvider(BasicProfile profile) {
this.profile = profile;
this.properties = profile.getProperties();
boolean hasCredentialSource = properties.containsKey(ProfileKeyConstants.CREDENTIAL_SOURCE);

@Override
public void refresh() {
// No Op
}
if (hasCredentialSource) {
CredentialSourceType credentialSource = CredentialSourceType.parse(profile.getCredentialSource());
this.credentialsProvider = credentialSourceCredentialProvider(credentialSource);
} else {
this.credentialsProvider = new StaticCredentialsProvider(fromStaticCredentials());
}
}

private AWSCredentials fromStaticCredentials() {
if (StringUtils.isNullOrEmpty(profile.getAwsAccessIdKey())) {
throw new SdkClientException(String.format(
"Unable to load credentials into profile [%s]: AWS Access Key ID is not specified.",
profile.getProfileName()));
}
if (StringUtils.isNullOrEmpty(profile.getAwsSecretAccessKey())) {
throw new SdkClientException(String.format(
"Unable to load credentials into profile [%s]: AWS Secret Access Key is not specified.",
profile.getAwsSecretAccessKey()));
}
@Override
public AWSCredentials getCredentials() {
return credentialsProvider.getCredentials();
}

if (profile.getAwsSessionToken() == null) {
return new BasicAWSCredentials(profile.getAwsAccessIdKey(),
profile.getAwsSecretAccessKey());
} else {
if (profile.getAwsSessionToken().isEmpty()) {
throw new SdkClientException(String.format(
"Unable to load credentials into profile [%s]: AWS Session Token is empty.",
profile.getProfileName()));
}
@Override
public void refresh() {
// No Op
}

return new BasicSessionCredentials(profile.getAwsAccessIdKey(),
profile.getAwsSecretAccessKey(),
profile.getAwsSessionToken());
}
}
private AWSCredentials fromStaticCredentials() {
if (StringUtils.isNullOrEmpty(profile.getAwsAccessIdKey())) {
throw new SdkClientException(
String.format("Unable to load credentials into profile [%s]: AWS Access Key ID is not specified.",
profile.getProfileName()));
}
if (StringUtils.isNullOrEmpty(profile.getAwsSecretAccessKey())) {
throw new SdkClientException(String.format(
"Unable to load credentials into profile [%s]: AWS Secret Access Key is not specified.",
profile.getAwsSecretAccessKey()));
}

if (profile.getAwsSessionToken() == null) {
return new BasicAWSCredentials(profile.getAwsAccessIdKey(), profile.getAwsSecretAccessKey());
} else {
if (profile.getAwsSessionToken().isEmpty()) {
throw new SdkClientException(
String.format("Unable to load credentials into profile [%s]: AWS Session Token is empty.",
profile.getProfileName()));
}

return new BasicSessionCredentials(profile.getAwsAccessIdKey(), profile.getAwsSecretAccessKey(),
profile.getAwsSessionToken());
}
}

private AWSCredentialsProvider credentialSourceCredentialProvider(CredentialSourceType credentialSource) {
switch (credentialSource) {
case ECS_CONTAINER:
return new ContainerCredentialsProvider();
case EC2_INSTANCE_METADATA:
return InstanceProfileCredentialsProvider.getInstance();
case ENVIRONMENT:
List<AWSCredentialsProvider> credProviders = new ArrayList<AWSCredentialsProvider>();
credProviders.add(new EnvironmentVariableCredentialsProvider());
credProviders.add(new SystemPropertiesCredentialsProvider());
return new AWSCredentialsProviderChain(credProviders);
default:
throw noSourceCredentialsException();
}
}

private IllegalStateException noSourceCredentialsException() {
String error = String.format("The source profile of '%s', but that source profile has no "
+ "credentials configured.", profile.getProfileName());
return new IllegalStateException(error);
}
}