-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add docs and validation for endpoint patterns (#2069)
* Add docs and validation for endpoint patterns used by standardRegionalEndpoints and standardPartitionalEndpoints * Fixes from PR * Add validation for scheme to endpoint patterns * Update docs * Add additional url validation on endpoint patterns * Fixes from PR
- Loading branch information
1 parent
1a858da
commit 8fa7d38
Showing
13 changed files
with
252 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
...va/software/amazon/smithy/rulesengine/aws/validators/AwsSpecialCaseEndpointValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package software.amazon.smithy.rulesengine.aws.validators; | ||
|
||
import java.net.MalformedURLException; | ||
import java.net.URISyntaxException; | ||
import java.net.URL; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import software.amazon.smithy.model.FromSourceLocation; | ||
import software.amazon.smithy.model.Model; | ||
import software.amazon.smithy.model.shapes.ServiceShape; | ||
import software.amazon.smithy.model.validation.AbstractValidator; | ||
import software.amazon.smithy.model.validation.ValidationEvent; | ||
import software.amazon.smithy.rulesengine.aws.traits.PartitionEndpointSpecialCase; | ||
import software.amazon.smithy.rulesengine.aws.traits.PartitionSpecialCase; | ||
import software.amazon.smithy.rulesengine.aws.traits.RegionSpecialCase; | ||
import software.amazon.smithy.rulesengine.aws.traits.StandardPartitionalEndpointsTrait; | ||
import software.amazon.smithy.rulesengine.aws.traits.StandardRegionalEndpointsTrait; | ||
import software.amazon.smithy.utils.SetUtils; | ||
|
||
/** | ||
* Validate special case endpoints from endpoint traits that are applied on a service. | ||
*/ | ||
public final class AwsSpecialCaseEndpointValidator extends AbstractValidator { | ||
|
||
private static final Set<String> SUPPORTED_PATTERNS = SetUtils.of( | ||
"{region}", "{service}", "{dnsSuffix}", "{dualStackDnsSuffix}" | ||
); | ||
|
||
private static final Pattern PATTERN = Pattern.compile("\\{[^\\}]*\\}"); | ||
|
||
@Override | ||
public List<ValidationEvent> validate(Model model) { | ||
List<ValidationEvent> events = new ArrayList<>(); | ||
for (ServiceShape serviceShape : model.getServiceShapesWithTrait(StandardRegionalEndpointsTrait.class)) { | ||
events.addAll(validateRegionalEndpointPatterns(serviceShape, | ||
serviceShape.expectTrait(StandardRegionalEndpointsTrait.class))); | ||
} | ||
for (ServiceShape serviceShape : model.getServiceShapesWithTrait(StandardPartitionalEndpointsTrait.class)) { | ||
events.addAll(validatePartitionalEndpointPatterns(serviceShape, | ||
serviceShape.expectTrait(StandardPartitionalEndpointsTrait.class))); | ||
} | ||
return events; | ||
} | ||
|
||
private List<ValidationEvent> validateRegionalEndpointPatterns( | ||
ServiceShape serviceShape, StandardRegionalEndpointsTrait regionalEndpoints) { | ||
List<ValidationEvent> events = new ArrayList<>(); | ||
|
||
for (List<RegionSpecialCase> specialCases : regionalEndpoints.getRegionSpecialCases().values()) { | ||
for (RegionSpecialCase specialCase : specialCases) { | ||
events.addAll(validateEndpointPatterns( | ||
serviceShape, regionalEndpoints, specialCase.getEndpoint())); | ||
} | ||
} | ||
|
||
for (List<PartitionSpecialCase> specialCases : regionalEndpoints.getPartitionSpecialCases().values()) { | ||
for (PartitionSpecialCase specialCase : specialCases) { | ||
events.addAll(validateEndpointPatterns( | ||
serviceShape, regionalEndpoints, specialCase.getEndpoint())); | ||
} | ||
} | ||
|
||
return events; | ||
} | ||
|
||
private List<ValidationEvent> validatePartitionalEndpointPatterns( | ||
ServiceShape serviceShape, StandardPartitionalEndpointsTrait partitionalEndpoints) { | ||
|
||
List<ValidationEvent> events = new ArrayList<>(); | ||
|
||
for (List<PartitionEndpointSpecialCase> specialCases | ||
: partitionalEndpoints.getPartitionEndpointSpecialCases().values()) { | ||
for (PartitionEndpointSpecialCase specialCase : specialCases) { | ||
events.addAll(validateEndpointPatterns( | ||
serviceShape, partitionalEndpoints, specialCase.getEndpoint())); | ||
} | ||
} | ||
|
||
return events; | ||
} | ||
|
||
private List<ValidationEvent> validateEndpointPatterns( | ||
ServiceShape serviceShape, FromSourceLocation location, String endpoint) { | ||
List<ValidationEvent> events = new ArrayList<>(); | ||
|
||
Matcher m = PATTERN.matcher(endpoint); | ||
List<String> unsupportedPatterns = new ArrayList<>(); | ||
while (m.find()) { | ||
if (!SUPPORTED_PATTERNS.contains(m.group())) { | ||
unsupportedPatterns.add(m.group()); | ||
} | ||
} | ||
|
||
if (!unsupportedPatterns.isEmpty()) { | ||
events.add(danger( | ||
serviceShape, location, | ||
String.format("Endpoint `%s` contains unsupported patterns: %s", | ||
endpoint, String.join(", ", unsupportedPatterns)), | ||
"UnsupportedEndpointPattern")); | ||
} | ||
|
||
if (!(endpoint.startsWith("http://") || endpoint.startsWith("https://"))) { | ||
events.add(danger( | ||
serviceShape, location, | ||
String.format("Endpoint `%s` should start with scheme `http://` or `https://`", | ||
endpoint), | ||
"InvalidEndpointPatternScheme")); | ||
} | ||
|
||
if (!isValidURL(endpoint)) { | ||
events.add(error( | ||
serviceShape, location, | ||
String.format("Endpoint `%s` should be a valid URL.", | ||
endpoint), | ||
"InvalidEndpointPatternUrl")); | ||
} | ||
|
||
return events; | ||
} | ||
|
||
private boolean isValidURL(String endpointPattern) { | ||
String url = endpointPattern | ||
.replace("{", "") | ||
.replace("}", ""); | ||
try { | ||
new URL(url).toURI(); | ||
return true; | ||
} catch (MalformedURLException e) { | ||
return false; | ||
} catch (URISyntaxException e) { | ||
return false; | ||
} | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...ts/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.Validator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
software.amazon.smithy.rulesengine.aws.validators.RuleSetAwsBuiltInValidator | ||
software.amazon.smithy.rulesengine.aws.validators.AwsSpecialCaseEndpointValidator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
...hy/rulesengine/aws/language/functions/errorfiles/invalid/invalid-endpoint-patterns.errors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[WARNING] example#Service1: This shape applies a trait that is unstable: aws.endpoints#standardRegionalEndpoints | UnstableTrait.aws.endpoints#standardRegionalEndpoints | ||
[DANGER] example#Service1: Endpoint `https://myservice.{invalid}.{dnsSuffix}` contains unsupported patterns: {invalid} | AwsSpecialCaseEndpoint.UnsupportedEndpointPattern | ||
[DANGER] example#Service1: Endpoint `{invalid}-fips.{region}.{badSuffix}` contains unsupported patterns: {invalid}, {badSuffix} | AwsSpecialCaseEndpoint.UnsupportedEndpointPattern | ||
[DANGER] example#Service1: Endpoint `{invalid}-fips.{region}.{badSuffix}` should start with scheme `http://` or `https://` | AwsSpecialCaseEndpoint.InvalidEndpointPatternScheme | ||
[ERROR] example#Service1: Endpoint `{invalid}-fips.{region}.{badSuffix}` should be a valid URL. | AwsSpecialCaseEndpoint.InvalidEndpointPatternUrl | ||
[ERROR] example#Service1: Endpoint `https://{region}. invalidurl {dnsSuffix}` should be a valid URL. | AwsSpecialCaseEndpoint.InvalidEndpointPatternUrl | ||
[WARNING] example#Service2: This shape applies a trait that is unstable: aws.endpoints#standardPartitionalEndpoints | UnstableTrait.aws.endpoints#standardPartitionalEndpoints | ||
[DANGER] example#Service2: Endpoint `myservice.{invalid}.{dnsSuffix}` should start with scheme `http://` or `https://` | AwsSpecialCaseEndpoint.InvalidEndpointPatternScheme | ||
[DANGER] example#Service2: Endpoint `myservice.{invalid}.{dnsSuffix}` contains unsupported patterns: {invalid} | AwsSpecialCaseEndpoint.UnsupportedEndpointPattern | ||
[ERROR] example#Service2: Endpoint `myservice.{invalid}.{dnsSuffix}` should be a valid URL. | AwsSpecialCaseEndpoint.InvalidEndpointPatternUrl |
42 changes: 42 additions & 0 deletions
42
...hy/rulesengine/aws/language/functions/errorfiles/invalid/invalid-endpoint-patterns.smithy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
$version: "1.0" | ||
|
||
namespace example | ||
|
||
use aws.endpoints#standardRegionalEndpoints | ||
use aws.endpoints#standardPartitionalEndpoints | ||
|
||
@standardRegionalEndpoints( | ||
regionSpecialCases: { | ||
"us-east-1": [ | ||
{ | ||
endpoint: "https://myservice.{invalid}.{dnsSuffix}", | ||
} | ||
] | ||
}, | ||
partitionSpecialCases: { | ||
"aws": [ | ||
{ | ||
endpoint: "{invalid}-fips.{region}.{badSuffix}", | ||
fips: true | ||
}, | ||
{ | ||
endpoint: "https://{region}. invalidurl {dnsSuffix}", | ||
dualStack: true | ||
} | ||
] | ||
} | ||
) | ||
service Service1 {} | ||
|
||
@standardPartitionalEndpoints( | ||
endpointPatternType: "service_dnsSuffix", | ||
partitionEndpointSpecialCases: { | ||
"aws": [ | ||
{ | ||
endpoint: "myservice.{invalid}.{dnsSuffix}", | ||
region: "us-east-1" | ||
} | ||
] | ||
} | ||
) | ||
service Service2 {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.