Repository navigation
feat(formats): add AWS::IAM::Role.Name format keyword as E1165 - #4936
Merged
kddejong merged 1 commit intoOct 27, 2026
Merged
Conversation
Several properties accept an IAM role as either an ARN or a bare role
name, for example AWS::Batch::ComputeEnvironment ServiceRole and
ComputeResources/SpotIamFleetRole. Expressing that in a schema needs both
halves of an anyOf:
{"anyOf": [{"format": "AWS::IAM::Role.Arn"},
{"format": "AWS::IAM::Role.Name"}]}
The ARN half already exists as E1156. The name half did not, so that
branch accepted any string and the schema change would have been
silently unenforced.
The pattern is ^(/[!-~]+/)?[a-zA-Z0-9_+=,.@-]{1,64}$. The name part is
IAM's RoleName spec [\w+=,.@-]{1,64} and the optional leading group is
IAM's Path spec (\u002F)|(\u002F[\u0021-\u007E]+\u002F), because the
accepting APIs take the path and the name concatenated. Printable ASCII
includes /, so nested service-linked role paths match too.
\w is spelled out in ASCII because it is Unicode-aware in Python but
ASCII-only in ECMA-262, and these patterns are consumed by both. Tests
assert the literal spelling agrees with the escaped spec form over every
ASCII code point so the readable form cannot drift.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4936 +/- ##
=======================================
Coverage 94.68% 94.68%
=======================================
Files 441 442 +1
Lines 16067 16077 +10
Branches 3116 3116
=======================================
+ Hits 15213 15223 +10
Misses 470 470
Partials 384 384
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
kddejong
marked this pull request as ready for review
October 27, 2026 14:41
This was referenced Oct 27, 2026
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Several properties accept an IAM role as either an ARN or a bare role name. The measured cases are
AWS::Batch::ComputeEnvironmentServiceRoleandComputeResources/SpotIamFleetRole. A schema expresses that with both halves of ananyOf:{"anyOf": [{"format": "AWS::IAM::Role.Arn"}, {"format": "AWS::IAM::Role.Name"}]}The ARN half already exists as
E1156. The name half did not, so that branch accepted any string and a schema change using it would have been silently unenforced.This is step 1 of 2. A matching
resource-provider-enhanced-schemaschange depends on this landing first. An earlier attempt on the schema side inlined a rawpattern; a named format is preferable because that repo's output has consumers beyond cfn-lint, and a format carries the semantic concept where a regex is opaque.The change
E1165/AWS::IAM::Role.Name, mirroringIamRoleArn.py(E1156). This follows the three existing.Nameformats —AWS::EC2::SecurityGroup.Name(E1153),AWS::Logs::LogGroup.Name(E1155),AWS::S3::Bucket.Name(E1161).Both halves are IAM's own published specs:
RoleName,[\w+=,.@-]{1,64}Path,(\u002F)|(\u002F[\u0021-\u007E]+\u002F), because the accepting APIs take the path and the name concatenated. Printable ASCII includes/, so nested service-linked role paths match too.\wis spelled out in ASCII deliberately: it is Unicode-aware in Python but ASCII-only in ECMA-262, and these patterns are consumed by both. Two tests pin the readable spelling to the spec form so it cannot drift — the path form is string-identical once the escapes resolve, and the name class has zero disagreements against[\w+=,.@-]read with ECMA-262 semantics across all 128 ASCII code points. A third test pins the consequence: Python's\wacceptsé,中and١, and IAM does not.Rule id
E1165.E1163is a retired id — it wasLambdaFunctionName/AWS::Lambda::Function.Name, removed in #4529 — so it was left alone rather than recycled, since reusing it would collide with any existing user suppression.E1164(KmsAliasName) is the current ceiling;E1165has no occurrence anywhere in the tree or onmain.Evidence for the pattern
AWSBatchServiceRole/foo/bar/service-role/AWSBatchServiceRole/aws-service-role/spotfleet.amazonaws.com/AWSServiceRoleForEC2SpotFleetrole-with-plus+equals=comma,dot.at@dash-a(boundary)a//foo/arn:aws:iam::123456789012:role/MyRolebad name with spacesThe ARN is rejected here on purpose:
:is outside the name charset, and matching it is the other branch's job.Verification
cfn-lint --update-specsfirst, then:The 19 suite failures are pre-existing and come from optional dependencies absent locally (
pydot,pygraphviz,sarif_om). Confirmed rather than assumed: stashing only this change's paths and re-running produced a byte-identical failure set, with the pass count dropping by exactly the 24 new tests.The good-fixture sweep was also diffed against the same tree with the rule file removed. The findings are byte-identical at 162 either way, so this introduces zero new findings.
Enforcement, end to end
Registration was not taken on faith.
cfn-lint -llistsE1165, and a scratch registry schema (-s) carryingformat: AWS::IAM::Role.Namewas linted for real:/foo/— each raiseE1165at the right line!Ref,!GetAtt,!Sub, and!If, matching the existing format rules, sinceFormatKeyword.formatreturnsTruefor anything that is not a stringThe real
anyOfshape was exercised too. A bare name, an ARN, the path form,!GetAtt Role.Arnand an unresolved!Refare all accepted, and only a genuinely invalid value is rejected — by both branches, surfacing asE1156+E1165+E3017.The counterfactual confirms the rule is load-bearing: the same
anyOfwith an unregistered format name on the second branch exits0onbad name with spaces, silently accepting it.What is not proven here: no real resource schema ships
format: AWS::IAM::Role.Nameyet, so enforcement onAWS::Batch::ComputeEnvironmentitself cannot be observed until the enhanced-schemas change lands. The scratch registry schema is a stand-in for it.One thing worth flagging for the schema side: declaring a pure
.Nameformat on a property makesE1040compare GetAtt source formats against it, so!GetAtt Role.Arninto a name-only slot is flagged. Under the intendedanyOfthe ARN branch satisfies it and noE1040appears, which is the behaviour observed above.