• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CognitoLoginTokenPair(String identityProviderName, String identityProviderToken)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          */
CognitoCredentialsProviderBuilder()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          */
withEndpoint(String endpoint)65         public CognitoCredentialsProviderBuilder withEndpoint(String endpoint) {
66             this.endpoint = endpoint;
67             return this;
68         }
69 
getEndpoint()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          */
withIdentity(String identity)77         public CognitoCredentialsProviderBuilder withIdentity(String identity) {
78             this.identity = identity;
79             return this;
80         }
81 
getIdentity()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          */
withCustomRoleArn(String customRoleArn)91         public CognitoCredentialsProviderBuilder withCustomRoleArn(String customRoleArn) {
92             this.customRoleArn = customRoleArn;
93             return this;
94         }
95 
getCustomRoleArn()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          */
withLogin(CognitoLoginTokenPair login)103         public CognitoCredentialsProviderBuilder withLogin(CognitoLoginTokenPair login) {
104             this.logins.add(login);
105             return this;
106         }
107 
getLogins()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          */
withClientBootstrap(ClientBootstrap clientBootstrap)116         public CognitoCredentialsProviderBuilder withClientBootstrap(ClientBootstrap clientBootstrap) {
117             this.clientBootstrap = clientBootstrap;
118 
119             return this;
120         }
121 
getClientBootstrap()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          */
withTlsContext(TlsContext tlsContext)129         public CognitoCredentialsProviderBuilder withTlsContext(TlsContext tlsContext) {
130             this.tlsContext = tlsContext;
131 
132             return this;
133         }
134 
getTlsContext()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          */
withHttpProxyOptions(HttpProxyOptions httpProxyOptions)143         public CognitoCredentialsProviderBuilder withHttpProxyOptions(HttpProxyOptions httpProxyOptions) {
144             this.httpProxyOptions = httpProxyOptions;
145 
146             return this;
147         }
148 
getHttpProxyOptions()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          */
build()156         public CognitoCredentialsProvider build() {
157             return new CognitoCredentialsProvider(this);
158         }
159     }
160 
CognitoCredentialsProvider(CognitoCredentialsProviderBuilder builder)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 
writeLengthPrefixedBytesSafe(ByteBuffer buffer, byte[] bytes)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 
marshalLoginsForJni(ArrayList<CognitoLoginTokenPair> logins)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 
cognitoCredentialsProviderNew(CognitoCredentialsProvider thisObj, long bootstrapHandle, long tlsContextHandle, String endpoint, String identity, String customRoleArn, byte[] marshalledLogins, int proxyConnectionType, byte[] proxyHost, int proxyPort, long proxyTlsContext, int proxyAuthorizationType, byte[] proxyAuthorizationUsername, byte[] proxyAuthorizationPassword)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 }
278