InSpec for AWS

January 23, 2023 · View on GitHub

  • Project State: Maintained

For more information on project states and SLAs, see this documentation.

This InSpec resource pack uses the AWS Ruby SDK v3 and provides the required resources to write tests for resources in AWS.

Prerequisites

AWS Credentials

Valid AWS credentials are required, see AWS Documentation

There are multiple ways to set the AWS credentials, as shown below:

1) Environment Variables

Set your AWS credentials in a .envrc file or export them in your shell. (See example .envrc file)

    # Example configuration
    export AWS_ACCESS_KEY_ID="AKIAJUMP347SLS66IGCQ"
    export AWS_SECRET_ACCESS_KEY="vD2lfoNvPdwsofqyuO9jRuWUkZIMqisdfeFmkHTy7ON+w"
    export AWS_REGION="eu-west-3"
    export AWS_AVAILABILITY_ZONE="eu-west-3a"  
2) Configuration File

Set your AWS credentials in ~/.aws/config and ~/.aws/credentials file. (See example aws configure credentials)

Example ~/.aws/credentials :

   [default]
   aws_access_key_id=AKIAIOSFODNN7EXAMPLE
   aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
   
   [engineering]
   aws_access_key_id=AKIAIOSFODNN7EXAMPLF
   aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY1

Example ~/.aws/config :

   [default]
   region=us-west-2
   
   [engineering]
   region=us-east-2

AWS SDK selects the default credentials unless aws_profile is set in an .envrc.

    # Example configuration
    export AWS_PROFILE="engineering"
The credentials precedence is
  1. Credentials set in .envrc OR as an Environment variable.
  2. Credentials set in ~/.aws/credentials AND ~/.aws/config AND AWS_PROFILE set as an Environment variable.
  3. Credentials set in ~/.aws/credentials AND ~/.aws/config AND AWS_PROFILE is NOT set as an Environment variable. Default credentials are used.

AWS Region

The aws_region parameter queries resources in a specific region. If not provided, the AWS region set in environment variables or configuration files are used.

Example:

describe aws_ec2_instances(aws_region: 'us-west-2') do
  its('count') { should eq 10 }
end

Assuming an IAM role

Assuming an IAM role allows an IAM users gain additional (or different) permissions to perform actions in a different AWS account. (See example aws configure IAM role)

Example:

   [profile example_profile]
   role_arn = arn:aws:iam::123456789012:role/example_profile
   source_profile = user1

Permissions

Each resource requires specific permissions to perform the operations required for testing. For example, to test an AWS EC2 instance, your service principal requires the ec2:DescribeInstances and iam:GetInstanceProfile permissions. You can find a comprehensive list of each resource's permissions needed in the documentation.

Use the Resources

Since this is an InSpec resource pack, it defines the InSpec resources and includes example tests only. To use the AWS resources in your tests, do the following:

inspec init profile --platform aws my-profile

The above command generates a sample inspec.yml that depends on master. We recommend this is pinned to a release of the resource pack as follows:

name: my-profile
title: My own AWS profile
version: 0.1.0
inspec_version: '>= 4.6.9'
depends:
  - name: inspec-aws
    url: https://github.com/inspec/inspec-aws/archive/x.tar.gz
supports:
  - platform: aws

Use the Resources

Since this is an InSpec resource pack, it only defines InSpec resources. To use these resources in your controls, create your profile:

Create a profile

inspec init profile --platform aws my-profile

The above command generates a sample inspec.yml that depends on master. We recommend this is pinned to a release of the resource pack as follows.

Example inspec.yml:

name: my-profile
title: My own AWS profile
version: 0.1.0
inspec_version: '>= 4.6.9'
depends:
 - name: inspec-aws
   url: https://github.com/inspec/inspec-aws/archive/x.tar.gz
supports:
 - platform: aws

(For available inspec-aws versions, see this list of inspec-aws versions.)

If a resource is in local, change the url to path.

name: my-profile
title: My own AWS profile
version: 0.1.0
inspec_version: '>= 4.6.9'
depends:
 - name: inspec-aws
   path: ../my-profile
supports:
 - platform: aws

(For available inspec-aws versions, see this list of inspec-aws versions.)

Add some tests and run the profile via:

inspec exec my-profile -t aws://

Resource documentation

This resource pack allows the testing of the following AWS resources. If a resource you wish to test is not listed, please feel free to open an Issue. As an open-source project, we also welcome public contributions via Pull Request.

InSpec AWS Supported Resources https://docs.chef.io/inspec/resources/

Module NameServicesResource & Property ReferenceSingular ResourcePlural Resource
AmazonMQApplication IntegrationAWS::AmazonMQ::Brokeraws_mq_brokeraws_mq_brokers
AWS::AmazonMQ::Configurationaws_mq_configurationaws_mq_configurations
Amplify ConsoleFront-end Web & MobileAWS::Amplify::Appaws_amplify_appaws_amplify_apps
AWS::Amplify::Branchaws_amplify_branchaws_amplify_branches
API GatewayNetworking & Content DeliveryAWS::ApiGateway::Accountaws_apigateway_accountNo Plural Resource
AWS::ApiGateway::ApiKeyaws_apigateway_api_keyaws_apigateway_api_keys
AWS::ApiGateway::Authorizeraws_apigateway_authorizeraws_apigateway_authorizers
AWS::ApiGateway::BasePathMappingaws_apigateway_base_path_mappingaws_apigateway_base_path_mappings
AWS::ApiGateway::ClientCertificateaws_apigateway_client_certificateaws_apigateway_client_certificates
AWS::ApiGateway::Deploymentaws_api_gateway_deploymentaws_api_gateway_deployments
AWS::ApiGateway::DocumentationPartaws_api_gateway_documentation_partaws_api_gateway_documentation_parts
AWS::ApiGateway::DocumentationVersionaws_api_gateway_documentation_versionaws_api_gateway_documentation_versions
AWS::ApiGateway::DomainNameaws_api_gateway_domain_nameaws_api_gateway_domain_names
AWS::ApiGateway::GatewayResponseaws_api_gateway_responseaws_api_gateway_responses
AWS::ApiGateway::Methodaws_api_gateway_methodaws_api_gateway_methods
AWS::ApiGateway::Modelaws_api_gateway_modelaws_api_gateway_models
AWS::ApiGateway::RequestValidatoraws_api_gateway_request_validatoraws_api_gateway_request_validators
AWS::ApiGateway::Resourceaws_api_gateway_resourceaws_api_gateway_resources
AWS::ApiGateway::RestApiaws_api_gateway_restapiaws_api_gateway_restapis
AWS::ApiGateway::Stageaws_api_gateway_stageaws_api_gateway_stages
AWS::ApiGateway::UsagePlanaws_api_gateway_usage_planaws_api_gateway_usage_plans
AWS::ApiGateway::UsagePlanKeyaws_api_gateway_usage_plan_keyaws_api_gateway_usage_plan_keys
AWS::ApiGateway::VpcLinkaws_api_gateway_vpc_linkaws_api_gateway_vpc_links
Application Auto ScalingComputeAWS::ApplicationAutoScaling::ScalableTargetaws_application_autoscaling_scalable_targetaws_application_autoscaling_scalable_targets
AWS::ApplicationAutoScaling::ScalingPolicyaws_application_autoscaling_scaling_policyaws_application_autoscaling_scaling_policies
AthenaAnalyticsAWS::Athena::WorkGroupaws_athena_work_groupaws_athena_work_groups
Amazon EC2 Auto ScalingComputeAWS::AutoScaling::AutoScalingGroupaws_auto_scaling_groupaws_auto_scaling_groups
AWS::AutoScaling::LaunchConfigurationaws_launch_configurationNo Plural Resource
AWS::AutoScaling::ScalingPolicyaws_autoscaling_scaling_policyaws_autoscaling_scaling_policies
AWS BatchComputeAWS::Batch::ComputeEnvironmentaws_batch_compute_environmentaws_batch_compute_environments
AWS::Batch::JobDefinitionaws_batch_job_definitionaws_batch_job_definitions
AWS::Batch::JobQueueaws_batch_job_queueaws_batch_job_queues
CloudFormationManagement & GovernanceAWS::CloudFormation::Stackaws_cloudformation_stackaws_cloudformation_stacks
AWS::CloudFormation::StackSetaws_cloud_formation_stack_setaws_cloud_formation_stack_sets
Othersaws_cloudformation_templateNo Plural Resource
CloudFrontNetworking & Content DeliveryAWS::CloudFront::CachePolicyaws_cloudfront_cache_policyaws_cloudfront_cache_policies
AWS::CloudFront::CloudFrontOriginAccessIdentityaws_cloudfront_origin_access_identityaws_cloudfront_origin_access_identities
AWS::CloudFront::Distributionaws_cloudfront_distributionaws_cloudfront_distributions
AWS::CloudFront::KeyGroupaws_cloudfront_key_groupaws_cloudfront_key_groups
AWS::CloudFront::OriginRequestPolicyaws_cloud_front_origin_request_policyNo Plural Resource
AWS::CloudFront::PublicKeyaws_cloudfront_public_keyaws_cloudfront_public_keys
AWS::CloudFront::RealtimeLogConfigaws_cloudfront_realtime_log_configaws_cloudfront_realtime_log_configs
AWS::CloudFront::StreamingDistributionaws_cloudfront_streaming_distributionaws_cloudfront_streaming_distributions
CloudTrailManagement & GovernanceAWS::CloudTrail::Trailaws_cloudtrail_trailaws_cloudtrail_trails
CloudWatchManagement & GovernanceAWS::CloudWatch::Alarmaws_cloudwatch_alarmNo Plural Resource
AWS::CloudWatch::AnomalyDetectoraws_cloudwatch_anomaly_detectoraws_cloudwatch_anomaly_detectors
AWS::CloudWatch::CompositeAlarmaws_cloudwatch_composite_alarmaws_cloudwatch_composite_alarms
AWS::CloudWatch::Dashboardaws_cloudwatch_dashboardaws_cloudwatch_dashboards
AWS::CloudWatch::InsightRuleNo Singular Resourceaws_cloudwatch_insight_rules
AWS::CloudWatch::MetricStreamaws_cloudwatch_metric_streamaws_cloudwatch_metric_streams
CloudWatch LogsManagement & GovernanceAWS::Logs::Destinationaws_cloudwatchlogs_destinationaws_cloudwatchlogs_destinations
AWS::Logs::LogGroupaws_cloudwatch_log_groupNo Plural Resource
AWS::Logs::LogStreamaws_cloudwatchlogs_log_streamaws_cloudwatchlogs_log_streams
AWS::Logs::MetricFilteraws_cloudwatch_log_metric_filterNo Plural Resource
aws_logs_metric_filteraws_logs_metric_filters
AWS::Logs::SubscriptionFilteraws_cloudwatchlogs_subscription_filteraws_cloudwatchlogs_subscription_filters
Amazon CognitoSecurity, Identity, & ComplianceAWS::Cognito::IdentityPoolaws_cognito_identity_poolaws_cognito_identity_pools
AWS::Cognito::UserPoolaws_cognito_userpoolaws_cognito_userpools
AWS::Cognito::UserPoolClientaws_cognito_userpool_clientaws_cognito_userpool_clients
ConfigManagement & GovernanceAWS::Config::ConfigurationRecorderaws_config_recorderNo Plural Resource
AWS::Config::DeliveryChannelaws_config_delivery_channelNo Plural Resource
DMSComputeAWS::DMS::Endpointaws_dms_endpointaws_dms_endpoints
AWS::DMS::ReplicationInstanceaws_dms_replication_instanceaws_dms_replication_instances
AWS::DMS::ReplicationSubnetGroupaws_dms_replication_subnet_groupaws_dms_replication_subnet_groups
DynamoDBDatabaseAWS::DynamoDB::Tableaws_dynamodb_tableaws_dynamodb_tables
EC2ComputeAWS::EC2::CapacityReservationaws_ec2_capacity_reservationaws_ec2_capacity_reservations
AWS::EC2::CarrierGatewayaws_ec2_carrier_gatewayaws_ec2_carrier_gateways
AWS::EC2::CustomerGatewayaws_ec2_customer_gatewayaws_ec2_customer_gateways
AWS::EC2::DHCPOptionsNo Singular Resourceaws_dhcp_options
aws_ec2_dhcp_optionaws_ec2_dhcp_options
AWS::EC2::Fleetaws_ec2_fleetaws_ec2_fleets
AWS::EC2::EgressOnlyInternetGatewayaws_ec2_egress_only_internet_gatewayaws_ec2_egress_only_internet_gateways
AWS::EC2::EIPaws_ec2_eipaws_ec2_eips
AWS::EC2::EIPAssociationaws_ec2_eip_associationaws_ec2_eip_associations
AWS::EC2::FlowLogaws_flow_logNo Plural Resource
AWS::EC2::Hostaws_ec2_hostaws_ec2_hosts
AWS::EC2::Instanceaws_ec2_instanceaws_ec2_instances
AWS::EC2::InternetGatewayaws_ec2_internet_gatewayaws_ec2_internet_gateways
aws_internet_gatewayaws_internet_gateways
AWS::EC2::LaunchTemplateaws_ec2_launch_templateaws_ec2_launch_templates
AWS::EC2::NatGatewayaws_nat_gatewayaws_nat_gateways
AWS::EC2::NetworkAclaws_network_aclaws_network_acls
AWS::EC2::NetworkAclEntryaws_network_aclaws_network_acls
AWS::EC2::NetworkInsightsAnalysisaws_ec2_network_insights_analysisaws_ec2_network_insights_analysis_plural
AWS::EC2::NetworkInsightsPathaws_ec2_network_insights_pathaws_ec2_network_insights_paths
AWS::EC2::NetworkInterfaceaws_ec2_network_interfaceaws_ec2_network_interfaces
AWS::EC2::NetworkInterfaceAttachmentaws_ec2_network_interface_attachmentaws_ec2_network_interface_attachments
AWS::EC2::NetworkInterfacePermissionaws_ec2_network_interface_permissionaws_ec2_network_interface_permission
AWS::EC2::PlacementGroupaws_ec2_placement_groupaws_ec2_placement_groups
AWS::EC2::PrefixListaws_ec2_prefix_listaws_ec2_prefix_lists
AWS::EC2::Routeaws_route_tableaws_route_tables
AWS::EC2::RouteTableaws_route_tableaws_route_tables
AWS::EC2::SecurityGroupaws_security_groupaws_security_groups
AWS::EC2::SecurityGroupEgressaws_security_groupaws_security_groups
AWS::EC2::SecurityGroupIngressaws_security_groupaws_security_groups
AWS::EC2::SpotFleetaws_ec2_spot_fleetaws_ec2_spot_fleets
AWS::EC2::Subnetaws_subnetaws_subnets
AWS::EC2::TrafficMirrorFilteraws_ec2_traffic_mirror_filteraws_ec2_traffic_mirror_filters
AWS::EC2::TrafficMirrorSessionaws_ec2_traffic_mirror_sessionaws_ec2_traffic_mirror_sessions
AWS::EC2::TrafficMirrorTargetaws_ec2_traffic_mirror_targetaws_ec2_traffic_mirror_targets
AWS::EC2::TransitGatewayaws_transit_gatewayNo Plural Resource
AWS::EC2::TransitGatewayAttachmentaws_ec2_transit_gateway_attachmentaws_ec2_transit_gateway_attachments
AWS::EC2::TransitGatewayConnectaws_transit_gateway_connectaws_transit_gateway_connects
AWS::EC2::TransitGatewayMulticastDomainaws_transit_gateway_multicast_domainaws_transit_gateway_multicast_domains
AWS::EC2::TransitGatewayMulticastDomainAssociationaws_transit_gateway_multicast_domain_associationaws_transit_gateway_multicast_domain_associations
AWS::EC2::TransitGatewayMulticastGroupMemberaws_transit_gateway_multicast_group_memberaws_transit_gateway_multicast_group_members
AWS::EC2::TransitGatewayMulticastGroupSourceaws_transit_gateway_multicast_group_sourceaws_transit_gateway_multicast_group_sources
AWS::EC2::TransitGatewayRouteaws_transit_gateway_routeaws_transit_gateway_routes
AWS::EC2::TransitGatewayRouteTableaws_ec2_transit_gateway_route_tableaws_ec2_transit_gateway_route_tables
AWS::EC2::TransitGatewayRouteTableAssociationaws_ec2_transit_gateway_route_table_associationaws_ec2_transit_gateway_route_table_associations
AWS::EC2::TransitGatewayRouteTablePropagationaws_ec2_transit_gateway_route_table_propagationaws_ec2_transit_gateway_route_table_propagations
AWS::EC2::Volumeaws_ebs_volumeaws_ebs_volumes
AWS::EC2::VolumeAttachmentNo Singular Resourceaws_ec2_volume_attachments
AWS::EC2::VPCaws_vpcaws_vpcs
AWS::EC2::VPCEndpointaws_vpc_endpointaws_vpc_endpoints
AWS::EC2::VPCEndpointConnectionNotificationaws_vpc_endpoint_connection_notificationaws_vpc_endpoint_connection_notifications
aws_vpc_endpoint_notificationaws_vpc_endpoint_notifications
AWS::EC2::VPCEndpointServiceaws_vpc_endpoint_serviceaws_vpc_endpoint_services
AWS::EC2::VPCEndpointServicePermissionsaws_vpc_endpoint_service_permissionaws_vpc_endpoint_service_permissions
AWS::EC2::VPCPeeringConnectionaws_ec2_vpc_peering_connectionaws_ec2_vpc_peering_connections
AWS::EC2::VPNConnectionNo Singular Resourceaws_vpn_connections
AWS::EC2::VPNConnectionRouteNo Singular Resourceaws_ec2_vpn_connection_routes
AWS::EC2::VPNGatewayaws_vpn_gatewayaws_vpn_gateways
AWS::EC2::VPNGatewayRoutePropagationaws_ec2_vpn_gateway_route_propagationaws_ec2_vpn_gateway_route_propagations
Othersaws_regionaws_regions
aws_ebs_snapshotaws_ebs_snapshots
aws_amiaws_amis
Amazon ECRContainersAWS::ECR::PublicRepositoryaws_ecrpublic_repositoryaws_ecrpublic_repositories
AWS::ECR::Repositoryaws_ecr_repositoryaws_ecr_repositories
Amazon ECSContainersAWS::ECS::Clusteraws_ecs_clusteraws_ecs_clusters
AWS::ECS::Serviceaws_ecs_serviceaws_ecs_services
AWS::ECS::TaskDefinitionaws_ecs_task_definitionaws_ecs_task_definitions
Othersaws_ecr_repository_policyNo Plural Resource
aws_ecrNo Plural Resource
aws_ecr_imageaws_ecr_images
EFSStorageAWS::EFS::FileSystemaws_efs_file_systemaws_efs_file_systems
AWS::EFS::MountTargetaws_efs_mount_targetaws_efs_mount_targets
EKSContainersAWS::EKS::Clusteraws_eks_clusteraws_eks_clusters
ElasticCacheDatabaseAWS::ElastiCache::CacheClusteraws_elasticache_clusteraws_elasticache_clusters
AWS::ElastiCache::ReplicationGroupaws_elasticache_replication_groupaws_elasticache_replication_groups
aws_elasticache_cluster_nodeNo Plural Resource
ElasticsearchAnalyticsAWS::Elasticsearch::Domainaws_elasticsearchservice_domainaws_elasticsearchservice_domains
ElasticLoadBalancingV2Networking & Content DeliveryAWS::ElasticLoadBalancingV2::Listeneraws_elasticloadbalancingv2_listeneraws_elasticloadbalancingv2_listeners
AWS::ElasticLoadBalancingV2::ListenerCertificateaws_elasticloadbalancingv2_listener_certificateaws_elasticloadbalancingv2_listener_certificates
AWS::ElasticLoadBalancingV2::ListenerRuleaws_elasticloadbalancingv2_listener_ruleaws_elasticloadbalancingv2_listener_rules
AWS::ElasticLoadBalancingV2::LoadBalanceraws_elbaws_elbs
aws_albaws_albs
AWS::ElasticLoadBalancingV2::TargetGroupaws_elasticloadbalancingv2_target_groupaws_elasticloadbalancingv2_target_groups
Amazon EMRAnalyticsAWS::EMR::Clusteraws_emr_clusteraws_emr_clusters
AWS::EMR::SecurityConfigurationaws_emr_security_configurationaws_emr_security_configurations
Amazon EventBridgeApplication IntegrationAWS::Events::Ruleaws_eventbridge_ruleaws_eventbridge_rules
AWS GlueAnalyticsAWS::Glue::Crawleraws_glue_crawleraws_glue_crawlers
AWS::Glue::Databaseaws_glue_databaseaws_glue_databases
GuardDutySecurity, Identity, & ComplianceAWS::GuardDuty::Detectoraws_guardduty_detectoraws_guardduty_detectors
IAMSecurity, Identity, & ComplianceAWS::IAM::AccessKeyaws_iam_access_keyaws_iam_access_keys
No Singular Resourceaws_iam_account_alias
aws_iam_ssh_public_keyaws_iam_ssh_public_keys
AWS::IAM::Groupaws_iam_groupaws_iam_groups
AWS::IAM::InstanceProfileaws_iam_instance_profileaws_iam_instance_profiles
AWS::IAM::ManagedPolicyaws_iam_managed_policyaws_iam_managed_policies
AWS::IAM::OIDCProvideraws_iam_oidc_provideraws_iam_oidc_providers
AWS::IAM::Policyaws_iam_policyaws_iam_policies
aws_iam_password_policyNo Plural Resource
aws_iam_inline_policyNo Plural Resource
AWS::IAM::Roleaws_iam_roleaws_iam_roles
AWS::IAM::SAMLProvideraws_iam_saml_provideraws_iam_saml_providers
AWS::IAM::ServerCertificateaws_iam_server_certificateaws_iam_server_certificates
AWS::IAM::ServiceLinkedRoleaws_iam_service_linked_role_deletion_statusNo Plural Resource
AWS::IAM::Useraws_iam_useraws_iam_users
aws_iam_root_userNo Plural Resource
AWS::IAM::VirtualMFADeviceNo Singular Resourceaws_iam_virtual_mfa_devices
Othersaws_iam_ssh_public_keyaws_iam_ssh_public_keys
KMSSecurity, Identity, & ComplianceAWS::KMS::Keyaws_kms_keyaws_kms_keys
LambdaComputeAWS::Lambda::Aliasaws_lambda_aliasaws_lambda_aliases
AWS::Lambda::CodeSigningConfigaws_lambda_code_signing_configaws_lambda_code_signing_configs
AWS::Lambda::EventInvokeConfigaws_lambda_event_invoke_configaws_lambda_event_invoke_configs
AWS::Lambda::EventSourceMappingaws_lambda_event_source_mappingaws_lambda_event_source_mappings
AWS::Lambda::Functionaws_lambdaaws_lambdas
AWS::Lambda::LayerVersionPermissionaws_lambda_layer_version_permissionNo Plural Resource
AWS::Lambda::Permissionaws_lambda_permissionaws_lambda_permissions
AWS::Lambda::Versionaws_lambda_versionaws_lambda_versions
Network FirewallSecurity, Identity, & ComplianceAWS::NetworkFirewall::Firewallaws_network_firewall_firewallaws_network_firewall_firewalls
AWS::NetworkFirewall::FirewallPolicyaws_network_firewall_firewall_policyaws_network_firewall_firewall_policies
AWS::NetworkFirewall::LoggingConfigurationaws_network_firewall_logging_configurationNo Plural Resource
AWS::NetworkFirewall::RuleGroupaws_network_firewall_rule_groupaws_network_firewall_rule_groups
NetworkManagerNetworking & Content DeliveryAWS::NetworkManager::CustomerGatewayAssociationaws_network_manager_customer_gateway_associationaws_network_manager_customer_gateway_associations
AWS::NetworkManager::Deviceaws_network_manager_deviceaws_network_manager_devices
AWS::NetworkManager::GlobalNetworkaws_network_manager_global_networkaws_network_manager_global_networks
OrganizationsManagement & GovernanceAWS::Organizations::Memberaws_organizations_memberNo Plural Resource
RAMSecurity, Identity, & ComplianceAWS::RAM::ResourceShareaws_ram_resource_shareaws_ram_resource_shares
RDSDatabaseAWS::RDS::DBClusteraws_rds_clusteraws_rds_clusters
aws_rds_db_cluster_snapshotaws_rds_db_cluster_snapshots
AWS::RDS::DBInstanceaws_rds_instanceaws_rds_instances
AWS::RDS::DBParameterGroupaws_db_parameter_groupaws_db_parameter_groups
AWS::RDS::DBProxyaws_rds_db_proxyNo Plural Resource
AWS::RDS::DBProxyEndpointaws_rds_db_proxy_endpointaws_rds_db_proxy_endpoints
AWS::RDS::DBProxyTargetGroupaws_rds_db_proxy_target_groupaws_rds_db_proxy_target_groups
AWS::RDS::DBSecurityGroupaws_rds_db_security_groupaws_rds_db_security_groups
AWS::RDS::DBSubnetGroupaws_db_subnet_groupaws_db_subnet_groups
AWS::RDS::EventSubscriptionaws_rds_event_subscriptionaws_rds_event_subscriptions
AWS::RDS::GlobalClusteraws_rds_global_clusteraws_rds_global_clusters
AWS::RDS::OptionGroupaws_rds_group_optionaws_rds_group_options
Othersaws_rds_snapshotaws_rds_snapshots
No Singular Resourceaws_rds_snapshot_attributes
Amazon RedshiftAnalyticsAWS::Redshift::Clusteraws_redshift_clusteraws_redshift_clusters
AWS::Redshift::ClusterParameterGroupaws_redshift_cluster_parameter_groupaws_redshift_cluster_parameter_groups
Route 53Networking & Content DeliveryAWS::Route53::HostedZoneaws_hosted_zoneaws_hosted_zones
AWS::Route53::RecordSetaws_route53_record_setaws_route53_record_sets
Route 53 ResolverNetworking & Content DeliveryAWS::Route53Resolver::ResolverEndpointaws_route53resolver_resolver_endpointaws_route53resolver_resolver_endpoints
AWS::Route53Resolver::ResolverRuleaws_route53resolver_resolver_ruleaws_route53resolver_resolver_rules
AWS::Route53Resolver::ResolverRuleAssociationaws_route53resolver_resolver_rule_associationaws_route53resolver_resolver_rule_associations
Amazon S3ComputeAWS::S3::AccessPointaws_s3_access_pointaws_s3_access_points
AWS::S3::Bucketaws_s3_bucketaws_s3_buckets
AWS::S3::BucketPolicyaws_s3_bucket_policyNo Plural Resource
Othersaws_s3_bucket_objectaws_s3_bucket_objects
Secrets ManagerSecurity, Identity, & ComplianceAWS::SecretsManager::Secretaws_secretsmanager_secretaws_secretsmanager_secrets
Service CatalogManagement & GovernanceAWS::ServiceCatalog::CloudFormationProductaws_servicecatalog_cloud_formation_productNo Plural Resource
AWS::ServiceCatalog::LaunchRoleConstraintaws_servicecatalog_launch_role_constraintaws_servicecatalog_launch_role_constraints
AWS::ServiceCatalog::PortfolioPrincipalAssociationaws_servicecatalog_portfolio_principal_associationaws_servicecatalog_portfolio_principal_associations
AWS::ServiceCatalog::PortfolioProductAssociationaws_servicecatalog_portfolio_product_associationaws_servicecatalog_portfolio_product_associations
ShieldSecurity, Identity, & ComplianceAWS::Shield::Subscriptionaws_shield_subscriptionNo Plural Resource
SecurityHubSecurity, Identity, & ComplianceAWS::SecurityHub::Hubaws_securityhub_hubNo Plural Resource
Amazon SESBusiness ApplicationsAWS::SES::ReceiptRuleaws_ses_receipt_ruleNo Plural Resource
AWS::SES::ReceiptRuleSetaws_ses_receipt_rule_setaws_ses_receipt_rule_sets
AWS::SES::Templateaws_ses_templateaws_ses_templates
Amazon SimpleDBSimple Database ServiceAWS::SDB::DomainNo Singular Resourceaws_sdb_domains
SignerSecurity, Identity, & ComplianceAWS::Signer::ProfilePermissionNo Singular Resourceaws_signer_profile_permissions
AWS::Signer::SigningProfileaws_signer_signing_profileaws_signer_signing_profiles
Amazon SNSApplication IntegrationAWS::SNS::Subscriptionaws_sns_subscriptionaws_sns_subscriptions
AWS::SNS::Topicaws_sns_topicaws_sns_topics
AWS::SNS::TopicPolicyaws_sns_topicaws_sns_topics
Amazon SQSApplication IntegrationAWS::SQS::Queueaws_sqs_queueaws_sqs_queues
AWS::SQS::QueuePolicyaws_sqs_queueaws_sqs_queues
SSOSecurity, Identity, & ComplianceAWS::SSO::Assignmentaws_sso_assignmentaws_sso_assignments
AWS::SSO::InstanceAccessControlAttributeConfigurationaws_sso_instance_access_control_attribute_configurationaws_sso_instance_access_control_attribute_configurations
AWS::SSO::PermissionSetaws_sso_permission_setaws_sso_permission_sets
Step FunctionsApplication IntegrationAWS::StepFunctions::Activityaws_stepfunctions_activityaws_stepfunctions_activities
AWS::StepFunctions::StateMachineaws_stepfunctions_state_machineaws_stepfunctions_state_machines
STSSecurity, Identity, & ComplianceAWS::STS::CallerIdentityaws_sts_caller_identityNo Plural Resource
CloudWatch SyntheticsSyntheticsAWS::Synthetics::Canaryaws_synthetics_canaryaws_synthetics_canaries
System ManagerManagement & GovernanceAWS::SSM::Associationaws_ssm_associationaws_ssm_associations
AWS::SSM::Documentaws_ssm_documentaws_ssm_documents
AWS::SSM::MaintenanceWindowaws_ssm_maintenance_windowaws_ssm_maintenance_windows
AWS::SSM::MaintenanceWindowTargetaws_ssm_maintenance_window_targetaws_ssm_maintenance_window_targets
AWS::SSM::MaintenanceWindowTaskaws_ssm_maintenance_window_taskaws_ssm_maintenance_window_tasks
AWS::SSM::Parameteraws_ssm_parameteraws_ssm_parameters
AWS::SSM::PatchBaselineaws_ssm_patch_baselineaws_ssm_patch_baselines
AWS::SSM::ResourceDataSyncNo Singular Resourcesaws_ssm_resource_data_syncs
Othersaws_ssm_activationaws_ssm_activations
aws_ssm_resource_compliance_summaryaws_ssm_resource_compliance_summaries
Amazon TimestreamMigration & TransferAWS::Transfer::Useraws_transfer_useraws_transfer_users
WAFSecurity, Identity, & ComplianceAWS::WAF::ByteMatchSetaws_waf_byte_match_setaws_waf_byte_match_sets
AWS::WAF::IPSetaws_waf_ip_setaws_waf_ip_sets
AWS::WAF::Ruleaws_waf_ruleaws_waf_rules
AWS::WAF::SizeConstraintSetaws_waf_size_constraint_setaws_waf_size_constraint_sets
AWS::WAF::SqlInjectionMatchSetaws_waf_sql_injection_match_setaws_waf_sql_injection_match_sets
AWS::WAF::WebACLaws_waf_web_aclaws_waf_web_acls
AWS::WAF::XssMatchSetaws_waf_xss_match_setaws_waf_xss_match_sets

Examples

Ensure Security Groups disallow FTP

For disallowing FTP, we check that there is no ingress from 0.0.0.0/0 on port 21. The below sample control loops across all regions, checking all security groups for the account:

title 'Test AWS Security Groups Across All Regions For an Account Disallow FTP'

control 'aws-multi-region-security-group-ftp-1.0' do

  impact 1.0
  title 'Ensure AWS Security Groups disallow FTP ingress from 0.0.0.0/0.'

  aws_regions.region_names.each do |region|
    aws_security_groups(aws_region: region).group_ids.each do |security_group_id|
      describe aws_security_group(aws_region: region, group_id: security_group_id) do
        it { should exist }
        it { should_not allow_in(ipv4_range: '0.0.0.0/0', port: 21) }
      end
    end
  end
end

Test that an EC2 instance is running and using the correct AMI

    describe aws_ec2_instance(name: 'ProdWebApp') do
      it              { should be_running }
      its('image_id') { should eq 'ami-27a58d5c' }
    end

Ensure all AWS Users have MFA enabled

    describe aws_iam_users.where( has_mfa_enabled: false) do
      it { should_not exist }
    end

Properties Applying to All InSpec AWS Resources

aws_region

To provide multi-region support, the aws_region property is specified to a resource. This property affects AWS resources that have a region dependency. For example, security groups. One special case worth mentioning is the aws_s3_bucket resource that updates its region based on the location returned from S3.

The aws_regions resource is used to loop across all regions.

  aws_regions.region_names.each do |region|
    <use region in other resources here>
  end

aws_endpoint

A custom endpoint URL can optionally be specified to resources for testing other compatible providers. This propagates to the AWS client configuration. An example is provided below for Minio S3 compatible buckets.

title 'Test For Minio Buckets Existing at a Custom Endpoint'

endpoint = attribute(:minio_server, value: 'http://127.0.0.1:9000', description: 'The Minio server custom endpoint.')

control 'minio-buckets-1.0' do
  impact 1.0
  title 'Ensure Minio buckets exist.'

  describe aws_s3_bucket(aws_endpoint: endpoint, bucket_name: 'miniobucket') do
    it { should exist }
  end

  describe aws_s3_bucket(aws_endpoint: endpoint, bucket_name: 'notthere') do
    it { should_not exist }
  end
end

{{< note >}}

The InSpec AWS assumes full compatibility with the underlying AWS SDK, and unsupported operations cause failures. Hence, depending on the external provider implementation, your mileage may vary!

{{< /note >}}

aws_retry_limit and aws_retry_backoff

In certain cases, AWS implements rate-limiting. To mitigate this issue, the Retry Limit and Retry Backoff can be set in two ways:

1) Environment Variables

Setting AWS_RETRY_LIMIT and AWS_RETRY_BACKOFF environment variables is implemented at the session level.

   export AWS_RETRY_LIMIT=5
   export aws_retry_limit=5

Note environment variables are case insensitive.

2) InSpec Control

InSpec AWS resources now support setting the Retry Limit and Retry Backoff at the control level, as shown below.

  describe aws_config_recorder(recorder_name: aws_config_recorder_name, aws_retry_limit=5, aws_retry_backoff=5) do
    it { should exist }
    its('recorder_name') { should eq aws_config_recorder_name }
  end

#####The aws_retry_limit and aws_retry_backoff precedence:

  1. Set at Inspec control level.
  2. Set at Environment level.

Retry Limit and Retry Backoff documentation

NullResponse

InSpec AWS resources returns NullResponse when an undefined property is tested from version 1.24 onwards instead of raising a NoMethodError.

describe aws_ec2_instance(instance_id: 'i-12345678') do
  its('fake_property') { should be_nil }
end
# =>   EC2 Instance i-12345678
#          ✔  fake_property is expected to be nil

describe aws_ec2_instance(instance_id: 'i-12345678') do
  its('instance_ID') { should eq 'i-12345678' }
end
# =>  ×  instance_ID is expected to eq "i-12345678"    
#     expected: "i-12345678"
#          got: #<#<Class:0x00007ffc4aa24c68>::NullResponse:0x00007ffc39f16070>    
#     (compared using ==)

Prior to version 1.24.

describe aws_ec2_instance(instance_id: 'i-12345678') do
  its('fake_property') { should be_nil }
end
# => EC2 Instance i-12345678
#          ×  fake_property 
#          undefined method `fake_property' for EC2 Instance i-12345678

describe aws_ec2_instance(instance_id: 'i-12345678') do
  its('instance_ID') { should eq 'i-12345678' }
end
# => undefined method `instance_ID' for EC2 Instance i-12345678

Environment and Setup Notes

Train and InSpec Dependencies

InSpec AWS depends on version 3 of the AWS SDK provided via Train AWS. InSpec depends on Train AWS, so this is not explicitly listed in the Gemfile here.

Running a sample profile using Docker

A Dockerfile is provided at the root of this resource pack repository.

cd inspec-aws
docker build -t inspec-aws -f Dockerfile
docker run -it inspec-aws /bin/bash
export AWS_ACCESS_KEY_ID=<your creds here>
export AWS_SECRET_ACCESS_KEY=<your creds here>
bundle exec inspec exec sample_profile -t aws://

If successful, output similar to below code is seen:

# bundle exec inspec exec sample_profile -t aws://

Profile: AWS InSpec Profile (InSpec AWS Sample Profile)
Version: 0.1.0
Target:  aws://us-east-1

  aws-vpcs-multi-region-status-check: Check AWS VPCs in all regions have status "available"
  VPC vpc-1234abcd in eu-north-1 should exist
  VPC vpc-1234abcd in eu-north-1 should be available
<curtailing> ...


Profile: Amazon Web Services  Resource Pack (inspec-aws)
Version: 0.1.0
Target:  aws://us-east-1

     No tests were executed.

Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
Test Summary: 50 successful, 0 failures, 0 skipped

Running a single unit test

rake test TEST=inspec-aws/test/unit/resources/aws_alb_test.rb

The above example is for running the aws_alb_test.rb file.

Running the unit and integration tests

Run the linting and unit tests via the below:

$ bundle exec rake
Running RuboCop...
Inspecting 2 files
..

2 files inspected, no offenses detected
/Users/spaterson/.rubies/ruby-2.4.3/bin/ruby -I"lib:libraries:test/unit" -I"/Users/spaterson/.rubies/ruby-2.4.3/lib/ruby/gems/2.4.0/gems/rake-12.3.1/lib" "/Users/spaterson/.rubies/ruby-2.4.3/lib/ruby/gems/2.4.0/gems/rake-12.3.1/lib/rake/rake_test_loader.rb" "test/unit/resources/aws_vpc_test.rb"
Run options: --seed 64195

# Running:

.................

Fabulous run in 0.253300s, 67.1141 runs/s, 51.3225 assertions/s.

17 runs, 13 assertions, 0 failures, 0 errors, 0 skips
bundle exec inspec check /Users/spaterson/Documents/workspace/aws/inspec-aws
Location:    /Users/spaterson/Documents/workspace/aws/inspec-aws
Profile:     inspec-aws
Controls:    0
Timestamp:   2018-11-29T15:02:33+00:00
Valid:       true

  !  No controls or tests were defined.

Summary:     0 errors, 1 warnings

Conversely, run using within a docker container, using the make file:

To run unit tests and linting:

make sure

Will result in...

make sure

docker-compose run --rm builder 
Running RuboCop...
Inspecting 68 files
....................................................................

68 files inspected, no offenses detected
/usr/local/bin/ruby -I"lib:libraries:test/unit" -I"/usr/local/bundle/gems/rake-12.3.3/lib" "/usr/local/bundle/gems/rake-12.3.3/lib/rake/rake_test_loader.rb" "test/unit/resources/aws_alb_test.rb" "test/unit/resources/aws_auto_scaling_group_test.rb" "test/unit/resources/aws_cloudformation_stack_test.rb" "test/unit/resources/aws_cloudtrail_trail_test.rb" "test/unit/resources/aws_cloudtrail_trails_test.rb" "test/unit/resources/aws_cloudwatch_alarm_test.rb" "test/unit/resources/aws_cloudwatch_log_metric_filter_test.rb" "test/unit/resources/aws_config_delivery_channel_test.rb" "test/unit/resources/aws_config_recorder_test.rb" "test/unit/resources/aws_dynamodb_table_test.rb" "test/unit/resources/aws_ebs_volume_test.rb" "test/unit/resources/aws_ebs_volumes_test.rb" "test/unit/resources/aws_ec2_instance_test.rb" "test/unit/resources/aws_ec2_instances_test.rb" "test/unit/resources/aws_ecr_test.rb" "test/unit/resources/aws_ecs_cluster_test.rb" "test/unit/resources/aws_eks_cluster_test.rb" "test/unit/resources/aws_eks_clusters_test.rb" "test/unit/resources/aws_elb_test.rb" "test/unit/resources/aws_flow_log_test.rb" "test/unit/resources/aws_hosted_zones_test.rb" "test/unit/resources/aws_iam_account_alias_test.rb" "test/unit/resources/aws_iam_group_test.rb" "test/unit/resources/aws_iam_password_policy_test.rb" "test/unit/resources/aws_iam_policy_test.rb" "test/unit/resources/aws_iam_role_test.rb" "test/unit/resources/aws_iam_root_user_test.rb" "test/unit/resources/aws_iam_saml_provider_test.rb" "test/unit/resources/aws_iam_user_test.rb" "test/unit/resources/aws_kms_key_test.rb" "test/unit/resources/aws_kms_keys_test.rb" "test/unit/resources/aws_launch_configuration_test.rb" "test/unit/resources/aws_organizations_member_test.rb" "test/unit/resources/aws_rds_instance_test.rb" "test/unit/resources/aws_rds_instances_test.rb" "test/unit/resources/aws_region_test.rb" "test/unit/resources/aws_regions_test.rb" "test/unit/resources/aws_route_table_test.rb" "test/unit/resources/aws_route_tables_test.rb" "test/unit/resources/aws_s3_bucket_object_test.rb" "test/unit/resources/aws_s3_bucket_test.rb" "test/unit/resources/aws_s3_buckets_test.rb" "test/unit/resources/aws_security_group_test.rb" "test/unit/resources/aws_security_groups_test.rb" "test/unit/resources/aws_sns_subscription_test.rb" "test/unit/resources/aws_sns_topic_test.rb" "test/unit/resources/aws_sns_topics_test.rb" "test/unit/resources/aws_sqs_queue_test.rb" "test/unit/resources/aws_sts_caller_identity_test.rb" "test/unit/resources/aws_subnet_test.rb" "test/unit/resources/aws_subnets_test.rb" "test/unit/resources/aws_vpc_test.rb" "test/unit/resources/aws_vpcs_test.rb" 
Run options: --seed 22010

# Running:

..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Fabulous run in 4.613042s, 155.6457 runs/s, 172.3375 assertions/s.

718 runs, 795 assertions, 0 failures, 0 errors, 0 skips

To run the full suite of tests, run

make doubly_sure

This test runs the unit tests, creates the target infrastructure, and runs the intergration tests. If successful, the test automatically destroy everything. If it fails, it will keep the environment up, testing then can be achieved by running:

make int_test

The AWS credentials can either be supplied via environmental variables or files located on ./aws folder.

This requires docker, docker-compose and make, see Three Musketeers Pattern for details.

Running the integration tests (after setup_integration_tests):

$ bundle exec rake test:run_integration_tests
----> Run
bundle exec inspec exec test/integration/verify --attrs test/integration/build/aws-inspec-attributes.yaml; rc=$?; if [ $rc -eq 0 ] || [ $rc -eq 101 ]; then exit 0; else exit 1; fi

Profile: Amazon Web Services  Resource Pack (inspec-aws)
Version: 0.1.0
Target:  aws://eu-west-2

  aws-vpc-1.0: Ensure AWS VPC has the correct properties.
  VPC vpc-0373aeb7284407ffd should exist
  VPC vpc-0373aeb7284407ffd should not be default
  VPC vpc-0373aeb7284407ffd cidr_block should eq "10.0.0.0/27"
  VPC vpc-0373aeb7284407ffd instance_tenancy should eq "dedicated"
  VPC vpc-0373aeb7284407ffd vpc_id should eq "vpc-0373aeb7284407ffd"
  VPC vpc-0373aeb7284407ffd state should eq "available"
  VPC vpc-0373aeb7284407ffd dhcp_options_id should eq "dopt-f557819d"
  VPC default should exist
  VPC default should be default
  VPC default vpc_id should eq "vpc-1ea06476"
  VPC vpc-0373aeb7284407ffd should exist
  VPC vpc-0373aeb7284407ffd should not be default
  VPC vpc-0373aeb7284407ffd vpc_id should eq "vpc-0373aeb7284407ffd"
...

Profile: Amazon Web Services  Resource Pack (inspec-aws)
Version: 0.1.0
Target:  aws://eu-west-2

     No tests were executed.

Profile Summary: 50 successful controls, 0 control failures, 3 controls skipped
Test Summary: 602 successful, 0 failures, 18 skipped

FAQ

Failure running "inspec exec" on my AWS profile

If an error occurs when running "inspec exec" on a newly created AWS profile, check that the AWS transport is specified as below:

inspec exec . -t aws://

If a method missing error occurs and all the steps documented above is followed try running the following command within the profile directory:

inspec vendor --overwrite

Support

The InSpec AWS resources are community-supported. For bugs and features, please open a GitHub issue and label it appropriately.

Kudos

This work builds on the InSpec 2 AWS resources that are originally shipped as part of InSpec.