Skip to content

Commit 4ca7a42

Browse files
authored
Merge pull request #2820 from aws/feature/s3-express-release
Feature/s3 express release
2 parents 19cf073 + eafe74e commit 4ca7a42

File tree

151 files changed

+8808
-510
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+8808
-510
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": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Add `cloudwatch-metric-publisher` to `aws-sdk-java` module so that it can be included in the bundle JAR."
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "Amazon S3",
4+
"contributor": "",
5+
"description": "Adds SDK support for Amazon S3 Express One Zone. For usage, consult Javadocs and the official documentation. Note that users can switch off CreateSession authentication and use the regular credential providers to sign requests by using the `disableS3ExpressSessionAuth` option on the client builder, environment variables, system properties or the config file."
6+
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,5 @@ target/
2727

2828
*.pyc
2929
*.swp
30+
31+

codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ public class CustomizationConfig {
257257

258258
private boolean useGlobalEndpoint;
259259

260+
private boolean useS3ExpressSessionAuth;
261+
260262
private List<String> interceptors = new ArrayList<>();
261263

262264
private List<String> internalPlugins = new ArrayList<>();
@@ -291,6 +293,13 @@ public class CustomizationConfig {
291293
*/
292294
private Map<String, ClientContextParam> customClientContextParams;
293295

296+
private boolean s3ExpressAuthSupport;
297+
298+
/**
299+
* Customization related to auth scheme derived from endpoints.
300+
*/
301+
private EndpointAuthSchemeConfig endpointAuthSchemeConfig;
302+
294303
private CustomizationConfig() {
295304
}
296305

@@ -685,6 +694,14 @@ public void setUseGlobalEndpoint(boolean useGlobalEndpoint) {
685694
this.useGlobalEndpoint = useGlobalEndpoint;
686695
}
687696

697+
public boolean useS3ExpressSessionAuth() {
698+
return useS3ExpressSessionAuth;
699+
}
700+
701+
public void setUseS3ExpressSessionAuth(boolean useS3ExpressSessionAuth) {
702+
this.useS3ExpressSessionAuth = useS3ExpressSessionAuth;
703+
}
704+
688705
public Map<String, String> getSkipEndpointTests() {
689706
return skipEndpointTests;
690707
}
@@ -756,11 +773,28 @@ public void setCustomClientContextParams(Map<String, ClientContextParam> customC
756773
this.customClientContextParams = customClientContextParams;
757774
}
758775

776+
public boolean getS3ExpressAuthSupport() {
777+
return s3ExpressAuthSupport;
778+
}
779+
780+
public void setS3ExpressAuthSupport(boolean s3ExpressAuthSupport) {
781+
this.s3ExpressAuthSupport = s3ExpressAuthSupport;
782+
}
783+
759784
public MultipartCustomization getMultipartCustomization() {
760785
return this.multipartCustomization;
761786
}
762787

763788
public void setMultipartCustomization(MultipartCustomization multipartCustomization) {
764789
this.multipartCustomization = multipartCustomization;
765790
}
791+
792+
public EndpointAuthSchemeConfig getEndpointAuthSchemeConfig() {
793+
return endpointAuthSchemeConfig;
794+
}
795+
796+
public void setEndpointAuthSchemeConfig(EndpointAuthSchemeConfig endpointAuthSchemeConfig) {
797+
this.endpointAuthSchemeConfig = endpointAuthSchemeConfig;
798+
}
799+
766800
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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.codegen.model.config.customization;
17+
18+
import java.util.Map;
19+
20+
public class EndpointAuthSchemeConfig {
21+
22+
private String authSchemeStrategyFactoryClass;
23+
private String knownEndpointProperties;
24+
25+
private Map<String, KeyTypePair> endpointProviderTestKeys;
26+
27+
public String getAuthSchemeStrategyFactoryClass() {
28+
return authSchemeStrategyFactoryClass;
29+
}
30+
31+
public void setAuthSchemeStrategyFactoryClass(String authSchemeStrategyFactoryClass) {
32+
this.authSchemeStrategyFactoryClass = authSchemeStrategyFactoryClass;
33+
}
34+
35+
public String getKnownEndpointProperties() {
36+
return knownEndpointProperties;
37+
}
38+
39+
public void setKnownEndpointProperties(String knownEndpointProperties) {
40+
this.knownEndpointProperties = knownEndpointProperties;
41+
}
42+
43+
public Map<String, KeyTypePair> getEndpointProviderTestKeys() {
44+
return endpointProviderTestKeys;
45+
}
46+
47+
public void setEndpointProviderTestKeys(Map<String, KeyTypePair> endpointProviderTestKeys) {
48+
this.endpointProviderTestKeys = endpointProviderTestKeys;
49+
}
50+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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.codegen.model.config.customization;
17+
18+
import software.amazon.awssdk.utils.ToString;
19+
20+
public class KeyTypePair {
21+
private String key;
22+
private String type;
23+
24+
public String getKey() {
25+
return key;
26+
}
27+
28+
public void setKey(String key) {
29+
this.key = key;
30+
}
31+
32+
public String getType() {
33+
return type;
34+
}
35+
36+
public void setType(String type) {
37+
this.type = type;
38+
}
39+
40+
@Override
41+
public String toString() {
42+
return ToString.builder("KeyTypePair")
43+
.add("key", key)
44+
.add("type", type)
45+
.build();
46+
}
47+
}

codegen/src/main/java/software/amazon/awssdk/codegen/model/rules/endpoints/ExpectModel.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.fasterxml.jackson.core.TreeNode;
1919
import java.util.List;
2020
import java.util.Map;
21+
import software.amazon.awssdk.utils.ToString;
2122

2223
public class ExpectModel {
2324
private String error;
@@ -39,6 +40,14 @@ public void setEndpoint(Endpoint endpoint) {
3940
this.endpoint = endpoint;
4041
}
4142

43+
@Override
44+
public String toString() {
45+
return ToString.builder("ExpectModel")
46+
.add("error", error)
47+
.add("endpoint", endpoint)
48+
.build();
49+
}
50+
4251
public static class Endpoint {
4352
private String url;
4453
private Map<String, List<String>> headers;
@@ -67,5 +76,14 @@ public Map<String, TreeNode> getProperties() {
6776
public void setProperties(Map<String, TreeNode> properties) {
6877
this.properties = properties;
6978
}
79+
80+
@Override
81+
public String toString() {
82+
return ToString.builder("Endpoint")
83+
.add("url", url)
84+
.add("headers", headers)
85+
.add("properties", properties)
86+
.build();
87+
}
7088
}
7189
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeInterceptorSpec.java

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.squareup.javapoet.ClassName;
1919
import com.squareup.javapoet.FieldSpec;
2020
import com.squareup.javapoet.MethodSpec;
21+
import com.squareup.javapoet.ParameterSpec;
2122
import com.squareup.javapoet.ParameterizedTypeName;
2223
import com.squareup.javapoet.TypeName;
2324
import com.squareup.javapoet.TypeSpec;
@@ -40,6 +41,7 @@
4041
import software.amazon.awssdk.core.SdkRequest;
4142
import software.amazon.awssdk.core.SelectedAuthScheme;
4243
import software.amazon.awssdk.core.exception.SdkException;
44+
import software.amazon.awssdk.core.identity.SdkIdentityProperty;
4345
import software.amazon.awssdk.core.interceptor.Context;
4446
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
4547
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
@@ -91,7 +93,8 @@ public TypeSpec poetSpec() {
9193
.addMethod(generateSelectAuthScheme())
9294
.addMethod(generateAuthSchemeParams())
9395
.addMethod(generateTrySelectAuthScheme())
94-
.addMethod(generateGetIdentityMetric());
96+
.addMethod(generateGetIdentityMetric())
97+
.addMethod(putSelectedAuthSchemeMethodSpec());
9598
return builder.build();
9699
}
97100

@@ -108,8 +111,7 @@ private MethodSpec generateBeforeExecution() {
108111
listOf(AuthSchemeOption.class))
109112
.addStatement("$T selectedAuthScheme = selectAuthScheme(authOptions, executionAttributes)",
110113
wildcardSelectedAuthScheme())
111-
.addStatement("$T.putSelectedAuthScheme(executionAttributes, selectedAuthScheme)",
112-
endpointRulesSpecUtils.rulesRuntimeClassName("AuthSchemeUtils"));
114+
.addStatement("putSelectedAuthScheme(executionAttributes, selectedAuthScheme)");
113115
return builder.build();
114116
}
115117

@@ -208,7 +210,7 @@ private MethodSpec generateSelectAuthScheme() {
208210
{
209211
builder.addStatement("$T authScheme = authSchemes.get(authOption.schemeId())", wildcardAuthScheme())
210212
.addStatement("$T selectedAuthScheme = trySelectAuthScheme(authOption, authScheme, identityProviders, "
211-
+ "discardedReasons, metricCollector)",
213+
+ "discardedReasons, metricCollector, executionAttributes)",
212214
wildcardSelectedAuthScheme());
213215
builder.beginControlFlow("if (selectedAuthScheme != null)");
214216
{
@@ -229,6 +231,7 @@ private MethodSpec generateSelectAuthScheme() {
229231
return builder.build();
230232
}
231233

234+
//TODO (s3express) Review "general" identity properties and their propagation
232235
private MethodSpec generateTrySelectAuthScheme() {
233236
MethodSpec.Builder builder = MethodSpec.methodBuilder("trySelectAuthScheme")
234237
.addModifiers(Modifier.PRIVATE)
@@ -238,6 +241,7 @@ private MethodSpec generateTrySelectAuthScheme() {
238241
.addParameter(IdentityProviders.class, "identityProviders")
239242
.addParameter(listOfStringSuppliers(), "discardedReasons")
240243
.addParameter(MetricCollector.class, "metricCollector")
244+
.addParameter(ExecutionAttributes.class, "executionAttributes")
241245
.addTypeVariable(TypeVariableName.get("T", Identity.class));
242246

243247
builder.beginControlFlow("if (authScheme == null)");
@@ -262,7 +266,12 @@ private MethodSpec generateTrySelectAuthScheme() {
262266
ResolveIdentityRequest.class,
263267
ResolveIdentityRequest.class);
264268
builder.addStatement("authOption.forEachIdentityProperty(identityRequestBuilder::putProperty)");
265-
269+
if (endpointRulesSpecUtils.isS3()) {
270+
builder.addStatement("identityRequestBuilder.putProperty($T.SDK_CLIENT, "
271+
+ "executionAttributes.getAttribute($T.SDK_CLIENT))",
272+
SdkIdentityProperty.class,
273+
SdkInternalExecutionAttribute.class);
274+
}
266275
builder.addStatement("$T identity", namedIdentityFuture());
267276
builder.addStatement("$T metric = getIdentityMetric(identityProvider)", durationSdkMetric());
268277
builder.beginControlFlow("if (metric == null)")
@@ -295,6 +304,43 @@ private MethodSpec generateGetIdentityMetric() {
295304
return builder.build();
296305
}
297306

307+
private MethodSpec putSelectedAuthSchemeMethodSpec() {
308+
String attributeParamName = "attributes";
309+
String selectedAuthSchemeParamName = "selectedAuthScheme";
310+
MethodSpec.Builder builder = MethodSpec.methodBuilder("putSelectedAuthScheme")
311+
.addModifiers(Modifier.PRIVATE)
312+
.addTypeVariable(TypeVariableName.get("T", Identity.class))
313+
.addParameter(ExecutionAttributes.class, attributeParamName)
314+
.addParameter(ParameterSpec.builder(
315+
ParameterizedTypeName.get(ClassName.get(SelectedAuthScheme.class),
316+
TypeVariableName.get("T")),
317+
selectedAuthSchemeParamName).build());
318+
builder.addStatement("$T existingAuthScheme = $N.getAttribute($T.SELECTED_AUTH_SCHEME)",
319+
ParameterizedTypeName.get(ClassName.get(SelectedAuthScheme.class),
320+
WildcardTypeName.subtypeOf(Object.class)),
321+
attributeParamName,
322+
SdkInternalExecutionAttribute.class);
323+
324+
builder.beginControlFlow("if (existingAuthScheme != null)")
325+
.addStatement("$T selectedOption = $N.authSchemeOption().toBuilder()",
326+
AuthSchemeOption.Builder.class, selectedAuthSchemeParamName)
327+
.addStatement("existingAuthScheme.authSchemeOption().forEachIdentityProperty"
328+
+ "(selectedOption::putIdentityPropertyIfAbsent)")
329+
.addStatement("existingAuthScheme.authSchemeOption().forEachSignerProperty"
330+
+ "(selectedOption::putSignerPropertyIfAbsent)")
331+
.addStatement("$N = new $T<>($N.identity(), $N.signer(), selectedOption.build())",
332+
selectedAuthSchemeParamName,
333+
SelectedAuthScheme.class,
334+
selectedAuthSchemeParamName,
335+
selectedAuthSchemeParamName);
336+
builder.endControlFlow();
337+
338+
builder.addStatement("$N.putAttribute($T.SELECTED_AUTH_SCHEME, $N)",
339+
attributeParamName, SdkInternalExecutionAttribute.class, selectedAuthSchemeParamName);
340+
341+
return builder.build();
342+
}
343+
298344
private void addLogDebugDiscardedOptions(MethodSpec.Builder builder) {
299345
builder.beginControlFlow("if (!discardedReasons.isEmpty())");
300346
{

codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ private String internalPackage() {
7171
return intermediateModel.getMetadata().getFullInternalAuthSchemePackageName();
7272
}
7373

74+
public String baseClientPackageName() {
75+
return intermediateModel.getMetadata().getFullClientPackageName();
76+
}
77+
7478
public ClassName parametersInterfaceName() {
7579
return ClassName.get(basePackage(), intermediateModel.getMetadata().getServiceName() + "AuthSchemeParams");
7680
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/EndpointBasedAuthSchemeProviderSpec.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ private void addAuthSchemeSwitch(MethodSpec.Builder spec) {
147147
spec.beginControlFlow("switch(name)");
148148
addAuthSchemeSwitchSigV4Case(spec);
149149
addAuthSchemeSwitchSigV4aCase(spec);
150+
if (endpointRulesSpecUtils.useS3Express()) {
151+
addAuthSchemeSwitchS3ExpressCase(spec);
152+
}
150153
addAuthSchemeSwitchDefaultCase(spec);
151154
spec.endControlFlow();
152155
}
@@ -184,6 +187,26 @@ private void addAuthSchemeSwitchSigV4aCase(MethodSpec.Builder spec) {
184187
spec.addStatement("break");
185188
}
186189

190+
private void addAuthSchemeSwitchS3ExpressCase(MethodSpec.Builder spec) {
191+
spec.addCode("case $S:", "sigv4-s3express");
192+
ClassName s3ExpressEndpointAuthScheme = ClassName.get(
193+
authSchemeSpecUtils.baseClientPackageName() + ".endpoints.authscheme",
194+
"S3ExpressEndpointAuthScheme");
195+
spec.addStatement("$T s3ExpressAuthScheme = $T.isInstanceOf($T.class, authScheme, $S, authScheme.getClass().getName())",
196+
s3ExpressEndpointAuthScheme, Validate.class, s3ExpressEndpointAuthScheme,
197+
"Expecting auth scheme of class S3ExpressAuthScheme, got instead object of class %s");
198+
199+
ClassName s3ExpressAuthScheme = ClassName.get(authSchemeSpecUtils.baseClientPackageName() + ".s3express",
200+
"S3ExpressAuthScheme");
201+
spec.addCode("options.add($T.builder().schemeId($T.SCHEME_ID)", AuthSchemeOption.class, s3ExpressAuthScheme)
202+
.addCode(".putSignerProperty($T.SERVICE_SIGNING_NAME, s3ExpressAuthScheme.signingName())", AwsV4HttpSigner.class)
203+
.addCode(".putSignerProperty($T.REGION_NAME, s3ExpressAuthScheme.signingRegion())", AwsV4HttpSigner.class)
204+
.addCode(".putSignerProperty($T.DOUBLE_URL_ENCODE, !s3ExpressAuthScheme.disableDoubleEncoding())",
205+
AwsV4HttpSigner.class)
206+
.addCode(".build());");
207+
spec.addStatement("break");
208+
}
209+
187210
private void addAuthSchemeSwitchDefaultCase(MethodSpec.Builder spec) {
188211
spec.addCode("default:");
189212
spec.addStatement("throw new $T($S + name)", IllegalArgumentException.class, "Unknown auth scheme: ");

0 commit comments

Comments
 (0)