-
Notifications
You must be signed in to change notification settings - Fork 183
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
[RFC] Block Evaluation #111
[RFC] Block Evaluation #111
Conversation
Would it make sense to allow setting strict checking in a block? Being able to specify that a certain block needs strict checking (or doesn't need it), would ensure that rules are always evaluated the same way. Some other remarks related to rule meta-data:
|
think finalizing ruleset file extensions is the key to this, along with autocompletion / syntax highlighting / validating rulesets |
AWS::ApiGateway::Method RestApiId == ApiGatewayBadBot | ||
``` | ||
|
||
In the above ruleset, every statement clause needs to repeat the type information like AWS::ApiGateway::Method, type has to be repeated across OR clauses, and OR clauses have to present on a single line which makes it hard to read end to end. This violates our tenet of simplicity. The current rule authoring experience is quite tedious because of this, with a large amount of information replicated line to line that is the same for a given resource type. |
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.
[copied from our previous discussion] think there's multiple sides to this. Lines being their own rules that can be evaluated independently and being able to sort and autocomplete rules more easily is arguably simpler
} | ||
``` | ||
|
||
Would like to see the preference of users on this specific point as to what is easiest to use. |
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.
Personally would prefer not having to specify the top-level Properties
in almost every rule
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.
Why not using the spring boot yaml format or sort of, with indentation for each sub-level. The Properties
would be visible once, and same for each sub-level. Last sample could be simplified like this:
AWS::EC2::Instance {
Properties {
BlockDeviceMappings {
*.Ebs != null
*.device_name == /^\/dev\/ebs-/
*.Ebs.encrypted == true
*.Ebs.delete_on_termination == true
}
}
}
Not sure however if the * could be used for a block...
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 like this way of specifying a lot to reduce repetition. Let me see how we can incorporate this into the block evaluation.
Is it possible to add details on rule suppression by resource in this RFC? In some cases, security engineers would like to give developers an option to skip a certain rule on a specific resource. For example, if a developer has two S3 buckets ( On the contrary, does it make sense to add an optional condition to the rule grammar for cases where rule suppression should not be allowed? For example, if some organization wants to enforce a policy that S3 buckets must never allow world read/write, so in this case, a rule block should allow a field like |
i think you should be able to write something of the following where either the check is satisfied or the rule is explicitly suppressed. For example, with the following template: Resources:
BucketRuleNotEnforced:
Type: AWS::S3::Bucket
Properties:
AccessControl: public-read-write
Metadata:
cfn-guard:
SuppressedRules:
- public_read_write_rule
BucketRuleEnforced:
Type: AWS::S3::Bucket
Properties:
AccessControl: public-read-write one could author a ruleset that can apply a rule named
This would have to be done for every rule so it isn't streamlined right now, but it makes it explicity clear what the rule block allows. No magic variables or anything; if you don't want to allow suppression on the rule, you'd just remove the Metadata check line |
Co-authored-by: Pat Myron <[email protected]>
Co-authored-by: Pat Myron <[email protected]>
I think as far as levels go, a way to achieve this with the current setup is to group rules of a certain level together in a block which would represent the overall status for said level. For example:
In the output for evaluation, as per the RFC, there will be some output of the form:
If we also offer multiple evaluation result formats like JSON with this enhanced output, end users could define their own rule block "levels" and choose which rule evaluations to consider when running guard. |
I think both my remark about levels and @shreyasdamle's about supression, point to a similar (potential) feature. It does not have to be part of this RFC, but in both cases, we're looking at adding metadata to rules, so that cfn-guard can treat failures differently depending on the metadata. It's worth considering how the language could support those cases, even when not implemented right away (if ever). Additionally, I'd argue that to meet all the tenants, strict checking should be removed as a cli option and added to the rules themself (and it makes sense to do that on block-level, or globally) |
Here, _rule_ keyword designates the start of a named rule block. The keyword is followed by the *rule_name* that is a human readable name. Rule names are optional but provide context in output as to what exactly failed. When evaluating the rules file, the *rule_name* is displayed along with with status for the evaluation <b>PASS. FAIL or SKIP</b>. The rule name can be followed by optional conditions (_When_ guards) that act as a guard to determine if the rule is application for evaluation or must be skipped, a.k.a conditionally evaluated (akin to WHEN CHECK in the previous language). | ||
|
||
|
||
The block contains a set of clauses in Conjunctive Normal Form. To simplify authoring clauses and provide a consistent interpretation model, the following rules apply: |
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'd rather see the rule syntax support parenthesis. The CNF form, the explicit OR vs implicit AND etc are new rules that developers have to learn. Yes it can be abused to write complex rules. But that should be caught by normal s/w sdlc, code reviews etc. I personally prefer this construction.
rule example_rule when stage == 'prod' {
let ec2_instance_types := [/^t*/, /^m*/]
dependent_rule
AND
AWS::EC2::Instance InstanceType IN %ec2_instance_types
AND
(
AWS::EC2::Instance {
xxxxx
}
OR
AWS::EC2::Instance {
yyyyy
}
)
}
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.
so with this construction, you would have to specify AND and couldn't implicitly rely on the next rule being ANDed, right? I think as long as it is explicit blocks being ANDed makes sense. this seems a repetitive, but with the added benefit of being explicit as possible.
I agree with removing strict checks as a cli option. Without it, rulesets are not deteministic. Planning on following up with another RFC more related to enhancing property access in templates and introducing more operations like existence checks (AWS::S3::Bucket PropertyA EXISTS/ AWS::S3::Bucket PropertyA != null). If we have those, ruleset authors should be able to craft rules that achieve parity with existing strict checked rulesets. |
Some other points I'd love to see addressed (though perhaps not part of this RFC), are:
|
I think #115 should address some of these concerns such as existence checks and dynamic variables. We are planning on introducing advanced filtering to select certain items in a template and then do checks on said items after filtering. |
All issues linked in this RFC PR have been addressed. I am merging this RFC to the |
Issue #, if available: #105, #79, #45
Description of changes: This request for comments details proposed enhancements of block evaluations, allowing rule authors to make more composable, less redundant, and unambiguous rules using named rules, type blocks, and conditional blocks. Full details on the proposal are in the below file.
All feedback is welcome on these proposed features, particularly on type blocks and the divergence in behavior detailed below on setting the root object for evaluation to the parent of the properties object of a resource. (Previously was the properties object)
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.