github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/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  				ConflictsWith: []string{"source_security_group_id"},
    73  			},
    74  
    75  			"source_security_group_id": &schema.Schema{
    76  				Type:          schema.TypeString,
    77  				Optional:      true,
    78  				ForceNew:      true,
    79  				ConflictsWith: []string{"cidr_ip"},
    80  			},
    81  
    82  			"source_group_owner_account": &schema.Schema{
    83  				Type:     schema.TypeString,
    84  				Optional: true,
    85  				ForceNew: true,
    86  			},
    87  		},
    88  	}
    89  }
    90  
    91  func resourceAliyunSecurityGroupRuleCreate(d *schema.ResourceData, meta interface{}) error {
    92  	client := meta.(*AliyunClient)
    93  	conn := client.ecsconn
    94  
    95  	direction := d.Get("type").(string)
    96  	sgId := d.Get("security_group_id").(string)
    97  	ptl := d.Get("ip_protocol").(string)
    98  	port := d.Get("port_range").(string)
    99  	nicType := d.Get("nic_type").(string)
   100  
   101  	var autherr error
   102  	switch GroupRuleDirection(direction) {
   103  	case GroupRuleIngress:
   104  		args, err := buildAliyunSecurityIngressArgs(d, meta)
   105  		if err != nil {
   106  			return err
   107  		}
   108  		autherr = conn.AuthorizeSecurityGroup(args)
   109  	case GroupRuleEgress:
   110  		args, err := buildAliyunSecurityEgressArgs(d, meta)
   111  		if err != nil {
   112  			return err
   113  		}
   114  		autherr = conn.AuthorizeSecurityGroupEgress(args)
   115  	default:
   116  		return fmt.Errorf("Security Group Rule must be type 'ingress' or type 'egress'")
   117  	}
   118  
   119  	if autherr != nil {
   120  		return fmt.Errorf(
   121  			"Error authorizing security group rule type %s: %s",
   122  			direction, autherr)
   123  	}
   124  
   125  	d.SetId(sgId + ":" + direction + ":" + ptl + ":" + port + ":" + nicType)
   126  
   127  	return resourceAliyunSecurityGroupRuleRead(d, meta)
   128  }
   129  
   130  func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{}) error {
   131  	client := meta.(*AliyunClient)
   132  	parts := strings.Split(d.Id(), ":")
   133  	sgId := parts[0]
   134  	direction := parts[1]
   135  	ip_protocol := parts[2]
   136  	port_range := parts[3]
   137  	nic_type := parts[4]
   138  	rule, err := client.DescribeSecurityGroupRule(sgId, direction, nic_type, ip_protocol, port_range)
   139  
   140  	if err != nil {
   141  		if notFoundError(err) {
   142  			d.SetId("")
   143  			return nil
   144  		}
   145  		return fmt.Errorf("Error SecurityGroup rule: %#v", err)
   146  	}
   147  
   148  	d.Set("type", rule.Direction)
   149  	d.Set("ip_protocol", strings.ToLower(string(rule.IpProtocol)))
   150  	d.Set("nic_type", rule.NicType)
   151  	d.Set("policy", strings.ToLower(string(rule.Policy)))
   152  	d.Set("port_range", rule.PortRange)
   153  	d.Set("priority", rule.Priority)
   154  	d.Set("security_group_id", sgId)
   155  	//support source and desc by type
   156  	if GroupRuleDirection(direction) == GroupRuleIngress {
   157  		d.Set("cidr_ip", rule.SourceCidrIp)
   158  		d.Set("source_security_group_id", rule.SourceGroupId)
   159  		d.Set("source_group_owner_account", rule.SourceGroupOwnerAccount)
   160  	} else {
   161  		d.Set("cidr_ip", rule.DestCidrIp)
   162  		d.Set("source_security_group_id", rule.DestGroupId)
   163  		d.Set("source_group_owner_account", rule.DestGroupOwnerAccount)
   164  	}
   165  
   166  	return nil
   167  }
   168  
   169  func deleteSecurityGroupRule(d *schema.ResourceData, meta interface{}) error {
   170  	client := meta.(*AliyunClient)
   171  	ruleType := d.Get("type").(string)
   172  
   173  	if GroupRuleDirection(ruleType) == GroupRuleIngress {
   174  		args, err := buildAliyunSecurityIngressArgs(d, meta)
   175  		if err != nil {
   176  			return err
   177  		}
   178  		revokeArgs := &ecs.RevokeSecurityGroupArgs{
   179  			AuthorizeSecurityGroupArgs: *args,
   180  		}
   181  		return client.RevokeSecurityGroup(revokeArgs)
   182  	}
   183  
   184  	args, err := buildAliyunSecurityEgressArgs(d, meta)
   185  
   186  	if err != nil {
   187  		return err
   188  	}
   189  	revokeArgs := &ecs.RevokeSecurityGroupEgressArgs{
   190  		AuthorizeSecurityGroupEgressArgs: *args,
   191  	}
   192  	return client.RevokeSecurityGroupEgress(revokeArgs)
   193  }
   194  
   195  func resourceAliyunSecurityGroupRuleDelete(d *schema.ResourceData, meta interface{}) error {
   196  	client := meta.(*AliyunClient)
   197  	parts := strings.Split(d.Id(), ":")
   198  	sgId, direction, ip_protocol, port_range, nic_type := parts[0], parts[1], parts[2], parts[3], parts[4]
   199  
   200  	return resource.Retry(5*time.Minute, func() *resource.RetryError {
   201  		err := deleteSecurityGroupRule(d, meta)
   202  
   203  		if err != nil {
   204  			resource.RetryableError(fmt.Errorf("Security group rule in use - trying again while it is deleted."))
   205  		}
   206  
   207  		_, err = client.DescribeSecurityGroupRule(sgId, direction, nic_type, ip_protocol, port_range)
   208  		if err != nil {
   209  			if notFoundError(err) {
   210  				return nil
   211  			}
   212  			return resource.NonRetryableError(err)
   213  		}
   214  
   215  		return resource.RetryableError(fmt.Errorf("Security group rule in use - trying again while it is deleted."))
   216  	})
   217  
   218  }
   219  
   220  func checkCidrAndSourceGroupId(cidrIp, sourceGroupId string) error {
   221  	if cidrIp == "" && sourceGroupId == "" {
   222  		return fmt.Errorf("Either cidr_ip or source_security_group_id is required.")
   223  	}
   224  
   225  	if cidrIp != "" && sourceGroupId != "" {
   226  		return fmt.Errorf("You should set only one value of cidr_ip or source_security_group_id.")
   227  	}
   228  	return nil
   229  }
   230  func buildAliyunSecurityIngressArgs(d *schema.ResourceData, meta interface{}) (*ecs.AuthorizeSecurityGroupArgs, error) {
   231  	conn := meta.(*AliyunClient).ecsconn
   232  
   233  	args := &ecs.AuthorizeSecurityGroupArgs{
   234  		RegionId: getRegion(d, meta),
   235  	}
   236  
   237  	if v := d.Get("ip_protocol").(string); v != "" {
   238  		args.IpProtocol = ecs.IpProtocol(v)
   239  	}
   240  
   241  	if v := d.Get("port_range").(string); v != "" {
   242  		args.PortRange = v
   243  	}
   244  
   245  	if v := d.Get("policy").(string); v != "" {
   246  		args.Policy = ecs.PermissionPolicy(v)
   247  	}
   248  
   249  	if v := d.Get("priority").(int); v != 0 {
   250  		args.Priority = v
   251  	}
   252  
   253  	if v := d.Get("cidr_ip").(string); v != "" {
   254  		args.SourceCidrIp = v
   255  	}
   256  
   257  	if v := d.Get("source_security_group_id").(string); v != "" {
   258  		args.SourceGroupId = v
   259  	}
   260  
   261  	if v := d.Get("source_group_owner_account").(string); v != "" {
   262  		args.SourceGroupOwnerAccount = v
   263  	}
   264  
   265  	sgId := d.Get("security_group_id").(string)
   266  
   267  	sgArgs := &ecs.DescribeSecurityGroupAttributeArgs{
   268  		SecurityGroupId: sgId,
   269  		RegionId:        getRegion(d, meta),
   270  	}
   271  
   272  	group, err := conn.DescribeSecurityGroupAttribute(sgArgs)
   273  	if err != nil {
   274  		return nil, fmt.Errorf("Error get security group %s error: %#v", sgId, err)
   275  	}
   276  
   277  	if v := d.Get("nic_type").(string); v != "" {
   278  		if (group != nil && group.VpcId != "") || args.SourceGroupId != "" {
   279  			if GroupRuleNicType(v) != GroupRuleIntranet {
   280  				return nil, fmt.Errorf("When security group in the vpc or authorizing permission for source security group, " +
   281  					"the nic_type must be 'intranet'.")
   282  			}
   283  		}
   284  		args.NicType = ecs.NicType(v)
   285  	}
   286  
   287  	args.SecurityGroupId = sgId
   288  
   289  	return args, nil
   290  }
   291  
   292  func buildAliyunSecurityEgressArgs(d *schema.ResourceData, meta interface{}) (*ecs.AuthorizeSecurityGroupEgressArgs, error) {
   293  	conn := meta.(*AliyunClient).ecsconn
   294  
   295  	args := &ecs.AuthorizeSecurityGroupEgressArgs{
   296  		RegionId: getRegion(d, meta),
   297  	}
   298  
   299  	if v := d.Get("ip_protocol").(string); v != "" {
   300  		args.IpProtocol = ecs.IpProtocol(v)
   301  	}
   302  
   303  	if v := d.Get("port_range").(string); v != "" {
   304  		args.PortRange = v
   305  	}
   306  
   307  	if v := d.Get("policy").(string); v != "" {
   308  		args.Policy = ecs.PermissionPolicy(v)
   309  	}
   310  
   311  	if v := d.Get("priority").(int); v != 0 {
   312  		args.Priority = v
   313  	}
   314  
   315  	if v := d.Get("cidr_ip").(string); v != "" {
   316  		args.DestCidrIp = v
   317  	}
   318  
   319  	if v := d.Get("source_security_group_id").(string); v != "" {
   320  		args.DestGroupId = v
   321  	}
   322  
   323  	if v := d.Get("source_group_owner_account").(string); v != "" {
   324  		args.DestGroupOwnerAccount = v
   325  	}
   326  
   327  	sgId := d.Get("security_group_id").(string)
   328  
   329  	sgArgs := &ecs.DescribeSecurityGroupAttributeArgs{
   330  		SecurityGroupId: sgId,
   331  		RegionId:        getRegion(d, meta),
   332  	}
   333  
   334  	group, err := conn.DescribeSecurityGroupAttribute(sgArgs)
   335  	if err != nil {
   336  		return nil, fmt.Errorf("Error get security group %s error: %#v", sgId, err)
   337  	}
   338  
   339  	if v := d.Get("nic_type").(string); v != "" {
   340  		if (group != nil && group.VpcId != "") || args.DestGroupId != "" {
   341  			if GroupRuleNicType(v) != GroupRuleIntranet {
   342  				return nil, fmt.Errorf("When security group in the vpc or authorizing permission for destination security group, " +
   343  					"the nic_type must be 'intranet'.")
   344  			}
   345  		}
   346  		args.NicType = ecs.NicType(v)
   347  	}
   348  
   349  	args.SecurityGroupId = sgId
   350  
   351  	return args, nil
   352  }