-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validator for duplicate names in iamResource trait #2293
Conversation
for (ResourceShape resource : topDownIndex.getContainedResources(service)) { | ||
String resourceName = resource.getId().getName(); | ||
IamResourceTrait iamResourceTrait; | ||
if (resource.hasTrait(IamResourceTrait.class) && resource.getTrait(IamResourceTrait.class).isPresent() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can use expectTrait. As hasTrait is already called, if the trait isn't actually resolved then that's an error - https://smithy.io/javadoc/1.5.1/software/amazon/smithy/model/shapes/Shape.html#expectTrait(java.lang.Class)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think can use expectTrait - https://smithy.io/javadoc/1.5.1/software/amazon/smithy/model/shapes/Shape.html#expectTrait(java.lang.Class)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of creating an event per conflict found, I think it would be better to collect all conflicting resources and then emit 1 event.
For example, if there were 3 resources that conflict:
// Omitted other irrelevant shapes
@aws.iam#iamResource(name: "Beer")
resource BadIamResourceName1 {}
@aws.iam#iamResource(name: "Beer")
resource BadIamResourceName2 {}
@aws.iam#iamResource(name: "Beer")
resource BadIamResourceName3 {}
the validator currently would emit 2 events:
[ERROR] smithy.example#BadIamResourceName2: Conflicting IAM resource names in an entire service closure is not allowed. This IAM resource name `Beer` conflicts with other resource `(resource: `smithy.example#BadIamResourceName1`)` in the service `smithy.example#MyService`. | IamResourceTraitConflictingName
[ERROR] smithy.example#BadIamResourceName3: Conflicting IAM resource names in an entire service closure is not allowed. This IAM resource name `Beer` conflicts with other resource `(resource: `smithy.example#BadIamResourceName1`)` in the service `smithy.example#MyService`. | IamResourceTraitConflictingName
Also, this will create events based on the order the model is traversed, which may not be stable across model changes.
Instead, I think it would be better to collect all of the conflicting names into 1 event:
[ERROR] smithy.example#MyService: Multiple IAM resources defined with the same IAM resource name is not allowed in a service closure, but found multiple resources named `Beer` in the service `smithy.example#MyService`: `smithy.example#BadIamResourceName1`, `smithy.example#BadIamResourceName2`, `smithy.example#BadIamResourceName3` | IamResourceTraitConflictingName
Also, should resources without the iamResource
trait be included in this validation?
...ain/java/software/amazon/smithy/aws/iam/traits/IamResourceTraitConflictingNameValidator.java
Outdated
Show resolved
Hide resolved
...ain/java/software/amazon/smithy/aws/iam/traits/IamResourceTraitConflictingNameValidator.java
Outdated
Show resolved
Hide resolved
String resourceName = resource.getId().getName(); | ||
IamResourceTrait iamResourceTrait; | ||
if (resource.hasTrait(IamResourceTrait.class) | ||
&& resource.expectTrait(IamResourceTrait.class).getName().isPresent()) { | ||
resourceName = resource.getTrait(IamResourceTrait.class).get().getName().get(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the method you want to use is IamResourceTrait::resolveResourceName()
.
To get the resource name in the IAM space, something like this could work:
String resourceName = IamResourceTrait.resolveResourceName(resource);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this means the .getName
check in the if
must also be removed, as resolveResourceName
checks other sources.
Background
IamResourceTraitValidator does not validates conflicting resource names in IAM space. For example, assume there exists two resource shapes Resource1 and Resource2. If I add trait @iamResource(name: "Resource1") on Resource2, there are conflicting resource names in the IAM space. This behavior is not detected/prevented by any validator in smithy.
Testing
Wrote a unit test for the validator.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.