Skip to content

Commit d9a4675

Browse files
committed
Adds accountId to STS credentials providers
1 parent 17a7da5 commit d9a4675

24 files changed

+451
-88
lines changed

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/AwsBasicCredentials.java

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@
1818
import static software.amazon.awssdk.utils.StringUtils.trimToNull;
1919

2020
import java.util.Objects;
21+
import java.util.Optional;
2122
import software.amazon.awssdk.annotations.Immutable;
2223
import software.amazon.awssdk.annotations.SdkInternalApi;
2324
import software.amazon.awssdk.annotations.SdkPublicApi;
2425
import software.amazon.awssdk.utils.ToString;
2526
import software.amazon.awssdk.utils.Validate;
2627

2728
/**
28-
* Provides access to the AWS credentials used for accessing services: AWS access key ID and secret access key. These
29-
* credentials are used to securely sign requests to services (e.g., AWS services) that use them for authentication.
29+
* Provides access to the AWS credentials used for accessing services: AWS access key ID and secret access key. These credentials
30+
* are used to securely sign requests to services (e.g., AWS services) that use them for authentication.
3031
*
3132
* <p>For more details on AWS access keys, see:
3233
* <a href="https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys">
@@ -39,43 +40,43 @@
3940
public final class AwsBasicCredentials implements AwsCredentials {
4041
/**
4142
* A set of AWS credentials without an access key or secret access key, indicating that anonymous access should be used.
42-
*
43+
* <p>
4344
* This should be accessed via {@link AnonymousCredentialsProvider#resolveCredentials()}.
4445
*/
4546
@SdkInternalApi
46-
static final AwsBasicCredentials ANONYMOUS_CREDENTIALS = new AwsBasicCredentials(null, null, false);
47+
static final AwsBasicCredentials ANONYMOUS_CREDENTIALS = builder().build();
4748

4849
private final String accessKeyId;
4950
private final String secretAccessKey;
5051

51-
/**
52-
* Constructs a new credentials object, with the specified AWS access key and AWS secret key.
53-
*
54-
* @param accessKeyId The AWS access key, used to identify the user interacting with AWS.
55-
* @param secretAccessKey The AWS secret access key, used to authenticate the user interacting with AWS.
56-
*/
57-
protected AwsBasicCredentials(String accessKeyId, String secretAccessKey) {
58-
this(accessKeyId, secretAccessKey, true);
59-
}
52+
private final String accountId;
6053

61-
private AwsBasicCredentials(String accessKeyId, String secretAccessKey, boolean validateCredentials) {
62-
this.accessKeyId = trimToNull(accessKeyId);
63-
this.secretAccessKey = trimToNull(secretAccessKey);
54+
private AwsBasicCredentials(Builder builder) {
55+
this.accessKeyId = trimToNull(builder.accessKeyId);
56+
this.secretAccessKey = trimToNull(builder.secretAccessKey);
6457

65-
if (validateCredentials) {
58+
if (builder.validateCredentials) {
6659
Validate.notNull(this.accessKeyId, "Access key ID cannot be blank.");
6760
Validate.notNull(this.secretAccessKey, "Secret access key cannot be blank.");
6861
}
62+
this.accountId = builder.accountId;
63+
}
64+
65+
public static Builder builder() {
66+
return new Builder();
6967
}
7068

7169
/**
7270
* Constructs a new credentials object, with the specified AWS access key and AWS secret key.
7371
*
74-
* @param accessKeyId The AWS access key, used to identify the user interacting with AWS.
72+
* @param accessKeyId The AWS access key, used to identify the user interacting with AWS.
7573
* @param secretAccessKey The AWS secret access key, used to authenticate the user interacting with AWS.
76-
* */
74+
*/
7775
public static AwsBasicCredentials create(String accessKeyId, String secretAccessKey) {
78-
return new AwsBasicCredentials(accessKeyId, secretAccessKey);
76+
return builder().accessKeyId(accessKeyId)
77+
.secretAccessKey(secretAccessKey)
78+
.validateCredentials(true)
79+
.build();
7980
}
8081

8182
/**
@@ -94,10 +95,16 @@ public String secretAccessKey() {
9495
return secretAccessKey;
9596
}
9697

98+
@Override
99+
public Optional<String> accountId() {
100+
return Optional.ofNullable(accountId);
101+
}
102+
97103
@Override
98104
public String toString() {
99105
return ToString.builder("AwsCredentials")
100106
.add("accessKeyId", accessKeyId)
107+
.add("accountId", accountId)
101108
.build();
102109
}
103110

@@ -111,14 +118,47 @@ public boolean equals(Object o) {
111118
}
112119
AwsBasicCredentials that = (AwsBasicCredentials) o;
113120
return Objects.equals(accessKeyId, that.accessKeyId) &&
114-
Objects.equals(secretAccessKey, that.secretAccessKey);
121+
Objects.equals(secretAccessKey, that.secretAccessKey) &&
122+
Objects.equals(accountId, that.accountId().orElse(null));
115123
}
116124

117125
@Override
118126
public int hashCode() {
119127
int hashCode = 1;
120128
hashCode = 31 * hashCode + Objects.hashCode(accessKeyId());
121129
hashCode = 31 * hashCode + Objects.hashCode(secretAccessKey());
130+
hashCode = 31 * hashCode + Objects.hashCode(accountId);
122131
return hashCode;
123132
}
133+
134+
public static final class Builder {
135+
private String accessKeyId;
136+
private String secretAccessKey;
137+
private String accountId;
138+
private boolean validateCredentials;
139+
140+
public Builder accessKeyId(String accessKeyId) {
141+
this.accessKeyId = accessKeyId;
142+
return this;
143+
}
144+
145+
public Builder secretAccessKey(String secretAccessKey) {
146+
this.secretAccessKey = secretAccessKey;
147+
return this;
148+
}
149+
150+
public Builder accountId(String accountId) {
151+
this.accountId = accountId;
152+
return this;
153+
}
154+
155+
public Builder validateCredentials(boolean validateCredentials) {
156+
this.validateCredentials = validateCredentials;
157+
return this;
158+
}
159+
160+
public AwsBasicCredentials build() {
161+
return new AwsBasicCredentials(this);
162+
}
163+
}
124164
}

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/AwsSessionCredentials.java

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.awssdk.auth.credentials;
1717

1818
import java.util.Objects;
19+
import java.util.Optional;
1920
import software.amazon.awssdk.annotations.Immutable;
2021
import software.amazon.awssdk.annotations.SdkPublicApi;
2122
import software.amazon.awssdk.identity.spi.AwsSessionCredentialsIdentity;
@@ -34,11 +35,17 @@ public final class AwsSessionCredentials implements AwsCredentials, AwsSessionCr
3435
private final String accessKeyId;
3536
private final String secretAccessKey;
3637
private final String sessionToken;
38+
private final String accountId;
3739

38-
private AwsSessionCredentials(String accessKey, String secretKey, String sessionToken) {
39-
this.accessKeyId = Validate.paramNotNull(accessKey, "accessKey");
40-
this.secretAccessKey = Validate.paramNotNull(secretKey, "secretKey");
41-
this.sessionToken = Validate.paramNotNull(sessionToken, "sessionToken");
40+
private AwsSessionCredentials(Builder builder) {
41+
this.accessKeyId = Validate.paramNotNull(builder.accessKeyId, "accessKey");
42+
this.secretAccessKey = Validate.paramNotNull(builder.secretAccessKey, "secretKey");
43+
this.sessionToken = Validate.paramNotNull(builder.sessionToken, "sessionToken");
44+
this.accountId = builder.accountId;
45+
}
46+
47+
public static Builder builder() {
48+
return new Builder();
4249
}
4350

4451
/**
@@ -50,7 +57,7 @@ private AwsSessionCredentials(String accessKey, String secretKey, String session
5057
* received temporary permission to access some resource.
5158
*/
5259
public static AwsSessionCredentials create(String accessKey, String secretKey, String sessionToken) {
53-
return new AwsSessionCredentials(accessKey, secretKey, sessionToken);
60+
return builder().accessKeyId(accessKey).secretAccessKey(secretKey).sessionToken(sessionToken).build();
5461
}
5562

5663
@Override
@@ -68,10 +75,16 @@ public String sessionToken() {
6875
return sessionToken;
6976
}
7077

78+
@Override
79+
public Optional<String> accountId() {
80+
return Optional.ofNullable(accountId);
81+
}
82+
7183
@Override
7284
public String toString() {
7385
return ToString.builder("AwsSessionCredentials")
7486
.add("accessKeyId", accessKeyId())
87+
.add("accountId", accountId)
7588
.build();
7689
}
7790

@@ -87,7 +100,8 @@ public boolean equals(Object o) {
87100
AwsSessionCredentials that = (AwsSessionCredentials) o;
88101
return Objects.equals(accessKeyId, that.accessKeyId) &&
89102
Objects.equals(secretAccessKey, that.secretAccessKey) &&
90-
Objects.equals(sessionToken, that.sessionToken);
103+
Objects.equals(sessionToken, that.sessionToken) &&
104+
Objects.equals(accountId, that.accountId().orElse(null));
91105
}
92106

93107
@Override
@@ -96,6 +110,38 @@ public int hashCode() {
96110
hashCode = 31 * hashCode + Objects.hashCode(accessKeyId());
97111
hashCode = 31 * hashCode + Objects.hashCode(secretAccessKey());
98112
hashCode = 31 * hashCode + Objects.hashCode(sessionToken());
113+
hashCode = 31 * hashCode + Objects.hashCode(accountId);
99114
return hashCode;
100115
}
116+
117+
public static final class Builder {
118+
private String accessKeyId;
119+
private String secretAccessKey;
120+
private String sessionToken;
121+
private String accountId;
122+
123+
public Builder accessKeyId(String accessKeyId) {
124+
this.accessKeyId = accessKeyId;
125+
return this;
126+
}
127+
128+
public Builder secretAccessKey(String secretAccessKey) {
129+
this.secretAccessKey = secretAccessKey;
130+
return this;
131+
}
132+
133+
public Builder sessionToken(String sessionToken) {
134+
this.sessionToken = sessionToken;
135+
return this;
136+
}
137+
138+
public Builder accountId(String accountId) {
139+
this.accountId = accountId;
140+
return this;
141+
}
142+
143+
public AwsSessionCredentials build() {
144+
return new AwsSessionCredentials(this);
145+
}
146+
}
101147
}

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/CredentialUtils.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,21 @@ public static AwsCredentials toCredentials(AwsCredentialsIdentity awsCredentials
7171
// identity-spi defines 2 known types - AwsCredentialsIdentity and a sub-type AwsSessionCredentialsIdentity
7272
if (awsCredentialsIdentity instanceof AwsSessionCredentialsIdentity) {
7373
AwsSessionCredentialsIdentity awsSessionCredentialsIdentity = (AwsSessionCredentialsIdentity) awsCredentialsIdentity;
74-
return AwsSessionCredentials.create(awsSessionCredentialsIdentity.accessKeyId(),
75-
awsSessionCredentialsIdentity.secretAccessKey(),
76-
awsSessionCredentialsIdentity.sessionToken());
74+
return AwsSessionCredentials.builder()
75+
.accessKeyId(awsSessionCredentialsIdentity.accessKeyId())
76+
.secretAccessKey(awsSessionCredentialsIdentity.secretAccessKey())
77+
.sessionToken(awsSessionCredentialsIdentity.sessionToken())
78+
.accountId(awsSessionCredentialsIdentity.accountId().orElse(null))
79+
.build();
7780
}
7881
if (isAnonymous(awsCredentialsIdentity)) {
7982
return AwsBasicCredentials.ANONYMOUS_CREDENTIALS;
8083
}
81-
return AwsBasicCredentials.create(awsCredentialsIdentity.accessKeyId(),
82-
awsCredentialsIdentity.secretAccessKey());
84+
return AwsBasicCredentials.builder()
85+
.accessKeyId(awsCredentialsIdentity.accessKeyId())
86+
.secretAccessKey(awsCredentialsIdentity.secretAccessKey())
87+
.accountId(awsCredentialsIdentity.accountId().orElse(null))
88+
.build();
8389
}
8490

8591
/**

core/auth/src/test/java/software/amazon/awssdk/auth/credentials/StaticCredentialsProviderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
public class StaticCredentialsProviderTest {
2323
@Test
2424
public void getAwsCredentials_ReturnsSameCredentials() throws Exception {
25-
final AwsCredentials credentials = new AwsBasicCredentials("akid", "skid");
25+
final AwsCredentials credentials = AwsBasicCredentials.create("akid", "skid");
2626
final AwsCredentials actualCredentials =
2727
StaticCredentialsProvider.create(credentials).resolveCredentials();
2828
assertEquals(credentials, actualCredentials);

core/auth/src/test/java/software/amazon/awssdk/auth/credentials/internal/AwsSessionCredentialsTest.java

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,74 @@
1616
package software.amazon.awssdk.auth.credentials.internal;
1717

1818

19-
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.junit.jupiter.api.Assertions.assertEquals;
20+
import static org.junit.jupiter.api.Assertions.assertFalse;
21+
import static org.junit.jupiter.api.Assertions.assertThrows;
22+
import static org.junit.jupiter.api.Assertions.assertTrue;
2023

24+
import nl.jqno.equalsverifier.EqualsVerifier;
2125
import org.junit.jupiter.api.Test;
22-
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
26+
import software.amazon.awssdk.identity.spi.AwsSessionCredentialsIdentity;
27+
import software.amazon.awssdk.identity.spi.internal.DefaultAwsSessionCredentialsIdentity;
2328

2429
public class AwsSessionCredentialsTest {
2530

31+
private static final String ACCESS_KEY_ID = "accessKeyId";
32+
private static final String SECRET_ACCESS_KEY = "secretAccessKey";
33+
private static final String SESSION_TOKEN = "sessionToken";
34+
private static final String ACCOUNT_ID = "accountId";
2635

2736
@Test
28-
public void equalsHashCode() {
29-
AwsSessionCredentials credentials =
30-
AwsSessionCredentials.create("test", "key", "sessionToken");
31-
32-
AwsSessionCredentials anotherCredentials =
33-
AwsSessionCredentials.create("test", "key", "sessionToken");
34-
assertThat(credentials).isEqualTo(anotherCredentials);
35-
assertThat(credentials.hashCode()).isEqualTo(anotherCredentials.hashCode());
37+
public void equalsHashcode() {
38+
EqualsVerifier.forClass(DefaultAwsSessionCredentialsIdentity.class)
39+
.verify();
40+
}
41+
42+
@Test
43+
public void emptyBuilder_ThrowsException() {
44+
assertThrows(NullPointerException.class, () -> AwsSessionCredentialsIdentity.builder().build());
45+
}
46+
47+
@Test
48+
public void builderMissingSessionToken_ThrowsException() {
49+
assertThrows(NullPointerException.class, () -> AwsSessionCredentialsIdentity.builder()
50+
.accessKeyId(ACCESS_KEY_ID)
51+
.secretAccessKey(SECRET_ACCESS_KEY)
52+
.build());
53+
}
54+
55+
@Test
56+
public void builderMissingAccessKeyId_ThrowsException() {
57+
assertThrows(NullPointerException.class, () -> AwsSessionCredentialsIdentity.builder()
58+
.secretAccessKey(SECRET_ACCESS_KEY)
59+
.sessionToken(SESSION_TOKEN)
60+
.build());
61+
}
62+
63+
@Test
64+
public void create_isSuccessful() {
65+
AwsSessionCredentialsIdentity identity = AwsSessionCredentialsIdentity.create(ACCESS_KEY_ID,
66+
SECRET_ACCESS_KEY,
67+
SESSION_TOKEN);
68+
assertEquals(ACCESS_KEY_ID, identity.accessKeyId());
69+
assertEquals(SECRET_ACCESS_KEY, identity.secretAccessKey());
70+
assertEquals(SESSION_TOKEN, identity.sessionToken());
71+
assertFalse(identity.accountId().isPresent());
72+
}
73+
74+
@Test
75+
public void build_isSuccessful() {
76+
AwsSessionCredentialsIdentity identity = AwsSessionCredentialsIdentity.builder()
77+
.accessKeyId(ACCESS_KEY_ID)
78+
.secretAccessKey(SECRET_ACCESS_KEY)
79+
.sessionToken(SESSION_TOKEN)
80+
.accountId(ACCOUNT_ID)
81+
.build();
82+
assertEquals(ACCESS_KEY_ID, identity.accessKeyId());
83+
assertEquals(SECRET_ACCESS_KEY, identity.secretAccessKey());
84+
assertEquals(SESSION_TOKEN, identity.sessionToken());
85+
assertTrue(identity.accountId().isPresent());
86+
assertEquals(ACCOUNT_ID, identity.accountId().get());
3687
}
3788

3889
}

core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/internal/DefaultAwsSessionCredentialsIdentity.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,10 @@ public final class DefaultAwsSessionCredentialsIdentity implements AwsSessionCre
3232

3333

3434
private DefaultAwsSessionCredentialsIdentity(Builder builder) {
35-
this.accessKeyId = builder.accessKeyId;
36-
this.secretAccessKey = builder.secretAccessKey;
37-
this.sessionToken = builder.sessionToken;
35+
this.accessKeyId = Validate.paramNotNull(builder.accessKeyId, "accessKeyId");
36+
this.secretAccessKey = Validate.paramNotNull(builder.secretAccessKey, "secretAccessKey");
37+
this.sessionToken = Validate.paramNotNull(builder.sessionToken, "sessionToken");
3838
this.accountId = builder.accountId;
39-
40-
Validate.paramNotNull(accessKeyId, "accessKeyId");
41-
Validate.paramNotNull(secretAccessKey, "secretAccessKey");
42-
Validate.paramNotNull(sessionToken, "sessionToken");
4339
}
4440

4541
public static AwsSessionCredentialsIdentity.Builder builder() {
@@ -86,7 +82,7 @@ public boolean equals(Object o) {
8682
return Objects.equals(accessKeyId, that.accessKeyId()) &&
8783
Objects.equals(secretAccessKey, that.secretAccessKey()) &&
8884
Objects.equals(sessionToken, that.sessionToken()) &&
89-
Objects.equals(accountId, that.accountId().orElse(null));
85+
Objects.equals(accountId, that.accountId().orElse(null));
9086
}
9187

9288
@Override

0 commit comments

Comments
 (0)