inspec-aws icon indicating copy to clipboard operation
inspec-aws copied to clipboard

Feature Request: Add 'allow_in' & 'allow_out' for 'aws_security_groups'

Open evgmoskalenko opened this issue 6 years ago • 9 comments

🎛 Description

Please add:

  • allow_in
  • allow_out
  • allow_in_only
  • allow_out_only

for 'aws_security_groups' as done for 'aws_security_group'.

Something like this:

all_groups = aws_security_groups

describe all_groups.where(vpc_id: 'vpc-00120123') do
  it { should allow_in(ipv4_range: "0.0.0.0/0", port: 80)}
  it { should_not allow_in(ipv4_range: "0.0.0.0/0", port: 22)}
end

This will be useful if the instance has several security groups to abstracting on behalf of the group id, group name and etc. It will be helpful for infrastructure tests. Thanks.. :-)

evgmoskalenko avatar Oct 29 '18 19:10 evgmoskalenko

It will be useful for my tests as well

kchistova avatar Oct 30 '18 08:10 kchistova

Yeah, +1 to this, just had recent work that we would benefit from this capability.

Caprowni avatar Nov 16 '18 12:11 Caprowni

Just to get the semantics down, your example:

describe aws_security_groups.where(vpc_id: 'vpc-00120123') do
  it { should allow_in(ipv4_range: "0.0.0.0/0", port: 80)}
  it { should_not allow_in(ipv4_range: "0.0.0.0/0", port: 22)}
end

would mean: "Consider all security groups in VPC vpc-00120123. To be correct, the following facts must be true of each of the security groups individually:

  • each security group must allow in port 80 from ipv4 "anywhere"
  • each security group must NOT allow in port 22 from ipv4 "anywhere" "

In other words, if someone were to implement the allow_* matchers on the plural aws_security_groups, they would behave in an 'ALL' capacity, not an 'ANY' capacity. Is that what you'd like?

clintoncwolfe avatar Nov 16 '18 15:11 clintoncwolfe

Implementation-wise, it's fairly straightforward to make a matcher that does this.

However, would you also be wanting this to act as a filter criterion - in other words, something you could use in where?

That would change the OP's example to something like this for the SSH portion:

vpc_groups = aws_security_groups.where(vpc_id: 'vpc-00120123')
describe vpc_groups.where { allow_in(ipv4_range: "0.0.0.0/0", port: 22) } do
  it { should_not exist }
end

That doesn't make the port 80 line easy (it's actually easier to say "all of them must do something" using the matcher approach).

Also, the filter criterion approach would be more difficult for implementation, but not impossible.

clintoncwolfe avatar Nov 16 '18 15:11 clintoncwolfe

Yes sort of like that, if possible - and tbh I'm not that familiar with Ruby so not too sure how possible this is - but create an iterator based off the result of describe security groups; example below:

describe aws_security_groups.where(sg_name: /example-*/) do
   Iterate to check sg rules etc.

I tried this out myself (which didn't work as I assume it's not supposed to) via below code:

for i in describe aws_security_groups.where(sg_name: /example-*/) do
   describe aws_security_group.where(groupid: i) do
   it { should_exist }

A bit of background is that, we are currently testing a new environment that is being handed over to us, this requires a bit of verification/continual inspection. We want to avoid having open SG's, drifted SG rules that people have added. I understand that there is a way to do that via the normal aws_security_group resource however if possible I would like to automate it as much as possible so:

A - We don't need to continually update the tests with new SG's B - Allow for auto updates as everything is created/torn down by either CF or Terraform.

Caprowni avatar Nov 16 '18 16:11 Caprowni

You might like this proposal, which is related: #3621

clintoncwolfe avatar Nov 16 '18 16:11 clintoncwolfe

(this comment is a support answer, unrelated to the main topic of the issue).

Your example above, in which you want to find security groups based on criteria, then examine each in detail, is a very common pattern. If you want to do regexes on group names, you can do that:

control "No group starting with quiet should allow in port 22" do
  aws_security_groups.where(group_name: /^quiet/).security_group_ids.each do |security_group_id|
    describe aws_security_group(security_group_id) do
      it { should_not allow_in port: 22 }
    end
  end
end

clintoncwolfe avatar Nov 16 '18 17:11 clintoncwolfe

Yeah looks awesome, it wasn't too clear from documentation that it was possible to do it in the way you just noted, so for time being we can use the example you just gave that works to achieve what we wanted 👍 thanks a bunch!

Caprowni avatar Nov 16 '18 17:11 Caprowni

Its getting somewhat off topic, filtering would be huge bonus for inspec. Right now one needs to invoke AWS ruby sdk to filter out resources for a test in dynamic infrastructure

mahsoud avatar Nov 16 '18 17:11 mahsoud