A collection of security and best practice tests for static code analysis of terraform templates using terraform_validate.
- GitHub Repo: https://github.com/cesar-rodriguez/terrascan
- Documentation: https://terrascan.readthedocs.io.
- Tutorial: https://www.cloudsecuritymusings.com/blog/using-terrascan-for-static-code-analysis-of-your-infrastructure-code-part-1
- Free software: GNU General Public License v3
Terrascan will perform tests on your terraform templates to ensure:
- Encryption
- Server Side Encryption (SSE) enabled
- Use of AWS Key Management Service (KMS) with Customer Managed Keys (CMK)
- Use of SSL/TLS and proper configuration
- Security Groups
- Provisioning SGs in EC2-classic
- Ingress open to 0.0.0.0/0
- Public Exposure
- Services with public exposure other than Gateways (NAT, VGW, IGW)
- Logging & Monitoring
- Access logs enabled to resources that support it
Terrascan uses Python and depends on pyhcl and terraform-validate (a fork has been included as part of terrascan that supports terraform 0.12+). After installing python in your system you can follow these steps:
$ pip install terrascan
To run, execute terrascan.py as follows replacing with the location of your terraform templates:
$ terrascan --location tests/infrastructure/success --vars tests/infrastructure/vars.json
- Returns 0 if no failures or errors; 4 otherwise
- helps with use in a delivery pipeline
Parameters:
-h, --help show this help message and exit -l LOCATION, --location LOCATION location of terraform templates to scan -v [VARS [VARS ...]], --vars [VARS [VARS ...]] variables json or .tf file name -o OVERRIDES, --overrides OVERRIDES override rules file name -r RESULTS, --results RESULTS output results file name -d [DISPLAYRULES], --displayRules [DISPLAYRULES] display the rules used -w [WARRANTY], --warranty [WARRANTY] displays the warranty -g [GPL], --gpl [GPL] displays license information -c CONFIG, --config CONFIG logging configuration: error, warning, info, debug, or none; default is error
Override file example
- The first attribute is the name of the rule to be overridden.
- The second attribute is the name of the resource to be overridden.
3. The third atttribute is the RR or RAR number that waives the failure. This is required for high severity rules; can be an empty string for medium and low severity rules.
{
"overrides": [
[
"aws_s3_bucket_server_side_encryption_configuration",
"noEncryptionWaived",
"RR-1234"
],
[
"aws_rds_cluster_encryption",
"rds_cluster_bad",
"RAR-98765"
]
]
}
Example output:
Logging level set to error. ................ ---------------------------------------------------------------------- Ran 16 tests in 0.015s OK Processed 19 files in C:\DEV\terraforms\backends\10-network-analytics Results (took 1.08 seconds): Failures: (2) [high] [aws_dynamodb_table.encryption.server_side_encryption.enabled] should be 'True'. Is: 'False' in module 10-network-analytics, file C:\DEV\terraforms\backends\10-network-analytics\main.tf [high] [aws_s3_bucket.noEncryption] should have property: 'server_side_encryption_configuration' in module 10-network-analytics, file C:\DEV\terraforms\backends\10-network-analytics\main.tf Errors: (0)
Terrascan can be used on pre-commit hooks to prevent accidental introduction of security weaknesses into your repository. This requires having pre-commit installed. An example configuration is provided in the comments of the here file in this repository.
- Legend:
- ➖ = test needs to be implemented
- ✔️ = test implemented
- blank - N/A
Terraform resources | Encryption | Security Groups | Public exposure | Logging & Monitoring |
---|---|---|---|---|
aws_alb | ✔️ | ✔️ | ||
aws_alb_listener | ✔️ | |||
aws_ami | ✔️ | |||
aws_ami_copy | ✔️ | |||
aws_api_gateway_domain_name | ✔️ | |||
aws_cloudfront_distribution | ✔️ | ✔️ | ||
aws_cloudtrail | ✔️ | ✔️ | ||
aws_codebuild_project | ✔️ | |||
aws_codepipeline | ✔️ | |||
aws_db_instance | ✔️ | ✔️ | ||
aws_db_security_group | ✔️ | |||
aws_dms_endpoint | ✔️ | |||
aws_dms_replication_instance | ✔️ | ✔️ | ||
aws_dynamodb_table | ✔️ | |||
aws_ebs_volume | ✔️ | |||
aws_efs_file_system | ✔️ | |||
aws_elasticache_security_group | ✔️ | |||
aws_efs_file_system | ✔️ | |||
aws_elasticache_security_group | ✔️ | |||
aws_elastictranscoder_pipeline | ✔️ | |||
aws_elb | ✔️ | ✔️ | ✔️ | |
aws_emr_cluster | ✔️ | |||
aws_instance | ✔️ | ✔️ | ||
aws_kinesis_firehose_delivery_stream | ✔️ | ✔️ | ||
aws_lambda_function | ✔️ | |||
aws_launch_configuration | ✔️ | |||
aws_lb_ssl_negotiation_policy | ➖ | |||
aws_load_balancer_backend_server_policy | ➖ | |||
aws_load_balancer_listener_policy | ➖ | |||
aws_load_balancer_policy | ➖ | |||
aws_opsworks_application | ✔️ | ➖ | ||
aws_opsworks_custom_layer | ➖ | |||
aws_opsworks_ganglia_layer | ➖ | |||
aws_opsworks_haproxy_layer | ➖ | |||
aws_opsworks_instance | ➖ | |||
aws_opsworks_java_app_layer | ➖ | |||
aws_opsworks_memcached_layer | ➖ | |||
aws_opsworks_mysql_layer | ➖ | |||
aws_opsworks_nodejs_app_layer | ➖ | |||
aws_opsworks_php_app_layer | ➖ | |||
aws_opsworks_rails_app_layer | ➖ | |||
aws_opsworks_static_web_layer | ➖ | |||
aws_rds_cluster | ✔️ | |||
aws_rds_cluster_instance | ✔️ | |||
aws_redshift_cluster | ✔️ | ✔️ | ✔️ | |
aws_redshift_parameter_group | ➖ | ➖ | ||
aws_redshift_security_group | ✔️ | |||
aws_s3_bucket | ✔️ | ✔️ | ✔️ | |
aws_s3_bucket_object | ✔️ | |||
aws_security_group | ✔️ | ✔️ | ||
aws_security_group_rule | ✔️ | ✔️ | ||
aws_ses_receipt_rule | ➖ | |||
aws_sqs_queue | ✔️ | |||
aws_ssm_maintenance_window_task | ✔️ | |||
aws_ssm_parameter | ✔️ |