Skip to content

Commit

Permalink
Recording identity provider names in user agent string (#5047)
Browse files Browse the repository at this point in the history
* Adding source to identity (provider name) (#5008)

* Adding identity provider source to user agent string (#5029)

* Adds provider name to all SDK identity providers (#5040)
  • Loading branch information
cenedhryn committed Apr 2, 2024
1 parent 34f4743 commit d3e828a
Show file tree
Hide file tree
Showing 60 changed files with 1,267 additions and 266 deletions.
6 changes: 6 additions & 0 deletions .changes/next-release/feature-AWSSDKforJavav2-5ae2bad.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "feature",
"category": "AWS SDK for Java v2",
"contributor": "",
"description": "Records identity provider names in a resolved identity and adds this information to the user agent string"
}
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@
<Bug pattern="NP_BOOLEAN_RETURN_NULL"/>
</Match>

<Match>
<Class name="software.amazon.awssdk.auth.credentials.AwsSessionCredentials$Builder"/>
<Bug pattern="BAD_TO_BUILDER"/>
</Match>

<!-- New flags as of spotbogs 4.7.3.5 -->
<!-- TODO: Fix or explicitly exclude each occurrence -->
<Match>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
@SdkPublicApi
public final class AnonymousCredentialsProvider implements AwsCredentialsProvider {

private static final String PROVIDER_NAME = "AnonymousCredentialsProvider";

private AnonymousCredentialsProvider() {
}

Expand All @@ -34,11 +36,14 @@ public static AnonymousCredentialsProvider create() {

@Override
public AwsCredentials resolveCredentials() {
return AwsBasicCredentials.ANONYMOUS_CREDENTIALS;
return AwsBasicCredentials.builder()
.validateCredentials(false)
.providerName(PROVIDER_NAME)
.build();
}

@Override
public String toString() {
return ToString.create("AnonymousCredentialsProvider");
return ToString.create(PROVIDER_NAME);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@
import static software.amazon.awssdk.utils.StringUtils.trimToNull;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Immutable;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;

/**
* Provides access to the AWS credentials used for accessing services: AWS access key ID and secret access key. These
Expand All @@ -36,17 +40,31 @@
*/
@Immutable
@SdkPublicApi
public final class AwsBasicCredentials implements AwsCredentials {
public final class AwsBasicCredentials implements AwsCredentials,
ToCopyableBuilder<AwsBasicCredentials.Builder, AwsBasicCredentials> {
/**
* A set of AWS credentials without an access key or secret access key, indicating that anonymous access should be used.
*
* This should be accessed via {@link AnonymousCredentialsProvider#resolveCredentials()}.
*/
// TODO(sra-identity-and-auth): Check if this static member can be removed after cleanup
@SdkInternalApi
static final AwsBasicCredentials ANONYMOUS_CREDENTIALS = new AwsBasicCredentials(null, null, false);
static final AwsBasicCredentials ANONYMOUS_CREDENTIALS = builder().validateCredentials(false).build();

private final String accessKeyId;
private final String secretAccessKey;
private final boolean validateCredentials;
private final String providerName;

private AwsBasicCredentials(Builder builder) {
this.accessKeyId = trimToNull(builder.accessKeyId);
this.secretAccessKey = trimToNull(builder.secretAccessKey);
this.validateCredentials = builder.validateCredentials;
this.providerName = builder.providerName;

if (builder.validateCredentials) {
Validate.notNull(this.accessKeyId, "Access key ID cannot be blank.");
Validate.notNull(this.secretAccessKey, "Secret access key cannot be blank.");
}
}

/**
* Constructs a new credentials object, with the specified AWS access key and AWS secret key.
Expand All @@ -55,17 +73,14 @@ public final class AwsBasicCredentials implements AwsCredentials {
* @param secretAccessKey The AWS secret access key, used to authenticate the user interacting with AWS.
*/
protected AwsBasicCredentials(String accessKeyId, String secretAccessKey) {
this(accessKeyId, secretAccessKey, true);
}

private AwsBasicCredentials(String accessKeyId, String secretAccessKey, boolean validateCredentials) {
this.accessKeyId = trimToNull(accessKeyId);
this.secretAccessKey = trimToNull(secretAccessKey);
this.validateCredentials = false;
this.providerName = null;
}

if (validateCredentials) {
Validate.notNull(this.accessKeyId, "Access key ID cannot be blank.");
Validate.notNull(this.secretAccessKey, "Secret access key cannot be blank.");
}
public static Builder builder() {
return new Builder();
}

/**
Expand All @@ -75,7 +90,9 @@ private AwsBasicCredentials(String accessKeyId, String secretAccessKey, boolean
* @param secretAccessKey The AWS secret access key, used to authenticate the user interacting with AWS.
* */
public static AwsBasicCredentials create(String accessKeyId, String secretAccessKey) {
return new AwsBasicCredentials(accessKeyId, secretAccessKey);
return builder().accessKeyId(accessKeyId)
.secretAccessKey(secretAccessKey)
.build();
}

/**
Expand All @@ -94,10 +111,19 @@ public String secretAccessKey() {
return secretAccessKey;
}

/**
* The name of the identity provider that created this credential identity.
*/
@Override
public Optional<String> providerName() {
return Optional.ofNullable(providerName);
}

@Override
public String toString() {
return ToString.builder("AwsCredentials")
.add("accessKeyId", accessKeyId)
.add("providerName", providerName)
.build();
}

Expand All @@ -121,4 +147,69 @@ public int hashCode() {
hashCode = 31 * hashCode + Objects.hashCode(secretAccessKey());
return hashCode;
}

@Override
public Builder toBuilder() {
return builder().accessKeyId(accessKeyId)
.secretAccessKey(secretAccessKey)
.validateCredentials(validateCredentials)
.providerName(providerName);
}

@Override
public AwsBasicCredentials copy(Consumer<? super AwsBasicCredentials.Builder> modifier) {
return ToCopyableBuilder.super.copy(modifier);
}

/**
* A builder for creating an instance of {@link AwsBasicCredentials}. This can be created with the static
* {@link #builder()} method.
*/
public static final class Builder implements CopyableBuilder<AwsBasicCredentials.Builder, AwsBasicCredentials> {
private String accessKeyId;
private String secretAccessKey;
private String providerName;
private boolean validateCredentials = true;

private Builder() {
}

/**
* The AWS access key, used to identify the user interacting with services.
*/
public Builder accessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
return this;
}

/**
* The AWS secret access key, used to authenticate the user interacting with services.
*/
public Builder secretAccessKey(String secretAccessKey) {
this.secretAccessKey = secretAccessKey;
return this;
}

/**
* The name of the identity provider that created this credential identity.
*/
public Builder providerName(String providerName) {
this.providerName = providerName;
return this;
}

/**
* Whether this class should verify that accessKeyId and secretAccessKey are not null.
* Used internally by the SDK for legacy reasons.
*/
@SdkInternalApi
public Builder validateCredentials(Boolean validateCredentials) {
this.validateCredentials = validateCredentials;
return this;
}

public AwsBasicCredentials build() {
return new AwsBasicCredentials(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@
import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Immutable;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.identity.spi.AwsSessionCredentialsIdentity;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;

/**
* A special type of {@link AwsCredentials} that provides a session token to be used in service authentication. Session
Expand All @@ -31,19 +34,21 @@
*/
@Immutable
@SdkPublicApi
public final class AwsSessionCredentials implements AwsCredentials, AwsSessionCredentialsIdentity {

public final class AwsSessionCredentials implements AwsCredentials, AwsSessionCredentialsIdentity,
ToCopyableBuilder<AwsSessionCredentials.Builder, AwsSessionCredentials> {
private final String accessKeyId;
private final String secretAccessKey;
private final String sessionToken;

private final Instant expirationTime;
private final String providerName;

private AwsSessionCredentials(Builder builder) {
this.accessKeyId = Validate.paramNotNull(builder.accessKeyId, "accessKey");
this.secretAccessKey = Validate.paramNotNull(builder.secretAccessKey, "secretKey");
this.sessionToken = Validate.paramNotNull(builder.sessionToken, "sessionToken");
this.expirationTime = builder.expirationTime;
this.providerName = builder.providerName;
}

/**
Expand Down Expand Up @@ -93,14 +98,24 @@ public Optional<Instant> expirationTime() {
* Retrieve the AWS session token. This token is retrieved from an AWS token service, and is used for authenticating that this
* user has received temporary permission to access some resource.
*/
@Override
public String sessionToken() {
return sessionToken;
}

/**
* The name of the identity provider that created this credential identity.
*/
@Override
public Optional<String> providerName() {
return Optional.ofNullable(providerName);
}

@Override
public String toString() {
return ToString.builder("AwsSessionCredentials")
.add("accessKeyId", accessKeyId())
.add("providerName", providerName)
.build();
}

Expand Down Expand Up @@ -130,15 +145,30 @@ public int hashCode() {
return hashCode;
}

@Override
public Builder toBuilder() {
return builder().accessKeyId(accessKeyId)
.secretAccessKey(secretAccessKey)
.sessionToken(sessionToken)
.expirationTime(expirationTime)
.providerName(providerName);
}

@Override
public AwsSessionCredentials copy(Consumer<? super Builder> modifier) {
return ToCopyableBuilder.super.copy(modifier);
}

/**
* A builder for creating an instance of {@link AwsSessionCredentials}. This can be created with the static
* {@link #builder()} method.
*/
public static final class Builder {
public static final class Builder implements CopyableBuilder<AwsSessionCredentials.Builder, AwsSessionCredentials> {
private String accessKeyId;
private String secretAccessKey;
private String sessionToken;
private Instant expirationTime;
private String providerName;

/**
* The AWS access key, used to identify the user interacting with services. Required.
Expand Down Expand Up @@ -175,6 +205,14 @@ public Builder expirationTime(Instant expirationTime) {
return this;
}

/**
* The name of the identity provider that created this credential identity.
*/
public Builder providerName(String providerName) {
this.providerName = providerName;
return this;
}

public AwsSessionCredentials build() {
return new AwsSessionCredentials(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
public final class ContainerCredentialsProvider
implements HttpCredentialsProvider,
ToCopyableBuilder<ContainerCredentialsProvider.Builder, ContainerCredentialsProvider> {
private static final String PROVIDER_NAME = "ContainerCredentialsProvider";
private static final Predicate<InetAddress> IS_LOOPBACK_ADDRESS = InetAddress::isLoopbackAddress;
private static final Predicate<InetAddress> ALLOWED_HOSTS_RULES = IS_LOOPBACK_ADDRESS;
private static final String HTTPS = "https";
Expand All @@ -97,7 +98,7 @@ private ContainerCredentialsProvider(BuilderImpl builder) {
this.endpoint = builder.endpoint;
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
this.asyncThreadName = builder.asyncThreadName;
this.httpCredentialsLoader = HttpCredentialsLoader.create();
this.httpCredentialsLoader = HttpCredentialsLoader.create(PROVIDER_NAME);

if (Boolean.TRUE.equals(builder.asyncCredentialUpdateEnabled)) {
Validate.paramNotBlank(builder.asyncThreadName, "asyncThreadName");
Expand All @@ -121,7 +122,7 @@ public static Builder builder() {

@Override
public String toString() {
return ToString.create("ContainerCredentialsProvider");
return ToString.create(PROVIDER_NAME);
}

private RefreshResult<AwsCredentials> refreshCredentials() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
@SdkPublicApi
public final class EnvironmentVariableCredentialsProvider extends SystemSettingsCredentialsProvider {

private static final String PROVIDER_NAME = "EnvironmentVariableCredentialsProvider";

private EnvironmentVariableCredentialsProvider() {
}

Expand All @@ -43,8 +45,13 @@ protected Optional<String> loadSetting(SystemSetting setting) {
// CHECKSTYLE:ON
}

@Override
protected String provider() {
return PROVIDER_NAME;
}

@Override
public String toString() {
return ToString.create("EnvironmentVariableCredentialsProvider");
return ToString.create(PROVIDER_NAME);
}
}

0 comments on commit d3e828a

Please sign in to comment.