Skip to content

Commit 4a2b49f

Browse files
lukeina2zlaurit
andauthored
feat: AWS SDK v2 Secrets Manager auto-instrumentation support (#14001)
Co-authored-by: Lauri Tulmin <[email protected]>
1 parent 70588cd commit 4a2b49f

File tree

7 files changed

+84
-5
lines changed

7 files changed

+84
-5
lines changed

instrumentation/aws-sdk/aws-sdk-2.2/javaagent/build.gradle.kts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,10 @@ dependencies {
121121
testLibrary("software.amazon.awssdk:lambda:2.2.0")
122122
testLibrary("software.amazon.awssdk:rds:2.2.0")
123123
testLibrary("software.amazon.awssdk:s3:2.2.0")
124-
testLibrary("software.amazon.awssdk:sqs:2.2.0")
125-
testLibrary("software.amazon.awssdk:sns:2.2.0")
126124
testLibrary("software.amazon.awssdk:ses:2.2.0")
125+
testLibrary("software.amazon.awssdk:secretsmanager:2.2.0")
126+
testLibrary("software.amazon.awssdk:sns:2.2.0")
127+
testLibrary("software.amazon.awssdk:sqs:2.2.0")
127128
}
128129

129130
val latestDepTest = findProperty("testLatestDeps") as Boolean

instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ dependencies {
1818
testLibrary("software.amazon.awssdk:lambda:2.2.0")
1919
testLibrary("software.amazon.awssdk:rds:2.2.0")
2020
testLibrary("software.amazon.awssdk:s3:2.2.0")
21-
testLibrary("software.amazon.awssdk:sqs:2.2.0")
21+
testLibrary("software.amazon.awssdk:secretsmanager:2.2.0")
2222
testLibrary("software.amazon.awssdk:sns:2.2.0")
23+
testLibrary("software.amazon.awssdk:sqs:2.2.0")
2324
}
2425

2526
tasks {

instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ dependencies {
2626
testLibrary("software.amazon.awssdk:kinesis:2.2.0")
2727
testLibrary("software.amazon.awssdk:rds:2.2.0")
2828
testLibrary("software.amazon.awssdk:s3:2.2.0")
29+
testLibrary("software.amazon.awssdk:secretsmanager:2.2.0")
2930
testLibrary("software.amazon.awssdk:ses:2.2.0")
3031
}
3132

instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkRequest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.AwsSdkRequestType.DYNAMODB;
1010
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.AwsSdkRequestType.KINESIS;
1111
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.AwsSdkRequestType.S3;
12+
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.AwsSdkRequestType.SECRETSMANAGER;
1213
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.AwsSdkRequestType.SNS;
1314
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.AwsSdkRequestType.SQS;
1415
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.FieldMapping.request;
@@ -35,6 +36,7 @@ enum AwsSdkRequest {
3536
SnsRequest(SNS, "SnsRequest"),
3637
SqsRequest(SQS, "SqsRequest"),
3738
KinesisRequest(KINESIS, "KinesisRequest"),
39+
SecretsManagerRequest(SECRETSMANAGER, "SecretsManagerRequest"),
3840
// specific requests
3941
BatchGetItem(
4042
DYNAMODB,

instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/AwsSdkRequestType.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
package io.opentelemetry.instrumentation.awssdk.v2_2.internal;
77

8+
import static io.opentelemetry.api.common.AttributeKey.stringKey;
89
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.FieldMapping.request;
10+
import static io.opentelemetry.instrumentation.awssdk.v2_2.internal.FieldMapping.response;
911

1012
import io.opentelemetry.api.common.AttributeKey;
1113
import java.util.Collections;
@@ -18,6 +20,7 @@ enum AwsSdkRequestType {
1820
KINESIS(request("aws.stream.name", "StreamName")),
1921
DYNAMODB(request("aws.table.name", "TableName")),
2022
BEDROCK_RUNTIME(),
23+
SECRETSMANAGER(response(AttributeKeys.AWS_SECRETSMANAGER_SECRET_ARN.getKey(), "ARN")),
2124
SNS(
2225
/*
2326
* Only one of TopicArn and TargetArn are permitted on an SNS request.
@@ -38,6 +41,10 @@ List<FieldMapping> fields(FieldMapping.Type type) {
3841
}
3942

4043
private static class AttributeKeys {
44+
// Copied from AwsIncubatingAttributes
45+
static final AttributeKey<String> AWS_SECRETSMANAGER_SECRET_ARN =
46+
stringKey("aws.secretsmanager.secret.arn");
47+
4148
// copied from MessagingIncubatingAttributes
4249
static final AttributeKey<String> MESSAGING_DESTINATION_NAME =
4350
AttributeKey.stringKey("messaging.destination.name");

instrumentation/aws-sdk/aws-sdk-2.2/testing/build.gradle.kts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ dependencies {
1818
compileOnly("software.amazon.awssdk:lambda:2.2.0")
1919
compileOnly("software.amazon.awssdk:rds:2.2.0")
2020
compileOnly("software.amazon.awssdk:s3:2.2.0")
21-
compileOnly("software.amazon.awssdk:sqs:2.2.0")
22-
compileOnly("software.amazon.awssdk:sns:2.2.0")
21+
compileOnly("software.amazon.awssdk:secretsmanager:2.2.0")
2322
compileOnly("software.amazon.awssdk:ses:2.2.0")
23+
compileOnly("software.amazon.awssdk:sns:2.2.0")
24+
compileOnly("software.amazon.awssdk:sqs:2.2.0")
2425

2526
// needed for SQS - using emq directly as localstack references emq v0.15.7 ie WITHOUT AWS trace header propagation
2627
implementation("org.elasticmq:elasticmq-rest-sqs_2.13")

instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2ClientTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
1515
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
1616
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_REQUEST_ID;
17+
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_SECRETSMANAGER_SECRET_ARN;
1718
import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME;
1819
import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_MESSAGE_ID;
1920
import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_OPERATION;
@@ -79,6 +80,12 @@
7980
import software.amazon.awssdk.services.s3.S3ClientBuilder;
8081
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
8182
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
83+
import software.amazon.awssdk.services.secretsmanager.SecretsManagerAsyncClient;
84+
import software.amazon.awssdk.services.secretsmanager.SecretsManagerAsyncClientBuilder;
85+
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
86+
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder;
87+
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
88+
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
8289
import software.amazon.awssdk.services.sns.SnsAsyncClient;
8390
import software.amazon.awssdk.services.sns.SnsAsyncClientBuilder;
8491
import software.amazon.awssdk.services.sns.SnsClient;
@@ -112,6 +119,18 @@ public abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest
112119
+ " <ResponseMetadata><RequestId>0ac9cda2-bbf4-11d3-f92b-31fa5e8dbc99</RequestId></ResponseMetadata>"
113120
+ "</DeleteOptionGroupResponse>";
114121

122+
private static final String secretsManagerBodyContent =
123+
"{"
124+
+ " \"ARN\": \"arn:aws:secretsmanager:us-east-1:123456789012:secret:MySecretFromCLI-sNkBwD\","
125+
+ " \"Name\": \"MySecretFromCLI\","
126+
+ " \"VersionId\": \"9959b95b-1234-5678-a19b-a4b0315ca5aa\","
127+
+ " \"SecretString\": \"super-secret-value\","
128+
+ " \"VersionStages\": ["
129+
+ " \"AWSCURRENT\""
130+
+ " ],"
131+
+ " \"CreatedDate\": \"1.523477145713E9\""
132+
+ "}";
133+
115134
private static void assumeSupportedConfig(String operation) {
116135
Assumptions.assumeFalse(
117136
operation.equals("SendMessage") && isSqsAttributeInjectionEnabled(),
@@ -214,6 +233,13 @@ private void clientAssertions(
214233
equalTo(MESSAGING_SYSTEM, AWS_SQS))));
215234
}
216235

236+
if (service.equals("SecretsManager")) {
237+
attributes.add(
238+
equalTo(
239+
AWS_SECRETSMANAGER_SECRET_ARN,
240+
"arn:aws:secretsmanager:us-east-1:123456789012:secret:MySecretFromCLI-sNkBwD"));
241+
}
242+
217243
String evaluatedOperation;
218244
SpanKind operationKind;
219245
if (operation.equals("SendMessage")) {
@@ -722,4 +748,44 @@ void testS3ListNullBucket() {
722748

723749
assertThat(Context.current()).isEqualTo(Context.root());
724750
}
751+
752+
@Test
753+
void testSecretsManagerSendOperationRequestWithBuilder() {
754+
SecretsManagerClientBuilder builder = SecretsManagerClient.builder();
755+
configureSdkClient(builder);
756+
SecretsManagerClient client =
757+
builder
758+
.endpointOverride(clientUri)
759+
.region(Region.AP_NORTHEAST_1)
760+
.credentialsProvider(CREDENTIALS_PROVIDER)
761+
.build();
762+
763+
server.enqueue(
764+
HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, secretsManagerBodyContent));
765+
Object response =
766+
client.getSecretValue(GetSecretValueRequest.builder().secretId("MySecretFromCLI").build());
767+
assertThat(response.getClass().getSimpleName())
768+
.satisfies(
769+
v -> assertThat(v).isEqualTo("GetSecretValueResponse"),
770+
v -> assertThat(response).isInstanceOf(GetSecretValueResponse.class));
771+
clientAssertions("SecretsManager", "GetSecretValue", "POST", response, "UNKNOWN");
772+
}
773+
774+
@Test
775+
void testSecretsManagerAsyncSendOperationRequestWithBuilder() {
776+
SecretsManagerAsyncClientBuilder builder = SecretsManagerAsyncClient.builder();
777+
configureSdkClient(builder);
778+
SecretsManagerAsyncClient client =
779+
builder
780+
.endpointOverride(clientUri)
781+
.region(Region.AP_NORTHEAST_1)
782+
.credentialsProvider(CREDENTIALS_PROVIDER)
783+
.build();
784+
785+
server.enqueue(
786+
HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, secretsManagerBodyContent));
787+
Object response =
788+
client.getSecretValue(GetSecretValueRequest.builder().secretId("MySecretFromCLI").build());
789+
clientAssertions("SecretsManager", "GetSecretValue", "POST", response, "UNKNOWN");
790+
}
725791
}

0 commit comments

Comments
 (0)