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

     1  package alicloud
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/denverdino/aliyungo/ecs"
     6  	"github.com/hashicorp/terraform/helper/resource"
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  	"strings"
     9  	"time"
    10  )
    11  
    12  func resourceAliyunSecurityGroupRule() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceAliyunSecurityGroupRuleCreate,
    15  		Read:   resourceAliyunSecurityGroupRuleRead,
    16  		Delete: resourceAliyunSecurityGroupRuleDelete,
    17  
    18  		Schema: map[string]*schema.Schema{
    19  			"type": &schema.Schema{
    20  				Type:         schema.TypeString,
    21  				Required:     true,
    22  				ForceNew:     true,
    23  				ValidateFunc: validateSecurityRuleType,
    24  				Description:  "Type of rule, ingress (inbound) or egress (outbound).",
    25  			},
    26  
    27  			"ip_protocol": &schema.Schema{
    28  				Type:         schema.TypeString,
    29  				Required:     true,
    30  				ForceNew:     true,
    31  				ValidateFunc: validateSecurityRuleIpProtocol,
    32  			},
    33  
    34  			"nic_type": &schema.Schema{
    35  				Type:         schema.TypeString,
    36  				Optional:     true,
    37  				ForceNew:     true,
    38  				Computed:     true,
    39  				ValidateFunc: validateSecurityRuleNicType,
    40  			},
    41  
    42  			"policy": &schema.Schema{
    43  				Type:         schema.TypeString,
    44  				Optional:     true,
    45  				ForceNew:     true,
    46  				ValidateFunc: validateSecurityRulePolicy,
    47  			},
    48  
    49  			"port_range": &schema.Schema{
    50  				Type:     schema.TypeString,
    51  				Required: true,
    52  				ForceNew: true,
    53  			},
    54  
    55  			"priority": &schema.Schema{
    56  				Type:         schema.TypeInt,
    57  				Optional:     true,
    58  				ForceNew:     true,
    59  				ValidateFunc: validateSecurityPriority,
    60  			},
    61  
    62  			"security_group_id": &schema.Schema{
    63  				Type:     schema.TypeString,
    64  				Required: true,
    65  				ForceNew: true,
    66  			},
    67  
    68  			"cidr_ip": &schema.Schema{
    69  				Type:     schema.TypeString,
    70  				Optional: true,
    71  				ForceNew: true,
    72  			},
    73  
    74  			"source_security_group_id": &schema.Schema{
    75  				Type:     schema.TypeString,
    76  				Optional: true,
    77  				ForceNew: true,
    78  			},
    79  
    80  			"source_group_owner_account": &schema.Schema{
    81  				Type:     schema.TypeString,
    82  				Optional: true,
    83  				ForceNew: true,
    84  			},
    85  		},
    86  	}
    87  }
    88  
    89  func resourceAliyunSecurityGroupRuleCreate(d *schema.ResourceData, meta interface{}) error {
    90  	client := meta.(*AliyunClient)
    91  	conn := client.ecsconn
    92  
    93  	direction := d.Get("type").(string)
    94  	sgId := d.Get("security_group_id").(string)
    95  	ptl := d.Get("ip_protocol").(string)
    96  	port := d.Get("port_range").(string)
    97  	nicType := d.Get("nic_type").(string)
    98  
    99  	var autherr error
   100  	switch GroupRuleDirection(direction) {
   101  	case GroupRuleIngress:
   102  		args, err := buildAliyunSecurityIngressArgs(d, meta)
   103  		if err != nil {
   104  			return err
   105  		}
   106  		autherr = conn.AuthorizeSecurityGroup(args)
   107  	case GroupRuleEgress:
   108  		args, err := buildAliyunSecurityEgressArgs(d, meta)
   109  		if err != nil {
   110  			return err
   111  		}
   112  		autherr = conn.AuthorizeSecurityGroupEgress(args)
   113  	default:
   114  		return fmt.Errorf("Security Group Rule must be type 'ingress' or type 'egress'")
   115  	}
   116  
   117  	if autherr != nil {
   118  		return fmt.Errorf(
   119  			"Error authorizing security group rule type %s: %s",
   120  			direction, autherr)
   121  	}
   122  
   123  	d.SetId(sgId + ":" + direction + ":" + ptl + ":" + port + ":" + nicType)
   124  
   125  	return resourceAliyunSecurityGroupRuleRead(d, meta)
   126  }
   127  
   128  func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{}) error {
   129  	client := meta.(*AliyunClient)
   130  	parts := strings.Split(d.Id(), ":")
   131  	sgId := parts[0]
   132  	direction := parts[1]
   133  	ip_protocol := parts[2]
   134  	port_range := parts[3]
   135  	nic_type := parts[4]
   136  	rule, err := client.DescribeSecurityGroupRule(sgId, direction, nic_type, ip_protocol, port_range)
   137  
   138  	if err != nil {
   139  		if notFoundError(err) {
   140  			d.SetId("")
   141  			return nil
   142  		}
   143  		return fmt.Errorf("Error SecurityGroup rule: %#v", err)
   144  	}
   145  
   146  	d.Set("type", rule.Direction)
   147  	d.Set("ip_protocol", strings.ToLower(string(rule.IpProtocol)))
   148  	d.Set("nic_type", rule.NicType)
   149  	d.Set("policy", strings.ToLower(string(rule.Policy)))
   150  	d.Set("port_range", rule.PortRange)
   151  	d.Set("priority", rule.Priority)
   152  	d.Set("security_group_id", sgId)
   153  	//support source and desc by type
   154  	if GroupRuleDirection(direction) == GroupRuleIngress {
   155  		d.Set("cidr_ip", rule.SourceCidrIp)
   156  		d.Set("source_security_group_id", rule.SourceGroupId)
   157  		d.Set("source_group_owner_account", rule.SourceGroupOwnerAccount)
   158  	} else {
   159  		d.Set("cidr_ip", rule.DestCidrIp)
   160  		d.Set("source_security_group_id", rule.DestGroupId)
   161  		d.Set("source_group_owner_account", rule.DestGroupOwnerAccount)
   162  	}
   163  
   164  	return nil
   165  }
   166  
   167  func deleteSecurityGroupRule(d *schema.ResourceData, meta interface{}) error {
   168  	client := meta.(*AliyunClient)
   169  	ruleType := d.Get("type").(string)
   170  
   171  	if GroupRuleDirection(ruleType) == GroupRuleIngress {
   172  		args, err := buildAliyunSecurityIngressArgs(d, meta)
   173  		if err != nil {
   174  			return err
   175  		}
   176  		revokeArgs := &ecs.RevokeSecurityGroupArgs{
   177  			AuthorizeSecurityGroupArgs: *args,
   178  		}
   179  		return client.RevokeSecurityGroup(revokeArgs)
   180  	}
   181  
   182  	args, err := buildAliyunSecurityEgressArgs(d, meta)
   183  
   184  	if err != nil {
   185  		return err
   186  	}
   187  	revokeArgs := &ecs.RevokeSecurityGroupEgressArgs{
   188  		AuthorizeSecurityGroupEgressArgs: *args,
   189  	}
   190  	return client.RevokeSecurityGroupEgress(revokeArgs)
   191  }
   192  
   193  func resourceAliyunSecurityGroupRuleDelete(d *schema.ResourceData, meta interface{}) error {
   194  	client := meta.(*AliyunClient)
   195  	parts := strings.Split(d.Id(), ":")
   196  	sgId, direction, ip_protocol, port_range, nic_type := parts[0], parts[1], parts[2], parts[3], parts[4]
   197  
   198  	return resource.Retry(5*time.Minute, func() *resource.RetryError {
   199  		err := deleteSecurityGroupRule(d, meta)
   200  
   201  		if err != nil {
   202  			resource.RetryableError(fmt.Errorf("Security group rule in use - trying again while it is deleted."))
   203  		}
   204  
   205  		_, err = client.DescribeSecurityGroupRule(sgId, direction, nic_type, ip_protocol, port_range)
   206  		if err != nil {
   207  			if notFoundError(err) {
   208  				return nil
   209  			}
   210  			return resource.NonRetryableError(err)
   211  		}
   212  
   213  		return resource.RetryableError(fmt.Errorf("Security group rule in use - trying again while it is deleted."))
   214  	})
   215  
   216  }
   217  
   218  func checkCidrAndSourceGroupId(cidrIp, sourceGroupId string) error {
   219  	if cidrIp == "" && sourceGroupId == "" {
   220  		return fmt.Errorf("Either cidr_ip or source_security_group_id is required.")
   221  	}
   222  
   223  	if cidrIp != "" && sourceGroupId != "" {
   224  		return fmt.Errorf("You should set only one value of cidr_ip or source_security_group_id.")
   225  	}
   226  	return nil
   227  }
   228  func buildAliyunSecurityIngressArgs(d *schema.ResourceData, meta interface{}) (*ecs.AuthorizeSecurityGroupArgs, error) {
   229  	conn := meta.(*AliyunClient).ecsconn
   230  
   231  	args := &ecs.AuthorizeSecurityGroupArgs{
   232  		RegionId: getRegion(d, meta),
   233  	}
   234  
   235  	if v := d.Get("ip_protocol").(string); v != "" {
   236  		args.IpProtocol = ecs.IpProtocol(v)
   237  	}
   238  
   239  	if v := d.Get("port_range").(string); v != "" {
   240  		args.PortRange = v
   241  	}
   242  
   243  	if v := d.Get("policy").(string); v != "" {
   244  		args.Policy = ecs.PermissionPolicy(v)
   245  	}
   246  
   247  	if v := d.Get("priority").(int); v != 0 {
   248  		args.Priority = v
   249  	}
   250  
   251  	if v := d.Get("nic_type").(string); v != "" {
   252  		args.NicType = ecs.NicType(v)
   253  	}
   254  
   255  	cidrIp := d.Get("cidr_ip").(string)
   256  	sourceGroupId := d.Get("source_security_group_id").(string)
   257  	if err := checkCidrAndSourceGroupId(cidrIp, sourceGroupId); err != nil {
   258  		return nil, err
   259  	}
   260  	if cidrIp != "" {
   261  		args.SourceCidrIp = cidrIp
   262  	}
   263  
   264  	if sourceGroupId != "" {
   265  		args.SourceGroupId = sourceGroupId
   266  	}
   267  
   268  	if v := d.Get("source_group_owner_account").(string); v != "" {
   269  		args.SourceGroupOwnerAccount = v
   270  	}
   271  
   272  	sgId := d.Get("security_group_id").(string)
   273  
   274  	sgArgs := &ecs.DescribeSecurityGroupAttributeArgs{
   275  		SecurityGroupId: sgId,
   276  		RegionId:        getRegion(d, meta),
   277  	}
   278  
   279  	_, err := conn.DescribeSecurityGroupAttribute(sgArgs)
   280  	if err != nil {
   281  		return nil, fmt.Errorf("Error get security group %s error: %#v", sgId, err)
   282  	}
   283  
   284  	args.SecurityGroupId = sgId
   285  
   286  	return args, nil
   287  }
   288  
   289  func buildAliyunSecurityEgressArgs(d *schema.ResourceData, meta interface{}) (*ecs.AuthorizeSecurityGroupEgressArgs, error) {
   290  	conn := meta.(*AliyunClient).ecsconn
   291  
   292  	args := &ecs.AuthorizeSecurityGroupEgressArgs{
   293  		RegionId: getRegion(d, meta),
   294  	}
   295  
   296  	if v := d.Get("ip_protocol").(string); v != "" {
   297  		args.IpProtocol = ecs.IpProtocol(v)
   298  	}
   299  
   300  	if v := d.Get("port_range").(string); v != "" {
   301  		args.PortRange = v
   302  	}
   303  
   304  	if v := d.Get("policy").(string); v != "" {
   305  		args.Policy = ecs.PermissionPolicy(v)
   306  	}
   307  
   308  	if v := d.Get("priority").(int); v != 0 {
   309  		args.Priority = v
   310  	}
   311  
   312  	if v := d.Get("nic_type").(string); v != "" {
   313  		args.NicType = ecs.NicType(v)
   314  	}
   315  
   316  	cidrIp := d.Get("cidr_ip").(string)
   317  	sourceGroupId := d.Get("source_security_group_id").(string)
   318  	if err := checkCidrAndSourceGroupId(cidrIp, sourceGroupId); err != nil {
   319  		return nil, err
   320  	}
   321  	if cidrIp != "" {
   322  		args.DestCidrIp = cidrIp
   323  	}
   324  
   325  	if sourceGroupId != "" {
   326  		args.DestGroupId = sourceGroupId
   327  	}
   328  
   329  	if v := d.Get("source_group_owner_account").(string); v != "" {
   330  		args.DestGroupOwnerAccount = v
   331  	}
   332  
   333  	sgId := d.Get("security_group_id").(string)
   334  
   335  	sgArgs := &ecs.DescribeSecurityGroupAttributeArgs{
   336  		SecurityGroupId: sgId,
   337  		RegionId:        getRegion(d, meta),
   338  	}
   339  
   340  	_, err := conn.DescribeSecurityGroupAttribute(sgArgs)
   341  	if err != nil {
   342  		return nil, fmt.Errorf("Error get security group %s error: %#v", sgId, err)
   343  	}
   344  
   345  	args.SecurityGroupId = sgId
   346  
   347  	return args, nil
   348  }