github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_default_security_group.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/aws/aws-sdk-go/aws"
     8  	"github.com/aws/aws-sdk-go/service/ec2"
     9  	"github.com/hashicorp/errwrap"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  )
    12  
    13  func resourceAwsDefaultSecurityGroup() *schema.Resource {
    14  	// reuse aws_security_group_rule schema, and methods for READ, UPDATE
    15  	dsg := resourceAwsSecurityGroup()
    16  	dsg.Create = resourceAwsDefaultSecurityGroupCreate
    17  	dsg.Delete = resourceAwsDefaultSecurityGroupDelete
    18  
    19  	// Descriptions cannot be updated
    20  	delete(dsg.Schema, "description")
    21  
    22  	// name is a computed value for Default Security Groups and cannot be changed
    23  	delete(dsg.Schema, "name_prefix")
    24  	dsg.Schema["name"] = &schema.Schema{
    25  		Type:     schema.TypeString,
    26  		Computed: true,
    27  	}
    28  
    29  	// We want explicit management of Rules here, so we do not allow them to be
    30  	// computed. Instead, an empty config will enforce just that; removal of the
    31  	// rules
    32  	dsg.Schema["ingress"].Computed = false
    33  	dsg.Schema["egress"].Computed = false
    34  	return dsg
    35  }
    36  
    37  func resourceAwsDefaultSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error {
    38  	conn := meta.(*AWSClient).ec2conn
    39  	securityGroupOpts := &ec2.DescribeSecurityGroupsInput{
    40  		Filters: []*ec2.Filter{
    41  			&ec2.Filter{
    42  				Name:   aws.String("group-name"),
    43  				Values: []*string{aws.String("default")},
    44  			},
    45  		},
    46  	}
    47  
    48  	var vpcId string
    49  	if v, ok := d.GetOk("vpc_id"); ok {
    50  		vpcId = v.(string)
    51  		securityGroupOpts.Filters = append(securityGroupOpts.Filters, &ec2.Filter{
    52  			Name:   aws.String("vpc-id"),
    53  			Values: []*string{aws.String(vpcId)},
    54  		})
    55  	}
    56  
    57  	var err error
    58  	log.Printf("[DEBUG] Commandeer Default Security Group: %s", securityGroupOpts)
    59  	resp, err := conn.DescribeSecurityGroups(securityGroupOpts)
    60  	if err != nil {
    61  		return fmt.Errorf("Error creating Default Security Group: %s", err)
    62  	}
    63  
    64  	var g *ec2.SecurityGroup
    65  	if vpcId != "" {
    66  		// if vpcId contains a value, then we expect just a single Security Group
    67  		// returned, as default is a protected name for each VPC, and for each
    68  		// Region on EC2 Classic
    69  		if len(resp.SecurityGroups) != 1 {
    70  			return fmt.Errorf("[ERR] Error finding default security group; found (%d) groups: %s", len(resp.SecurityGroups), resp)
    71  		}
    72  		g = resp.SecurityGroups[0]
    73  	} else {
    74  		// we need to filter through any returned security groups for the group
    75  		// named "default", and does not belong to a VPC
    76  		for _, sg := range resp.SecurityGroups {
    77  			if sg.VpcId == nil && *sg.GroupName == "default" {
    78  				g = sg
    79  			}
    80  		}
    81  	}
    82  
    83  	if g == nil {
    84  		return fmt.Errorf("[ERR] Error finding default security group: no matching group found")
    85  	}
    86  
    87  	d.SetId(*g.GroupId)
    88  
    89  	log.Printf("[INFO] Default Security Group ID: %s", d.Id())
    90  
    91  	if err := setTags(conn, d); err != nil {
    92  		return err
    93  	}
    94  
    95  	if err := revokeDefaultSecurityGroupRules(meta, g); err != nil {
    96  		return errwrap.Wrapf("{{err}}", err)
    97  	}
    98  
    99  	return resourceAwsSecurityGroupUpdate(d, meta)
   100  }
   101  
   102  func resourceAwsDefaultSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error {
   103  	log.Printf("[WARN] Cannot destroy Default Security Group. Terraform will remove this resource from the state file, however resources may remain.")
   104  	d.SetId("")
   105  	return nil
   106  }
   107  
   108  func revokeDefaultSecurityGroupRules(meta interface{}, g *ec2.SecurityGroup) error {
   109  	conn := meta.(*AWSClient).ec2conn
   110  
   111  	log.Printf("[WARN] Removing all ingress and egress rules found on Default Security Group (%s)", *g.GroupId)
   112  	if len(g.IpPermissionsEgress) > 0 {
   113  		req := &ec2.RevokeSecurityGroupEgressInput{
   114  			GroupId:       g.GroupId,
   115  			IpPermissions: g.IpPermissionsEgress,
   116  		}
   117  
   118  		log.Printf("[DEBUG] Revoking default egress rules for Default Security Group for %s", *g.GroupId)
   119  		if _, err := conn.RevokeSecurityGroupEgress(req); err != nil {
   120  			return fmt.Errorf(
   121  				"Error revoking default egress rules for Default Security Group (%s): %s",
   122  				*g.GroupId, err)
   123  		}
   124  	}
   125  	if len(g.IpPermissions) > 0 {
   126  		// a limitation in EC2 Classic is that a call to RevokeSecurityGroupIngress
   127  		// cannot contain both the GroupName and the GroupId
   128  		for _, p := range g.IpPermissions {
   129  			for _, uigp := range p.UserIdGroupPairs {
   130  				if uigp.GroupId != nil && uigp.GroupName != nil {
   131  					uigp.GroupName = nil
   132  				}
   133  			}
   134  		}
   135  		req := &ec2.RevokeSecurityGroupIngressInput{
   136  			GroupId:       g.GroupId,
   137  			IpPermissions: g.IpPermissions,
   138  		}
   139  
   140  		log.Printf("[DEBUG] Revoking default ingress rules for Default Security Group for (%s): %s", *g.GroupId, req)
   141  		if _, err := conn.RevokeSecurityGroupIngress(req); err != nil {
   142  			return fmt.Errorf(
   143  				"Error revoking default ingress rules for Default Security Group (%s): %s",
   144  				*g.GroupId, err)
   145  		}
   146  	}
   147  
   148  	return nil
   149  }