From 926f656d7fe48d117d3406095d6df864212962d8 Mon Sep 17 00:00:00 2001 From: David Oguns Date: Mon, 16 Aug 2021 16:45:15 -0700 Subject: [PATCH 01/15] Added scheme property to HttpApiKeyAuth trait. --- ...api-key-scheme-trait-validator-test.errors | 1 + ...p-api-key-scheme-trait-validator-test.json | 39 +++++++++++++++ .../model/traits/HttpApiKeyAuthTrait.java | 24 +++++++-- .../HttpApiKeyAuthTraitValidator.java | 49 +++++++++++++++++++ ...e.amazon.smithy.model.validation.Validator | 1 + .../amazon/smithy/model/loader/prelude.smithy | 3 ++ .../model/traits/HttpApiKeyAuthTraitTest.java | 43 ++++++++++++++++ 7 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors create mode 100644 smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json create mode 100644 smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors new file mode 100644 index 00000000000..659af921728 --- /dev/null +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors @@ -0,0 +1 @@ +[ERROR] ns.foo#MyService: httpApiKeyAuth trait must use in="header" when scheme is specified. | HttpApiKeyAuthTrait diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json new file mode 100644 index 00000000000..8934b5cc2c0 --- /dev/null +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json @@ -0,0 +1,39 @@ +{ + "smithy": "1.0", + "shapes": { + "ns.foo#MyService": { + "type": "service", + "version": "2017-01-17", + "operations": [ + { + "target": "ns.foo#A" + } + ], + "traits": { + "smithy.api#httpApiKeyAuth": { + "scheme": "Baz", + "name": "ApiKeyName", + "in": "query" + } + } + }, + "ns.foo#A": { + "type": "operation", + "input": { + "target": "ns.foo#AInput" + }, + "output": { + "target": "ns.foo#AOutput" + }, + "traits": { + "smithy.api#readonly": { } + } + }, + "ns.foo#AInput": { + "type": "structure" + }, + "ns.foo#AOutput": { + "type": "structure" + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java index e1989e5928b..48ea5b36080 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java @@ -15,6 +15,7 @@ package software.amazon.smithy.model.traits; +import java.util.Optional; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.ShapeId; @@ -29,15 +30,21 @@ public final class HttpApiKeyAuthTrait extends AbstractTrait implements ToSmithy public static final ShapeId ID = ShapeId.from("smithy.api#httpApiKeyAuth"); + private final String scheme; private final String name; private final Location in; private HttpApiKeyAuthTrait(Builder builder) { super(ID, builder.getSourceLocation()); + scheme = builder.scheme; name = SmithyBuilder.requiredState("name", builder.name); in = SmithyBuilder.requiredState("in", builder.in); } + public Optional getScheme() { + return Optional.ofNullable(scheme); + } + public String getName() { return name; } @@ -50,17 +57,21 @@ public Location getIn() { public Builder toBuilder() { return builder() .sourceLocation(getSourceLocation()) + .scheme(getScheme().orElse(null)) .name(getName()) .in(getIn()); } @Override protected Node createNode() { - return Node.objectNodeBuilder() + ObjectNode.Builder builder = Node.objectNodeBuilder() .sourceLocation(getSourceLocation()) .withMember("name", getName()) - .withMember("in", getIn().toString()) - .build(); + .withMember("in", getIn().toString()); + getScheme().ifPresent(scheme -> { + builder.withMember("scheme", getScheme().get()); + }); + return builder.build(); } public static Builder builder() { @@ -101,6 +112,7 @@ public Provider() { public Trait createTrait(ShapeId target, Node value) { ObjectNode objectNode = value.expectObjectNode(); Builder builder = builder().sourceLocation(value.getSourceLocation()); + builder.scheme(objectNode.getStringMemberOrDefault("scheme", null)); builder.name(objectNode.expectStringMember("name").getValue()); builder.in(Location.from(objectNode.expectStringMember("in").expectOneOf("header", "query"))); return builder.build(); @@ -108,6 +120,7 @@ public Trait createTrait(ShapeId target, Node value) { } public static final class Builder extends AbstractTraitBuilder { + private String scheme; private String name; private Location in; @@ -118,6 +131,11 @@ public HttpApiKeyAuthTrait build() { return new HttpApiKeyAuthTrait(this); } + public Builder scheme(String scheme) { + this.scheme = scheme; + return this; + } + public Builder name(String name) { this.name = name; return this; diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java new file mode 100644 index 00000000000..dae095e8ab9 --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.smithy.model.validation.validators; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.traits.HttpApiKeyAuthTrait; +import software.amazon.smithy.model.validation.AbstractValidator; +import software.amazon.smithy.model.validation.ValidationEvent; + +/** + * Validates that if an HttpApiKeyAuth trait's scheme field is present then + * the 'in' field must specify "header". + */ +public final class HttpApiKeyAuthTraitValidator extends AbstractValidator { + @Override + public List validate(Model model) { + Set serviceShapesWithTrait = model.getServiceShapesWithTrait(HttpApiKeyAuthTrait.class); + List events = new ArrayList<>(); + + for (ServiceShape serviceShape:serviceShapesWithTrait) { + HttpApiKeyAuthTrait trait = serviceShape.expectTrait(HttpApiKeyAuthTrait.class); + trait.getScheme().ifPresent(scheme -> { + if (trait.getIn() != HttpApiKeyAuthTrait.Location.HEADER) { + events.add(error(serviceShape, + "httpApiKeyAuth trait must use in=\"header\" when scheme is specified.")); + } + }); + } + + return events; + } +} diff --git a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator index 174aef1ba4f..c275e2bc3c8 100644 --- a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator +++ b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator @@ -5,6 +5,7 @@ software.amazon.smithy.model.validation.validators.EventPayloadTraitValidator software.amazon.smithy.model.validation.validators.ExamplesTraitValidator software.amazon.smithy.model.validation.validators.ExclusiveStructureMemberTraitValidator software.amazon.smithy.model.validation.validators.HostLabelTraitValidator +software.amazon.smithy.model.validation.validators.HttpApiKeyAuthTraitValidator software.amazon.smithy.model.validation.validators.HttpBindingsMissingValidator software.amazon.smithy.model.validation.validators.HttpChecksumTraitValidator software.amazon.smithy.model.validation.validators.HttpHeaderTraitValidator diff --git a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy index 81b110620b1..9669474bece 100644 --- a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy +++ b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy @@ -196,6 +196,9 @@ structure httpApiKeyAuth { /// can be set to `"header"` or `"query"`. @required in: HttpApiKeyLocations, + + /// Defines an ApiKey scheme when Authorization header is used + scheme: NonEmptyString, } @private diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java index d2b73ee8ba3..a596f5f166e 100644 --- a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java +++ b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java @@ -18,6 +18,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Optional; @@ -39,6 +40,7 @@ public void loadsTraitWithHeader() { assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); + assertThat(auth.getScheme().isPresent(), is(Boolean.FALSE)); assertThat(auth.getName(), equalTo("X-Foo")); assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.HEADER)); assertThat(auth.toNode(), equalTo(node)); @@ -57,6 +59,47 @@ public void loadsTraitWithQuery() { assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); + assertThat(auth.getScheme().isPresent(), is(Boolean.FALSE)); + assertThat(auth.getName(), equalTo("blerg")); + assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.QUERY)); + assertThat(auth.toNode(), equalTo(node)); + assertThat(auth.toBuilder().build(), equalTo(auth)); + } + + @Test + public void loadsTraitWithHeaderAndScheme() { + TraitFactory provider = TraitFactory.createServiceFactory(); + ObjectNode node = Node.objectNode() + .withMember("scheme", "fenty") + .withMember("name", "X-Foo") + .withMember("in", "header"); + Optional trait = provider.createTrait( + HttpApiKeyAuthTrait.ID, ShapeId.from("ns.qux#foo"), node); + assertTrue(trait.isPresent()); + assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); + HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); + + assertThat(auth.getScheme().get(), equalTo("fenty")); + assertThat(auth.getName(), equalTo("X-Foo")); + assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.HEADER)); + assertThat(auth.toNode(), equalTo(node)); + assertThat(auth.toBuilder().build(), equalTo(auth)); + } + + @Test + public void loadsTraitWithQueryAndScheme() { + TraitFactory provider = TraitFactory.createServiceFactory(); + ObjectNode node = Node.objectNode() + .withMember("scheme", "fenty") + .withMember("name", "blerg") + .withMember("in", "query"); + Optional trait = provider.createTrait( + HttpApiKeyAuthTrait.ID, ShapeId.from("ns.qux#foo"), node); + assertTrue(trait.isPresent()); + assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); + HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); + + assertThat(auth.getScheme().get(), equalTo("fenty")); assertThat(auth.getName(), equalTo("blerg")); assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.QUERY)); assertThat(auth.toNode(), equalTo(node)); From e81db2abdd36e82343cfe2f96a946b274ae3c2d8 Mon Sep 17 00:00:00 2001 From: David Oguns Date: Mon, 16 Aug 2021 16:45:15 -0700 Subject: [PATCH 02/15] Add scheme property to HttpApiKeyAuth trait --- ...api-key-scheme-trait-validator-test.errors | 1 + ...p-api-key-scheme-trait-validator-test.json | 39 +++++++++++++++ .../model/traits/HttpApiKeyAuthTrait.java | 24 +++++++-- .../HttpApiKeyAuthTraitValidator.java | 49 +++++++++++++++++++ ...e.amazon.smithy.model.validation.Validator | 1 + .../amazon/smithy/model/loader/prelude.smithy | 3 ++ .../model/traits/HttpApiKeyAuthTraitTest.java | 43 ++++++++++++++++ 7 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors create mode 100644 smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json create mode 100644 smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors new file mode 100644 index 00000000000..659af921728 --- /dev/null +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors @@ -0,0 +1 @@ +[ERROR] ns.foo#MyService: httpApiKeyAuth trait must use in="header" when scheme is specified. | HttpApiKeyAuthTrait diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json new file mode 100644 index 00000000000..8934b5cc2c0 --- /dev/null +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json @@ -0,0 +1,39 @@ +{ + "smithy": "1.0", + "shapes": { + "ns.foo#MyService": { + "type": "service", + "version": "2017-01-17", + "operations": [ + { + "target": "ns.foo#A" + } + ], + "traits": { + "smithy.api#httpApiKeyAuth": { + "scheme": "Baz", + "name": "ApiKeyName", + "in": "query" + } + } + }, + "ns.foo#A": { + "type": "operation", + "input": { + "target": "ns.foo#AInput" + }, + "output": { + "target": "ns.foo#AOutput" + }, + "traits": { + "smithy.api#readonly": { } + } + }, + "ns.foo#AInput": { + "type": "structure" + }, + "ns.foo#AOutput": { + "type": "structure" + } + } +} diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java index e1989e5928b..48ea5b36080 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java @@ -15,6 +15,7 @@ package software.amazon.smithy.model.traits; +import java.util.Optional; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.ShapeId; @@ -29,15 +30,21 @@ public final class HttpApiKeyAuthTrait extends AbstractTrait implements ToSmithy public static final ShapeId ID = ShapeId.from("smithy.api#httpApiKeyAuth"); + private final String scheme; private final String name; private final Location in; private HttpApiKeyAuthTrait(Builder builder) { super(ID, builder.getSourceLocation()); + scheme = builder.scheme; name = SmithyBuilder.requiredState("name", builder.name); in = SmithyBuilder.requiredState("in", builder.in); } + public Optional getScheme() { + return Optional.ofNullable(scheme); + } + public String getName() { return name; } @@ -50,17 +57,21 @@ public Location getIn() { public Builder toBuilder() { return builder() .sourceLocation(getSourceLocation()) + .scheme(getScheme().orElse(null)) .name(getName()) .in(getIn()); } @Override protected Node createNode() { - return Node.objectNodeBuilder() + ObjectNode.Builder builder = Node.objectNodeBuilder() .sourceLocation(getSourceLocation()) .withMember("name", getName()) - .withMember("in", getIn().toString()) - .build(); + .withMember("in", getIn().toString()); + getScheme().ifPresent(scheme -> { + builder.withMember("scheme", getScheme().get()); + }); + return builder.build(); } public static Builder builder() { @@ -101,6 +112,7 @@ public Provider() { public Trait createTrait(ShapeId target, Node value) { ObjectNode objectNode = value.expectObjectNode(); Builder builder = builder().sourceLocation(value.getSourceLocation()); + builder.scheme(objectNode.getStringMemberOrDefault("scheme", null)); builder.name(objectNode.expectStringMember("name").getValue()); builder.in(Location.from(objectNode.expectStringMember("in").expectOneOf("header", "query"))); return builder.build(); @@ -108,6 +120,7 @@ public Trait createTrait(ShapeId target, Node value) { } public static final class Builder extends AbstractTraitBuilder { + private String scheme; private String name; private Location in; @@ -118,6 +131,11 @@ public HttpApiKeyAuthTrait build() { return new HttpApiKeyAuthTrait(this); } + public Builder scheme(String scheme) { + this.scheme = scheme; + return this; + } + public Builder name(String name) { this.name = name; return this; diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java new file mode 100644 index 00000000000..dae095e8ab9 --- /dev/null +++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.smithy.model.validation.validators; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.traits.HttpApiKeyAuthTrait; +import software.amazon.smithy.model.validation.AbstractValidator; +import software.amazon.smithy.model.validation.ValidationEvent; + +/** + * Validates that if an HttpApiKeyAuth trait's scheme field is present then + * the 'in' field must specify "header". + */ +public final class HttpApiKeyAuthTraitValidator extends AbstractValidator { + @Override + public List validate(Model model) { + Set serviceShapesWithTrait = model.getServiceShapesWithTrait(HttpApiKeyAuthTrait.class); + List events = new ArrayList<>(); + + for (ServiceShape serviceShape:serviceShapesWithTrait) { + HttpApiKeyAuthTrait trait = serviceShape.expectTrait(HttpApiKeyAuthTrait.class); + trait.getScheme().ifPresent(scheme -> { + if (trait.getIn() != HttpApiKeyAuthTrait.Location.HEADER) { + events.add(error(serviceShape, + "httpApiKeyAuth trait must use in=\"header\" when scheme is specified.")); + } + }); + } + + return events; + } +} diff --git a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator index 174aef1ba4f..c275e2bc3c8 100644 --- a/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator +++ b/smithy-model/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator @@ -5,6 +5,7 @@ software.amazon.smithy.model.validation.validators.EventPayloadTraitValidator software.amazon.smithy.model.validation.validators.ExamplesTraitValidator software.amazon.smithy.model.validation.validators.ExclusiveStructureMemberTraitValidator software.amazon.smithy.model.validation.validators.HostLabelTraitValidator +software.amazon.smithy.model.validation.validators.HttpApiKeyAuthTraitValidator software.amazon.smithy.model.validation.validators.HttpBindingsMissingValidator software.amazon.smithy.model.validation.validators.HttpChecksumTraitValidator software.amazon.smithy.model.validation.validators.HttpHeaderTraitValidator diff --git a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy index 81b110620b1..9669474bece 100644 --- a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy +++ b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy @@ -196,6 +196,9 @@ structure httpApiKeyAuth { /// can be set to `"header"` or `"query"`. @required in: HttpApiKeyLocations, + + /// Defines an ApiKey scheme when Authorization header is used + scheme: NonEmptyString, } @private diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java index d2b73ee8ba3..a596f5f166e 100644 --- a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java +++ b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java @@ -18,6 +18,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Optional; @@ -39,6 +40,7 @@ public void loadsTraitWithHeader() { assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); + assertThat(auth.getScheme().isPresent(), is(Boolean.FALSE)); assertThat(auth.getName(), equalTo("X-Foo")); assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.HEADER)); assertThat(auth.toNode(), equalTo(node)); @@ -57,6 +59,47 @@ public void loadsTraitWithQuery() { assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); + assertThat(auth.getScheme().isPresent(), is(Boolean.FALSE)); + assertThat(auth.getName(), equalTo("blerg")); + assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.QUERY)); + assertThat(auth.toNode(), equalTo(node)); + assertThat(auth.toBuilder().build(), equalTo(auth)); + } + + @Test + public void loadsTraitWithHeaderAndScheme() { + TraitFactory provider = TraitFactory.createServiceFactory(); + ObjectNode node = Node.objectNode() + .withMember("scheme", "fenty") + .withMember("name", "X-Foo") + .withMember("in", "header"); + Optional trait = provider.createTrait( + HttpApiKeyAuthTrait.ID, ShapeId.from("ns.qux#foo"), node); + assertTrue(trait.isPresent()); + assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); + HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); + + assertThat(auth.getScheme().get(), equalTo("fenty")); + assertThat(auth.getName(), equalTo("X-Foo")); + assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.HEADER)); + assertThat(auth.toNode(), equalTo(node)); + assertThat(auth.toBuilder().build(), equalTo(auth)); + } + + @Test + public void loadsTraitWithQueryAndScheme() { + TraitFactory provider = TraitFactory.createServiceFactory(); + ObjectNode node = Node.objectNode() + .withMember("scheme", "fenty") + .withMember("name", "blerg") + .withMember("in", "query"); + Optional trait = provider.createTrait( + HttpApiKeyAuthTrait.ID, ShapeId.from("ns.qux#foo"), node); + assertTrue(trait.isPresent()); + assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); + HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); + + assertThat(auth.getScheme().get(), equalTo("fenty")); assertThat(auth.getName(), equalTo("blerg")); assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.QUERY)); assertThat(auth.toNode(), equalTo(node)); From 8658c70496a38c14ff62acb3e8648be7741b3730 Mon Sep 17 00:00:00 2001 From: David Oguns Date: Wed, 18 Aug 2021 15:50:44 -0700 Subject: [PATCH 03/15] Add documentation with snippet. --- docs/source/1.0/spec/core/auth-traits.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/source/1.0/spec/core/auth-traits.rst b/docs/source/1.0/spec/core/auth-traits.rst index 25a5b8bcc8f..89aaacbcbd5 100644 --- a/docs/source/1.0/spec/core/auth-traits.rst +++ b/docs/source/1.0/spec/core/auth-traits.rst @@ -216,6 +216,9 @@ properties: - ``string`` - **Required**. Defines the location of where the key is serialized. This value can be set to ``header`` or ``query``. + * - scheme + - ``string`` + - Defines the ApiKey scheme to set on the intended Authoriation header The following example defines a service that accepts an API key in the "X-Api-Key" HTTP header: @@ -228,6 +231,14 @@ HTTP header: } +.. code-block:: smithy + + @httpApiKeyAuth(scheme: "ApiKey", name: "Authorization", in: "header") + service WeatherService { + version: "2017-02-11", + } + + .. smithy-trait:: smithy.api#optionalAuth .. _optionalAuth-trait: From 622eca1e654bb88128cbaafab3f91bb1c81d1e5d Mon Sep 17 00:00:00 2001 From: David Oguns Date: Thu, 19 Aug 2021 10:59:17 -0700 Subject: [PATCH 04/15] Add better documentation comment for validation --- docs/source/1.0/spec/core/auth-traits.rst | 2 +- .../amazon/smithy/model/traits/HttpApiKeyAuthTrait.java | 4 ++-- .../validation/validators/HttpApiKeyAuthTraitValidator.java | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/1.0/spec/core/auth-traits.rst b/docs/source/1.0/spec/core/auth-traits.rst index 89aaacbcbd5..0c46165ce4a 100644 --- a/docs/source/1.0/spec/core/auth-traits.rst +++ b/docs/source/1.0/spec/core/auth-traits.rst @@ -218,7 +218,7 @@ properties: This value can be set to ``header`` or ``query``. * - scheme - ``string`` - - Defines the ApiKey scheme to set on the intended Authoriation header + - Defines the ApiKey scheme to set on the intended Authorization header. The following example defines a service that accepts an API key in the "X-Api-Key" HTTP header: diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java index 48ea5b36080..a26e8eceebf 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. @@ -69,7 +69,7 @@ protected Node createNode() { .withMember("name", getName()) .withMember("in", getIn().toString()); getScheme().ifPresent(scheme -> { - builder.withMember("scheme", getScheme().get()); + builder.withMember("scheme", scheme); }); return builder.build(); } diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java index dae095e8ab9..4a063ab2d26 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. @@ -26,7 +26,8 @@ /** * Validates that if an HttpApiKeyAuth trait's scheme field is present then - * the 'in' field must specify "header". + * the 'in' field must specify "header". Scheme should only be used with the + * "Authorization" http header. */ public final class HttpApiKeyAuthTraitValidator extends AbstractValidator { @Override From bbcce08fb897f9ee492e9dafe1ab9948d37eb6aa Mon Sep 17 00:00:00 2001 From: David Oguns Date: Thu, 19 Aug 2021 11:07:22 -0700 Subject: [PATCH 05/15] Adding back license year to copyright header. --- .../validation/validators/HttpApiKeyAuthTraitValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java index 4a063ab2d26..f1ecce282d9 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java @@ -1,5 +1,5 @@ /* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. From ef13b4a57bcf307796953971713423b730324b8d Mon Sep 17 00:00:00 2001 From: David Oguns <38018552+DavidOgunsAWS@users.noreply.github.com> Date: Thu, 19 Aug 2021 16:17:04 -0700 Subject: [PATCH 06/15] Update smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy Co-authored-by: Jordon Phillips --- .../software/amazon/smithy/model/loader/prelude.smithy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy index 9669474bece..452caa45113 100644 --- a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy +++ b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy @@ -197,7 +197,7 @@ structure httpApiKeyAuth { @required in: HttpApiKeyLocations, - /// Defines an ApiKey scheme when Authorization header is used + /// Defines an ApiKey scheme when Authorization header is used. scheme: NonEmptyString, } From e112ef05f83a272619751959a0bdcbbc7a73e80a Mon Sep 17 00:00:00 2001 From: David Oguns Date: Fri, 20 Aug 2021 15:04:39 -0700 Subject: [PATCH 07/15] Add OpenAPI converstion for scheme enabled HttpApiKeyAuthTrait. --- .../security/HttpApiKeyAuthConverter.java | 10 ++++++++++ .../security/HttpApiKeyAuthConverterTest.java | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpApiKeyAuthConverter.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpApiKeyAuthConverter.java index 614d3a69189..bfc9cf1a74c 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpApiKeyAuthConverter.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/security/HttpApiKeyAuthConverter.java @@ -40,6 +40,16 @@ public Class getAuthSchemeType() { @Override public SecurityScheme createSecurityScheme(Context context, HttpApiKeyAuthTrait trait) { + if (trait.getScheme().isPresent()) { + return SecurityScheme.builder() + .type("http") + .scheme(trait.getScheme().get()) + .name(trait.getName()) + .in(trait.getIn().toString()) + .description("ApiKey authentication semantics via 'Authorization' header") + .build(); + } + return SecurityScheme.builder() .type("apiKey") .name(trait.getName()) diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpApiKeyAuthConverterTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpApiKeyAuthConverterTest.java index f8b7079fff5..59254868673 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpApiKeyAuthConverterTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/security/HttpApiKeyAuthConverterTest.java @@ -30,6 +30,23 @@ public void addsCustomApiKeyAuth() { Node.assertEquals(result, expectedNode); } + @Test + public void addsCustomApiKeyBearerAuth() { + Model model = Model.assembler() + .addImport(getClass().getResource("http-api-key-bearer-security.json")) + .discoverModels() + .assemble() + .unwrap(); + OpenApiConfig config = new OpenApiConfig(); + config.setService(ShapeId.from("smithy.example#Service")); + OpenApi result = OpenApiConverter.create().config(config).convert(model); + Node expectedNode = Node.parse(IoUtils.toUtf8String( + getClass().getResourceAsStream("http-api-key-bearer-security.openapi.json"))); + + Node.assertEquals(result, expectedNode); + } + + @Test public void returnsTraitHeader() { HttpApiKeyAuthConverter converter = new HttpApiKeyAuthConverter(); From fd89542332c75dae45cf3e5164d902e1c43a6ac8 Mon Sep 17 00:00:00 2001 From: David Oguns Date: Fri, 20 Aug 2021 15:05:51 -0700 Subject: [PATCH 08/15] Add test resource for ApiKey scheme conversion. --- .../http-api-key-bearer-security.json | 31 ++++++++++++++++ .../http-api-key-bearer-security.openapi.json | 35 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-api-key-bearer-security.json create mode 100644 smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-api-key-bearer-security.openapi.json diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-api-key-bearer-security.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-api-key-bearer-security.json new file mode 100644 index 00000000000..fdbb07f9a60 --- /dev/null +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-api-key-bearer-security.json @@ -0,0 +1,31 @@ +{ + "smithy": "1.0", + "shapes": { + "smithy.example#Service": { + "type": "service", + "version": "2006-03-01", + "operations": [ + { + "target": "smithy.example#Operation" + } + ], + "traits": { + "aws.protocols#restJson1": {}, + "smithy.api#httpApiKeyAuth": { + "name": "Authorization", + "in": "header", + "scheme": "ApiKey" + } + } + }, + "smithy.example#Operation": { + "type": "operation", + "traits": { + "smithy.api#http": { + "uri": "/", + "method": "GET" + } + } + } + } +} diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-api-key-bearer-security.openapi.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-api-key-bearer-security.openapi.json new file mode 100644 index 00000000000..e732a628293 --- /dev/null +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/security/http-api-key-bearer-security.openapi.json @@ -0,0 +1,35 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Service", + "version": "2006-03-01" + }, + "paths": { + "/": { + "get": { + "operationId": "Operation", + "responses": { + "200": { + "description": "Operation response" + } + } + } + } + }, + "components": { + "securitySchemes": { + "smithy.api.httpApiKeyAuth": { + "type": "http", + "description": "ApiKey authentication semantics via 'Authorization' header", + "name": "Authorization", + "in": "header", + "scheme": "ApiKey" + } + } + }, + "security": [ + { + "smithy.api.httpApiKeyAuth": [ ] + } + ] +} From 499254d2c258175c6867764d29b8f6877fd8138f Mon Sep 17 00:00:00 2001 From: David Oguns Date: Thu, 26 Aug 2021 17:38:25 -0700 Subject: [PATCH 09/15] Improve error location and message clarity, and addressed formatting issues. --- docs/source/1.0/spec/core/auth-traits.rst | 3 ++- .../amazon/smithy/model/traits/HttpApiKeyAuthTrait.java | 6 ++---- .../validation/validators/HttpApiKeyAuthTraitValidator.java | 6 +++--- .../software/amazon/smithy/model/loader/prelude.smithy | 3 ++- .../amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java | 3 ++- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/source/1.0/spec/core/auth-traits.rst b/docs/source/1.0/spec/core/auth-traits.rst index 0c46165ce4a..4d357b24d61 100644 --- a/docs/source/1.0/spec/core/auth-traits.rst +++ b/docs/source/1.0/spec/core/auth-traits.rst @@ -218,7 +218,8 @@ properties: This value can be set to ``header`` or ``query``. * - scheme - ``string`` - - Defines the ApiKey scheme to set on the intended Authorization header. + - Defines the ApiKey scheme to set on the intended ``Authorization`` header. + This can only be set if in is set to ``header``. The following example defines a service that accepts an API key in the "X-Api-Key" HTTP header: diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java index a26e8eceebf..fffa60c39e4 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java @@ -67,10 +67,8 @@ protected Node createNode() { ObjectNode.Builder builder = Node.objectNodeBuilder() .sourceLocation(getSourceLocation()) .withMember("name", getName()) - .withMember("in", getIn().toString()); - getScheme().ifPresent(scheme -> { - builder.withMember("scheme", scheme); - }); + .withMember("in", getIn().toString()) + .withOptionalMember("scheme", getScheme().map(Node::from)); return builder.build(); } diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java index f1ecce282d9..bac1e174614 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java @@ -35,12 +35,12 @@ public List validate(Model model) { Set serviceShapesWithTrait = model.getServiceShapesWithTrait(HttpApiKeyAuthTrait.class); List events = new ArrayList<>(); - for (ServiceShape serviceShape:serviceShapesWithTrait) { + for (ServiceShape serviceShape : serviceShapesWithTrait) { HttpApiKeyAuthTrait trait = serviceShape.expectTrait(HttpApiKeyAuthTrait.class); trait.getScheme().ifPresent(scheme -> { if (trait.getIn() != HttpApiKeyAuthTrait.Location.HEADER) { - events.add(error(serviceShape, - "httpApiKeyAuth trait must use in=\"header\" when scheme is specified.")); + events.add(error(serviceShape, trait, + String.format("The httpApiKeyAuth trait must have an `in` value of `header` when a `scheme` is provided, found: %s", trait.getIn()))); } }); } diff --git a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy index 452caa45113..e72906e8b9e 100644 --- a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy +++ b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy @@ -197,7 +197,8 @@ structure httpApiKeyAuth { @required in: HttpApiKeyLocations, - /// Defines an ApiKey scheme when Authorization header is used. + /// Defines the ApiKey scheme to set on the intended ``Authorization`` header. + /// This can only be set if in is set to ``header``. scheme: NonEmptyString, } diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java index a596f5f166e..06ef3590d3b 100644 --- a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java +++ b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java @@ -19,6 +19,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Optional; @@ -40,7 +41,7 @@ public void loadsTraitWithHeader() { assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); - assertThat(auth.getScheme().isPresent(), is(Boolean.FALSE)); + assertFalse(auth.getScheme().isPresent()); assertThat(auth.getName(), equalTo("X-Foo")); assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.HEADER)); assertThat(auth.toNode(), equalTo(node)); From febbc7aea75a642775db2deb74e84cc91fa1c6aa Mon Sep 17 00:00:00 2001 From: David Oguns Date: Mon, 30 Aug 2021 12:27:06 -0700 Subject: [PATCH 10/15] Move validation error test resources and re-word error message. --- ...api-key-scheme-trait-validator-test.errors | 1 - .../HttpApiKeyAuthTraitValidator.java | 3 ++- .../model/traits/HttpApiKeyAuthTraitTest.java | 20 ------------------- ...api-key-scheme-trait-validator-test.errors | 1 + ...p-api-key-scheme-trait-validator-test.json | 0 5 files changed, 3 insertions(+), 22 deletions(-) delete mode 100644 smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors create mode 100644 smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.errors rename {smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles => smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators}/http-api-key-scheme-trait-validator-test.json (100%) diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors deleted file mode 100644 index 659af921728..00000000000 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.errors +++ /dev/null @@ -1 +0,0 @@ -[ERROR] ns.foo#MyService: httpApiKeyAuth trait must use in="header" when scheme is specified. | HttpApiKeyAuthTrait diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java index bac1e174614..7b368a15f96 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/HttpApiKeyAuthTraitValidator.java @@ -40,7 +40,8 @@ public List validate(Model model) { trait.getScheme().ifPresent(scheme -> { if (trait.getIn() != HttpApiKeyAuthTrait.Location.HEADER) { events.add(error(serviceShape, trait, - String.format("The httpApiKeyAuth trait must have an `in` value of `header` when a `scheme` is provided, found: %s", trait.getIn()))); + String.format("The httpApiKeyAuth trait must have an `in` value of `header` when a `scheme`" + + " is provided, found: %s", trait.getIn()))); } }); } diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java index 06ef3590d3b..fa548f137f0 100644 --- a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java +++ b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java @@ -86,24 +86,4 @@ public void loadsTraitWithHeaderAndScheme() { assertThat(auth.toNode(), equalTo(node)); assertThat(auth.toBuilder().build(), equalTo(auth)); } - - @Test - public void loadsTraitWithQueryAndScheme() { - TraitFactory provider = TraitFactory.createServiceFactory(); - ObjectNode node = Node.objectNode() - .withMember("scheme", "fenty") - .withMember("name", "blerg") - .withMember("in", "query"); - Optional trait = provider.createTrait( - HttpApiKeyAuthTrait.ID, ShapeId.from("ns.qux#foo"), node); - assertTrue(trait.isPresent()); - assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); - HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); - - assertThat(auth.getScheme().get(), equalTo("fenty")); - assertThat(auth.getName(), equalTo("blerg")); - assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.QUERY)); - assertThat(auth.toNode(), equalTo(node)); - assertThat(auth.toBuilder().build(), equalTo(auth)); - } } diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.errors new file mode 100644 index 00000000000..e119174d6c4 --- /dev/null +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.errors @@ -0,0 +1 @@ +[ERROR] ns.foo#MyService: The httpApiKeyAuth trait must have an `in` value of `header` when a `scheme` is provided, found: query | HttpApiKeyAuthTrait \ No newline at end of file diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.json similarity index 100% rename from smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/http-api-key-scheme-trait-validator-test.json rename to smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.json From 850bf431995b5983d4de4722375d2537f53face8 Mon Sep 17 00:00:00 2001 From: David Oguns Date: Mon, 30 Aug 2021 12:40:31 -0700 Subject: [PATCH 11/15] Add lead in sentence for example. --- docs/source/1.0/spec/core/auth-traits.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/1.0/spec/core/auth-traits.rst b/docs/source/1.0/spec/core/auth-traits.rst index 4d357b24d61..d773326df49 100644 --- a/docs/source/1.0/spec/core/auth-traits.rst +++ b/docs/source/1.0/spec/core/auth-traits.rst @@ -231,6 +231,8 @@ HTTP header: version: "2017-02-11", } +The following example defines a service that uses an API key auth scheme through +the HTTP ``Authorization`` header: .. code-block:: smithy From fdcc568f21a5dc338debb426ee51e8bcf0361e97 Mon Sep 17 00:00:00 2001 From: David Oguns Date: Mon, 30 Aug 2021 12:43:00 -0700 Subject: [PATCH 12/15] Re-order field setting in constructor --- .../amazon/smithy/model/traits/HttpApiKeyAuthTrait.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java index fffa60c39e4..94f842789aa 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTrait.java @@ -36,9 +36,9 @@ public final class HttpApiKeyAuthTrait extends AbstractTrait implements ToSmithy private HttpApiKeyAuthTrait(Builder builder) { super(ID, builder.getSourceLocation()); - scheme = builder.scheme; name = SmithyBuilder.requiredState("name", builder.name); in = SmithyBuilder.requiredState("in", builder.in); + scheme = builder.scheme; } public Optional getScheme() { From db27e58c5012fa48c186b6687df1561eab2fcce9 Mon Sep 17 00:00:00 2001 From: David Oguns Date: Mon, 30 Aug 2021 14:10:46 -0700 Subject: [PATCH 13/15] Adjust and synchronize documentation and prelude for scheme property. --- docs/source/1.0/spec/core/auth-traits.rst | 4 ++-- .../software/amazon/smithy/model/loader/prelude.smithy | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/1.0/spec/core/auth-traits.rst b/docs/source/1.0/spec/core/auth-traits.rst index d773326df49..5b7084f7c19 100644 --- a/docs/source/1.0/spec/core/auth-traits.rst +++ b/docs/source/1.0/spec/core/auth-traits.rst @@ -218,8 +218,8 @@ properties: This value can be set to ``header`` or ``query``. * - scheme - ``string`` - - Defines the ApiKey scheme to set on the intended ``Authorization`` header. - This can only be set if in is set to ``header``. + - Defines the security scheme to use on the ``Authorization`` header value + This can only be set if the "in" property is set to ``header``. The following example defines a service that accepts an API key in the "X-Api-Key" HTTP header: diff --git a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy index e72906e8b9e..99575207ec8 100644 --- a/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy +++ b/smithy-model/src/main/resources/software/amazon/smithy/model/loader/prelude.smithy @@ -197,8 +197,8 @@ structure httpApiKeyAuth { @required in: HttpApiKeyLocations, - /// Defines the ApiKey scheme to set on the intended ``Authorization`` header. - /// This can only be set if in is set to ``header``. + /// Defines the security scheme to use on the ``Authorization`` header value + /// This can only be set if the "in" property is set to ``header``. scheme: NonEmptyString, } From b3373549cabe602b805c06bdb8c3200c6cacce6f Mon Sep 17 00:00:00 2001 From: David Oguns Date: Mon, 30 Aug 2021 15:48:44 -0700 Subject: [PATCH 14/15] Adjust assertThat(..., false) to assertFalse() --- .../amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java index fa548f137f0..17846ddd18b 100644 --- a/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java +++ b/smithy-model/src/test/java/software/amazon/smithy/model/traits/HttpApiKeyAuthTraitTest.java @@ -18,7 +18,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -60,7 +59,7 @@ public void loadsTraitWithQuery() { assertThat(trait.get(), instanceOf(HttpApiKeyAuthTrait.class)); HttpApiKeyAuthTrait auth = (HttpApiKeyAuthTrait) trait.get(); - assertThat(auth.getScheme().isPresent(), is(Boolean.FALSE)); + assertFalse(auth.getScheme().isPresent()); assertThat(auth.getName(), equalTo("blerg")); assertThat(auth.getIn(), equalTo(HttpApiKeyAuthTrait.Location.QUERY)); assertThat(auth.toNode(), equalTo(node)); From 07642536f5a77cef5a2eb01389b1d5aeaf5345d0 Mon Sep 17 00:00:00 2001 From: David Oguns Date: Wed, 1 Sep 2021 10:26:08 -0700 Subject: [PATCH 15/15] Add EOL --- .../validators/http-api-key-scheme-trait-validator-test.errors | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.errors b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.errors index e119174d6c4..9aa23d834a5 100644 --- a/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.errors +++ b/smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators/http-api-key-scheme-trait-validator-test.errors @@ -1 +1 @@ -[ERROR] ns.foo#MyService: The httpApiKeyAuth trait must have an `in` value of `header` when a `scheme` is provided, found: query | HttpApiKeyAuthTrait \ No newline at end of file +[ERROR] ns.foo#MyService: The httpApiKeyAuth trait must have an `in` value of `header` when a `scheme` is provided, found: query | HttpApiKeyAuthTrait