Last active
February 25, 2024 21:29
-
-
Save danielvrog/e1549f9b7504a2421fc496aa4d43abb6 to your computer and use it in GitHub Desktop.
OPA Conftest: Validate all AWS resources are tagged in your Terraform code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# In ordet to update the list of taggable resources: | |
git clone https://github.com/hashicorp/terraform-provider-aws.git | |
cd terraform-provider-aws/website/docs/r | |
grep -l "\`tags\`" *.html.markdown | awk -F'.' '$0="aws_"$1' | jq --raw-input . | jq --slurp . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package tag | |
deny[msg] { | |
some resource | |
isTaggableResource[resource] | |
not hasTags[resource] | |
resource_changes_address := input.resource_changes[resource].address | |
msg := sprintf("Resource '%s' must be tagged!", [resource_changes_address]) | |
} | |
isTaggableResource[resource] { | |
resource_changes_type := input.resource_changes[resource].type | |
taggable_resource_types[_] == resource_changes_type | |
} | |
hasTags[resource] { | |
input.resource_changes[resource].change.after.tags | |
} | |
# In ordet to update the list of taggable resources: | |
# git clone https://github.com/hashicorp/terraform-provider-aws.git | |
# cd terraform-provider-aws/website/docs/r | |
# grep -l "\`tags\`" *.html.markdown | awk -F'.' '$0="aws_"$1' | jq --raw-input . | jq --slurp . | |
taggable_resource_types = { | |
"aws_accessanalyzer_analyzer", | |
"aws_acm_certificate", | |
"aws_acmpca_certificate_authority", | |
"aws_ami", | |
"aws_ami_copy", | |
"aws_ami_from_instance", | |
"aws_amplify_app", | |
"aws_amplify_branch", | |
"aws_api_gateway_api_key", | |
"aws_api_gateway_client_certificate", | |
"aws_api_gateway_domain_name", | |
"aws_api_gateway_rest_api", | |
"aws_api_gateway_stage", | |
"aws_api_gateway_usage_plan", | |
"aws_api_gateway_vpc_link", | |
"aws_apigatewayv2_api", | |
"aws_apigatewayv2_domain_name", | |
"aws_apigatewayv2_stage", | |
"aws_apigatewayv2_vpc_link", | |
"aws_appmesh_gateway_route", | |
"aws_appmesh_mesh", | |
"aws_appmesh_route", | |
"aws_appmesh_virtual_gateway", | |
"aws_appmesh_virtual_node", | |
"aws_appmesh_virtual_router", | |
"aws_appmesh_virtual_service", | |
"aws_apprunner_auto_scaling_configuration_version", | |
"aws_apprunner_connection", | |
"aws_apprunner_service", | |
"aws_appsync_graphql_api", | |
"aws_athena_workgroup", | |
"aws_autoscaling_group", | |
"aws_backup_plan", | |
"aws_backup_vault", | |
"aws_batch_compute_environment", | |
"aws_batch_job_definition", | |
"aws_batch_job_queue", | |
"aws_cloud9_environment_ec2", | |
"aws_cloudformation_stack", | |
"aws_cloudformation_stack_set", | |
"aws_cloudfront_distribution", | |
"aws_cloudhsm_v2_cluster", | |
"aws_cloudtrail", | |
"aws_cloudwatch_composite_alarm", | |
"aws_cloudwatch_event_bus", | |
"aws_cloudwatch_event_rule", | |
"aws_cloudwatch_log_group", | |
"aws_cloudwatch_metric_alarm", | |
"aws_cloudwatch_metric_stream", | |
"aws_codeartifact_domain", | |
"aws_codeartifact_repository", | |
"aws_codebuild_project", | |
"aws_codebuild_report_group", | |
"aws_codecommit_repository", | |
"aws_codedeploy_app", | |
"aws_codedeploy_deployment_group", | |
"aws_config_config_rule", | |
"aws_config_configuration_aggregator", | |
"aws_customer_gateway", | |
"aws_datapipeline_pipeline", | |
"aws_datasync_agent", | |
"aws_datasync_location_efs", | |
"aws_datasync_location_fsx_windows_file_system", | |
"aws_datasync_location_nfs", | |
"aws_datasync_location_s3", | |
"aws_datasync_location_smb", | |
"aws_datasync_task", | |
"aws_dax_cluster", | |
"aws_db_cluster_snapshot", | |
"aws_db_event_subscription", | |
"aws_db_instance", | |
"aws_db_option_group", | |
"aws_db_parameter_group", | |
"aws_db_proxy", | |
"aws_db_proxy_endpoint", | |
"aws_db_security_group", | |
"aws_db_snapshot", | |
"aws_db_subnet_group", | |
"aws_default_network_acl", | |
"aws_default_route_table", | |
"aws_default_security_group", | |
"aws_default_subnet", | |
"aws_default_vpc", | |
"aws_default_vpc_dhcp_options", | |
"aws_devicefarm_project", | |
"aws_directory_service_directory", | |
"aws_dms_certificate", | |
"aws_dms_endpoint", | |
"aws_dms_event_subscription", | |
"aws_dms_replication_instance", | |
"aws_dms_replication_subnet_group", | |
"aws_dms_replication_task", | |
"aws_docdb_cluster", | |
"aws_docdb_cluster_instance", | |
"aws_docdb_cluster_parameter_group", | |
"aws_docdb_subnet_group", | |
"aws_dx_connection", | |
"aws_dx_hosted_private_virtual_interface_accepter", | |
"aws_dx_hosted_public_virtual_interface_accepter", | |
"aws_dx_hosted_transit_virtual_interface_accepter", | |
"aws_dx_lag", | |
"aws_dx_private_virtual_interface", | |
"aws_dx_public_virtual_interface", | |
"aws_dx_transit_virtual_interface", | |
"aws_dynamodb_table", | |
"aws_ebs_snapshot", | |
"aws_ebs_snapshot_copy", | |
"aws_ebs_volume", | |
"aws_ec2_capacity_reservation", | |
"aws_ec2_carrier_gateway", | |
"aws_ec2_client_vpn_endpoint", | |
"aws_ec2_fleet", | |
"aws_ec2_local_gateway_route_table_vpc_association", | |
"aws_ec2_managed_prefix_list", | |
"aws_ec2_traffic_mirror_filter", | |
"aws_ec2_traffic_mirror_session", | |
"aws_ec2_traffic_mirror_target", | |
"aws_ec2_transit_gateway", | |
"aws_ec2_transit_gateway_peering_attachment", | |
"aws_ec2_transit_gateway_peering_attachment_accepter", | |
"aws_ec2_transit_gateway_route_table", | |
"aws_ec2_transit_gateway_vpc_attachment", | |
"aws_ec2_transit_gateway_vpc_attachment_accepter", | |
"aws_ecr_repository", | |
"aws_ecs_capacity_provider", | |
"aws_ecs_cluster", | |
"aws_ecs_service", | |
"aws_ecs_task_definition", | |
"aws_efs_access_point", | |
"aws_efs_file_system", | |
"aws_egress_only_internet_gateway", | |
"aws_eip", | |
"aws_eks_addon", | |
"aws_eks_cluster", | |
"aws_eks_fargate_profile", | |
"aws_eks_node_group", | |
"aws_elastic_beanstalk_application", | |
"aws_elastic_beanstalk_application_version", | |
"aws_elastic_beanstalk_environment", | |
"aws_elasticache_cluster", | |
"aws_elasticache_parameter_group", | |
"aws_elasticache_replication_group", | |
"aws_elasticache_subnet_group", | |
"aws_elasticsearch_domain", | |
"aws_elb", | |
"aws_emr_cluster", | |
"aws_flow_log", | |
"aws_fsx_lustre_file_system", | |
"aws_fsx_windows_file_system", | |
"aws_gamelift_alias", | |
"aws_gamelift_build", | |
"aws_gamelift_fleet", | |
"aws_gamelift_game_session_queue", | |
"aws_glacier_vault", | |
"aws_glue_crawler", | |
"aws_glue_job", | |
"aws_glue_ml_transform", | |
"aws_glue_registry", | |
"aws_glue_schema", | |
"aws_glue_trigger", | |
"aws_glue_workflow", | |
"aws_guardduty_detector", | |
"aws_guardduty_filter", | |
"aws_guardduty_ipset", | |
"aws_guardduty_threatintelset", | |
"aws_iam_instance_profile", | |
"aws_iam_openid_connect_provider", | |
"aws_iam_policy", | |
"aws_iam_role", | |
"aws_iam_saml_provider", | |
"aws_iam_server_certificate", | |
"aws_iam_user", | |
"aws_imagebuilder_component", | |
"aws_imagebuilder_distribution_configuration", | |
"aws_imagebuilder_image", | |
"aws_imagebuilder_image_pipeline", | |
"aws_imagebuilder_image_recipe", | |
"aws_imagebuilder_infrastructure_configuration", | |
"aws_inspector_assessment_template", | |
"aws_inspector_resource_group", | |
"aws_instance", | |
"aws_internet_gateway", | |
"aws_iot_topic_rule", | |
"aws_key_pair", | |
"aws_kinesis_analytics_application", | |
"aws_kinesis_firehose_delivery_stream", | |
"aws_kinesis_stream", | |
"aws_kinesis_video_stream", | |
"aws_kinesisanalyticsv2_application", | |
"aws_kms_external_key", | |
"aws_kms_key", | |
"aws_lambda_function", | |
"aws_launch_template", | |
"aws_lb", | |
"aws_lb_listener", | |
"aws_lb_listener_rule", | |
"aws_lb_target_group", | |
"aws_lightsail_instance", | |
"aws_macie2_classification_job", | |
"aws_macie2_custom_data_identifier", | |
"aws_macie2_findings_filter", | |
"aws_macie2_member", | |
"aws_media_convert_queue", | |
"aws_media_package_channel", | |
"aws_media_store_container", | |
"aws_mq_broker", | |
"aws_mq_configuration", | |
"aws_msk_cluster", | |
"aws_mwaa_environment", | |
"aws_nat_gateway", | |
"aws_neptune_cluster", | |
"aws_neptune_cluster_instance", | |
"aws_neptune_cluster_parameter_group", | |
"aws_neptune_event_subscription", | |
"aws_neptune_parameter_group", | |
"aws_neptune_subnet_group", | |
"aws_network_acl", | |
"aws_networkfirewall_firewall", | |
"aws_networkfirewall_firewall_policy", | |
"aws_networkfirewall_rule_group", | |
"aws_opsworks_custom_layer", | |
"aws_opsworks_ganglia_layer", | |
"aws_opsworks_haproxy_layer", | |
"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_stack", | |
"aws_opsworks_static_web_layer", | |
"aws_organizations_account", | |
"aws_organizations_organizational_unit", | |
"aws_organizations_policy", | |
"aws_placement_group", | |
"aws_qldb_ledger", | |
"aws_rds_cluster", | |
"aws_rds_cluster_endpoint", | |
"aws_rds_cluster_instance", | |
"aws_redshift_cluster", | |
"aws_redshift_event_subscription", | |
"aws_redshift_parameter_group", | |
"aws_redshift_snapshot_copy_grant", | |
"aws_redshift_snapshot_schedule", | |
"aws_redshift_subnet_group", | |
"aws_resourcegroups_group", | |
"aws_route53_health_check", | |
"aws_route53_resolver_endpoint", | |
"aws_route53_resolver_query_log_config", | |
"aws_route53_resolver_rule", | |
"aws_route53_zone", | |
"aws_route_table", | |
"aws_s3_bucket", | |
"aws_s3_bucket_analytics_configuration", | |
"aws_s3_bucket_metric", | |
"aws_s3_bucket_object", | |
"aws_s3_object_copy", | |
"aws_s3control_bucket", | |
"aws_s3control_bucket_lifecycle_configuration", | |
"aws_sagemaker_app", | |
"aws_sagemaker_domain", | |
"aws_sagemaker_endpoint", | |
"aws_sagemaker_endpoint_configuration", | |
"aws_sagemaker_feature_group", | |
"aws_sagemaker_image", | |
"aws_sagemaker_model", | |
"aws_sagemaker_model_package_group", | |
"aws_sagemaker_notebook_instance", | |
"aws_sagemaker_user_profile", | |
"aws_schemas_discoverer", | |
"aws_schemas_registry", | |
"aws_schemas_schema", | |
"aws_secretsmanager_secret", | |
"aws_security_group", | |
"aws_serverlessapplicationrepository_cloudformation_stack", | |
"aws_service_discovery_http_namespace", | |
"aws_service_discovery_private_dns_namespace", | |
"aws_service_discovery_public_dns_namespace", | |
"aws_service_discovery_service", | |
"aws_servicecatalog_portfolio", | |
"aws_servicecatalog_product", | |
"aws_sfn_activity", | |
"aws_sfn_state_machine", | |
"aws_shield_protection", | |
"aws_signer_signing_profile", | |
"aws_sns_topic", | |
"aws_spot_fleet_request", | |
"aws_spot_instance_request", | |
"aws_sqs_queue", | |
"aws_ssm_activation", | |
"aws_ssm_document", | |
"aws_ssm_maintenance_window", | |
"aws_ssm_parameter", | |
"aws_ssm_patch_baseline", | |
"aws_ssoadmin_permission_set", | |
"aws_storagegateway_cached_iscsi_volume", | |
"aws_storagegateway_gateway", | |
"aws_storagegateway_nfs_file_share", | |
"aws_storagegateway_smb_file_share", | |
"aws_storagegateway_stored_iscsi_volume", | |
"aws_storagegateway_tape_pool", | |
"aws_subnet", | |
"aws_swf_domain", | |
"aws_synthetics_canary", | |
"aws_timestreamwrite_database", | |
"aws_timestreamwrite_table", | |
"aws_transfer_server", | |
"aws_transfer_user", | |
"aws_vpc", | |
"aws_vpc_dhcp_options", | |
"aws_vpc_endpoint", | |
"aws_vpc_endpoint_service", | |
"aws_vpc_peering_connection", | |
"aws_vpc_peering_connection_accepter", | |
"aws_vpn_connection", | |
"aws_vpn_gateway", | |
"aws_waf_rate_based_rule", | |
"aws_waf_rule", | |
"aws_waf_rule_group", | |
"aws_waf_web_acl", | |
"aws_wafregional_rate_based_rule", | |
"aws_wafregional_rule", | |
"aws_wafregional_rule_group", | |
"aws_wafregional_web_acl", | |
"aws_wafv2_ip_set", | |
"aws_wafv2_regex_pattern_set", | |
"aws_wafv2_rule_group", | |
"aws_wafv2_web_acl", | |
"aws_workspaces_directory", | |
"aws_workspaces_ip_group", | |
"aws_workspaces_workspace", | |
"aws_xray_group", | |
"aws_xray_sampling_rule" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package tag | |
test_empty_input { | |
deny with input as {} | |
} | |
test_taggable_resource_not_tagged { | |
deny with input as {"resource_changes": [{ | |
"address": "aws_s3_bucket.test_aws_s3_bucket", | |
"type": "aws_s3_bucket", | |
"name": "test_aws_s3_bucket", | |
"change": {"after": {}}, | |
}]} | |
} | |
test_taggable_resource_tagged { | |
not deny[""] with input as {"resource_changes": [{ | |
"address": "aws_s3_bucket.test_aws_s3_bucket", | |
"type": "aws_s3_bucket", | |
"name": "test_aws_s3_bucket", | |
"change": {"after": {"tags": {"key": "val"}}}, | |
}]} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment