Skip to content

Commit

Permalink
aws - appsync resource and waf filter/action (#7872)
Browse files Browse the repository at this point in the history
  • Loading branch information
cahn1 authored and HappyKid117 committed Oct 16, 2022
1 parent 544e897 commit 73c78a4
Show file tree
Hide file tree
Showing 14 changed files with 599 additions and 0 deletions.
173 changes: 173 additions & 0 deletions c7n/resources/appsync.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Copyright The Cloud Custodian Authors.
# SPDX-License-Identifier: Apache-2.0
import re

from c7n.actions import BaseAction
from c7n.filters import Filter
from c7n.manager import resources
from c7n.query import QueryResourceManager, TypeInfo
from c7n.utils import local_session, type_schema, get_retry


@resources.register('graphql-api')
class GraphQLApi(QueryResourceManager):
"""Resource Manager for AppSync GraphQLApi
"""
class resource_type(TypeInfo):
service = 'appsync'
enum_spec = ('list_graphql_apis', 'graphqlApis', {'maxResults': 25})
id = 'apiId'
name = 'name'
cfn_type = 'AWS::AppSync::GraphQLApi'
arn_type = 'apis'
arn = 'arn'
universal_taggable = True


@GraphQLApi.filter_registry.register('wafv2-enabled')
class WafV2Enabled(Filter):
"""Filter AppSync GraphQLApi by wafv2 web-acl
:example:
.. code-block:: yaml
policies:
- name: filter-graphql-api-wafv2
resource: graphql-api
filters:
- type: wafv2-enabled
state: false
web-acl: test-waf-v2
- name: filter-graphql-api-wafv2-regex
resource: graphql-api
filters:
- type: wafv2-enabled
state: false
web-acl: .*FMManagedWebACLV2-?FMS-.*
"""

schema = type_schema(
'wafv2-enabled', **{
'web-acl': {'type': 'string'},
'state': {'type': 'boolean'}})

permissions = ('wafv2:ListWebACLs',)

def process(self, resources, event=None):
wafs = self.manager.get_resource_manager('wafv2').resources(augment=False)
waf_name_id_map = {w['Name']: w['ARN'] for w in wafs}

target_acl = self.data.get('web-acl', '')
state = self.data.get('state', False)
target_acl_ids = [v for k, v in waf_name_id_map.items() if
re.match(target_acl, k)]

results = []
for r in resources:
r_web_acl_id = r.get('wafWebAclArn')
if state:
if not target_acl and r_web_acl_id:
results.append(r)
elif target_acl and r_web_acl_id in target_acl_ids:
results.append(r)
else:
if not target_acl and not r_web_acl_id:
results.append(r)
elif target_acl and r_web_acl_id not in target_acl_ids:
results.append(r)
return results


@GraphQLApi.action_registry.register('set-wafv2')
class SetWafv2(BaseAction):
"""Enable wafv2 protection on AppSync graphqlApi.
:example:
.. code-block:: yaml
policies:
- name: set-wafv2-for-graphql-api
resource: graphql-api
filters:
- type: wafv2-enabled
state: false
web-acl: test-waf-v2
actions:
- type: set-wafv2
state: true
force: true
web-acl: test-waf-v2
- name: unset-wafv2-for-graphql-api
resource: graphql-api
filters:
- type: wafv2-enabled
state: true
actions:
- type: set-wafv2
state: true
force: true
web-acl: test-waf-v2
policies:
- name: set-wafv2-for-graphql-api-regex
resource: graphql-api
filters:
- type: wafv2-enabled
state: false
web-acl: .*FMManagedWebACLV2-?FMS-.*
actions:
- type: set-wafv2
state: true
force: true
web-acl: FMManagedWebACLV2-?FMS-TestWebACL
"""
permissions = ('wafv2:AssociateWebACL',
'wafv2:DisassociateWebACL',
'wafv2:ListWebACLs')

schema = type_schema(
'set-wafv2', **{
'web-acl': {'type': 'string'},
'force': {'type': 'boolean'},
'state': {'type': 'boolean'}})

retry = staticmethod(get_retry((
'ThrottlingException',
'RequestLimitExceeded',
'Throttled',
'ThrottledException',
'Throttling',
'Client.RequestLimitExceeded')))

def process(self, resources):
wafs = self.manager.get_resource_manager('wafv2').resources(augment=False)
waf_name_id_map = {w['Name']: w['ARN'] for w in wafs}
state = self.data.get('state', True)

target_acl_id = ''
if state:
target_acl = self.data.get('web-acl', '')
target_acl_ids = [v for k, v in waf_name_id_map.items() if
re.match(target_acl, k)]
if len(target_acl_ids) != 1:
raise ValueError(f'{target_acl} matching to none or '
f'multiple webacls')
target_acl_id = target_acl_ids[0]

client = local_session(self.manager.session_factory).client('wafv2')
force = self.data.get('force', False)

arn_key = self.manager.resource_type.arn

for r in resources:
if r.get('wafWebAclArn') and not force:
continue
if r.get('wafWebAclArn') == target_acl_id:
continue
if state:
self.retry(client.associate_web_acl,
WebACLArn=target_acl_id,
ResourceArn=r[arn_key])
else:
self.retry(client.disassociate_web_acl,
ResourceArn=r[arn_key])
1 change: 1 addition & 0 deletions c7n/resources/resource_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"aws.app-elb": "c7n.resources.appelb.AppELB",
"aws.app-elb-target-group": "c7n.resources.appelb.AppELBTargetGroup",
"aws.app-flow": "c7n.resources.appflow.AppFlow",
"aws.graphql-api": "c7n.resources.appsync.GraphQLApi",
"aws.asg": "c7n.resources.asg.ASG",
"aws.backup-plan": "c7n.resources.backup.BackupPlan",
"aws.backup-vault": "c7n.resources.backup.BackupVault",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"status_code": 200,
"data": {
"graphqlApis": [
{
"name": "My AppSync Api1",
"apiId": "lopd6grtrnctrfi7g7ywvfkzta",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678912:apis/lopd6grtrnctrfi7g7ywvfkzta",
"uris": {
"REALTIME": "wss://az5joslekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://az5joslekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false,
"wafWebAclArn": "arn:aws:wafv2:us-east-1:012345678912:regional/webacl/FMManagedWebACLV2-FMS-TEST-1656966584517/96494e83-ee49-4505-9f68-9103c6cd9406"
},
{
"name": "My AppSync Api2",
"apiId": "mlpaw0grtrnctrfi7g7ywvfk908",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678912:apis/mlpaw0grtrnctrfi7g7ywvfk908",
"uris": {
"REALTIME": "wss://kslwp0lekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://kslwp0lekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false
},
{
"name": "My AppSync Api3",
"apiId": "p012w0grtrnctrfi7g7ywvf4y67",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678912:apis/p012w0grtrnctrfi7g7ywvf4y67",
"uris": {
"REALTIME": "wss://pqlap0lekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://pqlap0lekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false,
"wafWebAclArn": "arn:aws:wafv2:us-east-1:012345678912:regional/webacl/WebACL_TESTv2/887bbaec-c70b-4884-b290-ec7c7b5a43kl"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"status_code": 200,
"data": {
"ResponseMetadata": {}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"status_code": 200,
"data": {
"ResponseMetadata": {}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"status_code": 200,
"data": {
"NextMarker": "1ebe0b46-0fd2-4e07-a74c-27bf25adc0bf",
"ResponseMetadata": {
"RetryAttempts": 0,
"HTTPStatusCode": 200,
"RequestId": "05ff3012-a9c9-11e7-8af9-c510054683ae",
"HTTPHeaders": {
"x-amzn-requestid": "05ff3012-a9c9-11e7-8af9-c510054683ae",
"date": "Thu, 05 Oct 2017 12:30:50 GMT",
"content-length": "131",
"content-type": "application/x-amz-json-1.1"
}
},
"WebACLs": [
{
"Id": "96494e83-ee49-4505-9f68-9103c6cd9406",
"Name": "FMManagedWebACLV2-FMS-TEST-1656966584517",
"ARN": "arn:aws:wafv2:us-east-1:012345678912:regional/webacl/FMManagedWebACLV2-FMS-TEST-1656966584517/96494e83-ee49-4505-9f68-9103c6cd9406"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"status_code": 200,
"data": {
"graphqlApis": [
{
"name": "My AppSync Api1",
"apiId": "lopd6grtrnctrfi7g7ywvfkzta",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678901:apis/lopd6grtrnctrfi7g7ywvfkzta",
"uris": {
"REALTIME": "wss://az5joslekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://az5joslekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false,
"wafWebAclArn": "arn:aws:wafv2:us-east-1:012345678912:regional/webacl/FMManagedWebACLV2-FMS-TEST-1656966584517/96494e83-ee49-4505-9f68-9103c6cd9406"
},
{
"name": "My AppSync Api2",
"apiId": "mlpaw0grtrnctrfi7g7ywvfk908",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678901:apis/mlpaw0grtrnctrfi7g7ywvfk908",
"uris": {
"REALTIME": "wss://kslwp0lekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://kslwp0lekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false
},
{
"name": "My AppSync Api3",
"apiId": "p012w0grtrnctrfi7g7ywvf4y67",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678901:apis/p012w0grtrnctrfi7g7ywvf4y67",
"uris": {
"REALTIME": "wss://pqlap0lekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://pqlap0lekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false,
"wafWebAclArn": "arn:aws:wafv2:us-east-1:012345678901:regional/webacl/WebACL_TESTv2/887bbaec-c70b-4884-b290-ec7c7b5a43kl"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"status_code": 200,
"data": {
"NextMarker": "791f9fc9-16bb-4d32-8f6a-b55e9b6f11c8",
"WebACLs": [
{
"Id": "96494e83-ee49-4505-9f68-9103c6cd9406",
"Name": "FMManagedWebACLV2-FMS-TEST-1656966584517",
"ARN": "arn:aws:wafv2:us-east-1:123456789123:regional/webacl/FMManagedWebACLV2-FMS-TEST-1656966584517/96494e83-ee49-4505-9f68-9103c6cd9406"
},
{
"Id": "3c5f3db9-04c1-47f4-a6ab-23b70a3a8509",
"Name": "FMManagedWebACLV2-FMS-TEST2-1656966576062",
"ARN": "arn:aws:wafv2:us-east-1:123456789123:regional/webacl/FMManagedWebACLV2-FMS-TEST2-1656966576062/3c5f3db9-04c1-47f4-a6ab-23b70a3a8509"
}
],
"ResponseMetadata": {}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"status_code": 200,
"data": {
"graphqlApis": [
{
"name": "My AppSync Api1",
"apiId": "lopd6grtrnctrfi7g7ywvfkzta",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678901:apis/lopd6grtrnctrfi7g7ywvfkzta",
"uris": {
"REALTIME": "wss://az5joslekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://az5joslekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false,
"wafWebAclArn": "arn:aws:wafv2:us-east-1:012345678912:regional/webacl/FMManagedWebACLV2-FMS-TEST-1656966584517/96494e83-ee49-4505-9f68-9103c6cd9406"
},
{
"name": "My AppSync Api2",
"apiId": "mlpaw0grtrnctrfi7g7ywvfk908",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678901:apis/mlpaw0grtrnctrfi7g7ywvfk908",
"uris": {
"REALTIME": "wss://kslwp0lekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://kslwp0lekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false
},
{
"name": "My AppSync Api3",
"apiId": "p012w0grtrnctrfi7g7ywvf4y67",
"authenticationType": "API_KEY",
"arn": "arn:aws:appsync:us-east-1:012345678901:apis/p012w0grtrnctrfi7g7ywvf4y67",
"uris": {
"REALTIME": "wss://pqlap0lekdcedka43ordq3fcvq.appsync-realtime-api.us-east-1.amazonaws.com/graphql",
"GRAPHQL": "https://pqlap0lekdcedka43ordq3fcvq.appsync-api.us-east-1.amazonaws.com/graphql"
},
"tags": {
"waf": "test"
},
"xrayEnabled": false,
"wafWebAclArn": "arn:aws:wafv2:us-east-1:012345678901:regional/webacl/WebACL_TESTv2/887bbaec-c70b-4884-b290-ec7c7b5a43kl"
}
]
}
}

0 comments on commit 73c78a4

Please sign in to comment.