chef-provisioning-aws icon indicating copy to clipboard operation
chef-provisioning-aws copied to clipboard

Not possible to define Security Groups

Open lfrodrigues opened this issue 9 years ago • 14 comments

Current when creating RDS instance is not possible to select which security group will be used (currently default is selected)

lfrodrigues avatar Oct 14 '15 21:10 lfrodrigues

It looks like a shortcut is available to access the additional parameters that aren't exposed via attributes/properties, called additional_options which accepts a hash of keys/values - You need to specify what additional parameters you want to "make available" within the , such as db_security_groups in your case. I snipped the following out of the SDK documentation to show what is possible:

  • :db_security_groups - (Array<) A list of DB Security Groups to associate with this DB Instance.
  • :vpc_security_group_ids - (Array<) A list of EC2 VPC Security Groups to associate with this DB Instance. Default: The default EC2 VPC Security Group for the DB Subnet group's VPC.

As for the Chef Provisioning resource itself, a reasonable example is in the spec tests:

aws_rds_instance "test-rds-instance2" do
  engine "postgres"
  publicly_accessible false
  db_instance_class "db.t1.micro"
  master_username "thechief"
  master_user_password "securesecure"
  multi_az false
  allocated_storage 5
  additional_options(multi_az: true, backup_retention_period: 2)
end

So in your case you could change the additional_options to (for example):

additional_options(db_security_groups: %w(my-db-sg1 my-db-sg2))

I haven't actually used the RDS instance resource yet, but it's only a matter of time! I'm sure the resources will also get a little more polished over time and introduce some of the popular options as first-class attributes/properties (or not, who knows!)

HTH. :-)

lskillen avatar Oct 14 '15 22:10 lskillen

I just tried it in a test and it doesn't produce any results. Am I missing something?

aws_rds_instance "rds-core" do
  engine "postgres"
  publicly_accessible false
  db_instance_class "db.t1.micro"
  master_username "dbadmin"
  master_user_password "test" 
  multi_az true
  db_subnet_group_name "db-subnet-coredb"
  allocated_storage 10
  additional_options(db_security_groups: 'security-group-core-rds')
end

lfrodrigues avatar Oct 14 '15 23:10 lfrodrigues

Fwiw, vpc_security_group_ids really wants the ids, not the names as with db_security_groups.

josb avatar Oct 14 '15 23:10 josb

Thanks @josb but still no change:

security_group_core_rds = aws_security_group 'security-group-core-rds' do
  vpc 'vpc-my'
  inbound_rules [
    {:port => 5432, :protocol => :tcp, :sources => ["172.16.16.0/20"] },
  ]
  aws_tags :chef_type => "aws_security_group"
end


aws_rds_instance "rds-core" do
  engine "postgres"
  publicly_accessible false
  db_instance_class "db.t1.micro"
  master_username "dbadmin"
  master_user_password "test" 
  multi_az true
  db_subnet_group_name "db-subnet-coredb"
  allocated_storage 10
  additional_options(db_security_groups: security_group_core_rds.aws_object.id)
end

lfrodrigues avatar Oct 14 '15 23:10 lfrodrigues

@lfrodrigues A couple of points:

  1. I'm not 100% certain, but I think you need to provide an array of the values, rather than a string (not sure if the SDK API converts it into an array or not).
  2. You need to ensure you use vpc_security_group_ids instead of db_security_groups (note: I should have realised earlier you needed the VPC variant!)
  3. Depending on whether security-group-core-rds exists or not, you might need to wrap security_group_core_rds.aws_object.id in a lazy block to ensure that the value is only accessed during convergence.

So maybe something like this (untested):

aws_rds_instance "rds-core" do
  engine "postgres"
  publicly_accessible false
  db_instance_class "db.t1.micro"
  master_username "dbadmin"
  master_user_password "test" 
  multi_az true
  db_subnet_group_name "db-subnet-coredb"
  allocated_storage 10
  additional_options lazy {
    {
      vpc_security_groups_ids: [security_group_core_rds.aws_object.id]
    }
  }
end

If it works, great, I can do something similar when I need it later!

HTH. :-)

lskillen avatar Oct 14 '15 23:10 lskillen

Here's what I use:

libraries/recipe_helper.rb:

module Helper
  def get_aws_object(klass, name)
    klass.get_aws_object(
      name,
      run_context: run_context,
      driver: run_context.chef_provisioning.current_driver,
      managed_entry_store: ::Chef::Provisioning.chef_managed_entry_store(run_context.cheffish.current_chef_server)
    )
  end
end

In the recipe:

aws_rds_instance "mydb" do
  # <other options>
  extend Helper
  additional_options(
    lazy do
    {
      # We need the sg ids here
      vpc_security_group_ids: [
        get_aws_object(Chef::Resource::AwsSecurityGroup, "foo").id,
        get_aws_object(Chef::Resource::AwsSecurityGroup, "bar").id
      ],
    }
    end
  )
end

Alternatively, if you have the Chef resource object, you can use obj.aws_object.id instead of the helper method (which uses the resource name), as @lskillen points out.

josb avatar Oct 15 '15 00:10 josb

@josb Great! :+1: I've actually got something similar in my libraries as well. Probably makes a good candidate for something that can be made available in the provisioning library; perhaps monkey patched into Chef::DSL::Recipe and perhaps with additional helpers such as get_aws_security_group_id(name or resource).

lskillen avatar Oct 15 '15 08:10 lskillen

@lfrodrigues I'm going to go ahead and close this because I think the documentation explains the additional_options attribute and the confusion was around what AWS key to use (vpc_security_group_ids). Please re-open if you are still having issues!

tyler-ball avatar Oct 16 '15 20:10 tyler-ball

@tyler-ball Security groups are essential to define a RDS, shouldn't they be added as attributes and allow to reference an aws_security_group directly?

lfrodrigues avatar Oct 18 '15 12:10 lfrodrigues

@lfrodrigues You're right - it would be much nicer to specify

aws_rds_instance "mydb" do
  vpc_security_group_ids: ["foo", "bar]
  additional_options(...)
end

than

aws_rds_instance "mydb" do
  # <other options>
  extend Helper
  additional_options(
    lazy do
    {
      # We need the sg ids here
      vpc_security_group_ids: [
        get_aws_object(Chef::Resource::AwsSecurityGroup, "foo").id,
        get_aws_object(Chef::Resource::AwsSecurityGroup, "bar").id
      ],
    }
    end
  )
end

tyler-ball avatar Oct 27 '15 13:10 tyler-ball

:+1: to that last comment.

jeffbyrnes avatar Mar 04 '16 18:03 jeffbyrnes

I'm trying to create a aws_rds_instance using an additional_options(vpc_security_group_ids: [securitygroup1.aws_object.id]) line. When I run it, I get an InvalidParameterCombination, RDS does not exist at the default VPC.

[2017-01-02T23:07:57-03:00] INFO: [Aws::RDS::Client 400 1.728897 0 retries] create_db_instance(vpc_security_group_ids:["sg-c83896a1"],db_instance_identifier:"stage-rds-instance",allocated_storage:5,engine:"mysql",db_instance_class:"db.t2.micro",master_username:"root",master_user_password:"secretsecret",multi_az:false,publicly_accessible:false) Aws::RDS::Errors::InvalidParameterCombination Database is in vpc-2653a64f, but Ec2 Security Group sg-c83896a1 is in vpc-08409461

The Security Group is defined as:

securitygroup1 = aws_security_group 'be-sec-group' do
 # options
end

pulpo avatar Jan 03 '17 02:01 pulpo

@pulpo have you tried specifying the vpc in the above reference to securitygroup1?

josb avatar Jan 09 '17 23:01 josb

I missed the db_subnet_group_name at the aws_rds_instance resource, at the aws_security_group just the subnets where needed. I have it working now.

aws_rds_subnet_group "stage-db-subnet-group" do
    description "some_description"
    subnets ['octo-stage-private-a', 'octo-stage-private-c']
end

aws_rds_instance = aws_rds_instance "stage-rds-instance" do
  engine "mysql"
  publicly_accessible false
  db_instance_class "db.t2.micro"
  master_username data['stage']['db_username'] 
  master_user_password data['stage']['db_password'] 
  allocated_storage 5
  multi_az false 
  db_subnet_group_name 'stage-db-subnet-group'
  additional_options lazy {
    {
      vpc_security_group_ids: [securitygroupdb.aws_object.id]
    }
  }
end

thanks @josb

pulpo avatar Jan 10 '17 02:01 pulpo