Skip to content

Commit 55d4527

Browse files
authored
Merge pull request #3164 from aws/cherry-pick-pr
Add IAM Token Generation Utility for AxdbFrontend
2 parents ff7139a + 26b746a commit 55d4527

File tree

8 files changed

+890
-0
lines changed

8 files changed

+890
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "AxdbFrontend",
4+
"contributor": "APandher",
5+
"description": "Add IAM Token Generation Utility for AxdbFrontend"
6+
}

services/axdbfrontend/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
</plugins>
4242
</build>
4343
<dependencies>
44+
<dependency>
45+
<groupId>nl.jqno.equalsverifier</groupId>
46+
<artifactId>equalsverifier</artifactId>
47+
<scope>test</scope>
48+
</dependency>
4449
<dependency>
4550
<groupId>software.amazon.awssdk</groupId>
4651
<artifactId>protocol-core</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.axdbfrontend;
17+
18+
import java.util.function.Consumer;
19+
import software.amazon.awssdk.annotations.SdkPublicApi;
20+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
21+
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
22+
import software.amazon.awssdk.identity.spi.IdentityProvider;
23+
import software.amazon.awssdk.regions.Region;
24+
import software.amazon.awssdk.services.axdbfrontend.internal.DefaultAxdbFrontendUtilities;
25+
import software.amazon.awssdk.services.axdbfrontend.model.GenerateAuthenticationTokenRequest;
26+
27+
/**
28+
* Utilities for working with AxdbFrontend. An instance of this class can be created by:
29+
* <p>
30+
* 1) Using the low-level client {@link AxdbFrontendClient#utilities()} (or {@link AxdbFrontendAsyncClient#utilities()}} method.
31+
* This is recommended as SDK will use the same configuration from the {@link AxdbFrontendClient} object to create the
32+
* {@link AxdbFrontendUtilities} object.
33+
*
34+
* @snippet :
35+
* {@code
36+
* AxdbFrontendClient AxdbFrontendClient = AxdbFrontendClient.create();
37+
* AxdbFrontendUtilities utilities = AxdbFrontendClient.utilities();
38+
* }
39+
*
40+
* <p>
41+
* 2) Directly using the {@link #builder()} method.
42+
*
43+
* @snippet :
44+
* {@code
45+
* AxdbFrontendUtilities utilities = AxdbFrontendUtilities.builder()
46+
* .credentialsProvider(DefaultCredentialsProvider.create())
47+
* .region(Region.US_WEST_2)
48+
* .build()
49+
* }
50+
*
51+
* Note: This class does not make network calls.
52+
*/
53+
@SdkPublicApi
54+
public interface AxdbFrontendUtilities {
55+
/**
56+
* Create a builder that can be used to configure and create a {@link AxdbFrontendUtilities}.
57+
*/
58+
static Builder builder() {
59+
return new DefaultAxdbFrontendUtilities.DefaultBuilder();
60+
}
61+
62+
/**
63+
* Generates an authentication token for IAM authentication to an AxdbFrontend database.
64+
*
65+
* @param request The request used to generate the authentication token
66+
* @return String to use as the AxdbFrontend authentication token
67+
* @throws IllegalArgumentException if the required parameters are not valid
68+
*/
69+
default String generateAuthenticationToken(Consumer<GenerateAuthenticationTokenRequest.Builder> request) {
70+
return generateAuthenticationToken(GenerateAuthenticationTokenRequest.builder().applyMutation(request).build());
71+
}
72+
73+
/**
74+
* Generates an authentication token for IAM authentication to an AxdbFrontend database.
75+
*
76+
* @param request The request used to generate the authentication token
77+
* @return String to use as the AxdbFrontend authentication token
78+
* @throws IllegalArgumentException if the required parameters are not valid
79+
*/
80+
default String generateAuthenticationToken(GenerateAuthenticationTokenRequest request) {
81+
throw new UnsupportedOperationException();
82+
}
83+
84+
/**
85+
* Builder for creating an instance of {@link AxdbFrontendUtilities}. It can be configured using
86+
* {@link AxdbFrontendUtilities#builder()}.
87+
* Once configured, the {@link AxdbFrontendUtilities} can created using {@link #build()}.
88+
*/
89+
@SdkPublicApi
90+
interface Builder {
91+
/**
92+
* The default region to use when working with the methods in {@link AxdbFrontendUtilities} class.
93+
*
94+
* @return This object for method chaining
95+
*/
96+
Builder region(Region region);
97+
98+
/**
99+
* The default credentials provider to use when working with the methods in {@link AxdbFrontendUtilities} class.
100+
*
101+
* @return This object for method chaining
102+
*/
103+
default Builder credentialsProvider(AwsCredentialsProvider credentialsProvider) {
104+
return credentialsProvider((IdentityProvider<? extends AwsCredentialsIdentity>) credentialsProvider);
105+
}
106+
107+
/**
108+
* The default credentials provider to use when working with the methods in {@link AxdbFrontendUtilities} class.
109+
*
110+
* @return This object for method chaining
111+
*/
112+
default Builder credentialsProvider(IdentityProvider<? extends AwsCredentialsIdentity> credentialsProvider) {
113+
throw new UnsupportedOperationException();
114+
}
115+
116+
/**
117+
* Create a {@link AxdbFrontendUtilities}
118+
*/
119+
AxdbFrontendUtilities build();
120+
}
121+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.axdbfrontend.internal;
17+
18+
import java.time.Clock;
19+
import java.time.Instant;
20+
import software.amazon.awssdk.annotations.Immutable;
21+
import software.amazon.awssdk.annotations.SdkInternalApi;
22+
import software.amazon.awssdk.auth.credentials.AwsCredentials;
23+
import software.amazon.awssdk.auth.credentials.CredentialUtils;
24+
import software.amazon.awssdk.auth.signer.Aws4Signer;
25+
import software.amazon.awssdk.auth.signer.params.Aws4PresignerParams;
26+
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
27+
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
28+
import software.amazon.awssdk.http.SdkHttpFullRequest;
29+
import software.amazon.awssdk.http.SdkHttpMethod;
30+
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
31+
import software.amazon.awssdk.identity.spi.IdentityProvider;
32+
import software.amazon.awssdk.regions.Region;
33+
import software.amazon.awssdk.services.axdbfrontend.AxdbFrontendUtilities;
34+
import software.amazon.awssdk.services.axdbfrontend.model.GenerateAuthenticationTokenRequest;
35+
import software.amazon.awssdk.utils.CompletableFutureUtils;
36+
import software.amazon.awssdk.utils.Logger;
37+
import software.amazon.awssdk.utils.StringUtils;
38+
39+
@Immutable
40+
@SdkInternalApi
41+
public final class DefaultAxdbFrontendUtilities implements AxdbFrontendUtilities {
42+
private static final Logger log = Logger.loggerFor(AxdbFrontendUtilities.class);
43+
private final Aws4Signer signer = Aws4Signer.create();
44+
private final Region region;
45+
private final IdentityProvider<? extends AwsCredentialsIdentity> credentialsProvider;
46+
private final Clock clock;
47+
48+
public DefaultAxdbFrontendUtilities(DefaultBuilder builder) {
49+
this(builder, Clock.systemUTC());
50+
}
51+
52+
/**
53+
* For testing purposes only
54+
*/
55+
public DefaultAxdbFrontendUtilities(DefaultBuilder builder, Clock clock) {
56+
this.credentialsProvider = builder.credentialsProvider;
57+
this.region = builder.region;
58+
this.clock = clock;
59+
}
60+
61+
/**
62+
* Used by AxdbFrontend low-level client's utilities() method
63+
*/
64+
@SdkInternalApi
65+
static AxdbFrontendUtilities create(SdkClientConfiguration clientConfiguration) {
66+
return new DefaultBuilder().clientConfiguration(clientConfiguration).build();
67+
}
68+
69+
@Override
70+
public String generateAuthenticationToken(GenerateAuthenticationTokenRequest request) {
71+
SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder()
72+
.method(SdkHttpMethod.GET)
73+
.protocol("https")
74+
.host(request.hostname())
75+
.encodedPath("/")
76+
.putRawQueryParameter("Action", request.action().getAction())
77+
.build();
78+
79+
Instant expirationTime = Instant.now(clock).plus(request.expiresIn());
80+
81+
Aws4PresignerParams presignRequest = Aws4PresignerParams.builder()
82+
.signingClockOverride(clock)
83+
.expirationTime(expirationTime)
84+
.awsCredentials(resolveCredentials(request))
85+
.signingName("xanadu")
86+
.signingRegion(resolveRegion(request))
87+
.build();
88+
89+
SdkHttpFullRequest fullRequest = signer.presign(httpRequest, presignRequest);
90+
String signedUrl = fullRequest.getUri().toString();
91+
92+
String result = StringUtils.replacePrefixIgnoreCase(signedUrl, "https://", "");
93+
return result;
94+
}
95+
96+
private Region resolveRegion(GenerateAuthenticationTokenRequest request) {
97+
if (request.region() != null) {
98+
return request.region();
99+
}
100+
101+
if (this.region != null) {
102+
return this.region;
103+
}
104+
105+
throw new IllegalArgumentException("Region should be provided either in GenerateAuthenticationTokenRequest object " +
106+
"or AxdbFrontendUtilities object");
107+
}
108+
109+
// TODO: update this to use AwsCredentialsIdentity when we migrate Signers to accept the new type.
110+
private AwsCredentials resolveCredentials(GenerateAuthenticationTokenRequest request) {
111+
if (request.credentialsIdentityProvider() != null) {
112+
return CredentialUtils.toCredentials(
113+
CompletableFutureUtils.joinLikeSync(request.credentialsIdentityProvider().resolveIdentity()));
114+
}
115+
116+
if (this.credentialsProvider != null) {
117+
return CredentialUtils.toCredentials(CompletableFutureUtils.joinLikeSync(this.credentialsProvider.resolveIdentity()));
118+
}
119+
120+
throw new IllegalArgumentException("CredentialProvider should be provided either in GenerateAuthenticationTokenRequest " +
121+
"object or AxdbFrontendUtilities object");
122+
}
123+
124+
@SdkInternalApi
125+
public static final class DefaultBuilder implements Builder {
126+
private Region region;
127+
private IdentityProvider<? extends AwsCredentialsIdentity> credentialsProvider;
128+
129+
public DefaultBuilder() {
130+
}
131+
132+
Builder clientConfiguration(SdkClientConfiguration clientConfiguration) {
133+
this.credentialsProvider = clientConfiguration.option(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER);
134+
this.region = clientConfiguration.option(AwsClientOption.AWS_REGION);
135+
136+
return this;
137+
}
138+
139+
@Override
140+
public Builder region(Region region) {
141+
this.region = region;
142+
return this;
143+
}
144+
145+
@Override
146+
public Builder credentialsProvider(IdentityProvider<? extends AwsCredentialsIdentity> credentialsProvider) {
147+
this.credentialsProvider = credentialsProvider;
148+
return this;
149+
}
150+
151+
/**
152+
* Construct a {@link AxdbFrontendUtilities} object.
153+
*/
154+
@Override
155+
public AxdbFrontendUtilities build() {
156+
return new DefaultAxdbFrontendUtilities(this);
157+
}
158+
}
159+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.axdbfrontend.model;
17+
18+
import java.io.Serializable;
19+
import software.amazon.awssdk.annotations.SdkPublicApi;
20+
21+
/**
22+
* Enumerations of possible actions that can be performed on an AxdbFrontend database.
23+
*/
24+
@SdkPublicApi
25+
public enum Action implements Serializable {
26+
/**
27+
* The action of connecting to an AxdbFrontend database using DbConnect
28+
*/
29+
DB_CONNECT("DbConnect"),
30+
/**
31+
* The action of connecting to an AxdbFrontend database using DbConnectSuperuser
32+
*/
33+
DB_CONNECT_SUPERUSER("DbConnectSuperuser");
34+
35+
private final String action;
36+
37+
Action(String action) {
38+
this.action = action;
39+
}
40+
41+
public String getAction() {
42+
return action;
43+
}
44+
45+
public static Action fromValue(String value) {
46+
for (Action action : Action.values()) {
47+
if (value.equalsIgnoreCase(action.name())) {
48+
return action;
49+
}
50+
}
51+
throw new IllegalArgumentException("Invalid action: " + value);
52+
}
53+
}

0 commit comments

Comments
 (0)