yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/waf_domain.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aliyun 16 17 import ( 18 "fmt" 19 20 "yunion.io/x/jsonutils" 21 "yunion.io/x/pkg/errors" 22 23 api "yunion.io/x/cloudmux/pkg/apis/compute" 24 "yunion.io/x/cloudmux/pkg/cloudprovider" 25 "yunion.io/x/cloudmux/pkg/multicloud" 26 ) 27 28 type SWafDomain struct { 29 multicloud.SResourceBase 30 AliyunTags 31 region *SRegion 32 33 insId string 34 name string 35 Httptouserip int `json:"HttpToUserIp"` 36 Httpport []int `json:"HttpPort"` 37 Isaccessproduct int `json:"IsAccessProduct"` 38 Resourcegroupid string `json:"ResourceGroupId"` 39 Readtime int `json:"ReadTime"` 40 Sourceips []string `json:"SourceIps"` 41 Ipfollowstatus int `json:"IpFollowStatus"` 42 Clustertype int `json:"ClusterType"` 43 Loadbalancing int `json:"LoadBalancing"` 44 Cname string `json:"Cname"` 45 Writetime int `json:"WriteTime"` 46 HTTP2Port []interface{} `json:"Http2Port"` 47 Version int `json:"Version"` 48 Httpsredirect int `json:"HttpsRedirect"` 49 Connectiontime int `json:"ConnectionTime"` 50 Accesstype string `json:"AccessType"` 51 Httpsport []interface{} `json:"HttpsPort"` 52 } 53 54 func (self *SRegion) DescribeDomain(id, domain string) (*SWafDomain, error) { 55 params := map[string]string{ 56 "RegionId": self.RegionId, 57 "InstanceId": id, 58 "Domain": domain, 59 } 60 resp, err := self.wafRequest("DescribeDomain", params) 61 if err != nil { 62 return nil, errors.Wrapf(err, "DescribeDomain") 63 } 64 ret := &SWafDomain{region: self, name: domain, insId: id} 65 err = resp.Unmarshal(ret, "Domain") 66 if err != nil { 67 return nil, errors.Wrapf(err, "resp.Unmarshal") 68 } 69 return ret, nil 70 } 71 72 func (self *SRegion) DeleteDomain(id, domain string) error { 73 params := map[string]string{ 74 "RegionId": self.RegionId, 75 "InstanceId": id, 76 "Domain": domain, 77 } 78 _, err := self.wafRequest("DeleteDomain", params) 79 return errors.Wrapf(err, "DeleteDomain") 80 } 81 82 func (self *SRegion) DescribeDomainNames(id string) ([]string, error) { 83 params := map[string]string{ 84 "RegionId": self.RegionId, 85 "InstanceId": id, 86 } 87 resp, err := self.wafRequest("DescribeDomainNames", params) 88 if err != nil { 89 return nil, errors.Wrapf(err, "DescribeDomainNames") 90 } 91 domains := []string{} 92 err = resp.Unmarshal(&domains, "DomainNames") 93 return domains, errors.Wrapf(err, "resp.Unmarshal") 94 } 95 96 func (self *SRegion) SetDomainRuleGroup(insId, domain, ruleGroupId string) error { 97 params := map[string]string{ 98 "RegionId": self.RegionId, 99 "InstanceId": insId, 100 "Domains": domain, 101 "RuleGroupId": ruleGroupId, 102 } 103 _, err := self.wafRequest("SetDomainRuleGroup", params) 104 return err 105 } 106 107 func (self *SRegion) DescribeDomainRuleGroup(insId, domain string) (string, error) { 108 params := map[string]string{ 109 "RegionId": self.RegionId, 110 "InstanceId": insId, 111 "Domain": domain, 112 } 113 resp, err := self.wafRequest("DescribeDomainRuleGroup", params) 114 if err != nil { 115 return "", errors.Wrapf(err, "DescribeDomainRuleGroup") 116 } 117 return resp.GetString("RuleGroupId") 118 } 119 120 func (self *SRegion) GetICloudWafInstances() ([]cloudprovider.ICloudWafInstance, error) { 121 ins, err := self.DescribeInstanceSpecInfo() 122 if err != nil { 123 if errors.Cause(err) == cloudprovider.ErrNotFound { 124 return []cloudprovider.ICloudWafInstance{}, nil 125 } 126 return nil, errors.Wrapf(err, "DescribeInstanceSpecInfo") 127 } 128 domains, err := self.DescribeDomainNames(ins.InstanceId) 129 if err != nil { 130 return nil, errors.Wrapf(err, "DescribeDomainNames") 131 } 132 ret := []cloudprovider.ICloudWafInstance{} 133 for i := range domains { 134 domain, err := self.DescribeDomain(ins.InstanceId, domains[i]) 135 if err != nil { 136 return nil, errors.Wrapf(err, "DescribeDomain %s", domains[i]) 137 } 138 domain.region = self 139 domain.insId = ins.InstanceId 140 domain.name = domains[i] 141 ret = append(ret, domain) 142 } 143 return ret, nil 144 } 145 146 func (self *SRegion) GetICloudWafInstanceById(id string) (cloudprovider.ICloudWafInstance, error) { 147 ins, err := self.DescribeInstanceSpecInfo() 148 if err != nil { 149 return nil, errors.Wrapf(err, "DescribeInstanceSpecInfo") 150 } 151 return self.DescribeDomain(ins.InstanceId, id) 152 } 153 154 func (self *SWafDomain) GetId() string { 155 return self.name 156 } 157 158 func (self *SWafDomain) GetStatus() string { 159 return api.WAF_STATUS_AVAILABLE 160 } 161 162 func (self *SWafDomain) GetWafType() cloudprovider.TWafType { 163 return cloudprovider.WafTypeDefault 164 } 165 166 func (self *SWafDomain) GetEnabled() bool { 167 return true 168 } 169 170 func (self *SWafDomain) GetName() string { 171 return self.name 172 } 173 174 func (self *SWafDomain) GetGlobalId() string { 175 return self.name 176 } 177 178 func (self *SWafDomain) Delete() error { 179 return self.region.DeleteDomain(self.insId, self.name) 180 } 181 182 func (self *SWafDomain) GetDefaultAction() *cloudprovider.DefaultAction { 183 return &cloudprovider.DefaultAction{ 184 Action: cloudprovider.WafActionAllow, 185 InsertHeaders: map[string]string{}, 186 } 187 } 188 189 type ManagedRuleGroup struct { 190 waf *SWafDomain 191 192 insId string 193 domain string 194 ruleGroupId string 195 } 196 197 func (self *ManagedRuleGroup) GetName() string { 198 return "RuleGroup" 199 } 200 201 func (self *ManagedRuleGroup) GetDesc() string { 202 return "规则组" 203 } 204 205 func (self *ManagedRuleGroup) GetGlobalId() string { 206 return fmt.Sprintf("%s-%s", self.insId, self.domain) 207 } 208 209 func (self *ManagedRuleGroup) GetPriority() int { 210 return 0 211 } 212 213 func (self *ManagedRuleGroup) GetAction() *cloudprovider.DefaultAction { 214 return nil 215 } 216 217 func (self *ManagedRuleGroup) Delete() error { 218 return cloudprovider.ErrNotSupported 219 } 220 221 func (self *ManagedRuleGroup) Update(opts *cloudprovider.SWafRule) error { 222 for _, statement := range opts.Statements { 223 if len(statement.RuleGroupId) == 0 { 224 return self.waf.region.SetDomainRuleGroup(self.insId, self.domain, statement.RuleGroupId) 225 } else if len(statement.ManagedRuleGroupName) > 0 { 226 switch statement.ManagedRuleGroupName { 227 case "严格规则": 228 return self.waf.region.SetDomainRuleGroup(self.insId, self.domain, "1011") 229 case "中等规则": 230 return self.waf.region.SetDomainRuleGroup(self.insId, self.domain, "1012") 231 case "宽松规则": 232 return self.waf.region.SetDomainRuleGroup(self.insId, self.domain, "1013") 233 } 234 } 235 } 236 return nil 237 } 238 239 func (self *ManagedRuleGroup) GetStatementCondition() cloudprovider.TWafStatementCondition { 240 return cloudprovider.WafStatementConditionNone 241 } 242 243 func (self *ManagedRuleGroup) GetStatements() ([]cloudprovider.SWafStatement, error) { 244 groupName := self.ruleGroupId 245 switch self.ruleGroupId { 246 case "1011": 247 groupName = "严格规则" 248 case "1012": 249 groupName = "中等规则" 250 case "1013": 251 groupName = "宽松规则" 252 } 253 return []cloudprovider.SWafStatement{ 254 cloudprovider.SWafStatement{ 255 ManagedRuleGroupName: groupName, 256 RuleGroupId: self.ruleGroupId, 257 }, 258 }, nil 259 } 260 261 type SDefenseTypeRule struct { 262 insId string 263 domain string 264 defenseType string 265 action cloudprovider.TWafAction 266 } 267 268 func (self *SDefenseTypeRule) GetName() string { 269 switch self.defenseType { 270 case "waf": 271 return "正则防护引擎" 272 case "dld": 273 return "大数据深度学习引擎" 274 case "ac_cc": 275 return "CC安全防护" 276 case "antifraud": 277 return "数据风控" 278 case "normalized": 279 return "主动防御" 280 } 281 return self.defenseType 282 } 283 284 func (self *SDefenseTypeRule) GetDesc() string { 285 return "" 286 } 287 288 func (self *SDefenseTypeRule) GetGlobalId() string { 289 return fmt.Sprintf("%s-%s-%s", self.insId, self.domain, self.defenseType) 290 } 291 292 func (self *SDefenseTypeRule) GetPriority() int { 293 return 0 294 } 295 296 func (self *SDefenseTypeRule) GetAction() *cloudprovider.DefaultAction { 297 return &cloudprovider.DefaultAction{ 298 Action: self.action, 299 } 300 } 301 302 func (self *SDefenseTypeRule) GetStatementCondition() cloudprovider.TWafStatementCondition { 303 return cloudprovider.WafStatementConditionNone 304 } 305 306 func (self *SDefenseTypeRule) GetStatements() ([]cloudprovider.SWafStatement, error) { 307 return []cloudprovider.SWafStatement{}, nil 308 } 309 310 func (self *SDefenseTypeRule) Delete() error { 311 return cloudprovider.ErrNotSupported 312 } 313 314 func (self *SDefenseTypeRule) Update(opts *cloudprovider.SWafRule) error { 315 return cloudprovider.ErrNotSupported 316 } 317 318 func (self *SWafDomain) GetRules() ([]cloudprovider.ICloudWafRule, error) { 319 ruleGroupId, err := self.region.DescribeDomainRuleGroup(self.insId, self.name) 320 if err != nil { 321 return nil, errors.Wrapf(err, "DescribeDomainRuleGroup") 322 } 323 ret := []cloudprovider.ICloudWafRule{} 324 ret = append(ret, &ManagedRuleGroup{ 325 waf: self, 326 insId: self.insId, 327 domain: self.name, 328 ruleGroupId: ruleGroupId, 329 }) 330 for _, defenseType := range []string{ 331 "waf", 332 "dld", 333 "ac_cc", 334 "antifraud", 335 "normalized", 336 } { 337 act, _ := self.region.DescribeProtectionModuleMode(self.insId, self.name, defenseType) 338 ret = append(ret, &SDefenseTypeRule{ 339 insId: self.insId, 340 domain: self.name, 341 defenseType: defenseType, 342 action: act, 343 }) 344 } 345 return ret, nil 346 } 347 348 type SIpSegement struct { 349 IpV6s string 350 Ips string 351 } 352 353 func (self *SRegion) DescribeWafSourceIpSegment(insId string) (*SIpSegement, error) { 354 params := map[string]string{ 355 "RegionId": self.RegionId, 356 "InstanceId": insId, 357 } 358 resp, err := self.wafRequest("DescribeWafSourceIpSegment", params) 359 if err != nil { 360 return nil, errors.Wrapf(err, "DescribeWafSourceIpSegment") 361 } 362 ret := &SIpSegement{} 363 err = resp.Unmarshal(ret) 364 if err != nil { 365 return nil, errors.Wrapf(err, "") 366 } 367 return ret, nil 368 } 369 370 func (self *SRegion) CreateICloudWafInstance(opts *cloudprovider.WafCreateOptions) (cloudprovider.ICloudWafInstance, error) { 371 ins, err := self.DescribeInstanceSpecInfo() 372 if err != nil { 373 return nil, errors.Wrapf(err, "DescribeInstanceSpecInfo") 374 } 375 waf, err := self.CreateDomain(ins.InstanceId, opts.Name, opts.SourceIps, opts.CloudResources) 376 if err != nil { 377 return nil, errors.Wrapf(err, "CreateDomain") 378 } 379 return waf, nil 380 } 381 382 func (self *SRegion) CreateDomain(insId, domain string, sourceIps []string, cloudResources []cloudprovider.SCloudResource) (*SWafDomain, error) { 383 params := map[string]string{ 384 "RegionId": self.RegionId, 385 "InstanceId": insId, 386 "Domain": domain, 387 "IsAccessProduct": "0", 388 "HttpPort": `["80"]`, 389 "HttpsPort": `["443"]`, 390 "Http2Port": `["80", "443"]`, 391 } 392 if len(sourceIps) > 0 { 393 params["SourceIps"] = jsonutils.Marshal(sourceIps).String() 394 params["AccessType"] = "waf-cloud-dns" 395 } else if len(cloudResources) > 0 { 396 ins := jsonutils.NewArray() 397 for _, res := range cloudResources { 398 ins.Add(jsonutils.Marshal(map[string]interface{}{"InstanceId": res.Id, "Port": res.Port})) 399 } 400 params["CloudNativeInstances"] = ins.String() 401 params["AccessType"] = "waf-cloud-native" 402 } else { 403 return nil, errors.Error("missing source ips") 404 } 405 _, err := self.wafRequest("CreateDomain", params) 406 if err != nil { 407 return nil, errors.Wrapf(err, "CreateDomain") 408 } 409 return self.DescribeDomain(insId, domain) 410 } 411 412 func (self *SWafDomain) AddRule(opts *cloudprovider.SWafRule) (cloudprovider.ICloudWafRule, error) { 413 return nil, errors.Wrapf(cloudprovider.ErrNotSupported, "AddRule") 414 } 415 416 func (self *SWafDomain) Refresh() error { 417 domain, err := self.region.DescribeDomain(self.insId, self.name) 418 if err != nil { 419 return errors.Wrapf(err, "DescribeDomain") 420 } 421 return jsonutils.Update(self, domain) 422 } 423 424 func (self *SWafDomain) GetCloudResources() ([]cloudprovider.SCloudResource, error) { 425 ret := []cloudprovider.SCloudResource{} 426 if len(self.Cname) > 0 { 427 ret = append(ret, cloudprovider.SCloudResource{ 428 Type: "cname", 429 Name: "CNAME", 430 Id: self.Cname, 431 CanDissociate: false, 432 }) 433 } 434 ipseg, err := self.region.DescribeWafSourceIpSegment(self.insId) 435 if err == nil { 436 ret = append(ret, cloudprovider.SCloudResource{ 437 Type: "segment_ipv4", 438 Name: "Segment IPv4", 439 Id: ipseg.Ips, 440 CanDissociate: false, 441 }) 442 ret = append(ret, cloudprovider.SCloudResource{ 443 Type: "segment_ipv6", 444 Name: "Segment IPv6", 445 Id: ipseg.IpV6s, 446 CanDissociate: false, 447 }) 448 } 449 return ret, nil 450 } 451 452 func (self *SRegion) DescribeProtectionModuleMode(insId, domain, defenseType string) (cloudprovider.TWafAction, error) { 453 params := map[string]string{ 454 "RegionId": self.RegionId, 455 "Domain": domain, 456 "InstanceId": insId, 457 "DefenseType": defenseType, 458 } 459 resp, err := self.wafRequest("DescribeProtectionModuleMode", params) 460 if err != nil { 461 return cloudprovider.WafActionNone, errors.Wrapf(err, "DescribeProtectionModuleMode %s", defenseType) 462 } 463 if !resp.Contains("Mode") { 464 return cloudprovider.WafActionNone, nil 465 } 466 mode, _ := resp.Int("Mode") 467 switch defenseType { 468 case "waf": 469 if mode == 0 { 470 return cloudprovider.WafActionBlock, nil 471 } 472 if mode == 1 { 473 return cloudprovider.WafActionAlert, nil 474 } 475 case "dld": 476 if mode == 0 { 477 return cloudprovider.WafActionAlert, nil 478 } 479 if mode == 1 { 480 return cloudprovider.WafActionBlock, nil 481 } 482 case "ac_cc": 483 if mode == 0 { 484 return cloudprovider.WafActionAllow, nil 485 } 486 if mode == 1 { 487 return cloudprovider.WafActionBlock, nil 488 } 489 case "antifraud": 490 if mode == 0 { 491 return cloudprovider.WafActionAlert, nil 492 } 493 if mode == 1 || mode == 2 { 494 return cloudprovider.WafActionBlock, nil 495 } 496 case "normalized": 497 if mode == 0 { 498 return cloudprovider.WafActionAlert, nil 499 } 500 if mode == 1 { 501 return cloudprovider.WafActionBlock, nil 502 } 503 } 504 return cloudprovider.WafActionNone, nil 505 }