turbot / steampipe-plugin-aws

Use SQL to instantly query AWS resources across regions and accounts. Open source CLI. No DB required.
https://hub.steampipe.io/plugins/turbot/aws
Apache License 2.0
189 stars 104 forks source link

Bugs in SELECT ALL for AWS Tables in Multiregion Mode #855

Closed defec8edc0de closed 2 years ago

defec8edc0de commented 2 years ago

Describe the bug

When running a bash loop over ALL AWS tables with a multi-region connection (select * awsaccountxyzwithmfaadminaccess.aws_*) using the latest Steampipe and AWS plugin version, I discovered the following warnings/exceptions that impede my progress in automating security audits with steampipe (yes I am aware of the CIS mod, its just not enough for me). Please note, surely some of the bugs are covered in other single existing issues in the Github repo already, but I am too lazy to filter those out..

Steampipe version (steampipe -v) v0.11.2 (under latest Arch Linux Rolling)

Plugin version (steampipe plugin list) v0.44.0

To reproduce

Run the following bash snippet of my automation script, with the following ~/.steampipe/config/aws.spc that defines an aws cli connection over all regions with MFA enabled credentials (profile awsaccountxyzwithmfaadminaccessprofile has aws_session_token in ~/.aws/credentials) and access to the target AWS account with "AdministratorAccess" group permissions:

    connection "awsaccountxyzwithmfaadminaccess" {
    plugin      = "aws"
    profile     = "awsaccountxyzwithmfaadminaccessprofile"
    regions     = ["*"]
    }
#!/usr/bin/env bash

set -EeuoC pipefail
trap cleanup SIGINT SIGTERM ERR EXIT

cleanup() {
  trap - SIGINT SIGTERM ERR EXIT
}

STEAMPIPE_CONNECTION_NAME=awsaccountxyzwithmfaadminaccess

declare -a AWS_TABLES=(
"aws_accessanalyzer_analyzer"
"aws_account"
"aws_acm_certificate"
"aws_api_gateway_api_key"
"aws_api_gateway_authorizer"
"aws_api_gateway_rest_api"
"aws_api_gateway_stage"
"aws_api_gateway_usage_plan"
"aws_api_gatewayv2_api"
"aws_api_gatewayv2_domain_name"
"aws_api_gatewayv2_integration"
"aws_api_gatewayv2_stage"
"aws_appautoscaling_target"
"aws_auditmanager_assessment"
"aws_auditmanager_control"
"aws_auditmanager_evidence"
"aws_auditmanager_evidence_folder"
"aws_auditmanager_framework"
"aws_availability_zone"
"aws_backup_plan"
"aws_backup_protected_resource"
"aws_backup_recovery_point"
"aws_backup_selection"
"aws_backup_vault"
"aws_cloudcontrol_resource"
"aws_cloudformation_stack"
"aws_cloudfront_cache_policy"
"aws_cloudfront_distribution"
"aws_cloudfront_origin_access_identity"
"aws_cloudfront_origin_request_policy"
"aws_cloudtrail_trail"
"aws_cloudtrail_trail_event"
"aws_cloudwatch_alarm"
"aws_cloudwatch_log_event"
"aws_cloudwatch_log_group"
"aws_cloudwatch_log_metric_filter"
"aws_cloudwatch_log_resource_policy"
"aws_cloudwatch_log_stream"
"aws_codebuild_project"
"aws_codebuild_source_credential"
"aws_codecommit_repository"
"aws_codepipeline_pipeline"
"aws_config_configuration_recorder"
"aws_config_conformance_pack"
"aws_config_rule"
"aws_cost_by_account_daily"
"aws_cost_by_account_monthly"
"aws_cost_by_service_daily"
"aws_cost_by_service_monthly"
"aws_cost_by_service_usage_type_daily"
"aws_cost_by_service_usage_type_monthly"
"aws_cost_forecast_daily"
"aws_cost_forecast_monthly"
"aws_cost_usage"
"aws_dax_cluster"
"aws_directory_service_directory"
"aws_dms_replication_instance"
"aws_dynamodb_backup"
"aws_dynamodb_global_table"
"aws_dynamodb_metric_account_provisioned_read_capacity_util"
"aws_dynamodb_metric_account_provisioned_write_capacity_util"
"aws_dynamodb_table"
"aws_ebs_snapshot"
"aws_ebs_volume"
"aws_ebs_volume_metric_read_ops"
"aws_ebs_volume_metric_read_ops_daily"
"aws_ebs_volume_metric_read_ops_hourly"
"aws_ebs_volume_metric_write_ops"
"aws_ebs_volume_metric_write_ops_daily"
"aws_ebs_volume_metric_write_ops_hourly"
"aws_ec2_ami"
"aws_ec2_ami_shared"
"aws_ec2_application_load_balancer"
"aws_ec2_application_load_balancer_metric_request_count"
"aws_ec2_application_load_balancer_metric_request_count_daily"
"aws_ec2_autoscaling_group"
"aws_ec2_capacity_reservation"
"aws_ec2_classic_load_balancer"
"aws_ec2_gateway_load_balancer"
"aws_ec2_instance"
"aws_ec2_instance_availability"
"aws_ec2_instance_metric_cpu_utilization"
"aws_ec2_instance_metric_cpu_utilization_daily"
"aws_ec2_instance_metric_cpu_utilization_hourly"
"aws_ec2_instance_type"
"aws_ec2_key_pair"
"aws_ec2_launch_configuration"
"aws_ec2_load_balancer_listener"
"aws_ec2_managed_prefix_list"
"aws_ec2_network_interface"
"aws_ec2_network_load_balancer"
"aws_ec2_network_load_balancer_metric_net_flow_count"
"aws_ec2_network_load_balancer_metric_net_flow_count_daily"
"aws_ec2_regional_settings"
"aws_ec2_reserved_instance"
"aws_ec2_ssl_policy"
"aws_ec2_target_group"
"aws_ec2_transit_gateway"
"aws_ec2_transit_gateway_route"
"aws_ec2_transit_gateway_route_table"
"aws_ec2_transit_gateway_vpc_attachment"
"aws_ecr_repository"
"aws_ecrpublic_repository"
"aws_ecs_cluster"
"aws_ecs_cluster_metric_cpu_utilization"
"aws_ecs_cluster_metric_cpu_utilization_daily"
"aws_ecs_cluster_metric_cpu_utilization_hourly"
"aws_ecs_container_instance"
"aws_ecs_service"
"aws_ecs_task"
"aws_ecs_task_definition"
"aws_efs_access_point"
"aws_efs_file_system"
"aws_efs_mount_target"
"aws_eks_addon"
"aws_eks_addon_version"
"aws_eks_cluster"
"aws_eks_identity_provider_config"
"aws_elastic_beanstalk_application"
"aws_elastic_beanstalk_environment"
"aws_elasticache_cluster"
"aws_elasticache_parameter_group"
"aws_elasticache_redis_metric_cache_hits_hourly"
"aws_elasticache_redis_metric_curr_connections_hourly"
"aws_elasticache_redis_metric_engine_cpu_utilization_hourly"
"aws_elasticache_redis_metric_get_type_cmds_hourly"
"aws_elasticache_redis_metric_list_based_cmds_hourly"
"aws_elasticache_redis_metric_new_connections_hourly"
"aws_elasticache_replication_group"
"aws_elasticache_subnet_group"
"aws_elasticsearch_domain"
"aws_emr_cluster"
"aws_emr_cluster_metric_is_idle"
"aws_emr_instance_group"
"aws_eventbridge_bus"
"aws_eventbridge_rule"
"aws_fsx_file_system"
"aws_glacier_vault"
"aws_glue_catalog_database"
"aws_guardduty_detector"
"aws_guardduty_finding"
"aws_guardduty_ipset"
"aws_guardduty_threat_intel_set"
"aws_iam_access_advisor"
"aws_iam_access_key"
"aws_iam_account_password_policy"
"aws_iam_account_summary"
"aws_iam_action"
"aws_iam_credential_report"
"aws_iam_group"
"aws_iam_policy"
"aws_iam_policy_attachment"
"aws_iam_policy_simulator"
"aws_iam_role"
"aws_iam_server_certificate"
"aws_iam_user"
"aws_iam_virtual_mfa_device"
"aws_identitystore_group"
"aws_identitystore_user"
"aws_inspector_assessment_target"
"aws_inspector_assessment_template"
"aws_kinesis_consumer"
"aws_kinesis_firehose_delivery_stream"
"aws_kinesis_stream"
"aws_kinesis_video_stream"
"aws_kinesisanalyticsv2_application"
"aws_kms_key"
"aws_lambda_alias"
"aws_lambda_function"
"aws_lambda_function_metric_duration_daily"
"aws_lambda_function_metric_errors_daily"
"aws_lambda_function_metric_invocations_daily"
"aws_lambda_layer"
"aws_lambda_layer_version"
"aws_lambda_version"
"aws_macie2_classification_job"
"aws_media_store_container"
"aws_organizations_account"
"aws_rds_db_cluster"
"aws_rds_db_cluster_parameter_group"
"aws_rds_db_cluster_snapshot"
"aws_rds_db_event_subscription"
"aws_rds_db_instance"
"aws_rds_db_instance_metric_connections"
"aws_rds_db_instance_metric_connections_daily"
"aws_rds_db_instance_metric_connections_hourly"
"aws_rds_db_instance_metric_cpu_utilization"
"aws_rds_db_instance_metric_cpu_utilization_daily"
"aws_rds_db_instance_metric_cpu_utilization_hourly"
"aws_rds_db_instance_metric_read_iops"
"aws_rds_db_instance_metric_read_iops_daily"
"aws_rds_db_instance_metric_read_iops_hourly"
"aws_rds_db_instance_metric_write_iops"
"aws_rds_db_instance_metric_write_iops_daily"
"aws_rds_db_instance_metric_write_iops_hourly"
"aws_rds_db_option_group"
"aws_rds_db_parameter_group"
"aws_rds_db_snapshot"
"aws_rds_db_subnet_group"
"aws_redshift_cluster"
"aws_redshift_cluster_metric_cpu_utilization_daily"
"aws_redshift_event_subscription"
"aws_redshift_parameter_group"
"aws_redshift_snapshot"
"aws_redshift_subnet_group"
"aws_region"
"aws_route53_domain"
"aws_route53_record"
"aws_route53_resolver_endpoint"
"aws_route53_resolver_rule"
"aws_route53_zone"
"aws_s3_access_point"
"aws_s3_account_settings"
"aws_s3_bucket"
"aws_sagemaker_endpoint_configuration"
"aws_sagemaker_model"
"aws_sagemaker_notebook_instance"
"aws_sagemaker_training_job"
"aws_secretsmanager_secret"
"aws_securityhub_hub"
"aws_securityhub_product"
"aws_securityhub_standards_subscription"
"aws_serverlessapplicationrepository_application"
"aws_sfn_state_machine"
"aws_sfn_state_machine_execution"
"aws_sfn_state_machine_execution_history"
"aws_sns_topic"
"aws_sns_topic_subscription"
"aws_sqs_queue"
"aws_ssm_association"
"aws_ssm_document"
"aws_ssm_maintenance_window"
"aws_ssm_managed_instance"
"aws_ssm_managed_instance_compliance"
"aws_ssm_parameter"
"aws_ssm_patch_baseline"
"aws_ssoadmin_instance"
"aws_ssoadmin_managed_policy_attachment"
"aws_ssoadmin_permission_set"
"aws_tagging_resource"
"aws_vpc"
"aws_vpc_customer_gateway"
"aws_vpc_dhcp_options"
"aws_vpc_egress_only_internet_gateway"
"aws_vpc_eip"
"aws_vpc_endpoint"
"aws_vpc_endpoint_service"
"aws_vpc_flow_log"
"aws_vpc_flow_log_event"
"aws_vpc_internet_gateway"
"aws_vpc_nat_gateway"
"aws_vpc_network_acl"
"aws_vpc_peering_connection"
"aws_vpc_route"
"aws_vpc_route_table"
"aws_vpc_security_group"
"aws_vpc_security_group_rule"
"aws_vpc_subnet"
"aws_vpc_vpn_connection"
"aws_vpc_vpn_gateway"
"aws_waf_rate_based_rule"
"aws_waf_rule"
"aws_wafv2_ip_set"
"aws_wafv2_regex_pattern_set"
"aws_wafv2_rule_group"
"aws_wafv2_web_acl"
"aws_wellarchitected_workload"
"aws_workspaces_workspace"
)

echo "Starting to fetch all information of the aws hyperscaler account(s) with the provided steampipe connection ${STEAMPIPE_CONNECTION_NAME} and dump it as JSON, CSV and Table format into ${PWD}. Grab a c[_]..."

# Dispatch required cloud provider
for table in "${AWS_TABLES[@]}"
do
     echo "[*] Fetching steampipe table ${table}..."
     if [ -f "${PWD}/${STEAMPIPE_CONNECTION_NAME}_${table}.log" ]; then
       echo "[!] WARN: ${PWD}/${STEAMPIPE_CONNECTION_NAME}_${table}.log already exists! Need c[_]? Skipping ${table}..."
     else
       steampipe query "select * from ${STEAMPIPE_CONNECTION_NAME}.${table}" > ${STEAMPIPE_CONNECTION_NAME}_${table}.log
       steampipe query "select * from ${STEAMPIPE_CONNECTION_NAME}.${table}" --output json > ${STEAMPIPE_CONNECTION_NAME}_${table}.json
       steampipe query "select * from ${STEAMPIPE_CONNECTION_NAME}.${table}" --output csv > ${STEAMPIPE_CONNECTION_NAME}_${table}.csv
     fi
done

Please note, not all of the queried AWS resources are actually used in my target AWS account (e.g. iam_credential_report etc.), perhaps this could also be a reason for some of the errors listed below in the additoinal context.

Expected behavior

Graceful handling of errors and return of empty results for non-existing resource information. Authorization errors could/should be raised in --dry-run? Update: I got informed, some steampipe tables REQUIRE a where clause. Which is expected behaviour. Please ignore errors below where this is the case. Have to do more research.

Additional context

Here are the collected errors (as of 17.01.2022):

  - aws_appautoscaling_target: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'service_namespace' operator: = (SQLSTATE HV000)
  - aws_cloudcontrol_resource: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'type_name' operator: = (SQLSTATE HV000)
  - aws_cloudtrail_trail_event: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'log_group_name' operator: = (SQLSTATE HV000)
  - aws_cloudwatch_log_event: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'log_group_name' operator: = (SQLSTATE HV000)
  - aws_codepipeline_pipeline: Sometimes aws regions don't respond/are unavailable:
    Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = RequestError: send request failed
    caused by: Post "https://codepipeline.ap-northeast-3.amazonaws.com/": dial tcp: lookup codepipeline.ap-northeast-3.amazonaws.com on 192.168.234.1:53: read udp 192.168.234.129:36471->192.168.234.1:53: read: connection refused (SQLSTATE HV000)
  - aws_cost_usage: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'granularity' operator: = column:'dimension_type_1' operator: = column:'dimension_type_2' operator: = (SQLSTATE HV000)       
   - aws_dax_cluster: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = RequestError: send request failed
caused by: Post "https://dax.ap-northeast-3.amazonaws.com/": dial tcp: lookup dax.ap-northeast-3.amazonaws.com on 192.168.234.1:53: read udp 192.168.234.129:60885->192.168.234.1:53: read: connection refused (SQLSTATE HV000)
   - aws_dynamodb_backup: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = InternalServerError: Internal server error (SQLSTATE HV000)
   - aws_ec2_ami_shared: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'owner_id' operator: = (SQLSTATE HV000)
   - aws_iam_access_advisor: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'principal_arn' operator: = (SQLSTATE HV000)
   - aws_iam_credential_report: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = Credential report not available. Please run aws iam generate-credential-report to generate it and try again. (SQLSTATE HV000)
   - aws_iam_policy_simulator: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'principal_arn' operator: = column:'action' operator: = column:'resource_arn' operator: = (SQLSTATE HV000)
   - aws_identitystore_group: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'identity_store_id' operator: = column:'name' operator: = (SQLSTATE HV000)
   - aws_identitystore_user: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'identity_store_id' operator: = column:'name' operator: = (SQLSTATE HV000)
   - aws_inspector_assessment_target: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = RequestError: send request failed caused by: Post "https://inspector.ap-northeast-3.amazonaws.com/": dial tcp: lookup inspector.ap-northeast-3.amazonaws.com on 192.168.234.1:53: read udp 192.168.234.129:60248->192.168.234.1:53: read: connection refused (SQLSTATE HV000)
   - aws_inspector_assessment_template: Takes too long, even though the feature in the target aws account is not used/enabled
   - aws_kinesis_video_stream: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = RequestError: send request failed caused by: Post "https://kinesisvideo.us-west-1.amazonaws.com/listStreams": dial tcp: lookup kinesisvideo.us-west-1.amazonaws.com on 192.168.171.2:53: no such host (SQLSTATE HV000)
   - aws_media_store_container: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = SerializationError: failed to unmarshal response error status code: 503, request id: caused by: UnmarshalError: error message missing (SQLSTATE HV000)
   - aws_route53: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'zone_id' operator: = (SQLSTATE HV000)
   - aws_serverlessapplicationrepository_application: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = RequestError: send request failed caused by: Get "https://serverlessrepo.ap-northeast-3.amazonaws.com/applications?maxItems=100": dial tcp: lookup serverlessrepo.ap-northeast-3.amazonaws.com on 192.168.234.1:53: read udp 192.168.234.129:41944->192.168.234.1:53: read: connection refused (SQLSTATE HV000)
   - aws_ssm_document: Error: table 'aws_ssm_document' column 'account_ids' requires hydrate data from getAwsSSMDocumentPermissionDetail, which failed with error ThrottlingException: Rate exceeded         status code: 400, request id: e3c2d42c-f5a9-4e59-b75e-b1f68d13edb4.  (SQLSTATE HV000)
   - aws_ssm_managed_instance_compliance: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'resource_id' operator: = (SQLSTATE HV000)
   - aws_vpc_flow_log_event: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'log_group_name' operator: = (SQLSTATE HV000)
   - aws_wellarchitected_workload: took to long, likely errors happen in background
   - aws_workspaces_workspace: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = RequestError: send request failed caused by: Post "https://workspaces.eu-west-3.amazonaws.com/": dial tcp: lookup workspaces.eu-west-3.amazonaws.com on 192.168.234.1:53: read udp 192.168.234.129:52243->192.168.234.1:53: read: connection refused (SQLSTATE HV000)

   Special authorization required:
   - aws_config_conformance_pack: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = AccessDeniedException: 
        status code: 400, request id: 8e95747f-baff-41c0-9996-3fe825bfb33f (SQLSTATE HV000)
   - aws_ssoadmin_instance: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = AccessDeniedException: User: arn:aws:iam::[redacted]:user/[redacted] is not authorized to perform: sso:ListInstances (SQLSTATE HV000)
   - aws_organizations_account: 403 because usually you don't have authorization to access the org account in an audit...
   - aws_ssoadmin_managed_policy_attachment: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'permission_set_arn' operator: = (SQLSTATE HV000)
   - aws_ssoadmin_permission_set: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = AccessDeniedException: User: arn:aws:iam::[redacted]:user/[redacted] is not authorized to perform: sso:ListInstances (SQLSTATE HV000)

Thank you, happy fixing and please let me know if you have further questions~~ (I love Steampipe)

rajlearner17 commented 2 years ago

@defec8edc0de Wow !! love to hear you like Steampipe 💯 Very interesting to see a very detailed approach, appreciate your interest.

While we are checking it in detail, in the first place just want to inform you that, some of the tables need to pass the required column as per API requirement.

e.g. - aws_appautoscaling_target: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Internal desc = 'List' call is missing required quals: column:'service_namespace' operator: = (SQLSTATE HV000)

The above query can be modeled as (example)

select * from aws_appautoscaling_target where service_namespace = 'dynamodb'; ( here the service_namespace is the required field for list call of aws_appautoscaling_target )

I guess most of the tables mentioned are similar issues. I am still checking if all the tables fall into the same set of requirements.

Following tables being investigated may require a fix, will keep posted.

   - aws_wellarchitected_workload: took to long, likely errors happen in background
   - aws_workspaces_workspace: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = RequestError: send request failed caused by: Post "https://workspaces.eu-west-3.amazonaws.com/": dial tcp: lookup workspaces.eu-west-3.amazonaws.com on 192.168.234.1:53: read udp 192.168.234.129:52243->192.168.234.1:53: read: connection refused (SQLSTATE HV000) 

The ones mentioned in Special authorization required: combination of required column and permission requirement. Which I need to investigate or wait for somebody to respond. These are initial observation

A better approach from our side could have been to provide more information around it in the doc. We will definitely work around it to provide this information. Let us know

rajlearner17 commented 2 years ago

On further investigation, interestingly we found Conformance Packs does not support in Osaka (ap-northeast-3), hence if the aws.spc file is having * in the region, it breaks with the below exception.

aws_config_conformance_pack: Warning: executeQueries: query 1 of 1 failed: ERROR: rpc error: code = Unknown desc = AccessDeniedException: status code: 400, request id: 8e95747f-baff-41c0-9996-3fe825bfb33f (SQLSTATE HV000)

@bigdatasourav any other finding feel free to add here.

rajlearner17 commented 2 years ago

@defec8edc0de Thanks for waiting on this, the above had resulted in 2 bugs for which we have the PR ready to go this week.