Skip to content

Commit

Permalink
Adds business metrics for credential providers
Browse files Browse the repository at this point in the history
cenedhryn committed Jan 21, 2025
1 parent d8d52ae commit 73242f0
Showing 41 changed files with 350 additions and 151 deletions.
Original file line number Diff line number Diff line change
@@ -38,7 +38,9 @@ public interface ChildProfileCredentialsProviderFactory {
* provider. This credentials provider should be closed when it is no longer used.
* @param profile The profile that should be used to load the configuration necessary to create the child credentials
* provider.
* @param source A string list of {@link software.amazon.awssdk.core.useragent.BusinessMetricFeatureId} denoting
* previous credentials providers that are chained with this one.
* @return The credentials provider with permissions derived from the source credentials provider and profile.
*/
AwsCredentialsProvider create(AwsCredentialsProvider sourceCredentialsProvider, Profile profile);
}
AwsCredentialsProvider create(AwsCredentialsProvider sourceCredentialsProvider, Profile profile, String source);
}
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@
import software.amazon.awssdk.auth.credentials.internal.HttpCredentialsLoader.LoadedCredentials;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
import software.amazon.awssdk.core.util.SdkUserAgent;
import software.amazon.awssdk.regions.util.ResourcesEndpointProvider;
import software.amazon.awssdk.regions.util.ResourcesEndpointRetryPolicy;
@@ -72,7 +73,7 @@
public final class ContainerCredentialsProvider
implements HttpCredentialsProvider,
ToCopyableBuilder<ContainerCredentialsProvider.Builder, ContainerCredentialsProvider> {
private static final String PROVIDER_NAME = "ContainerCredentialsProvider";
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_HTTP.value();
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";
@@ -90,6 +91,7 @@ public final class ContainerCredentialsProvider
private final Boolean asyncCredentialUpdateEnabled;

private final String asyncThreadName;
private final String source;

/**
* @see #builder()
@@ -98,7 +100,8 @@ private ContainerCredentialsProvider(BuilderImpl builder) {
this.endpoint = builder.endpoint;
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
this.asyncThreadName = builder.asyncThreadName;
this.httpCredentialsLoader = HttpCredentialsLoader.create(PROVIDER_NAME);
this.source = builder.source;
this.httpCredentialsLoader = HttpCredentialsLoader.create(providerName());

if (Boolean.TRUE.equals(builder.asyncCredentialUpdateEnabled)) {
Validate.paramNotBlank(builder.asyncThreadName, "asyncThreadName");
@@ -160,6 +163,14 @@ private Instant prefetchTime(Instant expiration) {
return ComparableUtils.minimum(oneHourFromNow, fifteenMinutesBeforeExpiration);
}

private String providerName() {
String providerName = PROVIDER_NAME;
if (source != null && !source.isEmpty()) {
providerName = String.format("%s,%s", source, providerName);
}
return providerName;
}

@Override
public AwsCredentials resolveCredentials() {
return credentialsCache.get();
@@ -318,6 +329,7 @@ private static final class BuilderImpl implements Builder {
private String endpoint;
private Boolean asyncCredentialUpdateEnabled;
private String asyncThreadName;
private String source;

private BuilderImpl() {
asyncThreadName("container-credentials-provider");
@@ -327,6 +339,7 @@ private BuilderImpl(ContainerCredentialsProvider credentialsProvider) {
this.endpoint = credentialsProvider.endpoint;
this.asyncCredentialUpdateEnabled = credentialsProvider.asyncCredentialUpdateEnabled;
this.asyncThreadName = credentialsProvider.asyncThreadName;
this.source = credentialsProvider.source;
}

@Override
@@ -359,6 +372,17 @@ public void setAsyncThreadName(String asyncThreadName) {
asyncThreadName(asyncThreadName);
}

@Override
public Builder source(String source) {
this.source = source;
return this;
}

public void setSource(String source) {
source(source);
}


@Override
public ContainerCredentialsProvider build() {
return new ContainerCredentialsProvider(this);
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
import java.util.Optional;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.auth.credentials.internal.SystemSettingsCredentialsProvider;
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
import software.amazon.awssdk.utils.SystemSetting;
import software.amazon.awssdk.utils.ToString;

@@ -28,7 +29,7 @@
@SdkPublicApi
public final class EnvironmentVariableCredentialsProvider extends SystemSettingsCredentialsProvider {

private static final String PROVIDER_NAME = "EnvironmentVariableCredentialsProvider";
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_ENV_VARS.value();

private EnvironmentVariableCredentialsProvider() {
}
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
package software.amazon.awssdk.auth.credentials;

import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
import software.amazon.awssdk.utils.SdkAutoCloseable;

/**
@@ -48,6 +49,14 @@ interface Builder<TypeToBuildT extends HttpCredentialsProvider, BuilderT extends
*/
BuilderT endpoint(String endpoint);

/**
* An optional string list of {@link BusinessMetricFeatureId} denoting previous credentials providers
* that are chained with this one.
*/
default BuilderT source(String source) {
throw new UnsupportedOperationException();
}

/**
* Build the credentials provider based on the configuration on this builder.
*/
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.exception.SdkServiceException;
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
import software.amazon.awssdk.profiles.ProfileFile;
import software.amazon.awssdk.profiles.ProfileFileSupplier;
import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
@@ -68,7 +69,7 @@ public final class InstanceProfileCredentialsProvider
implements HttpCredentialsProvider,
ToCopyableBuilder<InstanceProfileCredentialsProvider.Builder, InstanceProfileCredentialsProvider> {
private static final Logger log = Logger.loggerFor(InstanceProfileCredentialsProvider.class);
private static final String PROVIDER_NAME = "InstanceProfileCredentialsProvider";
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_IMDS.value();
private static final String EC2_METADATA_TOKEN_HEADER = "x-aws-ec2-metadata-token";
private static final String SECURITY_CREDENTIALS_RESOURCE = "/latest/meta-data/iam/security-credentials/";
private static final String TOKEN_RESOURCE = "/latest/api/token";
@@ -89,6 +90,7 @@ public final class InstanceProfileCredentialsProvider
private final Supplier<ProfileFile> profileFile;

private final String profileName;
private final String source;

/**
* @see #builder()
@@ -102,8 +104,9 @@ private InstanceProfileCredentialsProvider(BuilderImpl builder) {
.orElseGet(() -> ProfileFileSupplier.fixedProfileFile(ProfileFile.defaultProfileFile()));
this.profileName = Optional.ofNullable(builder.profileName)
.orElseGet(ProfileFileSystemSetting.AWS_PROFILE::getStringValueOrThrow);
this.source = builder.source;

this.httpCredentialsLoader = HttpCredentialsLoader.create(PROVIDER_NAME);
this.httpCredentialsLoader = HttpCredentialsLoader.create(providerName());
this.configProvider =
Ec2MetadataConfigProvider.builder()
.profileFile(profileFile)
@@ -196,6 +199,14 @@ private Instant prefetchTime(Instant expiration) {
return now.plus(maximum(timeUntilExpiration.dividedBy(2), Duration.ofMinutes(5)));
}

private String providerName() {
String providerName = PROVIDER_NAME;
if (source != null && !source.isEmpty()) {
providerName = String.format("%s,%s", source, providerName);
}
return providerName;
}

@Override
public void close() {
credentialsCache.close();
@@ -346,6 +357,7 @@ static final class BuilderImpl implements Builder {
private String asyncThreadName;
private Supplier<ProfileFile> profileFile;
private String profileName;
private String source;

private BuilderImpl() {
asyncThreadName("instance-profile-credentials-provider");
@@ -358,6 +370,7 @@ private BuilderImpl(InstanceProfileCredentialsProvider provider) {
this.asyncThreadName = provider.asyncThreadName;
this.profileFile = provider.profileFile;
this.profileName = provider.profileName;
this.source = provider.source;
}

Builder clock(Clock clock) {
@@ -426,6 +439,16 @@ public void setProfileName(String profileName) {
profileName(profileName);
}

@Override
public Builder source(String source) {
this.source = source;
return this;
}

public void setSource(String source) {
source(source);
}

@Override
public InstanceProfileCredentialsProvider build() {
return new InstanceProfileCredentialsProvider(this);
Original file line number Diff line number Diff line change
@@ -25,12 +25,14 @@
import java.util.Collections;
import java.util.List;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
import software.amazon.awssdk.protocols.jsoncore.JsonNode;
import software.amazon.awssdk.protocols.jsoncore.JsonNodeParser;
import software.amazon.awssdk.utils.DateUtils;
import software.amazon.awssdk.utils.IoUtils;
import software.amazon.awssdk.utils.Platform;
import software.amazon.awssdk.utils.SdkAutoCloseable;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.awssdk.utils.ToString;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.builder.CopyableBuilder;
@@ -64,7 +66,7 @@ public final class ProcessCredentialsProvider
implements AwsCredentialsProvider,
SdkAutoCloseable,
ToCopyableBuilder<ProcessCredentialsProvider.Builder, ProcessCredentialsProvider> {
private static final String PROVIDER_NAME = "ProcessCredentialsProvider";
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_PROCESS.value();
private static final JsonNodeParser PARSER = JsonNodeParser.builder()
.removeErrorLocations(true)
.build();
@@ -73,6 +75,7 @@ public final class ProcessCredentialsProvider
private final Duration credentialRefreshThreshold;
private final long processOutputLimit;
private final String staticAccountId;
private final String source;

private final CachedSupplier<AwsCredentials> processCredentialCache;

@@ -93,6 +96,7 @@ private ProcessCredentialsProvider(Builder builder) {
this.commandAsListOfStringsFromBuilder = builder.commandAsListOfStrings;
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
this.staticAccountId = builder.staticAccountId;
this.source = builder.source;

CachedSupplier.Builder<AwsCredentials> cacheBuilder = CachedSupplier.builder(this::refreshCredentials)
.cachedValueName(toString());
@@ -192,13 +196,13 @@ private AwsCredentials credentials(JsonNode credentialsJson) {
.sessionToken(sessionToken)
.expirationTime(credentialExpirationTime(credentialsJson))
.accountId(resolvedAccountId)
.providerName(PROVIDER_NAME)
.providerName(providerName())
.build() :
AwsBasicCredentials.builder()
.accessKeyId(accessKeyId)
.secretAccessKey(secretAccessKey)
.accountId(resolvedAccountId)
.providerName(PROVIDER_NAME)
.providerName(providerName())
.build();
}

@@ -250,6 +254,14 @@ private String executeCommand() throws IOException, InterruptedException {
}
}

private String providerName() {
String providerName = PROVIDER_NAME;
if (!StringUtils.isEmpty(this.source)) {
providerName = String.format("%s,%s", this.source, providerName);
}
return providerName;
}

@Override
public void close() {
processCredentialCache.close();
@@ -270,6 +282,7 @@ public static class Builder implements CopyableBuilder<Builder, ProcessCredentia
private Duration credentialRefreshThreshold = Duration.ofSeconds(15);
private long processOutputLimit = 64000;
private String staticAccountId;
private String source;

/**
* @see #builder()
@@ -284,6 +297,7 @@ private Builder(ProcessCredentialsProvider provider) {
this.credentialRefreshThreshold = provider.credentialRefreshThreshold;
this.processOutputLimit = provider.processOutputLimit;
this.staticAccountId = provider.staticAccountId;
this.source = provider.source;
}

/**
@@ -357,6 +371,15 @@ public Builder staticAccountId(String staticAccountId) {
return this;
}

/**
* An optional string list of {@link BusinessMetricFeatureId} denoting previous credentials providers
* that are chained with this one.
*/
public Builder source(String source) {
this.source = source;
return this;
}

public ProcessCredentialsProvider build() {
return new ProcessCredentialsProvider(this);
}
Original file line number Diff line number Diff line change
@@ -29,10 +29,12 @@ public final class ProfileProviderCredentialsContext {

private final Profile profile;
private final ProfileFile profileFile;
private final String source;

private ProfileProviderCredentialsContext(Profile profile, ProfileFile profileFile) {
this.profile = profile;
this.profileFile = profileFile;
private ProfileProviderCredentialsContext(Builder builder) {
this.profile = builder.profile;
this.profileFile = builder.profileFile;
this.source = builder.source;
}

public static Builder builder() {
@@ -55,6 +57,14 @@ public ProfileFile profileFile() {
return profileFile;
}

/**
* An optional string list of {@link software.amazon.awssdk.core.useragent.BusinessMetricFeatureId} denoting previous
* credentials providers that are chained with this one.
*/
public String source() {
return source;
}

@Override
public boolean equals(Object o) {
if (this == o) {
@@ -78,6 +88,7 @@ public int hashCode() {
public static final class Builder {
private Profile profile;
private ProfileFile profileFile;
private String source;

private Builder() {
}
@@ -103,8 +114,19 @@ public Builder profileFile(ProfileFile profileFile) {
return this;
}

/**
* Builder interface to set source.
* @param source An optional string list of {@link software.amazon.awssdk.core.useragent.BusinessMetricFeatureId}
* denoting previous credentials providers that are chained with this one.
* @return Returns a reference to this object so that method calls can be chained together.
*/
public Builder source(String source) {
this.source = source;
return this;
}

public ProfileProviderCredentialsContext build() {
return new ProfileProviderCredentialsContext(profile, profileFile);
return new ProfileProviderCredentialsContext(this);
}
}
}
Loading

0 comments on commit 73242f0

Please sign in to comment.