-
Notifications
You must be signed in to change notification settings - Fork 71
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
Add plural resources #18
Conversation
…zones; google_compute_firewalls as well as example controls and documentation. Also added helpers for retrieving compute instance labels. Signed-off-by: Stuart Paterson <spaterson@chef.io>
…Extra protection against null result in plural resources. Signed-off-by: Stuart Paterson <spaterson@chef.io>
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 looks good, can we remove those un-needed methods before merging?
filter_table_config.add_accessor(:where) | ||
filter_table_config.add_accessor(:entries) | ||
filter_table_config.add(:exist?) { |filter_table| !filter_table.entries.empty? } | ||
filter_table_config.add(:count) { |filter_table| filter_table.entries.count } |
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.
With inspec/inspec#3104 we don't need to add where
, entries
, exist?
or count
properties to filter tables, they are now automatic.
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.
Happy to do this but worth noting all profiles using inspec-gcp will now have to update the minimum InSpec version because of inspec/inspec#3066
libraries/google_compute_zones.rb
Outdated
filter_table_config.add_accessor(:where) | ||
filter_table_config.add_accessor(:entries) | ||
filter_table_config.add(:exist?) { |filter_table| !filter_table.entries.empty? } | ||
filter_table_config.add(:count) { |filter_table| filter_table.entries.count } |
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.
As above.
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.
The FilterTable docs were in flight while this work was going on; now that it is available, I hope its users will have a better experience. So, mostly docs changes around that, and some testing coverage asks as well. Great work overall, really appreciate the effort!
### Test that there are no more than a specified number of firewalls available for the project | ||
|
||
describe google_compute_firewalls(project: 'chef-inspec-gcp') do | ||
its('entries.count') { should be <= 100} |
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 just use its('count') ...
here.
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.
sure, will update
### Test the exact number of firewalls in the project | ||
|
||
describe google_compute_firewalls(project: 'chef-inspec-gcp') do | ||
its('firewall_ids.count') { should cmp 8 } |
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'm not clear on the difference between this example and the previous one. If the resource matches 5 firewalls, are you not expected to have 5 firewall IDs?
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.
agreed, will remove
its('firewall_names') { should_not include "default-allow-ssh" } | ||
end | ||
|
||
### Test there are no firewalls for the "INGRESS" direction |
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.
Hrm, this is usually expressed like this:
describe google_compute_firewalls(project: 'chef-inspec-gcp').where(firewall_direction: 'INGRESS') do
it { should_not exist }
end
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.
thanks, will update the example
|
||
## Filter Criteria | ||
|
||
This resource currently does not support any filter criteria; it will always fetch all available firewalls. |
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.
Actually, you have firewall_id
, firewall_name
, and firewall_direction
. You can use any of them with where
, as a block or as a method.
Please read https://github.com/inspec/inspec/blob/master/docs/dev/filtertable-usage.md
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.
thanks, likely another copy/paste oversight, will update accordingly
|
||
## Properties | ||
|
||
* `firewall_id`, `firewall_name`, `firewall_directions` |
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.
The properties are all the plural forms - so firewall_ids
, firewall_names
. Typical would be to explicitly document each, describing what they are (likely arrays of strings, but what do the Strings mean?)
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.
sure
|
||
# google\_compute\_zones | ||
|
||
Use the `google_compute_zones` InSpec audit resource to test properties of all GCP compute zones for a project in a particular zone. |
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.
...all or a filtered group of ...
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.
will add
|
||
### Test that there are no more than a specified number of zones available for the project | ||
|
||
describe google_compute_zones(project: 'chef-inspec-gcp') do |
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, similar comments as on firewalls
. Use count
instead of entries.count
. You do actually have filter criteria. Your properties are plural.
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.
agreed
filter_table_config.add(:firewall_ids, field: :firewall_id) | ||
filter_table_config.add(:firewall_names, field: :firewall_name) | ||
filter_table_config.add(:firewall_directions, field: :firewall_direction) | ||
filter_table_config.add(:colors, field: :color, type: :simple) |
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.
Colors appears to be copypasta. Check your other plurals 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.
yup, removed
def fetch_data | ||
firewall_rows = [] | ||
catch_gcp_errors do | ||
@firewalls = @gcp.gcp_compute_client.list_firewalls(@project) |
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.
Do you need to paginate?
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.
The API supports pagination [https://cloud.google.com/compute/docs/reference/rest/v1/firewalls/list] but the default is 500 so it's probably fine to skip that 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.
thanks - just saw all the comments, will add pagination as it shouldn't take too much
it { should exist } | ||
its('entries.count') { should be <= 100} | ||
# assume this is a development setup for a moment | ||
its('firewall_names') { should include "default-allow-ssh" } |
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 also test firewall_ids - any property you expose. To obtain a value to check for, you can use the "output the ID in terraform, translate to YAML, read as an attribute" approach. AWS does this. Other methods also work.
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.
added tests for the plural resource id parameters
…r tables as they are now automatic, also removing copy paste error “color” property. Signed-off-by: Stuart Paterson <spaterson@chef.io>
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.
Thanks for taking this on @skpaterson! I recognize that this is early work, but some general comments:
-
I suspect a user will care about doing checks against FW rules to ensure protocols/ports/labels are present/absent. I'm new to InSpec, but stating intent such as 'ensure tcp:22 does not allow 0.0.0.0/0' would be very valuable for users.
-
I don't think there is any real utility for customers in checking
kind
(e.g.compute#zone
). It's extra work to strip it out, so it's probably fine to leave as-is. However, I'd just change up the examples to not do any checks against it.
|
||
The following examples show how to use this InSpec audit resource. | ||
|
||
### Test that a GCP compute zone 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.
Suggest flipping logic to test that a specified zone does 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.
sure can do - thanks
def fetch_data | ||
firewall_rows = [] | ||
catch_gcp_errors do | ||
@firewalls = @gcp.gcp_compute_client.list_firewalls(@project) |
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.
The API supports pagination [https://cloud.google.com/compute/docs/reference/rest/v1/firewalls/list] but the default is 500 so it's probably fine to skip that for now.
…roperties across firewalls, zones and instances. * Updated tests to use count instead of entries.count. * Added an up? method to google_compute_zone and associated example. Also included in test. Signed-off-by: Stuart Paterson <spaterson@chef.io>
…s. Also, flip logic to test for existence of a zone in documented example. Signed-off-by: Stuart Paterson <spaterson@chef.io>
Add configuration flag for optionally executing tests that rely on gcloud/grep. Correct zones filter criteria and properties documentation. Signed-off-by: Stuart Paterson <spaterson@chef.io>
Thanks for the feedback, hopefully the comments should all now be addressed (famous last words...) |
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.
Let's ship it :-) I still have some comments, but mainly aimed at getting it to be core-mergable.
Like core is perfect quality :-/
|
||
This resource supports the following filter criteria: `firewall_id`; `firewall_name`; and `firewall_direction`. Any of these may be used with `where`, as a block or as a method. | ||
|
||
## Properties |
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.
Let's go ahead and ship this, but typically we include one example per property. Users links straight to the property, then copy and paste the example.
<br> | ||
|
||
## Properties | ||
|
||
* `cpu_platform`, `creation_timestamp`, `deletion_protection`, `disks`, `id`, `kind`, `label_fingerprint`, `machine_type`, `metadata`, `name`, `network_interfaces`, `scheduling`, `start_restricted`, `status`, `tags`, `zone` | ||
* `cpu_platform`, `creation_timestamp`, `deletion_protection`, `disks`, `id`, `kind`, `label_fingerprint`, `machine_type`, `metadata`, `name`, `network_interfaces`, `scheduling`, `start_restricted`, `status`, `tags`, `zone`, `labels_keys`, `labels_values` |
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 be reluctant to add anything you want to remove later. It's very hard to deprecate once thing are in the wild. Since this isn't in core, let's ship it, but keep in mind if we have doubts about something, better to not expose it.
<br> | ||
|
||
## Properties | ||
|
||
* `cpu_platform`, `creation_timestamp`, `deletion_protection`, `disks`, `id`, `kind`, `label_fingerprint`, `machine_type`, `metadata`, `name`, `network_interfaces`, `scheduling`, `start_restricted`, `status`, `tags`, `zone` | ||
* `cpu_platform`, `creation_timestamp`, `deletion_protection`, `disks`, `id`, `kind`, `label_fingerprint`, `machine_type`, `metadata`, `name`, `network_interfaces`, `scheduling`, `start_restricted`, `status`, `tags`, `zone`, `labels_keys`, `labels_values` |
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.
@@ -57,11 +57,12 @@ The following examples show how to use this InSpec audit resource. | |||
|
|||
## Filter Criteria | |||
|
|||
This resource currently does not support any filter criteria; it will always fetch all instances in the zone. | |||
This resource supports the following filter criteria: `instance_id` and `instance_name`. Either of these may be used with `where`, as a block or as a method. |
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.
If you need it for a blog post, let's ship it, but please make a tech debt issue - people fiind where
very confusing, and need examples.
filter_table_config = FilterTable.create | ||
filter_table_config.add(:firewall_ids, field: :firewall_id) | ||
filter_table_config.add(:firewall_names, field: :firewall_name) | ||
filter_table_config.add(:firewall_directions, field: :firewall_direction) |
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 good as-is, but you might consider adding style: :simple
- having this de-duplicated might be useful (or at least having individual entries for each rule isn't very useful).
Includes resources required for upcoming blog post.