Skip to content

Commit cf240b7

Browse files
add waf
1 parent a5f10c3 commit cf240b7

File tree

11 files changed

+852
-0
lines changed

11 files changed

+852
-0
lines changed

tools/c7n_huaweicloud/c7n_huaweicloud/client.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@
105105
from huaweicloudsdkram.v1.region.ram_region import RamRegion
106106
from huaweicloudsdkcc.v3 import CcClient, ListCentralNetworksRequest
107107
from huaweicloudsdkcc.v3.region.cc_region import CcRegion
108+
from huaweicloudsdkwaf.v1 import WafClient, ListPolicyRequest, ShowLtsInfoConfigRequest
109+
from huaweicloudsdkwaf.v1.region.waf_region import WafRegion
108110

109111
log = logging.getLogger("custodian.huaweicloud.client")
110112

@@ -419,11 +421,19 @@ def client(self, service):
419421
.with_region(CcRegion.CN_NORTH_4)
420422
.build()
421423
)
424+
<<<<<<< HEAD
422425
elif service == "bms":
423426
client = (
424427
BmsClient.new_builder()
425428
.with_credentials(credentials)
426429
.with_region(BmsRegion.value_of(self.region))
430+
=======
431+
elif service in ["waf", "waf-policy", "waf-log-config"]:
432+
client = (
433+
WafClient.new_builder()
434+
.with_credentials(credentials)
435+
.with_region(WafRegion.value_of(self.region))
436+
>>>>>>> 954f7718f (add waf)
427437
.build()
428438
)
429439

@@ -538,5 +548,9 @@ def request(self, service):
538548
request = ListInstancesRequest()
539549
elif service == "bms":
540550
request = ListBareMetalServerDetailsRequest()
551+
elif service == 'waf-policy':
552+
request = ListPolicyRequest()
553+
elif service == 'waf-log-config':
554+
request = ShowLtsInfoConfigRequest()
541555

542556
return request

tools/c7n_huaweicloud/c7n_huaweicloud/query.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ def filter(self, resource_manager, **params):
6262
resources = self._non_pagination(m, enum_op, path)
6363
elif pagination == "page":
6464
resources = self._pagination_limit_page(m, enum_op, path)
65+
elif pagination == "waf":
66+
resources = self._pagination_waf(m, enum_op, path)
6567
else:
6668
log.exception(f"Unsupported pagination type: {pagination}")
6769
sys.exit(1)
@@ -310,6 +312,39 @@ def _pagination_ims(self, m, enum_op, path):
310312
data["tag_resource_type"] = m.tag_resource_type
311313
resources.extend(res)
312314
return resources
315+
316+
def _pagination_waf(self, m, enum_op, path):
317+
session = local_session(self.session_factory)
318+
client = session.client(m.service)
319+
320+
page = 1
321+
resources = []
322+
while 1:
323+
request = session.request(m.service)
324+
request.page = page
325+
response = self._invoke_client_enum(client, enum_op, request)
326+
res = jmespath.search(
327+
path,
328+
eval(
329+
str(response)
330+
.replace("null", "None")
331+
.replace("false", "False")
332+
.replace("true", "True")
333+
),
334+
)
335+
336+
if not res:
337+
return resources
338+
339+
# replace id with the specified one
340+
for data in res:
341+
data["id"] = data[m.id]
342+
data["tag_resource_type"] = m.tag_resource_type
343+
344+
resources = resources + res
345+
346+
page += 1
347+
return resources
313348

314349
def _get_obs_account_id(self, response, manager, resources):
315350
if manager.service == "obs":

tools/c7n_huaweicloud/c7n_huaweicloud/resources/resource_map.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@
4646
"huaweicloud.kafka": "c7n_huaweicloud.resources.kafka.Kafka",
4747
"huaweicloud.cc-cloud-connection": "c7n_huaweicloud.resources.cc.CloudConnection",
4848
"huaweicloud.bms": "c7n_huaweicloud.resources.bms.Bms",
49+
"huaweicloud.waf-policy": "c7n_huaweicloud.resources.waf.WafPolicy",
50+
"huaweicloud.waf-log-config": "c7n_huaweicloud.resources.waf.WafLogConfig",
4951
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Copyright The Cloud Custodian Authors.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import logging
5+
from c7n.utils import type_schema
6+
from c7n.filters.core import ValueFilter
7+
8+
from huaweicloudsdkcore.exceptions import exceptions
9+
from huaweicloudsdkwaf.v1.model.update_lts_info_config_request import UpdateLtsInfoConfigRequest
10+
from huaweicloudsdkwaf.v1.model.update_lts_info_config_request_body import UpdateLtsInfoConfigRequestBody
11+
from huaweicloudsdkwaf.v1.model.lts_id_info import LtsIdInfo
12+
13+
from c7n_huaweicloud.actions.base import HuaweiCloudBaseAction
14+
from c7n_huaweicloud.provider import resources
15+
from c7n_huaweicloud.query import QueryResourceManager, TypeInfo
16+
17+
log = logging.getLogger('custodian.huaweicloud.resources.waf')
18+
19+
20+
@resources.register('waf-policy')
21+
class WafPolicy(QueryResourceManager):
22+
"""Huawei Cloud Web Application Firewall (WAF) Policy Resource
23+
24+
:example:
25+
26+
.. code-block:: yaml
27+
28+
policies:
29+
- name: waf-policy-list
30+
resource: huaweicloud.waf-policy
31+
"""
32+
33+
class resource_type(TypeInfo):
34+
"""Define WAF policy resource metadata and type information"""
35+
service = 'waf-policy' # Specify the corresponding Huawei Cloud service name
36+
# Specify the API operation, result list key name, and pagination parameters for enumerating resources
37+
# 'list_policy' is the API method name
38+
# 'items' is the field name containing the instance list in the response
39+
# None indicates no pagination is used
40+
enum_spec = ('list_policy', 'items', "waf")
41+
id = 'id' # Specify the resource unique identifier field name
42+
name = 'name' # Specify the resource name field
43+
date = 'timestamp' # Specify the resource creation time field
44+
arn_type = 'waf-policy' # Resource ARN type
45+
tag_resource_type = None # Tag not supported
46+
47+
48+
@resources.register('waf-log-config')
49+
class WafLogConfig(QueryResourceManager):
50+
"""Huawei Cloud Web Application Firewall (WAF) Log Configuration Resource
51+
52+
:example:
53+
54+
.. code-block:: yaml
55+
56+
policies:
57+
- name: waf-log-config-list
58+
resource: huaweicloud.waf-log-config
59+
"""
60+
61+
class resource_type(TypeInfo):
62+
"""Define WAF log configuration resource metadata and type information"""
63+
service = 'waf-log-config' # Specify the corresponding Huawei Cloud service name
64+
# Specify the API operation, result list key name, and pagination parameters for enumerating resources
65+
# 'show_lts_info_config' is the API method name
66+
# 'lts_info' is the field name containing the instance info in the response
67+
# None indicates no pagination is used
68+
enum_spec = ('show_lts_info_config', "[ @ ]", None)
69+
id = 'id' # Specify the resource unique identifier field name
70+
name = 'id' # Specify the resource name field
71+
arn_type = 'waf-log-config' # Resource ARN type
72+
tag_resource_type = None # Tag not supported
73+
74+
75+
@WafLogConfig.filter_registry.register('enabled')
76+
class LogEnabledFilter(ValueFilter):
77+
"""Filter by WAF log configuration enabled status
78+
79+
:example:
80+
81+
.. code-block:: yaml
82+
83+
policies:
84+
- name: waf-logs-disabled
85+
resource: huaweicloud.waf-log-config
86+
filters:
87+
- type: enabled
88+
value: false # Not enabled
89+
"""
90+
schema = type_schema('enabled', rinherit=ValueFilter.schema)
91+
92+
def __init__(self, data, manager=None):
93+
"""Initialize the filter
94+
95+
:param data: Filter configuration data
96+
:param manager: Resource manager
97+
"""
98+
super(LogEnabledFilter, self).__init__(data, manager)
99+
self.data['key'] = 'enabled'
100+
101+
102+
@WafLogConfig.action_registry.register('update')
103+
class UpdateLogConfig(HuaweiCloudBaseAction):
104+
"""Update WAF log configuration
105+
106+
This operation allows enabling/disabling WAF log configuration and setting log group and log stream information.
107+
108+
:example:
109+
110+
.. code-block:: yaml
111+
112+
policies:
113+
- name: enable-waf-logs
114+
resource: huaweicloud.waf-log-config
115+
filters:
116+
- type: enabled
117+
value: false # Not enabled
118+
actions:
119+
- type: update
120+
enabled: true # Enabled
121+
lts_id_info:
122+
lts_group_id: "4bcff74d-f649-41c8-8325-1b0a264ff683"
123+
lts_access_stream_id: "0a7ef713-cc3e-418d-abda-85df04db1a3c"
124+
lts_attack_stream_id: "f4fa07f6-277b-4e4a-a257-26508ece81e6"
125+
"""
126+
schema = type_schema(
127+
'update',
128+
enabled={'type': 'boolean'},
129+
lts_id_info={
130+
'type': 'object',
131+
'properties': {
132+
'lts_group_id': {'type': 'string'},
133+
'lts_access_stream_id': {'type': 'string'},
134+
'lts_attack_stream_id': {'type': 'string'}
135+
},
136+
'additionalProperties': False
137+
}
138+
)
139+
140+
def perform_action(self, resource):
141+
"""Perform action on a single resource
142+
143+
:param resource: Resource to perform action on
144+
:return: API response
145+
"""
146+
client = self.manager.get_client()
147+
resource_id = resource['id']
148+
149+
# Construct log information object
150+
lts_id_info_data = self.data.get('lts_id_info')
151+
lts_id_info = None
152+
153+
if lts_id_info_data:
154+
lts_id_info = LtsIdInfo(
155+
lts_group_id=lts_id_info_data.get('lts_group_id'),
156+
lts_access_stream_id=lts_id_info_data.get('lts_access_stream_id'),
157+
lts_attack_stream_id=lts_id_info_data.get('lts_attack_stream_id')
158+
)
159+
160+
# Construct request body
161+
request_body = UpdateLtsInfoConfigRequestBody(
162+
enabled=self.data.get('enabled'),
163+
lts_id_info=lts_id_info
164+
)
165+
166+
# Construct request
167+
request = UpdateLtsInfoConfigRequest(
168+
ltsconfig_id=resource_id,
169+
body=request_body
170+
)
171+
172+
# Get enterprise project ID from resource data
173+
if 'enterprise_project_id' in resource:
174+
request.enterprise_project_id = resource['enterprise_project_id']
175+
176+
try:
177+
# Call API to update log configuration
178+
response = client.update_lts_info_config(request)
179+
log.info(f"Updated WAF log configuration: {resource_id}")
180+
return response
181+
except exceptions.ClientRequestException as e:
182+
log.error(f"Failed to update WAF log configuration: {e.status_code}, {e.request_id}, {e.error_code}, {e.error_msg}")
183+
raise
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate, zstd
9+
Connection:
10+
- keep-alive
11+
Content-Type:
12+
- application/json
13+
Host:
14+
- waf.ap-southeast-1.myhuaweicloud.com
15+
User-Agent:
16+
- huaweicloud-usdk-python/3.0
17+
X-Project-Id:
18+
- ap-southeat-1
19+
X-Sdk-Date:
20+
- 20250512T114219Z
21+
method: GET
22+
uri: https://waf.ap-southeast-1.myhuaweicloud.com/v1/ap-southeat-1/waf/config/lts
23+
response:
24+
body:
25+
string: '{"id": "log-config-12345", "enabled": false, "lts_id_info": {"lts_group_id": "group-id-12345", "lts_access_stream_id": "access-stream-id-12345", "lts_attack_stream_id": "attack-stream-id-12345"}, "created_at": 1619760096000, "updated_at": 1619760096000}'
26+
headers:
27+
Connection:
28+
- keep-alive
29+
Content-Type:
30+
- application/json
31+
Date:
32+
- Mon, 12 May 2025 11:42:19 GMT
33+
Server:
34+
- api-gateway
35+
Strict-Transport-Security:
36+
- max-age=31536000; includeSubdomains;
37+
Transfer-Encoding:
38+
- chunked
39+
X-Content-Type-Options:
40+
- nosniff
41+
X-Download-Options:
42+
- noopen
43+
X-Frame-Options:
44+
- SAMEORIGIN
45+
X-Request-Id:
46+
- 193cbe0734c19b58215a6d4ae57e10f3
47+
X-XSS-Protection:
48+
- 1; mode=block;
49+
status:
50+
code: 200
51+
message: success
52+
version: 1
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate, zstd
9+
Connection:
10+
- keep-alive
11+
Content-Type:
12+
- application/json
13+
Host:
14+
- waf.ap-southeast-1.myhuaweicloud.com
15+
User-Agent:
16+
- huaweicloud-usdk-python/3.0
17+
X-Project-Id:
18+
- ap-southeat-1
19+
X-Sdk-Date:
20+
- 20250512T114219Z
21+
method: GET
22+
uri: https://waf.ap-southeast-1.myhuaweicloud.com/v1/ap-southeat-1/waf/config/lts
23+
response:
24+
body:
25+
string: '{"id": "log-config-12345", "enabled": true, "lts_id_info": {"lts_group_id": "group-id-12345", "lts_access_stream_id": "access-stream-id-12345", "lts_attack_stream_id": "attack-stream-id-12345"}, "created_at": 1619760096000, "updated_at": 1619760096000}'
26+
headers:
27+
Connection:
28+
- keep-alive
29+
Content-Type:
30+
- application/json
31+
Date:
32+
- Mon, 12 May 2025 11:42:19 GMT
33+
Server:
34+
- api-gateway
35+
Strict-Transport-Security:
36+
- max-age=31536000; includeSubdomains;
37+
Transfer-Encoding:
38+
- chunked
39+
X-Content-Type-Options:
40+
- nosniff
41+
X-Download-Options:
42+
- noopen
43+
X-Frame-Options:
44+
- SAMEORIGIN
45+
X-Request-Id:
46+
- 2bc9734083ff7bc42e49dce25344025d
47+
X-XSS-Protection:
48+
- 1; mode=block;
49+
status:
50+
code: 200
51+
message: success
52+
version: 1

0 commit comments

Comments
 (0)