waf_rules.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  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. package models
  15. import (
  16. "context"
  17. "yunion.io/x/cloudmux/pkg/cloudprovider"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/pkg/errors"
  20. "yunion.io/x/pkg/tristate"
  21. "yunion.io/x/pkg/util/compare"
  22. "yunion.io/x/pkg/util/rbacscope"
  23. "yunion.io/x/sqlchemy"
  24. "yunion.io/x/onecloud/pkg/apis"
  25. api "yunion.io/x/onecloud/pkg/apis/compute"
  26. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  27. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  28. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  29. "yunion.io/x/onecloud/pkg/cloudcommon/validators"
  30. "yunion.io/x/onecloud/pkg/httperrors"
  31. "yunion.io/x/onecloud/pkg/mcclient"
  32. "yunion.io/x/onecloud/pkg/util/stringutils2"
  33. )
  34. type SWafRuleManager struct {
  35. db.SEnabledStatusStandaloneResourceBaseManager
  36. db.SExternalizedResourceBaseManager
  37. }
  38. var WafRuleManager *SWafRuleManager
  39. func init() {
  40. WafRuleManager = &SWafRuleManager{
  41. SEnabledStatusStandaloneResourceBaseManager: db.NewEnabledStatusStandaloneResourceBaseManager(
  42. SWafRule{},
  43. "waf_rules_tbl",
  44. "waf_rule",
  45. "waf_rules",
  46. ),
  47. }
  48. WafRuleManager.SetVirtualObject(WafRuleManager)
  49. }
  50. type SWafRule struct {
  51. db.SEnabledStatusStandaloneResourceBase
  52. db.SExternalizedResourceBase
  53. // 规则优先级
  54. Priority int `nullable:"false" default:"0" list:"domain" create:"optional"`
  55. // 规则默认行为
  56. Action *cloudprovider.DefaultAction `charset:"utf8" nullable:"true" list:"user" update:"domain" create:"required"`
  57. // 条件
  58. StatementConditon cloudprovider.TWafStatementCondition `width:"20" charset:"ascii" nullable:"false" list:"domain" create:"optional"`
  59. // 条件表达式
  60. Expression string `width:"512" charset:"ascii" nullable:"false" list:"domain" create:"optional"`
  61. // 规则类型
  62. Type string `width:"20" charset:"ascii" nullable:"false" list:"domain" create:"optional"`
  63. // 规则配置
  64. Config jsonutils.JSONObject `width:"512" charset:"utf8" nullable:"true" list:"domain" create:"optional"`
  65. // 规则组的id
  66. WafRuleGroupId string `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"optional"`
  67. // 所属waf实例id
  68. WafInstanceId string `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"optional"`
  69. }
  70. func (manager *SWafRuleManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
  71. values := struct {
  72. WafRuleGroupId string
  73. WafInstanceId string
  74. }{}
  75. data.Unmarshal(&values)
  76. return jsonutils.Marshal(values)
  77. }
  78. func (manager *SWafRuleManager) FilterByUniqValues(q *sqlchemy.SQuery, values jsonutils.JSONObject) *sqlchemy.SQuery {
  79. data := struct {
  80. WafRuleGroupId string
  81. WafInstanceId string
  82. }{}
  83. if len(data.WafRuleGroupId) > 0 {
  84. q = q.Equals("waf_rule_group_id", data.WafRuleGroupId)
  85. }
  86. if len(data.WafInstanceId) > 0 {
  87. q = q.Equals("waf_instance_id", data.WafInstanceId)
  88. }
  89. return q
  90. }
  91. func (manager *SWafRuleManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
  92. values := struct {
  93. WafRuleGroupId string
  94. WafInstanceId string
  95. }{}
  96. data.Unmarshal(&values)
  97. if len(values.WafInstanceId) > 0 {
  98. ins, err := db.FetchById(WafInstanceManager, values.WafInstanceId)
  99. if err != nil {
  100. return nil, errors.Wrapf(err, "db.FetchById(WafInstanceManager, %s)", values.WafInstanceId)
  101. }
  102. waf := ins.(*SWafInstance)
  103. return waf.GetOwnerId(), nil
  104. }
  105. if len(values.WafRuleGroupId) > 0 {
  106. rg, err := db.FetchById(WafRuleGroupManager, values.WafRuleGroupId)
  107. if err != nil {
  108. return nil, errors.Wrapf(err, "db.FetchById(WafRuleGroupManager, %s)", values.WafRuleGroupId)
  109. }
  110. return rg.GetOwnerId(), nil
  111. }
  112. return db.FetchDomainInfo(ctx, data)
  113. }
  114. func (manager *SWafRuleManager) FilterByOwner(ctx context.Context, q *sqlchemy.SQuery, man db.FilterByOwnerProvider, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery {
  115. sq1 := WafInstanceManager.Query("id")
  116. sq1 = db.SharableManagerFilterByOwner(ctx, WafInstanceManager, sq1, userCred, ownerId, scope)
  117. sq2 := WafRuleGroupManager.Query("id")
  118. sq2 = db.SharableManagerFilterByOwner(ctx, WafRuleGroupManager, sq2, userCred, ownerId, scope)
  119. return q.Filter(sqlchemy.OR(
  120. sqlchemy.In(q.Field("waf_instance_id"), sq1.SubQuery()),
  121. sqlchemy.In(q.Field("waf_rule_group_id"), sq2.SubQuery()),
  122. ))
  123. }
  124. func (manager *SWafRuleManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.WafRuleCreateInput) (api.WafRuleCreateInput, error) {
  125. if len(input.WafInstanceId) > 0 {
  126. ins, err := validators.ValidateModel(ctx, userCred, WafInstanceManager, &input.WafInstanceId)
  127. if err != nil {
  128. return input, err
  129. }
  130. waf := ins.(*SWafInstance)
  131. if waf.Status != api.WAF_STATUS_AVAILABLE {
  132. return input, httperrors.NewInvalidStatusError("waf %s status is not available", waf.Name)
  133. }
  134. region, err := waf.GetRegion()
  135. if err != nil {
  136. return input, httperrors.NewGeneralError(errors.Wrapf(err, "GetRegion"))
  137. }
  138. input, err = region.GetDriver().ValidateCreateWafRuleData(ctx, userCred, waf, input)
  139. if err != nil {
  140. return input, err
  141. }
  142. } else if len(input.WafRuleGroupId) > 0 {
  143. return input, httperrors.NewInputParameterError("not implement")
  144. } else {
  145. return input, httperrors.NewMissingParameterError("waf_instance_id")
  146. }
  147. var err error
  148. input.EnabledStatusStandaloneResourceCreateInput, err = manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusStandaloneResourceCreateInput)
  149. if err != nil {
  150. return input, err
  151. }
  152. return input, nil
  153. }
  154. func (self *SWafRule) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  155. self.SEnabledStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  156. input := &api.WafRuleCreateInput{}
  157. data.Unmarshal(input)
  158. for _, s := range input.Statements {
  159. statement := &SWafRuleStatement{}
  160. statement.SetModelManager(WafRuleStatementManager, statement)
  161. statement.SWafStatement = s
  162. statement.WafRuleId = self.Id
  163. WafRuleStatementManager.TableSpec().Insert(ctx, statement)
  164. }
  165. self.StartCreateTask(ctx, userCred)
  166. }
  167. func (self *SWafRule) StartCreateTask(ctx context.Context, userCred mcclient.TokenCredential) error {
  168. task, err := taskman.TaskManager.NewTask(ctx, "WafRuleCreateTask", self, userCred, nil, "", "", nil)
  169. if err != nil {
  170. return errors.Wrapf(err, "NewTask")
  171. }
  172. self.SetStatus(ctx, userCred, api.WAF_RULE_STATUS_CREATING, "")
  173. return task.ScheduleRun(nil)
  174. }
  175. // 列出WAF规则
  176. func (manager *SWafRuleManager) ListItemFilter(
  177. ctx context.Context,
  178. q *sqlchemy.SQuery,
  179. userCred mcclient.TokenCredential,
  180. query api.WafRuleListInput,
  181. ) (*sqlchemy.SQuery, error) {
  182. var err error
  183. q, err = manager.SEnabledStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
  184. if err != nil {
  185. return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.ListItemFilter")
  186. }
  187. q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
  188. if err != nil {
  189. return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
  190. }
  191. if len(query.Type) > 0 {
  192. q = q.Equals("type", query.Type)
  193. }
  194. if len(query.WafInstanceId) > 0 {
  195. _, err := validators.ValidateModel(ctx, userCred, WafInstanceManager, &query.WafInstanceId)
  196. if err != nil {
  197. return nil, err
  198. }
  199. q = q.Equals("waf_instance_id", query.WafInstanceId)
  200. }
  201. if len(query.WafRuleGroupId) > 0 {
  202. _, err := validators.ValidateModel(ctx, userCred, WafRuleGroupManager, &query.WafRuleGroupId)
  203. if err != nil {
  204. return nil, err
  205. }
  206. q = q.Equals("waf_rule_group_id", query.WafRuleGroupId)
  207. }
  208. return q, nil
  209. }
  210. func (manager *SWafRuleManager) FetchCustomizeColumns(
  211. ctx context.Context,
  212. userCred mcclient.TokenCredential,
  213. query jsonutils.JSONObject,
  214. objs []interface{},
  215. fields stringutils2.SSortedStrings,
  216. isList bool,
  217. ) []api.WafRuleDetails {
  218. rows := make([]api.WafRuleDetails, len(objs))
  219. stdRows := manager.SEnabledStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  220. ruleIds := make([]string, len(objs))
  221. for i := range rows {
  222. rows[i] = api.WafRuleDetails{
  223. EnabledStatusStandaloneResourceDetails: stdRows[i],
  224. }
  225. ruleIds[i] = objs[i].(*SWafRule).Id
  226. }
  227. q := WafRuleStatementManager.Query().In("waf_rule_id", ruleIds)
  228. statements := []SWafRuleStatement{}
  229. err := q.All(&statements)
  230. if err != nil {
  231. return rows
  232. }
  233. statementMaps := map[string][]cloudprovider.SWafStatement{}
  234. for i := range statements {
  235. _, ok := statementMaps[statements[i].WafRuleId]
  236. if !ok {
  237. statementMaps[statements[i].WafRuleId] = []cloudprovider.SWafStatement{}
  238. }
  239. statementMaps[statements[i].WafRuleId] = append(statementMaps[statements[i].WafRuleId], statements[i].SWafStatement)
  240. }
  241. for i := range rows {
  242. rows[i].Statements, _ = statementMaps[ruleIds[i]]
  243. }
  244. return rows
  245. }
  246. func (self *SWafRule) GetWafInstance() (*SWafInstance, error) {
  247. waf, err := WafInstanceManager.FetchById(self.WafInstanceId)
  248. if err != nil {
  249. return nil, errors.Wrapf(err, "WafInstanceManager.FetchById(%s)", self.WafInstanceId)
  250. }
  251. return waf.(*SWafInstance), nil
  252. }
  253. func (self *SWafRule) GetWafRuleGroup() (*SWafRuleGroup, error) {
  254. rg, err := WafRuleGroupManager.FetchById(self.WafRuleGroupId)
  255. if err != nil {
  256. return nil, errors.Wrapf(err, "WafRuleGroupManager.FetchById(%s)", self.WafRuleGroupId)
  257. }
  258. return rg.(*SWafRuleGroup), nil
  259. }
  260. func (self *SWafRule) GetOwnerId() mcclient.IIdentityProvider {
  261. if len(self.WafInstanceId) > 0 {
  262. ins, err := self.GetWafInstance()
  263. if err != nil {
  264. return nil
  265. }
  266. return ins.GetOwnerId()
  267. }
  268. if len(self.WafRuleGroupId) > 0 {
  269. rg, err := self.GetWafRuleGroup()
  270. if err != nil {
  271. return nil
  272. }
  273. return rg.GetOwnerId()
  274. }
  275. return nil
  276. }
  277. func (manager *SWafRuleManager) ResourceScope() rbacscope.TRbacScope {
  278. return rbacscope.ScopeDomain
  279. }
  280. func (self *SWafInstance) GetWafRules() ([]SWafRule, error) {
  281. q := WafRuleManager.Query().Equals("waf_instance_id", self.Id)
  282. rules := []SWafRule{}
  283. err := db.FetchModelObjects(WafRuleManager, q, &rules)
  284. if err != nil {
  285. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  286. }
  287. return rules, nil
  288. }
  289. func (self *SWafRule) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  290. return self.StartDeleteTask(ctx, userCred)
  291. }
  292. func (self *SWafRule) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential) error {
  293. task, err := taskman.TaskManager.NewTask(ctx, "WafRuleDeleteTask", self, userCred, nil, "", "", nil)
  294. if err != nil {
  295. return errors.Wrapf(err, "NewTask")
  296. }
  297. self.SetStatus(ctx, userCred, api.WAF_RULE_STATUS_DELETING, "")
  298. return task.ScheduleRun(nil)
  299. }
  300. func (self *SWafRule) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  301. return nil
  302. }
  303. func (self *SWafRule) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
  304. statements, err := self.GetRuleStatements()
  305. if err != nil {
  306. return errors.Wrapf(err, "GetRuleStatements")
  307. }
  308. for i := range statements {
  309. err = statements[i].Delete(ctx, userCred)
  310. if err != nil {
  311. return errors.Wrapf(err, "Delete statement %s(%s)", statements[i].Type, statements[i].MatchField)
  312. }
  313. }
  314. return self.SStatusStandaloneResourceBase.Delete(ctx, userCred)
  315. }
  316. func (self *SWafRule) syncRemove(ctx context.Context, userCred mcclient.TokenCredential) error {
  317. return self.RealDelete(ctx, userCred)
  318. }
  319. func (self *SWafRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.WafRuleUpdateInput) (api.WafRuleUpdateInput, error) {
  320. var err error
  321. if len(input.Name) > 0 && input.Name != self.Name {
  322. return input, httperrors.NewInputParameterError("Not allow update rule name")
  323. }
  324. input.EnabledStatusStandaloneResourceBaseUpdateInput, err = self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusStandaloneResourceBaseUpdateInput)
  325. if err != nil {
  326. return input, err
  327. }
  328. return input, nil
  329. }
  330. func (self *SWafRule) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  331. self.SEnabledStatusStandaloneResourceBase.PostUpdate(ctx, userCred, query, data)
  332. input := api.WafRuleUpdateInput{}
  333. data.Unmarshal(&input)
  334. statements, err := self.GetRuleStatements()
  335. if err != nil {
  336. return
  337. }
  338. for i := len(input.Statements); i < len(statements); i++ {
  339. statements[i].Delete(ctx, userCred)
  340. }
  341. for i := len(statements); i < len(input.Statements); i++ {
  342. statement := &SWafRuleStatement{}
  343. statement.SetModelManager(WafRuleStatementManager, statement)
  344. statement.SWafStatement = input.Statements[i]
  345. statement.WafRuleId = self.Id
  346. WafRuleStatementManager.TableSpec().Insert(ctx, statement)
  347. }
  348. for i := 0; i < len(input.Statements) && i < len(statements); i++ {
  349. db.Update(&statements[i], func() error {
  350. statements[i].SWafStatement = input.Statements[i]
  351. return nil
  352. })
  353. }
  354. self.StartUpdateTask(ctx, userCred, "")
  355. }
  356. func (self *SWafRule) StartUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  357. task, err := taskman.TaskManager.NewTask(ctx, "WafRuleUpdateTask", self, userCred, nil, parentTaskId, "", nil)
  358. if err != nil {
  359. return errors.Wrapf(err, "NewTask")
  360. }
  361. self.SetStatus(ctx, userCred, api.WAF_RULE_STATUS_UPDATING, "")
  362. return task.ScheduleRun(nil)
  363. }
  364. func (self *SWafRule) SyncWithCloudRule(ctx context.Context, userCred mcclient.TokenCredential, rule cloudprovider.ICloudWafRule) error {
  365. _, err := db.Update(self, func() error {
  366. var err error
  367. self.Action = rule.GetAction()
  368. self.StatementConditon = rule.GetStatementCondition()
  369. self.Priority = rule.GetPriority()
  370. self.Type = rule.GetType()
  371. self.Status = api.WAF_RULE_STATUS_AVAILABLE
  372. self.Name = rule.GetName()
  373. self.ExternalId = rule.GetGlobalId()
  374. self.Expression = rule.GetExpression()
  375. self.Config, err = rule.GetConfig()
  376. if err != nil {
  377. return errors.Wrapf(err, "GetConfig")
  378. }
  379. self.Enabled = tristate.NewFromBool(rule.GetEnabled())
  380. return nil
  381. })
  382. if err != nil {
  383. return errors.Wrapf(err, "db.Update")
  384. }
  385. return self.SyncStatements(ctx, userCred, rule)
  386. }
  387. func (self *SWafInstance) newFromCloudRule(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudWafRule) error {
  388. rule := &SWafRule{}
  389. rule.SetModelManager(WafRuleManager, rule)
  390. rule.WafInstanceId = self.Id
  391. rule.Name = ext.GetName()
  392. rule.Description = ext.GetDesc()
  393. rule.ExternalId = ext.GetGlobalId()
  394. rule.Action = ext.GetAction()
  395. rule.StatementConditon = ext.GetStatementCondition()
  396. rule.Priority = ext.GetPriority()
  397. rule.Type = ext.GetType()
  398. rule.Status = api.WAF_RULE_STATUS_AVAILABLE
  399. rule.Expression = ext.GetExpression()
  400. var err error
  401. rule.Config, err = ext.GetConfig()
  402. if err != nil {
  403. return errors.Wrapf(err, "GetConfig")
  404. }
  405. rule.Enabled = tristate.NewFromBool(ext.GetEnabled())
  406. err = WafRuleManager.TableSpec().Insert(ctx, rule)
  407. if err != nil {
  408. return errors.Wrapf(err, "Insert")
  409. }
  410. return rule.SyncStatements(ctx, userCred, ext)
  411. }
  412. func (self *SWafInstance) SyncWafRules(ctx context.Context, userCred mcclient.TokenCredential, exts []cloudprovider.ICloudWafRule) compare.SyncResult {
  413. lockman.LockRawObject(ctx, WafInstanceManager.Keyword(), self.Id)
  414. defer lockman.ReleaseRawObject(ctx, WafInstanceManager.Keyword(), self.Id)
  415. result := compare.SyncResult{}
  416. dbRules, err := self.GetWafRules()
  417. if err != nil {
  418. result.Error(err)
  419. return result
  420. }
  421. removed := make([]SWafRule, 0)
  422. commondb := make([]SWafRule, 0)
  423. commonext := make([]cloudprovider.ICloudWafRule, 0)
  424. added := make([]cloudprovider.ICloudWafRule, 0)
  425. if err := compare.CompareSets(dbRules, exts, &removed, &commondb, &commonext, &added); err != nil {
  426. result.Error(err)
  427. return result
  428. }
  429. for i := 0; i < len(removed); i++ {
  430. err := removed[i].syncRemove(ctx, userCred)
  431. if err != nil {
  432. result.DeleteError(err)
  433. continue
  434. }
  435. result.Delete()
  436. }
  437. for i := 0; i < len(commondb); i++ {
  438. err := commondb[i].SyncWithCloudRule(ctx, userCred, commonext[i])
  439. if err != nil {
  440. result.UpdateError(err)
  441. continue
  442. }
  443. result.Update()
  444. }
  445. for i := 0; i < len(added); i++ {
  446. err := self.newFromCloudRule(ctx, userCred, added[i])
  447. if err != nil {
  448. result.AddError(err)
  449. continue
  450. }
  451. result.Add()
  452. }
  453. return result
  454. }
  455. func (self *SWafRuleGroup) GetWafRules() ([]SWafRule, error) {
  456. q := WafRuleManager.Query().Equals("waf_rule_group_id", self.Id)
  457. rules := []SWafRule{}
  458. err := db.FetchModelObjects(WafRuleManager, q, &rules)
  459. return rules, err
  460. }
  461. func (self *SWafRuleGroup) newFromManagedRule(ctx context.Context, userCred mcclient.TokenCredential, ext SWafRule) error {
  462. ext.SetModelManager(WafRuleManager, &ext)
  463. ext.WafRuleGroupId = self.Id
  464. return WafRuleManager.TableSpec().Insert(ctx, &ext)
  465. }
  466. func (self *SWafRuleGroup) SyncManagedWafRules(ctx context.Context, userCred mcclient.TokenCredential, exts []SWafRule) (compare.SyncResult, error) {
  467. lockman.LockRawObject(ctx, WafRuleGroupManager.Keyword(), self.Id)
  468. defer lockman.ReleaseRawObject(ctx, WafRuleGroupManager.Keyword(), self.Id)
  469. result := compare.SyncResult{}
  470. dbRules, err := self.GetWafRules()
  471. if err != nil {
  472. return result, errors.Wrapf(err, "GetWafRules")
  473. }
  474. removed := make([]SWafRule, 0)
  475. commondb := make([]SWafRule, 0)
  476. commonext := make([]SWafRule, 0)
  477. added := make([]SWafRule, 0)
  478. err = compare.CompareSets(dbRules, exts, &removed, &commondb, &commonext, &added)
  479. if err != nil {
  480. return result, errors.Wrapf(err, "compare.CompareSets")
  481. }
  482. for i := 0; i < len(removed); i++ {
  483. err := removed[i].syncRemove(ctx, userCred)
  484. if err != nil {
  485. result.DeleteError(err)
  486. continue
  487. }
  488. result.Delete()
  489. }
  490. for i := 0; i < len(added); i++ {
  491. err := self.newFromManagedRule(ctx, userCred, added[i])
  492. if err != nil {
  493. result.AddError(err)
  494. continue
  495. }
  496. result.Add()
  497. }
  498. return result, nil
  499. }
  500. func (self *SWafRule) GetICloudWafInstance(ctx context.Context) (cloudprovider.ICloudWafInstance, error) {
  501. ins, err := self.GetWafInstance()
  502. if err != nil {
  503. return nil, errors.Wrapf(err, "GetWafInstance")
  504. }
  505. iWaf, err := ins.GetICloudWafInstance(ctx)
  506. if err != nil {
  507. return nil, errors.Wrapf(err, "GetICloudWafInstance")
  508. }
  509. return iWaf, nil
  510. }
  511. func (self *SWafRule) GetICloudWafRule(ctx context.Context) (cloudprovider.ICloudWafRule, error) {
  512. if len(self.ExternalId) == 0 {
  513. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty external id")
  514. }
  515. if len(self.WafInstanceId) > 0 {
  516. iWaf, err := self.GetICloudWafInstance(ctx)
  517. if err != nil {
  518. return nil, errors.Wrapf(err, "GetICloudWafInstance")
  519. }
  520. rules, err := iWaf.GetRules()
  521. if err != nil {
  522. return nil, errors.Wrapf(err, "GetWafRules")
  523. }
  524. for i := range rules {
  525. if rules[i].GetGlobalId() == self.ExternalId {
  526. return rules[i], nil
  527. }
  528. }
  529. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", self.ExternalId)
  530. }
  531. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "")
  532. }
  533. // 同步WAF规则状态
  534. func (self *SWafRule) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.WafSyncstatusInput) (jsonutils.JSONObject, error) {
  535. return nil, StartResourceSyncStatusTask(ctx, userCred, self, "WafRuleSyncstatusTask", "")
  536. }
  537. // 启用
  538. func (self *SWafRule) PerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.WafRuleEnableInput) (jsonutils.JSONObject, error) {
  539. _, err := self.SEnabledStatusStandaloneResourceBase.PerformEnable(ctx, userCred, query, input.PerformEnableInput)
  540. if err != nil {
  541. return nil, err
  542. }
  543. return nil, self.StartSetEnabledTask(ctx, userCred, "")
  544. }
  545. func (self *SWafRule) StartSetEnabledTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  546. params := jsonutils.NewDict()
  547. task, err := taskman.TaskManager.NewTask(ctx, "WafRuleSetEnabledTask", self, userCred, params, parentTaskId, "", nil)
  548. if err != nil {
  549. return errors.Wrap(err, "NewTask")
  550. }
  551. self.SetStatus(ctx, userCred, apis.STATUS_SYNC_STATUS, "")
  552. return task.ScheduleRun(nil)
  553. }
  554. // 禁用
  555. func (self *SWafRule) PerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.WafRuleDisableInput) (jsonutils.JSONObject, error) {
  556. _, err := self.SEnabledStatusStandaloneResourceBase.PerformDisable(ctx, userCred, query, input.PerformDisableInput)
  557. if err != nil {
  558. return nil, err
  559. }
  560. return nil, self.StartSetEnabledTask(ctx, userCred, "")
  561. }