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 }