Open mdesmarest opened 4 years ago
This gets it close, but has the glaring error of permitting an unencrypted ebs_block_device if the root device is encrypted and the ebs_block_device does not specify encrypted.
Feature: Check to make sure EC2 instances are encrypted if they are not named bastion
Scenario: root_block_device must be configured on all non bastion hosts
Given I have aws_instance defined
When its name is not bastion
Then it must have root_block_device
And it must have encrypted
And its value must be true
Scenario: ebs_block_device, if present, must be configured on all non bastion hosts
Given I have aws_instance defined
When its name is not bastion
When it has ebs_block_device
Then it must have encrypted
And its value must be true
Seems like compliance is regexing the first encrypted value it finds (although it does overwrite it if it finds another one). | Root Device | EBS Volume | Scenario 1 | Scenario 2 | |
---|---|---|---|---|---|
Encrypted | Encrypted | Pass | Pass | ||
Encrypted | Not Encrypted | Pass | Fail | ||
Encrypted | Not defined | Pass | Skip | ||
Encrypted | Defined but "encrypted not present" | Pass | (bad) Pass | This is the problem | |
Not Encrypted | Encrypted | Fail | Pass | ||
Not Encrypted | Not Encrypted | Fail | Fail | ||
Not Encrypted | Not Defined | Fail | Skip | ||
Not Encrypted | Defined but "encrypted not present" | Fail | Fail |
Thanks for making a chart, based on the blocks I posted above, This is similar on logic to what I had come to Except
for scenario 1: in addition to your findings above There apppears to be a Parsing error with terraform compliance, I have to report a bug on
Scenario: root_block_device must be configured on all non bastion hosts
Given I have aws_instance defined
When its name is not bastion
Then it must have root_block_device
And it must have encrypted <skips here
And its value must be true < Skips here
This should NOT SKIP,
When I look at the stash for And it must have encrypted
When its name is not bastion
>> Press enter to continue
Failure: aws_instance.root_block_missing (aws_instance) does not have root_block_device property.
Then it must have root_block_device
Failure:
>** REMOVED OTHER RESOURCES***
"address": "aws_instance.root_block_encrypted__field_missing", <show as part of the stash
"values": [
{
"delete_on_termination": true,
"volume_size": 200,
"volume_type": "gp2"
},
{
"device_name": true,
"encrypted": true, < show encrypted:true
"iops": true,
"kms_key_id": true,
"volume_id": true
}
],
"type": "aws_instance"
}
]
The initial stash also shows this, so this is happening in the initial stash pass:
When its name is not bastion
>> Press enter to continues
** REMOVED OTHER RESOURCES for brevity**
{
***REMOVED BLOCKS FOR BREVITY****
"ebs_block_device": [
{
"delete_on_termination": true,
"device_name": "/dev/sdb",
"encrypted": true,
"volume_size": 1000,
"volume_type": "gp2"
},
{
"iops": true,
"kms_key_id": true,
"snapshot_id": true,
"volume_id": true
}
],
"ebs_optimized": true,
"get_password_data": false,
"hibernation": null,
"iam_instance_profile": null,
"instance_initiated_shutdown_behavior": null,
"instance_type": "t2.medium",
"key_name": "tfcompliance_inf",
"monitoring": true,
"root_block_device": [
{
"delete_on_termination": true,
"volume_size": 200,
"volume_type": "gp2"
},
{
"device_name": true,
"encrypted": true, <<< ******SHOWING ENCRYPTED as true******
"iops": true,
"kms_key_id": true,
"volume_id": true
}
],
When you look at the actual plan JSON this is not correct, Terraform compliance is parsing incorrectly: Resource block:
resource "aws_instance" "root_block_encrypted__field_missing" {
ami = "ami-003634241a8fcdec0"
instance_type = "t2.medium"
key_name = "tfcompliance_inf"
disable_api_termination = true
monitoring = true
ebs_optimized = true
associate_public_ip_address = false
security_groups = [aws_security_group.ingress_host.id,aws_security_group.egress_host.id]
root_block_device {
volume_size = 200
volume_type = "gp2"
}
ebs_block_device {
device_name = "/dev/sdb"
volume_size = 1000
volume_type = "gp2"
delete_on_termination = true
encrypted = true
}
tags = {
budget-area = "security"
group = "cybersecurity"
}
}
ACTUAL JSON OUTPUT FOR RESOURCE:
{
"address":"aws_instance.root_block_encrypted__field_missing",
*REDACTED FOR BREVITY
"disable_api_termination":true,
"ebs_block_device":[
{
"delete_on_termination":true,
"device_name":"/dev/sdb",
"encrypted":true,
"volume_size":1000,
"volume_type":"gp2"
}
],
"ebs_optimized":true,
"get_password_data":false,
"hibernation":null,
"iam_instance_profile":null,
"instance_initiated_shutdown_behavior":null,
"instance_type":"t2.medium",
"key_name":"tfcompliance_inf",
"monitoring":true,
"root_block_device":[
{
"delete_on_termination":true,
"volume_size":200,
"volume_type":"gp2". <<<< NO ENCRYPTION IN THE PLAN JSON, terraform compliance sees it as True
}
],
*REDACTED FOR BREVITY****
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#encrypted. Default for encrypted field is false
A parsing issue also occurs for This piece of terraform code, ebs_block_device encryption is not declared in block:
resource "aws_instance" "ebs_encrypted_not_present" {
ami = "ami-003634241a8fcdec0"
instance_type = "t2.medium"
key_name = "tfcompliance_inf"
security_groups = [aws_security_group.ingress_host.id,aws_security_group.egress_host.id]
root_block_device {
volume_size = 200
volume_type = "gp2"
encrypted = true
}
ebs_block_device {
device_name = "/dev/sdg"
volume_size = 50
volume_type = "gp2"
delete_on_termination = true
}
tags = {
budget-area = "security"
group = "Cybersecurity"
}
}
STASH SHOWS INCORRECT, shows ebs_block_device encrypted = true https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#encrypted default is also FALSE on terraform registry
{
"address": "aws_instance.ebs_encrypted_not_present",
** REDACTED FOR BREVITY***
"ebs_block_device": [
{
"delete_on_termination": true,
"device_name": "/dev/sdg",
"volume_size": 50,
"volume_type": "gp2"
},
{
"encrypted": true, <<<< SHOWS AS TRUE IN STASH
"iops": true,
"kms_key_id": true,
"snapshot_id": true,
"volume_id": true
}
],
"ebs_optimized": null,
"get_password_data": false,
"hibernation": null,
"iam_instance_profile": null,
"instance_initiated_shutdown_behavior": null,
"instance_type": "t2.medium",
"key_name": "tfcompliance_inf",
"monitoring": null,
"root_block_device": [
{
"delete_on_termination": true,
"encrypted": true,
"volume_size": 200,
"volume_type": "gp2"
},
{
"device_name": true,
"iops": true,
"kms_key_id": true,
"volume_id": true
}
],
},
Plan JSON OUTPUT ALSO CONCURS. that terraform compliance is not passing the correct values to the stash:
{
"address":"aws_instance.ebs_encrypted_not_present",
"mode":"managed",
"type":"aws_instance",
"name":"ebs_encrypted_not_present",
"provider_name":"aws",
"schema_version":1,
"values":{
"ami":"ami-003634241a8fcdec0",
"credit_specification":[
],
"disable_api_termination":null,
"ebs_block_device":[
{
"delete_on_termination":true,
"device_name":"/dev/sdg",
"volume_size":50,
"volume_type":"gp2"
}
],
"ebs_optimized":null,
"get_password_data":false,
"hibernation":null,
"iam_instance_profile":null,
"instance_initiated_shutdown_behavior":null,
"instance_type":"t2.medium",
"key_name":"tfcompliance_inf",
"monitoring":null,
"root_block_device":[
{
"delete_on_termination":true,
"encrypted":true,
"volume_size":200,
"volume_type":"gp2"
}
],
This could be the best issue descriptions (and conversation) we might ever had. Thanks a lot for this guys! We spent few hours to really understand the root cause of this problem and we found it! PR is created but it has some other problems.
Will work on it, fix it and then release a new version as soon as possible :)
Thanks again for this SUPER detailed issue! ❤️ ❤️ ❤️
Just released 1.3.8
. Based on our tests it fixed the issue but please have a try and let us know 🙏
@eerkunt @Kudbettin See my reply on 416 Looks good, fantastic turn around on this!
Note again on another issue I opened, really need to account for new vs updated resources as a feature like this can cause a resource that is flagged for encryption to be replaced if changes need to be made. Would love to have this for only new resources.
I am creating a feature to flag aws_instance (ec2) to ensure both root_block_device configures, and encrypted is configured and set to true. I need to also do the same for ebs_block_device. I am having issues filtering for one or the other as the
encrypted
flag for one causes the feature to pass for the other.I can't account for the lack of encrypted for root_block_device if it is set for ebs_block_volume. I have tried to interpolate and slice and keep running into syntax errors. Please assist me with how to write a feature or features with a scenario pattern that matches this. I see this being a logistics hurdle for any resource where
When it has encrypted
Then it must have encrypted
if a particular subproperty of a resource is used twice. See below for my code/plan and output of feature thus far. (sorry in advance for the long post)Feature1:
This drills down to all encrypted, thus passing if one of the two properties contains encrypted. This prevents me from flagging on the absence of
encryption
on one or the other for ebs_block_device or root_block_device see stash below:I have tried
This gets me the entire stash of instances that have root block device, but I am lost to how I can drill into root_block_device for its encrypted property, if its a slicing issue, I can't get the syntax correct, easy to drill to in ipython though
The below scenario seems to get me to a good place but I can't drill further with additional Thens/Ands, probably a knowledge gap, see below:
I get the stash that only produces root_block_devices, this is good but how do I drill further? `and it must have encrypted skips, and any slicing I attempt does not need to work. Stash:
Resource Blocks: