chef-boneyard / chef-provisioning-aws

AWS driver and resources for Chef that uses the AWS SDK
Apache License 2.0
142 stars 121 forks source link

Security Group Data Bag Quote Parsing for Port Ranges #477

Open ajeba99 opened 8 years ago

ajeba99 commented 8 years ago

So I am trying to build the networking portion of my customer environment in AWS using data bags.

Here is my Chef environment ...

chef -v
Chef Development Kit Version: 0.12.0
chef-client version: 12.8.1
berks version: 4.3.0
kitchen version: 1.6.0

chef-provisioning (1.6.0)
chef-provisioning-aws (1.8.0)
chef-provisioning-azure (0.5.0)
chef-provisioning-fog (0.16.0)
chef-provisioning-vagrant (0.11.0)

I am having two issues.

First, when security groups are being created, if I am defining a range or list of ports, yet only the first port is being acknowledged. Here is my script ...

devices["securitygroups"].each do |securitygroups|
  aws_security_group securitygroups["security_group_name"] do
    vpc securitygroups["security_group_vpc"]

    @inboundrules = []
    @outboundrules = []

    securitygroups["inbound_rules"].each do |inbound|
      inboundopts = {}
      inboundopts = {
        port: inbound["port"],
        protocol: inbound["protocol"],
        sources: inbound["sources"]
      }
     @inboundrules << inboundopts
    end

    securitygroups["outbound_rules"].each do |outbound|
      outboundopts = {}
      outboundopts = {
        port: outbound["port"],
        protocol: outbound["protocol"],
        destinations: outbound["destinations"]
      }
     @outboundrules << outboundopts
    end

    inbound_rules @inboundrules
    outbound_rules @outboundrules
    aws_tags description: securitygroups["security_group_description"]
  end
end

Here is the security group portion of my data bag the script is pulling from ...

"securitygroups" : [
{
  "security_group_name" : "TestEnv_SG",
  "security_group_vpc" : "TestEnv_VPC",
  "security_group_description" : "aws_sg_TestEnv",
  "inbound_rules" : [
    {
      "port" : "80, 443",
      "protocol" : "tcp",
      "sources" : "0.0.0.0/0"
    },
    {
      "port" : "1024..2048",
      "protocol" : "tcp",
      "sources" : "127.0.0.1/32"
    },
    {
      "port" : "80, 443",
      "protocol" : "udp",
      "sources" : "1.1.1.0/24"
    }
  ],
  "outbound_rules" : [
    {
      "port" : "81",
      "protocol" : "tcp",
      "destinations" : "0.0.0.0/0"
    },
    {
      "port" : "2048..4096",
      "protocol" : "tcp",
      "destinations" : "TestEnv_SG"
    },
    {
      "port" : "8080, 8081",
      "protocol" : "tcp",
      "destinations" : "2.2.2.0/24"
    }
  ]
}
],

... And here is the output from the log ...

[2015-11-16T11:21:17-06:00] INFO: [AWS EC2 200 0.272027 0 retries] authorize_security_group_egress(:group_id=>"sg-c6f5a1a2",:ip_permissions=>[{:from_port=>2048,:ip_protocol=>"tcp",:to_port=>2048,:user_id_group_pairs=>[{:group_id=>"sg-c6f5a1a2",:user_id=>"115481970544"}]}])

- authorize group TestEnv_SG (sg-c6f5a1a2) to send traffic to sg-c6f5a1a2 on port_range "2048..4096" with protocol tcp
However, when I check the AWS Security Group in the GUI I only see the first port was created for this outbound rule (port 2048). This appears to be an issues with parsing quotes. You can even see this in the examples. Most (maybe all) options that involve numbers don't have any quotes around them. I cannot do this in json as it requires quotes. In my json data bag, when I am only using one number I don't use quotes to be able to get around this design. Yet when dealing with port ranges I must use quotes. How do I work around this?

Second, when I hit up-arrow and enter to just simply rerun the command again I get the following ...

[2015-11-16T11:29:26-06:00] INFO: [AWS EC2 400 0.272027 0 retries] authorize_security_group_egress(:group_id=>"sg-eaf7a38e",:ip_permissions=>[{:from_port=>81,:ip_protocol=>"tcp",:ip_ranges=>[{:cidr_ip=>"0.0.0.0/0"}],:to_port=>81}]) AWS::EC2::Errors::InvalidPermission::Duplicate the specified rule "peer: 0.0.0.0/0, TCP, from port: 81, to port: 81, ALLOW" already exists

================================================================================
Error executing action `create` on resource 'aws_security_group[TestEnv_SG]'
================================================================================

AWS::EC2::Errors::InvalidPermission::Duplicate
----------------------------------------------
the specified rule "peer: 0.0.0.0/0, TCP, from port: 81, to port: 81, ALLOW" already exists

It seems it's not doing what it's supposed to on subsequent runs.

eheydrick commented 8 years ago

Take a look at https://github.com/chef/chef-provisioning-aws/issues/398#issuecomment-159152224 to see the solution I found using the ranger gem to turn the string from the databag into a range that chef-provisioning-aws expects.

ajeba99 commented 8 years ago

Right, I do appreciate the potential work around but I am looking for this to work like other parts Chef Provisioning when using data bags.