AWS WAF
📚 Documentation 💠Hub 💬 Discourse
Overview​
The crowdsec-awf-waf-bouncer
automatically adds rules to an AWS WAF ACL and manages IPSets content to apply decisions taken by crowdsec.
This allows to protect the following AWS resources with crowdsec:
- AWS REST API Gateway
- Cloudfront distribution
- AWS Application LoadBalancer
- AWS AppSync GraphQL API
As the component does not manage your WAF ACLs, you will need to have existing ACLs already associated with your AWS resources for the component to work properly.
The component supports the ban
and captcha
remediation type and can be configured to fall back to one of those for decisions of unknown type.
It can block at the IP (using ip
scope in CrowdSec), range (using range
scope in CrowdSec) or country level (using country
scope in CrowdSec).
The component will create all required resources and associate them with your existing ACLs based on your provided configuration.
As the resources will incur an AWS cost, the component will remove everything it created when stopping.
If you do not have an existing AWS WAF configuration, you can refer to the official documentation to get started.
Installation​
Using packages​
Packages for crowdsec-aws-waf-bouncer are available on our repositories. You need to pick the package accord to your firewall system :
- Debian/Ubuntu
- RHEL/Centos/Fedora
sudo apt install crowdsec-aws-waf-bouncer
sudo yum install crowdsec-aws-waf-bouncer
Docker​
docker run -e BOUNCER_CONFIG_FILE=/cs-aws-waf-bouncer.yaml -v $(PWD)/config.yaml:/cs-aws-waf-bouncer.yaml crowdsecurity/aws-waf-bouncer
The remediation component can take some time to delete all created resources on shutdown.
The default docker timeout of 10s before sending a SIGKILL
to the process might not always been enough.
You can increase it by specifying --stop-timeout
in your run
command or by setting stop_grace_period
when using compose.
Configuration Reference​
You will need to edit /etc/crowdsec/bouncers/crowdsec-aws-waf-bouncer.yaml
to configure the ACLs you want the component to use.
api_key: XXXX
api_url: "http://127.0.0.1:8080/"
update_frequency: 10s
waf_config:
- web_acl_name: mywebacl
fallback_action: ban
rule_group_name: crowdsec-rule-group-eu-west-1
scope: REGIONAL
region: eu-west-1
ipset_prefix: crowdsec-ipset-a
ip_header: X-Forwarded-For
ip_header_position: LAST
aws_profile: myprofile
- web_acl_name: test-cloudfront
fallback_action: captcha
rule_group_name: crowdsec-rule-group-cloudfront
scope: CLOUDFRONT
ipset_prefix: crowdsec-ipset-cf
Optionally, the component can also be configured using only environment variables.
Environment variables will take priority over values defined in the configuration file, in which case the suggested approach is via systemctl edit crowdsec-aws-waf-bouncer
:
[Service]
Environment="BOUNCER_API_KEY=XXXXX"
AWS authentication is handled with the standard environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_PROFILE) or instance role.
You can also use the aws_profile
directive to specify a profile to use for a specific waf configuration.
api_key
​
string
Environment variable:
BOUNCER_API_KEY
API key to use for communication with LAPI.
api_url
​
string
Environment variable:
BOUNCER_API_URL
URL of LAPI EG http://127.0.0.1:8080
update_frequency
​
string (That is parseable by time.ParseDuration)
Environment variable:
BOUNCER_UPDATE_FREQUENCY
How often the component will contact LAPI to update its content.
supported_actions
​
string
Environment variable:
BOUNCER_SUPPORTED_ACTIONS
Which actions (ie, remediation type) the component supports.
List with any of the following: ban
, captcha
, count
.
Default to ban
, captcha
and count
.
If set from the environment, provide a comma-separated list: ban,captcha,count
.
waf_config
​
[ ]AclConfig
Environment variable:
BOUNCER_WAF_CONFIG_
List of object with the following properties:
waf_config:
- web_acl_name: mywebacl
fallback_action: ban
rule_group_name: crowdsec-rule-group-XXX
scope: REGIONAL
region: eu-west-1
ipset_prefix: crowdsec-ipset-
When configuring via environment variables, you can pass multiple BOUNCER_WAF_CONFIG_X_
variables, with X
being a unique identifier (eg, 0
, 1
, 2
).
web_acl_name
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_WEB_ACL_NAME
Name of the WAF ACL in which the rule group will be added
fallback_action
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_FALLBACK_ACTION
Action to use if the type of a decision is not in the list defined by supported_actions
.
Must be one of captcha
, ban
or count
.
rule_group_name
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_RULE_GROUP_NAME
Name of the rule group the component will create and add to the WAF ACL.
Must be unique across all the configuration.
2 rules can be created:
- crowdsec-rule-ban
- crowdsec-rule-captcha
Those rules are automatically deleted if no decisions of the associated type exist.
If a decision for a country is received, the following rules will be created:
- crowdsec-rule-ban-country: Contains a geomatch statement for banned countries
- crowdsec-rule-captcha-country: Contains a geomatch statement for captcha'ed countries
Those rules will be deleted on shutdown and recreated on startup if they already exist.
scope
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_SCOPE
Scope of the rule group and ipset. Can be REGIONAL
or CLOUDFRONT
.
Must match the scope of the WAF ACL.
region
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_REGION
Region where all resources will be created.
No required when scope is CLOUDFRONT
ipset_prefix
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_IPSET_PREFIX
Prefix for all the ipsets the component will create.
One ipset will be created per 10k IPs, and will be automatically deleted if it becomes empty.
Differents ipsets are used for ban and captcha.
All ipsets are deleted on shutdown.
aws_profile
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_AWS_PROFILE
Name of the AWS profile (defined in ~/.aws/config) to use.
ip_header
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_IP_HEADER
Name of the header to use to get the source IP. If not defined, the actual source IP will be used.
The request will be allowed if the header is not present or contains no valid IP.
ip_header_position
​
FIRST
,LAST
,ANY
Environment variable:
BOUNCER_WAF_CONFIG_X_IP_HEADER_POSITION
If the header used to get the source IP is a comma-separated list, this parameter can be used to specify which part of the list should be used.
Required when ip_header
is defined.
capacity
​
int
Environment variable:
BOUNCER_WAF_CONFIG_X_CAPACITY
Capacity of the rule group created by the component.
If not set, default to 300 (this value is way higher than it needs to be, but this prevents any kind of issue regarding capacity of the rule group).
For reference, a simple match on a IP with no custom header will cost 1 WCU per IPSet created by the bouncer, or 5 WCU if you are getting the source IP from a header.
See AWS WAF documentation for more information.
cloudwatch_enabled
​
boolean
Environment variable:
BOUNCER_WAF_CONFIG_X_CLOUDWATCH_ENABLED
Whether or not AWS WAF will send metrics to CloudWatch for the rule group.
cloudwatch_metric_name
​
string
Environment variable:
BOUNCER_WAF_CONFIG_X_CLOUDWATCH_METRIC_NAME
Name of the cloudwatch metric. Default to the rule group name.
sample_requests
​
boolean
Environment variable:
BOUNCER_WAF_CONFIG_X_SAMPLE_REQUESTS
Whether or not to sample requests from the rule groups created by the component.
IAM Permissions​
Because the component needs to interact with AWS resources, it need the proper permissions.
Here is the set of required permissions:
{
"Statement": [
{
"Action": [
"wafv2:UpdateWebACL",
"wafv2:UpdateRuleGroup",
"wafv2:UpdateIPSet",
"wafv2:TagResource",
"wafv2:GetWebACL",
"wafv2:GetRuleGroup",
"wafv2:GetIPSet",
"wafv2:DeleteRuleGroup",
"wafv2:DeleteIPSet",
"wafv2:CreateRuleGroup",
"wafv2:CreateIPSet"
],
"Effect": "Allow",
"Resource": [
"arn:aws:wafv2:*:*:global/webacl/*/*",
"arn:aws:wafv2:*:*:global/rulegroup/*/*",
"arn:aws:wafv2:*:*:global/managedruleset/*/*",
"arn:aws:wafv2:*:*:*/ipset/*/*"
],
"Sid": "WAF1"
},
{
"Action": [
"wafv2:ListWebACLs",
"wafv2:ListRuleGroups",
"wafv2:ListIPSets"
],
"Effect": "Allow",
"Resource": "*",
"Sid": "WAF2"
}
],
"Version": "2012-10-17"
}
AWS requires the resource for wafv2:List*
to be *
.
For the other permissions, we recommend to restrict the resources to only the WebACL the component is configured to interact with and the rule groups/ipsets the component will create.