yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/waf_rules.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 aws 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/aws/aws-sdk-go/service/wafv2" 22 23 "yunion.io/x/pkg/errors" 24 "yunion.io/x/pkg/utils" 25 26 "yunion.io/x/cloudmux/pkg/cloudprovider" 27 ) 28 29 type sWafRule struct { 30 waf *SWebAcl 31 *wafv2.Rule 32 } 33 34 func (self *sWafRule) GetAction() *cloudprovider.DefaultAction { 35 ret := &cloudprovider.DefaultAction{} 36 if self.Action == nil { 37 ret.Action = cloudprovider.WafActionNone 38 } else if self.Action.Allow != nil { 39 ret.Action = cloudprovider.WafActionAllow 40 } else if self.Action.Block != nil { 41 ret.Action = cloudprovider.WafActionBlock 42 } else if self.Action.Count != nil { 43 ret.Action = cloudprovider.WafActionCount 44 } 45 return ret 46 } 47 48 func (self *sWafRule) GetDesc() string { 49 return "" 50 } 51 52 func (self *sWafRule) GetName() string { 53 return *self.Rule.Name 54 } 55 56 func (self *sWafRule) GetGlobalId() string { 57 return self.GetName() 58 } 59 60 func (self *sWafRule) GetPriority() int { 61 return int(*self.Rule.Priority) 62 } 63 64 func (self *sWafRule) Delete() error { 65 input := wafv2.UpdateWebACLInput{} 66 rules := []*wafv2.Rule{} 67 for _, rule := range self.waf.Rules { 68 if *rule.Name == *self.Name { 69 continue 70 } 71 rules = append(rules, rule) 72 } 73 input.SetRules(rules) 74 input.SetLockToken(self.waf.LockToken) 75 input.SetId(*self.waf.Id) 76 input.SetName(*self.waf.Name) 77 input.SetScope(self.waf.scope) 78 input.SetDescription(*self.waf.Description) 79 input.SetDefaultAction(self.waf.DefaultAction) 80 input.SetVisibilityConfig(self.waf.WebACL.VisibilityConfig) 81 client, err := self.waf.region.getWafClient() 82 if err != nil { 83 return errors.Wrapf(err, "getWafClient") 84 } 85 _, err = client.UpdateWebACL(&input) 86 return errors.Wrapf(err, "UpdateWebACL") 87 } 88 89 func (self *sWafRule) Update(opts *cloudprovider.SWafRule) error { 90 return cloudprovider.ErrNotImplemented 91 } 92 93 func (self *sWafRule) GetStatementCondition() cloudprovider.TWafStatementCondition { 94 if self.Rule.Statement == nil { 95 return cloudprovider.WafStatementConditionNone 96 } 97 if self.Rule.Statement.AndStatement != nil { 98 return cloudprovider.WafStatementConditionAnd 99 } else if self.Rule.Statement.OrStatement != nil { 100 return cloudprovider.WafStatementConditionOr 101 } else if self.Rule.Statement.NotStatement != nil { 102 return cloudprovider.WafStatementConditionNot 103 } 104 return cloudprovider.WafStatementConditionNone 105 } 106 107 type sWafStatement struct { 108 *wafv2.Statement 109 } 110 111 func (self *sWafStatement) convert() cloudprovider.SWafStatement { 112 statement := cloudprovider.SWafStatement{ 113 Transformations: &cloudprovider.TextTransformations{}, 114 } 115 if self.ByteMatchStatement != nil { 116 statement.Type = cloudprovider.WafStatementTypeByteMatch 117 if self.ByteMatchStatement.PositionalConstraint != nil { 118 operator := strings.ReplaceAll(utils.CamelSplit(*self.ByteMatchStatement.PositionalConstraint, "_"), "_", "") 119 if operator == "None" { 120 operator = "" 121 } 122 statement.Operator = cloudprovider.TWafOperator(operator) 123 } 124 fillStatement(&statement, self.ByteMatchStatement.FieldToMatch) 125 statement.SearchString = string(self.ByteMatchStatement.SearchString) 126 fillTransformations(&statement, self.ByteMatchStatement.TextTransformations) 127 } else if self.GeoMatchStatement != nil { 128 statement.Type = cloudprovider.WafStatementTypeGeoMatch 129 statement.MatchFieldKey = "CountryCodes" 130 values := cloudprovider.TWafMatchFieldValues{} 131 for i := range self.GeoMatchStatement.CountryCodes { 132 values = append(values, *self.GeoMatchStatement.CountryCodes[i]) 133 } 134 statement.MatchFieldValues = &values 135 if self.GeoMatchStatement.ForwardedIPConfig != nil { 136 statement.ForwardedIPHeader = *self.GeoMatchStatement.ForwardedIPConfig.HeaderName 137 } 138 } else if self.IPSetReferenceStatement != nil { 139 statement.Type = cloudprovider.WafStatementTypeIPSet 140 statement.IPSetId = *self.IPSetReferenceStatement.ARN 141 if self.IPSetReferenceStatement.IPSetForwardedIPConfig != nil { 142 statement.ForwardedIPHeader = *self.IPSetReferenceStatement.IPSetForwardedIPConfig.HeaderName 143 } 144 } else if self.ManagedRuleGroupStatement != nil { 145 statement.Type = cloudprovider.WafStatementTypeManagedRuleGroup 146 statement.ManagedRuleGroupName = *self.ManagedRuleGroupStatement.Name 147 fillExcludeRules(&statement, self.ManagedRuleGroupStatement.ExcludedRules) 148 } else if self.RateBasedStatement != nil { 149 statement.Type = cloudprovider.WafStatementTypeRate 150 statement.MatchFieldValues = &cloudprovider.TWafMatchFieldValues{fmt.Sprintf("%d", *self.RateBasedStatement.Limit)} 151 if self.RateBasedStatement.ForwardedIPConfig != nil { 152 statement.ForwardedIPHeader = *self.RateBasedStatement.ForwardedIPConfig.HeaderName 153 } 154 } else if self.RegexPatternSetReferenceStatement != nil { 155 statement.Type = cloudprovider.WafStatementTypeRegexSet 156 statement.RegexSetId = *self.RegexPatternSetReferenceStatement.ARN 157 fillStatement(&statement, self.RegexPatternSetReferenceStatement.FieldToMatch) 158 } else if self.RuleGroupReferenceStatement != nil { 159 statement.Type = cloudprovider.WafStatementTypeRuleGroup 160 statement.RuleGroupId = *self.RuleGroupReferenceStatement.ARN 161 fillExcludeRules(&statement, self.RuleGroupReferenceStatement.ExcludedRules) 162 } else if self.SizeConstraintStatement != nil { 163 statement.Type = cloudprovider.WafStatementTypeSize 164 statement.Operator = cloudprovider.TWafOperator(*self.SizeConstraintStatement.ComparisonOperator) 165 statement.MatchFieldValues = &cloudprovider.TWafMatchFieldValues{fmt.Sprintf("%d", self.SizeConstraintStatement.Size)} 166 fillStatement(&statement, self.SizeConstraintStatement.FieldToMatch) 167 fillTransformations(&statement, self.SizeConstraintStatement.TextTransformations) 168 } else if self.SqliMatchStatement != nil { 169 statement.Type = cloudprovider.WafStatementTypeSqliMatch 170 fillStatement(&statement, self.SqliMatchStatement.FieldToMatch) 171 fillTransformations(&statement, self.SqliMatchStatement.TextTransformations) 172 } else if self.XssMatchStatement != nil { 173 statement.Type = cloudprovider.WafStatementTypeXssMatch 174 fillStatement(&statement, self.XssMatchStatement.FieldToMatch) 175 fillTransformations(&statement, self.XssMatchStatement.TextTransformations) 176 } else if self.LabelMatchStatement != nil { 177 statement.Type = cloudprovider.WafStatementTypeLabelMatch 178 if self.LabelMatchStatement.Scope != nil { 179 statement.MatchFieldKey = *self.LabelMatchStatement.Scope 180 } 181 if self.LabelMatchStatement.Key != nil { 182 statement.MatchFieldValues = &cloudprovider.TWafMatchFieldValues{*self.LabelMatchStatement.Key} 183 } 184 } else if self.NotStatement != nil { 185 s := &sWafStatement{Statement: self.NotStatement.Statement} 186 statement = s.convert() 187 statement.Negation = true 188 } 189 return statement 190 } 191 192 func fillStatement(statement *cloudprovider.SWafStatement, field *wafv2.FieldToMatch) { 193 if field.AllQueryArguments != nil { 194 statement.MatchField = cloudprovider.WafMatchFieldQuery 195 statement.MatchFieldKey = "AllArguments" 196 } else if field.Body != nil { 197 statement.MatchField = cloudprovider.WafMatchFieldBody 198 } else if field.Method != nil { 199 statement.MatchField = cloudprovider.WafMatchFieldMethod 200 } else if field.QueryString != nil { 201 statement.MatchField = cloudprovider.WafMatchFieldQuery 202 } else if field.SingleHeader != nil { 203 statement.MatchField = cloudprovider.WafMatchFiledHeader 204 statement.MatchFieldKey = *field.SingleHeader.Name 205 } else if field.SingleQueryArgument != nil { 206 statement.MatchField = cloudprovider.WafMatchFieldQuery 207 statement.MatchFieldKey = "SingleArgument" 208 } else if field.UriPath != nil { 209 statement.MatchField = cloudprovider.WafMatchFiledUriPath 210 } 211 } 212 213 func fillTransformations(statement *cloudprovider.SWafStatement, trans []*wafv2.TextTransformation) { 214 values := cloudprovider.TextTransformations{} 215 for _, tran := range trans { 216 switch *tran.Type { 217 case wafv2.TextTransformationTypeNone: 218 values = append(values, cloudprovider.WafTextTransformationNone) 219 case wafv2.TextTransformationTypeLowercase: 220 values = append(values, cloudprovider.WafTextTransformationLowercase) 221 case wafv2.TextTransformationTypeCmdLine: 222 values = append(values, cloudprovider.WafTextTransformationCmdLine) 223 case wafv2.TextTransformationTypeUrlDecode: 224 values = append(values, cloudprovider.WafTextTransformationUrlDecode) 225 case wafv2.TextTransformationTypeHtmlEntityDecode: 226 values = append(values, cloudprovider.WafTextTransformationHtmlEntityDecode) 227 case wafv2.TextTransformationTypeCompressWhiteSpace: 228 values = append(values, cloudprovider.WafTextTransformationCompressWithSpace) 229 default: 230 values = append(values, cloudprovider.TWafTextTransformation(*tran.Type)) 231 } 232 } 233 statement.Transformations = &values 234 } 235 236 func fillExcludeRules(statement *cloudprovider.SWafStatement, rules []*wafv2.ExcludedRule) { 237 values := cloudprovider.SExcludeRules{} 238 for _, rule := range rules { 239 values = append(values, cloudprovider.SExcludeRule{Name: *rule.Name}) 240 } 241 statement.ExcludeRules = &values 242 } 243 244 func (self *sWafRule) GetStatements() ([]cloudprovider.SWafStatement, error) { 245 if self.Rule.Statement == nil { 246 return []cloudprovider.SWafStatement{}, nil 247 } 248 ret := []cloudprovider.SWafStatement{} 249 if self.Rule.Statement.AndStatement != nil { 250 for i := range self.Rule.Statement.AndStatement.Statements { 251 statement := sWafStatement{self.Rule.Statement.AndStatement.Statements[i]} 252 ret = append(ret, statement.convert()) 253 } 254 } else if self.Rule.Statement.OrStatement != nil { 255 for i := range self.Rule.Statement.OrStatement.Statements { 256 statement := sWafStatement{self.Rule.Statement.OrStatement.Statements[i]} 257 ret = append(ret, statement.convert()) 258 } 259 } else if self.Rule.Statement.NotStatement != nil { 260 statement := sWafStatement{self.Rule.Statement.NotStatement.Statement} 261 ret = append(ret, statement.convert()) 262 } else { 263 statement := sWafStatement{self.Rule.Statement} 264 ret = append(ret, statement.convert()) 265 } 266 return ret, nil 267 } 268 269 func (self *SWebAcl) GetRules() ([]cloudprovider.ICloudWafRule, error) { 270 ret := []cloudprovider.ICloudWafRule{} 271 if len(self.Rules) == 0 { 272 err := self.Refresh() 273 if err != nil { 274 return nil, errors.Wrapf(err, "Refresh") 275 } 276 } 277 for i := range self.Rules { 278 ret = append(ret, &sWafRule{ 279 waf: self, 280 Rule: self.Rules[i], 281 }) 282 } 283 return ret, nil 284 }