Skip to content

Commit 3b1f633

Browse files
authored
Cognito credentials provider (#531)
* Cognito credentials provider
1 parent a8dceec commit 3b1f633

11 files changed

Lines changed: 575 additions & 8 deletions

File tree

.builder/actions/crt-ci-prep.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import Builder
2+
import json
3+
import os
4+
import re
5+
import subprocess
6+
import sys
7+
8+
9+
class CrtCiPrep(Builder.Action):
10+
11+
def run(self, env):
12+
env.shell.setenv("AWS_TESTING_COGNITO_IDENTITY", env.shell.get_secret("aws-c-auth-testing/cognito-identity"))
13+
14+
actions = []
15+
16+
return Builder.Script(actions, name='crt-ci-prep')

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
- 'docs'
88

99
env:
10-
BUILDER_VERSION: v0.9.15
10+
BUILDER_VERSION: v0.9.18
1111
BUILDER_SOURCE: releases
1212
BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net
1313
PACKAGE_NAME: aws-crt-java

builder.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"mvn -P continuous-integration -B compile"
88
],
99
"test_steps": [
10-
"aws-crt-java-test"
10+
"crt-ci-prep",
11+
"aws-crt-java-test"
1112
],
1213
"+imports": [
1314
"JDK8"

src/main/java/software/amazon/awssdk/crt/auth/credentials/CachedCredentialsProvider.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
16
package software.amazon.awssdk.crt.auth.credentials;
27

38
/**
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
6+
package software.amazon.awssdk.crt.auth.credentials;
7+
8+
import java.lang.IllegalArgumentException;
9+
import java.nio.ByteBuffer;
10+
import java.nio.charset.Charset;
11+
import java.util.ArrayList;
12+
13+
import software.amazon.awssdk.crt.http.HttpHeader;
14+
import software.amazon.awssdk.crt.http.HttpProxyOptions;
15+
import software.amazon.awssdk.crt.io.ClientBootstrap;
16+
import software.amazon.awssdk.crt.io.TlsContext;
17+
18+
19+
/**
20+
* A class that wraps a credentials provider that sources session credentials from the AWS Cognito Identity service.
21+
*/
22+
public class CognitoCredentialsProvider extends CredentialsProvider {
23+
24+
private final static Charset UTF8 = java.nio.charset.StandardCharsets.UTF_8;
25+
private final static int BUFFER_INT_SIZE = 4;
26+
27+
/**
28+
* Pair of strings specifying an identity provider name and an associated login token.
29+
*/
30+
static public class CognitoLoginTokenPair {
31+
32+
public final byte[] identityProviderName;
33+
public final byte[] identityProviderToken;
34+
35+
public CognitoLoginTokenPair(String identityProviderName, String identityProviderToken) {
36+
this.identityProviderName = identityProviderName.getBytes(UTF8);
37+
this.identityProviderToken = identityProviderToken.getBytes(UTF8);
38+
}
39+
};
40+
41+
/**
42+
* A builder class for the Cognito provider and its options
43+
*/
44+
static public class CognitoCredentialsProviderBuilder {
45+
46+
private String endpoint;
47+
private String identity;
48+
private String customRoleArn;
49+
private ArrayList<CognitoLoginTokenPair> logins = new ArrayList<CognitoLoginTokenPair>();
50+
51+
private TlsContext tlsContext;
52+
private ClientBootstrap clientBootstrap;
53+
private HttpProxyOptions httpProxyOptions;
54+
55+
/**
56+
* Default constructor
57+
*/
58+
public CognitoCredentialsProviderBuilder() {}
59+
60+
/**
61+
* Sets the Cognito service endpoint to use when sourcing credentials via HTTP
62+
* @param endpoint cognito service endpoint to use
63+
* @return The current builder
64+
*/
65+
public CognitoCredentialsProviderBuilder withEndpoint(String endpoint) {
66+
this.endpoint = endpoint;
67+
return this;
68+
}
69+
70+
public String getEndpoint() { return endpoint; }
71+
72+
/**
73+
* Sets the Cognito identity to source credentials for
74+
* @param identity the cognito identity to source credentials for
75+
* @return The current builder
76+
*/
77+
public CognitoCredentialsProviderBuilder withIdentity(String identity) {
78+
this.identity = identity;
79+
return this;
80+
}
81+
82+
public String getIdentity() { return identity; }
83+
84+
/**
85+
* (optional) Sets the ARN of the role to be assumed when multiple roles were received in the token from the
86+
* identity provider.
87+
* @param customRoleArn ARN of the role to be assumed when multiple roles were received in the token from the
88+
* identity provider
89+
* @return The current builder
90+
*/
91+
public CognitoCredentialsProviderBuilder withCustomRoleArn(String customRoleArn) {
92+
this.customRoleArn = customRoleArn;
93+
return this;
94+
}
95+
96+
public String getCustomRoleArn() { return customRoleArn; }
97+
98+
/**
99+
* Adds an identity provider token pair to allow for authenticated identity access.
100+
* @param login identity provider token pair
101+
* @return The current builder
102+
*/
103+
public CognitoCredentialsProviderBuilder withLogin(CognitoLoginTokenPair login) {
104+
this.logins.add(login);
105+
return this;
106+
}
107+
108+
public ArrayList<CognitoLoginTokenPair> getLogins() { return logins; }
109+
110+
/**
111+
* (Optional) Sets the client bootstrap (host resolver and event loop group) to use when making the connections
112+
* required by this provider.
113+
* @param clientBootstrap client bootstrap to use
114+
* @return The current builder
115+
*/
116+
public CognitoCredentialsProviderBuilder withClientBootstrap(ClientBootstrap clientBootstrap) {
117+
this.clientBootstrap = clientBootstrap;
118+
119+
return this;
120+
}
121+
122+
ClientBootstrap getClientBootstrap() { return clientBootstrap; }
123+
124+
/**
125+
* Sets the tls context to use when making HTTP requests to the Cognito Identity service
126+
* @param tlsContext the tls context to use when making HTTP requests
127+
* @return The current builder
128+
*/
129+
public CognitoCredentialsProviderBuilder withTlsContext(TlsContext tlsContext) {
130+
this.tlsContext = tlsContext;
131+
132+
return this;
133+
}
134+
135+
TlsContext getTlsContext() { return tlsContext; }
136+
137+
/**
138+
* Sets the proxy configuration to use when making the http request that fetches session
139+
* credentials from the AWS Cognito Identity service
140+
* @param httpProxyOptions proxy configuration for the credentials fetching http request
141+
* @return The current builder
142+
*/
143+
public CognitoCredentialsProviderBuilder withHttpProxyOptions(HttpProxyOptions httpProxyOptions) {
144+
this.httpProxyOptions = httpProxyOptions;
145+
146+
return this;
147+
}
148+
149+
HttpProxyOptions getHttpProxyOptions() { return httpProxyOptions; }
150+
151+
152+
/**
153+
* Creates a new Cognito credentials provider, based on this builder's configuration
154+
* @return a new Cognito credentials provider
155+
*/
156+
public CognitoCredentialsProvider build() {
157+
return new CognitoCredentialsProvider(this);
158+
}
159+
}
160+
161+
private CognitoCredentialsProvider(CognitoCredentialsProviderBuilder builder) {
162+
super();
163+
164+
String endpoint = builder.getEndpoint();
165+
String identity = builder.getIdentity();
166+
if (endpoint == null || identity == null) {
167+
throw new IllegalArgumentException("CognitoCredentialsProvider - endpoint and identity must not be null");
168+
}
169+
170+
ClientBootstrap clientBootstrap = builder.getClientBootstrap();
171+
if (clientBootstrap == null) {
172+
clientBootstrap = ClientBootstrap.getOrCreateStaticDefault();
173+
}
174+
175+
TlsContext tlsContext = builder.getTlsContext();
176+
if (clientBootstrap == null || tlsContext == null) {
177+
throw new IllegalArgumentException("CognitoCredentialsProvider - clientBootstrap and tlsContext must not be null");
178+
}
179+
180+
int proxyConnectionType = 0;
181+
long proxyTlsContextHandle = 0;
182+
String proxyHost = null;
183+
int proxyPort = 0;
184+
int proxyAuthorizationType = 0;
185+
String proxyAuthorizationUsername = null;
186+
String proxyAuthorizationPassword = null;
187+
HttpProxyOptions proxyOptions = builder.getHttpProxyOptions();
188+
if (proxyOptions != null) {
189+
proxyConnectionType = proxyOptions.getConnectionType().getValue();
190+
TlsContext proxyTlsContext = proxyOptions.getTlsContext();
191+
if (proxyTlsContext != null) {
192+
proxyTlsContextHandle = proxyTlsContext.getNativeHandle();
193+
}
194+
195+
proxyHost = proxyOptions.getHost();
196+
proxyPort = proxyOptions.getPort();
197+
proxyAuthorizationType = proxyOptions.getAuthorizationType().getValue();
198+
proxyAuthorizationUsername = proxyOptions.getAuthorizationUsername();
199+
proxyAuthorizationPassword = proxyOptions.getAuthorizationPassword();
200+
}
201+
202+
long nativeHandle = cognitoCredentialsProviderNew(
203+
this,
204+
clientBootstrap.getNativeHandle(),
205+
tlsContext.getNativeHandle(),
206+
endpoint,
207+
identity,
208+
builder.getCustomRoleArn(),
209+
marshalLoginsForJni(builder.getLogins()),
210+
proxyConnectionType,
211+
proxyHost != null ? proxyHost.getBytes(UTF8) : null,
212+
proxyPort,
213+
proxyTlsContextHandle,
214+
proxyAuthorizationType,
215+
proxyAuthorizationUsername != null ? proxyAuthorizationUsername.getBytes(UTF8) : null,
216+
proxyAuthorizationPassword != null ? proxyAuthorizationPassword.getBytes(UTF8) : null);
217+
218+
acquireNativeHandle(nativeHandle);
219+
addReferenceTo(clientBootstrap);
220+
addReferenceTo(tlsContext);
221+
}
222+
223+
private void writeLengthPrefixedBytesSafe(ByteBuffer buffer, byte[] bytes) {
224+
if (bytes != null) {
225+
buffer.putInt(bytes.length);
226+
buffer.put(bytes);
227+
} else {
228+
buffer.putInt(0);
229+
}
230+
}
231+
232+
private byte[] marshalLoginsForJni(ArrayList<CognitoLoginTokenPair> logins) {
233+
int size = 0;
234+
235+
for (CognitoLoginTokenPair login : logins) {
236+
size += BUFFER_INT_SIZE * 2;
237+
if (login.identityProviderName != null) {
238+
size += login.identityProviderName.length;
239+
}
240+
241+
if (login.identityProviderToken != null) {
242+
size += login.identityProviderToken.length;
243+
}
244+
}
245+
246+
if (size == 0) {
247+
return null;
248+
}
249+
250+
ByteBuffer buffer = ByteBuffer.allocate(size);
251+
for (CognitoLoginTokenPair login : logins) {
252+
writeLengthPrefixedBytesSafe(buffer, login.identityProviderName);
253+
writeLengthPrefixedBytesSafe(buffer, login.identityProviderToken);
254+
}
255+
256+
return buffer.array();
257+
}
258+
259+
/*******************************************************************************
260+
* Native methods
261+
******************************************************************************/
262+
263+
private static native long cognitoCredentialsProviderNew(CognitoCredentialsProvider thisObj,
264+
long bootstrapHandle,
265+
long tlsContextHandle,
266+
String endpoint,
267+
String identity,
268+
String customRoleArn,
269+
byte[] marshalledLogins,
270+
int proxyConnectionType,
271+
byte[] proxyHost,
272+
int proxyPort,
273+
long proxyTlsContext,
274+
int proxyAuthorizationType,
275+
byte[] proxyAuthorizationUsername,
276+
byte[] proxyAuthorizationPassword);
277+
}

src/main/java/software/amazon/awssdk/crt/auth/credentials/DelegateCredentialsHandler.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
16
package software.amazon.awssdk.crt.auth.credentials;
27

38
/**

src/main/java/software/amazon/awssdk/crt/auth/credentials/DelegateCredentialsProvider.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
16
package software.amazon.awssdk.crt.auth.credentials;
27

38
/**

0 commit comments

Comments
 (0)