-
Notifications
You must be signed in to change notification settings - Fork 389
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
[SA-535]Add support for security monitoring rules #763
Conversation
"default_only_filter": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Description: "Limit the search to default rules", | ||
}, | ||
"user_only_filter": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Description: "Limit the search to user rules", | ||
}, |
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.
Two different attributes are used for boolean values to work around GetOk
only checking if there was truthy value.
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.
Isn't that because you don't check the value returned? GetOk
is weird some time, but I'm not sure it's warranted here. AFAICT we only end up with one boolean, which you should be able to achieve with one field.
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 updated the resource to have a default value. Unless I am missing something, in this case though it will not be possible to filter out user rules only. Will we get d.GetOk("default_only_filter") == false, false
both in the case where the attribute is not present and in the case where the attribute is default_only_filter = false
.
(There are discussions about whether we should remove the datasource so leaving it as is for now).
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.
You're right, because you use nil
as a possible value, so there are effectively 3 states, not just 2.
return nil | ||
} | ||
|
||
func computeSecMonDataSourceRulesId(nameFilter *string, defaultFilter *bool, tagFilter map[string]bool) string { |
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.
This is a costly way to get a hash, I am not sure if this matters
ee4eb0b
to
9fafe42
Compare
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.
Looks great! Some minor question/remarks, plus need clarifications around boolean usage. Need to check why CI is red too.
"default_only_filter": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Description: "Limit the search to default rules", | ||
}, | ||
"user_only_filter": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Description: "Limit the search to user rules", | ||
}, |
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.
Isn't that because you don't check the value returned? GetOk
is weird some time, but I'm not sure it's warranted here. AFAICT we only end up with one boolean, which you should be able to achieve with one field.
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've made a first pass at custom security rules.
I'll check default rule resource and data source in a bit.
So far looks good with a few nits.
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Optional: true, |
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 name
is required when there's more than one case
.
Unfortunately I looked and it seems it's not possible to have that checked dynamically except maybe add a ValidateFunc
to the schema.
But I might be better to let the API fail. The only drawback is that the user will know it at apply
time.
Might be worth adding a note in the description?
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.
There's a trade-off between client-side validation and server-side validation. I think it easier and more maintenable to delegate most of it to the server, but we have to make sure the error message is descriptive and visible.
# Create a resource for each default rule id and enable the rule | ||
resource "datadog_security_monitoring_default_rule" "attack_rule" { | ||
for_each = toset(data.datadog_security_monitoring_rules.rules.rule_ids) | ||
rule_id = each.key | ||
enabled = true | ||
} |
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.
IIUC this is the motivation behind datadog_security_rules
datasource. It is a peculiar use of datasources AFAICT. For instance, how does it behave if you create datasources that overlaps? Say you have attack_default_rules
and specific_framework
rules. A rule could belong to both, and would result in multiple datadog_security_monitoring_default_rule
. My guess is that in this case, last write wins. but with lots of subtleties. Are we comfortable to recommend such usage?
I would have recommended dealing with default rules with a prior import.
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.
IIUC your edge case is something like this ?
resource "datadog_security_monitoring_default_rule" "rule1" {
rule_id = "SAMEID"
enabled = true
}
resource "datadog_security_monitoring_default_rule" "rule2" {
rule_id = "SAMEID"
enabled = false
}
I'm actually unsure what whould Terraform do here, It will probably conflict on the resource ID depending on how you build it.
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 am asking @NicolasLevaique what he thinks about this as well
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.
Also I just thought of a resource in the AWS provider that has a similar behavior, with no real create/delete
.
So at least this behavior exist.
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_vpc
https://github.com/hashicorp/terraform-provider-aws/blob/master/aws/resource_aws_default_vpc.go
Might be worth checking if they handle this edge case with two resource with different params.
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.
Also maybe a bit late but there's setintersection
, setunion
and setsubtract
functions that could have helped user with that issue.
9e58eb2
to
b015a85
Compare
Make all options required
Fix missing/incorrect fields
- tests are broken
- Remove Exists on default rule, the underlying resource should always exists - Rename file and fix indent
- Fix window management for datasource
- Stable ID for datasource - Only check that rules have been deleted
b015a85
to
fff4df2
Compare
@therve Can you take another look? After discussing with @NicolasLevaique, I changed the default rule so that it needs to be imported like other resources. I kept the datasource though since it can be useful and I don't know how to test the default rule without it.
but this would not be consistent with other datasources in the provider. |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
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.
A few minor comments, otherwise almost there.
|
||
if shouldUpdate { | ||
_, _, err := datadogClientV2.SecurityMonitoringApi.UpdateSecurityMonitoringRule(authV2, ruleId).Body(*ruleUpdate).Execute() | ||
if err != nil { |
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.
You should inline that if with the previous command.
|
||
func resourceDatadogSecurityMonitoringRule() *schema.Resource { | ||
return &schema.Resource{ | ||
Exists: resourceDatadogSecurityMonitoringRuleExists, |
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.
You should remove the exists, and check for 404 in read instead (and set the id to "" when you get a 404)
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.
Done in the last commit, can you double check how I did it though? I didn't find any other resources which omit exists
.
|
||
_, err := datadogClientV2.SecurityMonitoringApi.DeleteSecurityMonitoringRule(authV2, d.Id()).Execute() | ||
|
||
if err != nil { |
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.
You can inline that condition too.
``` | ||
|
||
``` | ||
terraform import datadog_security_monitoring_default_rule.adefaultrule |
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.
You're missing an ID here.
- Remove exists for secmon rule resource - Inline if err != nil checks - Add missing id in documentation
if err != nil { | ||
if httpResponse != nil && httpResponse.StatusCode == 404 { | ||
d.SetId("") | ||
return errors.New("security monitoring rule does not exist") |
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.
Almost that, just return nil in that case instead of an error. Thanks.
Add support for Security Monitoring public API.
See: https://docs.datadoghq.com/api/v2/security-monitoring/
Closes #509