Skip to content

Commit

Permalink
Adds business metrics for credential providers
Browse files Browse the repository at this point in the history
  • Loading branch information
cenedhryn committed Jan 21, 2025
1 parent d8d52ae commit 73242f0
Show file tree
Hide file tree
Showing 41 changed files with 350 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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;
Expand Down Expand Up @@ -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";
Expand All @@ -90,6 +91,7 @@ public final class ContainerCredentialsProvider
private final Boolean asyncCredentialUpdateEnabled;

private final String asyncThreadName;
private final String source;

/**
* @see #builder()
Expand All @@ -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");
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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");
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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";
Expand All @@ -89,6 +90,7 @@ public final class InstanceProfileCredentialsProvider
private final Supplier<ProfileFile> profileFile;

private final String profileName;
private final String source;

/**
* @see #builder()
Expand All @@ -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)
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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");
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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;

Expand All @@ -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());
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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();
Expand All @@ -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()
Expand All @@ -284,6 +297,7 @@ private Builder(ProcessCredentialsProvider provider) {
this.credentialRefreshThreshold = provider.credentialRefreshThreshold;
this.processOutputLimit = provider.processOutputLimit;
this.staticAccountId = provider.staticAccountId;
this.source = provider.source;
}

/**
Expand Down Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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) {
Expand All @@ -78,6 +88,7 @@ public int hashCode() {
public static final class Builder {
private Profile profile;
private ProfileFile profileFile;
private String source;

private Builder() {
}
Expand All @@ -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.