Skip to main content
AWSSecuritybeginner

Security Hub Overview

Get started with AWS Security Hub for centralized security findings and compliance checks.

CloudToolStack Team22 min readPublished Feb 22, 2026

Prerequisites

What Is AWS Security Hub?

AWS Security Hub is a cloud security posture management (CSPM) service that provides a comprehensive view of your security state across AWS accounts. It aggregates, organizes, and prioritizes security findings from multiple AWS services and third-party tools into a single dashboard, allowing you to understand your overall security posture and take action on the most critical issues.

Security Hub continuously evaluates your AWS environment against industry standards and best practices through automated security checks. It integrates with over 70 AWS and third-party services, consolidating findings into a standardized format called the AWS Security Finding Format (ASFF). Think of Security Hub as the central nervous system of your AWS security program. It does not replace individual security services but rather unifies them into a single operational view.

Without Security Hub, security findings are scattered across GuardDuty, Inspector, Config, IAM Access Analyzer, Macie, and dozens of other services. Each has its own console, its own finding format, and its own notification mechanism. Security Hub eliminates this fragmentation by normalizing everything into ASFF and providing a single pane of glass with aggregated security scores, trends, and prioritized action items.

Security Hub Pricing

Security Hub charges based on the number of security checks and findings ingested. The first 10,000 checks per account per region per month are $0.0010 each, with volume discounts thereafter. Finding ingestion events cost $0.00003 each after the first 10,000 per month. For a typical account with 200 resources, expect $5-15/month. Enable it in every account; the cost is negligible compared to the risk of undetected misconfigurations.

Security Standards and Controls

Security Hub includes several built-in security standards that automatically check your environment against documented best practices. Each standard contains a set of controls, and each control maps to a specific security check executed by AWS Config rules under the hood. When you enable a standard, Security Hub automatically creates the required Config rules and begins evaluating your resources.

Available Security Standards

StandardControlsFocusUse When
AWS Foundational Security Best Practices (FSBP)~200AWS-specific security best practicesAlways, the recommended starting point
CIS AWS Foundations Benchmark v1.4~50Center for Internet Security baselineNeed a recognized compliance framework
CIS AWS Foundations Benchmark v3.0~60Updated CIS baseline with new controlsLatest CIS compliance requirements
PCI DSS v3.2.1~150Payment card industry complianceProcessing, storing, or transmitting cardholder data
NIST SP 800-53 Rev. 5~200US federal government complianceFedRAMP, government, or defense workloads
AWS Resource Tagging Standard~30Tag compliance across resourcesEnforcing tagging governance

Understanding Controls and Findings

Each control within a standard generates findings for resources that fail the check. A finding contains detailed information about the affected resource, the control that was violated, the severity level, and remediation guidance. Controls are identified by a standardized ID (e.g., IAM.1, S3.5, EC2.19) that is consistent across standards when the same check appears in multiple frameworks.

Security Hub calculates a security score for each standard based on the ratio of passed controls to total controls. The overall security score is a weighted average across all enabled standards. Tracking this score over time provides a clear metric for security improvement.

check-security-score.sh
# Get the security score for FSBP
aws securityhub get-enabled-standards \
  --query 'StandardsSubscriptions[*].{Standard: StandardsArn, Status: StandardsStatus}' \
  --output table

# Get control status summary
aws securityhub describe-standards-controls \
  --standards-subscription-arn \
    "arn:aws:securityhub:us-east-1:123456789012:subscription/aws-foundational-security-best-practices/v/1.0.0" \
  --query 'Controls[?ControlStatus==`FAILED`].{Id: ControlId, Title: Title, Severity: SeverityRating}' \
  --output table

# Count findings by severity
aws securityhub get-findings \
  --filters '{
    "ComplianceStatus": [{"Value": "FAILED", "Comparison": "EQUALS"}],
    "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}]
  }' \
  --query 'length(Findings)' \
  --output text

Start with FSBP, Then Add Standards Incrementally

Enable the AWS Foundational Security Best Practices standard first. It provides the broadest coverage of AWS-specific security issues with actionable remediation guidance. Add CIS if you need a recognized compliance framework for auditors. Only enable PCI DSS or NIST if you have specific compliance obligations. Running unnecessary standards creates noise without adding value and increases your Config rule costs.

Consolidated Control Findings

By default, Security Hub may generate duplicate findings when the same control appears in multiple standards. Enable consolidated control findings to deduplicate these. With this feature enabled, each control generates a single finding regardless of how many standards reference it, significantly reducing noise and simplifying triage.

enable-consolidated-findings.sh
# Enable consolidated control findings
aws securityhub update-security-hub-configuration \
  --control-finding-generator SECURITY_CONTROL

# This changes the GeneratorId format from standard-specific
# (e.g., aws-foundational-security-best-practices/v/1.0.0/IAM.1)
# to a unified format (e.g., security-control/IAM.1)

# Verify the setting
aws securityhub describe-hub \
  --query 'ControlFindingGenerator'
AWS IAM Best Practices

Integrations and Finding Sources

Security Hub becomes truly powerful when it aggregates findings from multiple sources. Each integrated service feeds findings into the ASFF format, creating a unified view of your security posture across threat detection, vulnerability management, configuration compliance, data protection, and access analysis.

AWS Service Integrations

ServiceFinding TypeWhat It Detects
Amazon GuardDutyThreat detectionCompromised instances, unusual API calls, cryptocurrency mining, DNS exfiltration
Amazon InspectorVulnerability managementSoftware vulnerabilities in EC2, Lambda, and container images (CVEs)
AWS ConfigConfiguration complianceDrift from desired configuration, non-compliant resource settings
IAM Access AnalyzerAccess analysisResources shared with external entities, unused IAM access
Amazon MacieData protectionSensitive data (PII, financial, credentials) in S3 buckets
AWS Firewall ManagerNetwork securityNon-compliant security groups, missing WAF rules, Shield protections
AWS HealthOperational eventsSecurity-related AWS service events and notifications
Amazon DetectiveInvestigationEnriched findings with behavioral analysis for GuardDuty alerts

Third-Party Integrations

Security Hub integrates with dozens of third-party security tools. These integrations can send findings into Security Hub (finding providers) or receive findings from Security Hub (action targets). Popular integrations include:

  • Prowler: Open-source security assessment tool that sends findings to Security Hub covering hundreds of additional checks beyond built-in standards.
  • Snyk: Application security findings including container vulnerabilities, IaC misconfigurations, and open-source dependency risks.
  • Palo Alto Networks Prisma Cloud: Cross-cloud security posture findings for multi-cloud environments.
  • Splunk: Receives Security Hub findings for SIEM correlation and dashboarding alongside on-premises security data.
  • ServiceNow: Receives findings for ITSM ticket creation and workflow automation.
  • Jira: Through EventBridge integration, create issues for critical findings that require engineering remediation.
enable-integrations.sh
# Enable Security Hub with default standards
aws securityhub enable-security-hub \
  --enable-default-standards

# Enable GuardDuty integration
aws securityhub enable-import-findings-for-product \
  --product-arn "arn:aws:securityhub:us-east-1::product/aws/guardduty"

# Enable Inspector integration
aws securityhub enable-import-findings-for-product \
  --product-arn "arn:aws:securityhub:us-east-1::product/aws/inspector"

# Enable Macie integration
aws securityhub enable-import-findings-for-product \
  --product-arn "arn:aws:securityhub:us-east-1::product/aws/macie"

# Enable IAM Access Analyzer integration
aws securityhub enable-import-findings-for-product \
  --product-arn "arn:aws:securityhub:us-east-1::product/aws/access-analyzer"

# List all available integrations
aws securityhub describe-products \
  --query 'Products[*].{Name: ProductName, Arn: ProductArn, Categories: Categories}' \
  --output table

Custom Findings

You can import custom findings into Security Hub from your own security tools, CI/CD pipelines, or custom Lambda functions. Custom findings must conform to the ASFF schema and are treated identically to AWS-generated findings: they appear in the dashboard, trigger EventBridge rules, and are included in exports.

import-custom-finding.py
import boto3
from datetime import datetime

securityhub = boto3.client('securityhub')

def import_finding(account_id, region, resource_arn, title, description, severity):
    """Import a custom security finding into Security Hub."""
    finding = {
        'SchemaVersion': '2018-10-08',
        'Id': f'{resource_arn}/custom-finding-{datetime.utcnow().isoformat()}',
        'ProductArn': f'arn:aws:securityhub:{region}:{account_id}:product/{account_id}/default',
        'GeneratorId': 'custom-security-scanner',
        'AwsAccountId': account_id,
        'Types': ['Software and Configuration Checks/Custom'],
        'CreatedAt': datetime.utcnow().isoformat() + 'Z',
        'UpdatedAt': datetime.utcnow().isoformat() + 'Z',
        'Severity': {
            'Label': severity  # CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL
        },
        'Title': title,
        'Description': description,
        'Resources': [{
            'Type': 'Other',
            'Id': resource_arn,
            'Region': region
        }],
        'Compliance': {
            'Status': 'FAILED'
        },
        'Workflow': {
            'Status': 'NEW'
        },
        'RecordState': 'ACTIVE'
    }

    response = securityhub.batch_import_findings(Findings=[finding])
    print(f"Imported: {response['SuccessCount']} success, {response['FailedCount']} failed")
    return response

# Example: Flag a container image running as root
import_finding(
    account_id='123456789012',
    region='us-east-1',
    resource_arn='arn:aws:ecs:us-east-1:123456789012:task-definition/web-app:42',
    title='Container running as root user',
    description='The task definition web-app:42 runs the container as root. '
                'Configure a non-root USER in the Dockerfile to reduce blast radius.',
    severity='HIGH'
)

ASFF Is the Universal Language

The AWS Security Finding Format (ASFF) is what makes Security Hub powerful. Every finding, whether from GuardDuty, Inspector, a third-party tool, or your own custom scanner, conforms to the same schema. This means your automation (EventBridge rules, Lambda remediation functions, SIEM integrations) works uniformly regardless of the finding source. Invest time in understanding the ASFF schema; it pays dividends.

AWS Well-Architected Overview

Multi-Account Deployment with AWS Organizations

In an AWS Organizations environment, Security Hub supports a delegated administrator model that provides centralized visibility across all accounts without requiring cross-account IAM roles. This is the recommended deployment model for any organization with more than one AWS account.

Architecture Overview

The recommended multi-account architecture follows these principles:

  • Delegated administrator: Designate a dedicated Security Tooling account (not the management account) as the Security Hub administrator. This account receives all findings from all member accounts.
  • All accounts, all regions: Enable Security Hub in every account and every active AWS region. Security threats can emerge in any region, including regions where you do not actively deploy workloads.
  • Cross-region aggregation: Configure a finding aggregation region (typically your primary region) to view all findings from all regions in a single place.
  • Auto-enable for new accounts: Configure Security Hub to automatically enable in new accounts as they join the organization, ensuring no gaps in coverage.
org-setup.sh
# Step 1: From the MANAGEMENT account, designate a delegated admin
aws securityhub enable-organization-admin-account \
  --admin-account-id 111111111111

# Step 2: From the DELEGATED ADMIN account, auto-enable for all members
aws securityhub update-organization-configuration \
  --auto-enable \
  --auto-enable-standards DEFAULT

# Step 3: Enable cross-region aggregation to your primary region
aws securityhub create-finding-aggregator \
  --region us-east-1 \
  --region-linking-mode ALL_REGIONS

# Step 4: Verify all member accounts are enabled
aws securityhub list-members \
  --query 'Members[*].{AccountId: AccountId, Status: MemberStatus}' \
  --output table

# Step 5: Check aggregation status
aws securityhub get-finding-aggregator \
  --finding-aggregator-arn arn:aws:securityhub:us-east-1:111111111111:finding-aggregator/abc123

CloudFormation StackSets for Org-Wide Deployment

For organizations that want declarative, reproducible deployment across all accounts and regions, CloudFormation StackSets are the preferred mechanism. This ensures Security Hub, GuardDuty, and other security services are enabled consistently.

security-hub-stackset.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Enable Security Hub with FSBP and CIS standards in every account

Resources:
  SecurityHub:
    Type: AWS::SecurityHub::Hub
    Properties:
      EnableDefaultStandards: true
      ControlFindingGenerator: SECURITY_CONTROL
      Tags:
        ManagedBy: CloudFormation
        Purpose: SecurityBaseline

  # Enable additional standards
  CISStandard:
    Type: AWS::SecurityHub::Standard
    DependsOn: SecurityHub
    Properties:
      StandardsArn: !Sub 'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0'

  # Disable noisy or irrelevant controls
  # Example: Disable the hardware MFA control for non-root accounts
  DisableIAM6:
    Type: AWS::SecurityHub::Standard
    DependsOn: SecurityHub
    Properties:
      StandardsArn: !Sub 'arn:aws:securityhub:${AWS::Region}::standards/aws-foundational-security-best-practices/v/1.0.0'
      DisabledSecurityControlIdentifiers:
        - IAM.6  # Hardware MFA (not practical for most organizations)

Enable in All Regions

Security threats can emerge in any AWS region, not just the regions where you actively deploy workloads. An attacker who compromises credentials will often spin up resources in unused regions like ap-southeast-3 or af-south-1to mine cryptocurrency or stage further attacks. Enable Security Hub (and GuardDuty) in all regions, and use SCPs to restrict resource creation to approved regions while keeping security monitoring active everywhere.

SCP to Prevent Disabling Security Hub

To prevent account owners from disabling Security Hub (whether accidentally or maliciously), apply a Service Control Policy at the organization level.

prevent-disable-scp.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PreventDisablingSecurityHub",
      "Effect": "Deny",
      "Action": [
        "securityhub:DisableSecurityHub",
        "securityhub:DeleteMembers",
        "securityhub:DisassociateMembers",
        "securityhub:BatchDisableStandards"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotLike": {
          "aws:PrincipalArn": [
            "arn:aws:iam::*:role/SecurityAdminRole",
            "arn:aws:iam::*:role/OrganizationSetupRole"
          ]
        }
      }
    },
    {
      "Sid": "PreventDisablingGuardDuty",
      "Effect": "Deny",
      "Action": [
        "guardduty:DeleteDetector",
        "guardduty:DisassociateFromMasterAccount",
        "guardduty:UpdateDetector"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotLike": {
          "aws:PrincipalArn": [
            "arn:aws:iam::*:role/SecurityAdminRole"
          ]
        }
      }
    }
  ]
}
AWS IAM Best Practices

Finding Triage and Workflow Management

A common failure mode with Security Hub is enabling it but never acting on findings. Without a clear triage process, findings accumulate, the security score stagnates, and the tool becomes noise. Establishing a workflow for finding management is critical.

Finding Lifecycle

Every Security Hub finding has a workflow status that tracks its progression through your triage process:

  • NEW: The finding was just created and has not been reviewed.
  • NOTIFIED: A notification has been sent (e.g., Slack, Jira) but remediation has not started.
  • RESOLVED: The finding has been remediated and the underlying issue is fixed.
  • SUPPRESSED: The finding has been reviewed and consciously accepted as a known risk (e.g., a public S3 bucket intentionally serving a static website).

Automation Rules for Triage

Security Hub automation rules automatically update finding fields based on criteria you define. This is powerful for reducing noise, setting default workflow statuses, and routing findings to the right teams.

automation-rules.sh
# Suppress findings for known acceptable configurations
aws securityhub create-automation-rule \
  --rule-name "Suppress public website buckets" \
  --rule-order 1 \
  --description "Suppress S3 public access findings for approved static website buckets" \
  --criteria '{
    "GeneratorId": [
      {"Value": "security-control/S3.2", "Comparison": "EQUALS"},
      {"Value": "security-control/S3.3", "Comparison": "EQUALS"}
    ],
    "ResourceId": [
      {"Value": "arn:aws:s3:::company-website-prod", "Comparison": "EQUALS"},
      {"Value": "arn:aws:s3:::company-docs-public", "Comparison": "EQUALS"}
    ]
  }' \
  --actions '[{
    "Type": "FINDING_FIELDS_UPDATE",
    "FindingFieldsUpdate": {
      "Workflow": {"Status": "SUPPRESSED"},
      "Note": {
        "Text": "Auto-suppressed: approved public website bucket",
        "UpdatedBy": "automation-rule"
      }
    }
  }]'

# Auto-escalate critical findings
aws securityhub create-automation-rule \
  --rule-name "Escalate critical findings" \
  --rule-order 2 \
  --description "Mark critical findings as NOTIFIED to ensure rapid response" \
  --criteria '{
    "SeverityLabel": [{"Value": "CRITICAL", "Comparison": "EQUALS"}],
    "WorkflowStatus": [{"Value": "NEW", "Comparison": "EQUALS"}]
  }' \
  --actions '[{
    "Type": "FINDING_FIELDS_UPDATE",
    "FindingFieldsUpdate": {
      "Workflow": {"Status": "NOTIFIED"},
      "Note": {
        "Text": "Auto-escalated: critical severity finding",
        "UpdatedBy": "automation-rule"
      }
    }
  }]'

Weekly Security Review Cadence

Establish a weekly security review meeting where your team triages new Security Hub findings. Review all CRITICAL and HIGH findings, decide on remediation owners and timelines, suppress known acceptable findings, and track the security score trend. A 30-minute weekly review is far more effective than a monthly fire drill when an auditor asks for your security posture.

Automated Remediation Patterns

Security Hub findings can trigger automated remediation through Amazon EventBridge. When a finding is created or updated, EventBridge can invoke Lambda functions, Step Functions, or Systems Manager Automation documents to fix the issue automatically. This is the most powerful operational pattern for Security Hub, turning findings into automatic corrections.

Remediation Architecture

The standard architecture for automated remediation is:

  • Security Hub generates a finding (or receives one from an integrated service)
  • EventBridge rule matches the finding by GeneratorId, severity, or resource type
  • EventBridge triggers a Lambda function or Step Functions state machine
  • The Lambda function performs the remediation action using the AWS SDK
  • The Lambda function updates the finding workflow status to RESOLVED
  • Optionally, a notification is sent to Slack or a ticketing system

Common Auto-Remediation Targets

ControlFindingAuto-Remediation ActionRisk Level
S3.4S3 bucket without server-side encryptionEnable AES-256 default encryptionLow, safe to automate
S3.5S3 bucket without SSL enforcementApply deny-insecure-transport bucket policyLow, safe to automate
S3.8S3 bucket with public accessEnable Block Public Access settingsMedium, verify no public websites first
EC2.19Security group allows unrestricted SSHRevoke 0.0.0.0/0 on port 22Medium, may break access; notify first
EC2.2VPC default security group allows trafficRemove all rules from default security groupLow, safe to automate
RDS.3RDS instance without encryption at restCannot enable post-creation; notify and flagN/A, requires instance recreation
CloudTrail.1CloudTrail not enabledEnable CloudTrail with S3 loggingLow, safe to automate
IAM.3IAM access keys older than 90 daysDeactivate old keys + notify userHigh, may break applications; notify first

EventBridge Rule for S3 Remediation

eventbridge-rule.json
{
  "Source": ["aws.securityhub"],
  "DetailType": ["Security Hub Findings - Imported"],
  "Detail": {
    "findings": {
      "Compliance": {
        "Status": ["FAILED"]
      },
      "GeneratorId": [{
        "prefix": "security-control/S3"
      }],
      "Severity": {
        "Label": ["CRITICAL", "HIGH"]
      },
      "Workflow": {
        "Status": ["NEW"]
      },
      "RecordState": ["ACTIVE"]
    }
  }
}

Lambda Remediation Function

remediate-s3-encryption.py
import json
import boto3
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

s3 = boto3.client('s3')
securityhub = boto3.client('securityhub')

REMEDIATION_MAP = {
    'security-control/S3.4': remediate_encryption,
    'security-control/S3.5': remediate_ssl_only,
    'security-control/S3.9': remediate_access_logging,
}

def handler(event, context):
    """Route Security Hub S3 findings to appropriate remediation functions."""
    for finding in event['detail']['findings']:
        generator_id = finding['GeneratorId']
        bucket_arn = finding['Resources'][0]['Id']
        bucket_name = bucket_arn.split(':::')[-1]

        logger.info(f"Processing {generator_id} for bucket {bucket_name}")

        if generator_id in REMEDIATION_MAP:
            try:
                REMEDIATION_MAP[generator_id](bucket_name)
                update_finding(finding, 'RESOLVED',
                    f'Auto-remediated by {generator_id} handler')
                logger.info(f"Successfully remediated {bucket_name}")
            except Exception as e:
                logger.error(f"Failed to remediate {bucket_name}: {e}")
                update_finding(finding, 'NOTIFIED',
                    f'Auto-remediation failed: {str(e)}')
        else:
            logger.warning(f"No remediation handler for {generator_id}")

def remediate_encryption(bucket_name):
    """Enable default AES-256 encryption on the bucket."""
    s3.put_bucket_encryption(
        Bucket=bucket_name,
        ServerSideEncryptionConfiguration={
            'Rules': [{
                'ApplyServerSideEncryptionByDefault': {
                    'SSEAlgorithm': 'AES256'
                },
                'BucketKeyEnabled': True
            }]
        }
    )

def remediate_ssl_only(bucket_name):
    """Apply a bucket policy denying non-SSL requests."""
    policy = {
        "Version": "2012-10-17",
        "Statement": [{
            "Sid": "EnforceSSLOnly",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                f"arn:aws:s3:::{bucket_name}",
                f"arn:aws:s3:::{bucket_name}/*"
            ],
            "Condition": {
                "Bool": {"aws:SecureTransport": "false"}
            }
        }]
    }
    s3.put_bucket_policy(Bucket=bucket_name, Policy=json.dumps(policy))

def remediate_access_logging(bucket_name):
    """Enable server access logging to a central logging bucket."""
    s3.put_bucket_logging(
        Bucket=bucket_name,
        BucketLoggingStatus={
            'LoggingEnabled': {
                'TargetBucket': 'central-s3-access-logs',
                'TargetPrefix': f'{bucket_name}/'
            }
        }
    )

def update_finding(finding, status, note_text):
    """Update the finding workflow status in Security Hub."""
    securityhub.batch_update_findings(
        FindingIdentifiers=[{
            'Id': finding['Id'],
            'ProductArn': finding['ProductArn']
        }],
        Workflow={'Status': status},
        Note={
            'Text': note_text,
            'UpdatedBy': 'auto-remediation-lambda'
        }
    )

Start Manual, Then Automate Carefully

Do not automate remediation for all findings immediately. Start by reviewing findings manually to understand your environment and identify false positives. Automate only well-understood, low-risk remediations first (like enabling encryption or blocking public access). For high-risk remediations (like modifying security groups or deactivating IAM keys), start with notifications and manual approval workflows before full automation. A poorly targeted auto-remediation can cause outages.

AWS Lambda Performance Tuning

Notification and Alerting Patterns

For findings that should not be auto-remediated, you need a robust notification pipeline. Security Hub integrates with EventBridge, which can fan out to multiple notification channels including Slack, PagerDuty, Jira, email, and custom webhooks.

Slack Notifications for Critical Findings

slack-notification.py
import json
import urllib3
import os

http = urllib3.PoolManager()
SLACK_WEBHOOK = os.environ['SLACK_WEBHOOK_URL']

SEVERITY_COLORS = {
    'CRITICAL': '#FF0000',
    'HIGH': '#FF6600',
    'MEDIUM': '#FFCC00',
    'LOW': '#00CC00',
}

def handler(event, context):
    """Send Security Hub critical findings to Slack."""
    for finding in event['detail']['findings']:
        severity = finding['Severity']['Label']
        title = finding['Title']
        description = finding.get('Description', 'No description')
        account = finding['AwsAccountId']
        region = finding['Region']
        resource = finding['Resources'][0]['Id']
        generator = finding['GeneratorId']

        # Truncate description for Slack readability
        if len(description) > 300:
            description = description[:297] + '...'

        slack_message = {
            'attachments': [{
                'color': SEVERITY_COLORS.get(severity, '#808080'),
                'blocks': [
                    {
                        'type': 'header',
                        'text': {
                            'type': 'plain_text',
                            'text': f':rotating_light: {severity} Security Finding'
                        }
                    },
                    {
                        'type': 'section',
                        'fields': [
                            {'type': 'mrkdwn', 'text': f'*Title:*\n{title}'},
                            {'type': 'mrkdwn', 'text': f'*Account:*\n{account}'},
                            {'type': 'mrkdwn', 'text': f'*Region:*\n{region}'},
                            {'type': 'mrkdwn', 'text': f'*Control:*\n{generator}'},
                        ]
                    },
                    {
                        'type': 'section',
                        'text': {
                            'type': 'mrkdwn',
                            'text': f'*Resource:*\n`{resource}`'
                        }
                    },
                    {
                        'type': 'section',
                        'text': {
                            'type': 'mrkdwn',
                            'text': f'*Description:*\n{description}'
                        }
                    }
                ]
            }]
        }

        http.request(
            'POST', SLACK_WEBHOOK,
            body=json.dumps(slack_message),
            headers={'Content-Type': 'application/json'}
        )

Jira Ticket Creation

For findings that require engineering work, creating Jira tickets automatically ensures nothing falls through the cracks. Use Step Functions to orchestrate the workflow: check if a ticket already exists for the same resource and control, create a new one if not, and link back to the Security Hub finding.

eventbridge-to-jira.sh
# Create EventBridge rule for critical findings -> Jira
aws events put-rule \
  --name security-hub-critical-to-jira \
  --event-pattern '{
    "source": ["aws.securityhub"],
    "detail-type": ["Security Hub Findings - Imported"],
    "detail": {
      "findings": {
        "Severity": {"Label": ["CRITICAL"]},
        "Workflow": {"Status": ["NEW"]},
        "RecordState": ["ACTIVE"]
      }
    }
  }'

# Target: Step Functions state machine that creates Jira tickets
aws events put-targets \
  --rule security-hub-critical-to-jira \
  --targets '[{
    "Id": "JiraCreator",
    "Arn": "arn:aws:states:us-east-1:123456789012:stateMachine:CreateJiraTicket",
    "RoleArn": "arn:aws:iam::123456789012:role/EventBridgeToStepFunctionsRole"
  }]'

Insights and Custom Dashboards

Security Hub Insights are saved filter sets that group findings by specific criteria, giving you curated views into your security posture. You can use built-in insights or create custom ones tailored to your organization.

Built-In Insights

Security Hub ships with over 30 managed insights including:

  • AWS resources with the most findings
  • S3 buckets with public write or read access
  • AMIs with the most findings
  • EC2 instances involved in command and control activity
  • IAM users with suspicious activity
  • AWS accounts with the most critical findings

Custom Insights

custom-insights.sh
# Create an insight showing unresolved critical findings by account
aws securityhub create-insight \
  --name "Critical Findings by Account" \
  --filters '{
    "SeverityLabel": [{"Value": "CRITICAL", "Comparison": "EQUALS"}],
    "WorkflowStatus": [{"Value": "NEW", "Comparison": "EQUALS"}],
    "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}]
  }' \
  --group-by-attribute AwsAccountId

# Create an insight showing findings by service
aws securityhub create-insight \
  --name "Findings by AWS Service" \
  --filters '{
    "ComplianceStatus": [{"Value": "FAILED", "Comparison": "EQUALS"}],
    "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}]
  }' \
  --group-by-attribute ResourceType

# Create an insight tracking remediation SLA compliance
# (findings older than 7 days that are still NEW)
aws securityhub create-insight \
  --name "SLA Breached - Findings Older Than 7 Days" \
  --filters '{
    "SeverityLabel": [
      {"Value": "CRITICAL", "Comparison": "EQUALS"},
      {"Value": "HIGH", "Comparison": "EQUALS"}
    ],
    "WorkflowStatus": [{"Value": "NEW", "Comparison": "EQUALS"}],
    "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}],
    "CreatedAt": [{"DateRange": {"Value": 7, "Unit": "DAYS"}}]
  }' \
  --group-by-attribute AwsAccountId

Use Insights for Executive Reporting

Create custom insights that align with your executive reporting needs. A monthly security report should show: total findings by severity (trending down), security score by standard (trending up), top 5 accounts with the most findings, mean time to remediation by severity, and a list of consciously suppressed findings. Security Hub insights make this data easy to extract without custom tooling.

Advanced Configuration and Tuning

Out-of-the-box Security Hub works well for most organizations, but tuning it for your specific environment reduces noise and increases actionability.

Disabling Irrelevant Controls

Not every control is relevant to every organization. Disabling irrelevant controls reduces noise and improves your security score accuracy. Common controls to evaluate for disabling:

  • IAM.6 (Hardware MFA on root): If your organization uses virtual MFA for root and considers it acceptable risk.
  • EC2.8 (IMDSv2 required): Only if you have legacy applications that genuinely cannot use IMDSv2 (rare and should be temporary).
  • CloudTrail.5 (CloudTrail integration with CloudWatch Logs): If you use a third-party SIEM instead of CloudWatch for trail analysis.
disable-controls.sh
# Disable a specific control across all standards
aws securityhub update-standards-control \
  --standards-control-arn \
    "arn:aws:securityhub:us-east-1:123456789012:control/aws-foundational-security-best-practices/v/1.0.0/IAM.6" \
  --control-status DISABLED \
  --disabled-reason "Organization uses virtual MFA for root accounts as accepted risk"

# Bulk disable controls using a list
CONTROLS_TO_DISABLE=(
  "IAM.6"
  "CloudTrail.5"
)

SUBSCRIPTION_ARN="arn:aws:securityhub:us-east-1:123456789012:subscription/aws-foundational-security-best-practices/v/1.0.0"

for control in "${CONTROLS_TO_DISABLE[@]}"; do
  aws securityhub update-standards-control \
    --standards-control-arn "${SUBSCRIPTION_ARN}/${control}" \
    --control-status DISABLED \
    --disabled-reason "Disabled per security team review - $(date +%Y-%m-%d)"
done

Custom Actions for Manual Workflows

Custom actions create buttons in the Security Hub console that trigger EventBridge events. This lets security analysts take action directly from the findings dashboard without switching to other tools.

custom-actions.sh
# Create a custom action for "Send to Security Team"
aws securityhub create-action-target \
  --name "Send to Security Team" \
  --description "Escalate this finding to the security team Slack channel" \
  --id "SendToSecurityTeam"

# Create a custom action for "Create Jira Ticket"
aws securityhub create-action-target \
  --name "Create Jira Ticket" \
  --description "Create a Jira ticket for remediation tracking" \
  --id "CreateJiraTicket"

# Create EventBridge rule matching custom action events
aws events put-rule \
  --name security-hub-custom-action-escalate \
  --event-pattern '{
    "source": ["aws.securityhub"],
    "detail-type": ["Security Hub Findings - Custom Action"],
    "detail": {
      "actionName": ["SendToSecurityTeam"]
    }
  }'
AWS CloudFormation vs CDK

Security Hub with Container Workloads

Container workloads introduce unique security challenges that Security Hub addresses through integrations with Amazon Inspector (container image scanning), Amazon ECR (image vulnerability findings), and ECS/EKS security controls.

Container Image Scanning

Amazon Inspector automatically scans container images pushed to ECR for known vulnerabilities. These findings flow into Security Hub, where they can be triaged, tracked, and auto-remediated alongside infrastructure findings.

ecr-scanning-policy.sh
# Enable enhanced scanning on ECR (uses Amazon Inspector)
aws ecr put-registry-scanning-configuration \
  --scan-type ENHANCED \
  --rules '[
    {
      "scanFrequency": "CONTINUOUS_SCAN",
      "repositoryFilters": [
        {"filter": "*", "filterType": "WILDCARD"}
      ]
    }
  ]'

# Query Security Hub for container vulnerability findings
aws securityhub get-findings \
  --filters '{
    "ProductName": [{"Value": "Inspector", "Comparison": "EQUALS"}],
    "ResourceType": [{"Value": "AwsEcrContainerImage", "Comparison": "EQUALS"}],
    "SeverityLabel": [
      {"Value": "CRITICAL", "Comparison": "EQUALS"},
      {"Value": "HIGH", "Comparison": "EQUALS"}
    ],
    "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}]
  }' \
  --query 'Findings[*].{Title: Title, Image: Resources[0].Id, Severity: Severity.Label}' \
  --output table

ECS and EKS Security Controls

The FSBP standard includes controls specific to container services:

  • ECS.1: ECS task definitions should have a specific network mode (awsvpc)
  • ECS.2: ECS services should not have public IPs automatically assigned
  • ECS.3: ECS task definitions should not share the host process namespace
  • ECS.4: ECS containers should run as non-privileged
  • ECS.5: ECS containers should be limited to read-only root filesystems
  • ECS.8: Secrets should not be passed as container environment variables
  • ECS.10: ECS Fargate services should run on latest platform version
  • EKS.1: EKS cluster endpoints should not be publicly accessible
  • EKS.2: EKS clusters should run on a supported Kubernetes version
  • EKS.3: EKS clusters should use encrypted Kubernetes secrets
ECS vs EKS Decision Guide

Compliance Reporting and Auditing

Security Hub is a powerful tool for compliance reporting. Its built-in standards map directly to regulatory frameworks, and the findings data can be exported for auditors.

Exporting Findings for Auditors

export-compliance-report.sh
# Export all CIS findings for audit
aws securityhub get-findings \
  --filters '{
    "GeneratorId": [
      {"Value": "cis-aws-foundations-benchmark", "Comparison": "PREFIX"}
    ],
    "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}]
  }' \
  --max-items 1000 \
  --query 'Findings[*].{
    Control: GeneratorId,
    Title: Title,
    Status: Compliance.Status,
    Resource: Resources[0].Id,
    Account: AwsAccountId,
    Region: Region,
    FirstSeen: CreatedAt,
    LastSeen: UpdatedAt,
    WorkflowStatus: Workflow.Status
  }' \
  --output json > cis-audit-report.json

# Generate a summary of compliance by standard
aws securityhub get-enabled-standards \
  --query 'StandardsSubscriptions[*].{
    Standard: StandardsArn,
    Status: StandardsStatus
  }' --output table

# Count passed vs failed controls
echo "=== FSBP Compliance Summary ==="
echo -n "PASSED: "
aws securityhub get-findings --filters '{
  "GeneratorId": [{"Value": "security-control/", "Comparison": "PREFIX"}],
  "ComplianceStatus": [{"Value": "PASSED", "Comparison": "EQUALS"}],
  "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}]
}' --query 'length(Findings)' --output text

echo -n "FAILED: "
aws securityhub get-findings --filters '{
  "GeneratorId": [{"Value": "security-control/", "Comparison": "PREFIX"}],
  "ComplianceStatus": [{"Value": "FAILED", "Comparison": "EQUALS"}],
  "RecordState": [{"Value": "ACTIVE", "Comparison": "EQUALS"}]
}' --query 'length(Findings)' --output text

Continuous Compliance Monitoring

Security Hub's security score provides a continuous compliance metric. Configure CloudWatch alarms on the security score to detect regressions, and include the score in your operational dashboards alongside availability and performance metrics.

compliance-dashboard.sh
# Publish security score as a CloudWatch custom metric
# Run this as a scheduled Lambda function (every 6 hours)
import boto3

securityhub = boto3.client('securityhub')
cloudwatch = boto3.client('cloudwatch')

def publish_security_metrics():
    """Publish Security Hub metrics to CloudWatch for dashboarding."""

    # Count findings by severity
    for severity in ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']:
        findings = securityhub.get_findings(
            Filters={
                'SeverityLabel': [{'Value': severity, 'Comparison': 'EQUALS'}],
                'ComplianceStatus': [{'Value': 'FAILED', 'Comparison': 'EQUALS'}],
                'WorkflowStatus': [{'Value': 'NEW', 'Comparison': 'EQUALS'}],
                'RecordState': [{'Value': 'ACTIVE', 'Comparison': 'EQUALS'}]
            },
            MaxResults=1
        )

        cloudwatch.put_metric_data(
            Namespace='SecurityHub',
            MetricData=[{
                'MetricName': 'ActiveFindings',
                'Dimensions': [
                    {'Name': 'Severity', 'Value': severity}
                ],
                'Value': len(findings.get('Findings', [])),
                'Unit': 'Count'
            }]
        )

# Create CloudWatch alarm for critical finding spike
aws cloudwatch put-metric-alarm \
  --alarm-name security-hub-critical-spike \
  --metric-name ActiveFindings \
  --namespace SecurityHub \
  --dimensions Name=Severity,Value=CRITICAL \
  --statistic Maximum \
  --period 3600 \
  --threshold 5 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 1 \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:security-alerts

Compliance Is Not Security

A 100% security score on Security Hub does not mean your environment is secure. Security Hub checks for known misconfigurations and best practices, but it does not detect zero-day vulnerabilities, business logic flaws, insider threats, or application-level security issues. Use Security Hub as one layer in a defense-in-depth strategy that includes GuardDuty for threat detection, Inspector for vulnerability management, penetration testing, and security code reviews.

AWS Cost Optimization Strategies

Terraform Configuration for Security Hub

Deploying Security Hub via infrastructure as code ensures consistent configuration across accounts and enables version-controlled changes. Here is a comprehensive Terraform module for Security Hub deployment.

security-hub.tf
# Enable Security Hub
resource "aws_securityhub_account" "main" {}

# Enable FSBP standard
resource "aws_securityhub_standards_subscription" "fsbp" {
  standards_arn = "arn:aws:securityhub:${data.aws_region.current.name}::standards/aws-foundational-security-best-practices/v/1.0.0"
  depends_on    = [aws_securityhub_account.main]
}

# Enable CIS standard
resource "aws_securityhub_standards_subscription" "cis" {
  standards_arn = "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0"
  depends_on    = [aws_securityhub_account.main]
}

# Disable specific controls that are not applicable
resource "aws_securityhub_standards_control" "iam6_disable" {
  standards_control_arn = "${aws_securityhub_standards_subscription.fsbp.id}/IAM.6"
  control_status        = "DISABLED"
  disabled_reason       = "Organization uses virtual MFA for root accounts"
  depends_on            = [aws_securityhub_standards_subscription.fsbp]
}

# Enable product integrations
resource "aws_securityhub_product_subscription" "guardduty" {
  product_arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty"
  depends_on  = [aws_securityhub_account.main]
}

resource "aws_securityhub_product_subscription" "inspector" {
  product_arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/inspector"
  depends_on  = [aws_securityhub_account.main]
}

resource "aws_securityhub_product_subscription" "access_analyzer" {
  product_arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/access-analyzer"
  depends_on  = [aws_securityhub_account.main]
}

resource "aws_securityhub_product_subscription" "macie" {
  product_arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/macie"
  depends_on  = [aws_securityhub_account.main]
}

# Cross-region finding aggregation
resource "aws_securityhub_finding_aggregator" "main" {
  linking_mode = "ALL_REGIONS"
  depends_on   = [aws_securityhub_account.main]
}

# EventBridge rule for critical findings
resource "aws_cloudwatch_event_rule" "critical_findings" {
  name        = "security-hub-critical-findings"
  description = "Capture critical Security Hub findings"

  event_pattern = jsonencode({
    source      = ["aws.securityhub"]
    detail-type = ["Security Hub Findings - Imported"]
    detail = {
      findings = {
        Severity    = { Label = ["CRITICAL"] }
        Workflow    = { Status = ["NEW"] }
        RecordState = ["ACTIVE"]
      }
    }
  })
}

resource "aws_cloudwatch_event_target" "critical_to_sns" {
  rule      = aws_cloudwatch_event_rule.critical_findings.name
  target_id = "SendToSNS"
  arn       = aws_sns_topic.security_alerts.arn
}

# SNS topic for security alerts
resource "aws_sns_topic" "security_alerts" {
  name              = "security-hub-alerts"
  kms_master_key_id = aws_kms_key.security.id
}

data "aws_region" "current" {}
AWS CloudFormation vs CDK

Best Practices and Operational Maturity

Effective use of Security Hub evolves through maturity stages. Most organizations start at Level 1 (basic enablement) and should aim to reach Level 3 (automated governance) within 6-12 months.

Security Hub Maturity Model

LevelStageCharacteristics
Level 1Basic EnablementSecurity Hub enabled with FSBP, findings visible but not triaged regularly, no automation
Level 2Active ManagementWeekly triage meetings, Slack/email notifications for critical findings, manual remediation with tracking
Level 3Automated GovernanceAuto-remediation for low-risk findings, Jira integration for tracking, SLA enforcement, security score in dashboards
Level 4Proactive SecurityPreventive controls via SCPs and Config rules, shift-left scanning in CI/CD, security score gates on deployments

Operational Best Practices

  • Suppress known acceptable findings: Use automation rules or manual suppression to hide findings you have consciously accepted (e.g., a public S3 bucket serving a static website). Document the reason for every suppression.
  • Track your security score weekly: Monitor the overall compliance percentage and set improvement targets per quarter. A score below 80% requires immediate attention; aim for 95%+ as a mature target.
  • Define remediation SLAs by severity: CRITICAL: 24 hours. HIGH: 7 days. MEDIUM: 30 days. LOW: 90 days. Track SLA compliance using custom insights.
  • Integrate with your ticketing system: Every HIGH and CRITICAL finding should have a corresponding ticket with an owner and due date. Use EventBridge to automate ticket creation.
  • Use custom actions for analyst workflows: Create buttons in the Security Hub console that trigger specific actions (escalate to on-call, create Jira ticket, suppress with justification).
  • Prevent disabling: Use SCPs to prevent anyone from disabling Security Hub, GuardDuty, or other security services.
  • Review suppressed findings quarterly: Risk acceptances should be time-limited. Review all suppressed findings quarterly to ensure they are still valid.
  • Shift left with preventive controls: The best finding is one that never occurs. Use SCPs to prevent misconfiguration, Config rules to detect drift immediately, and CI/CD scanning to catch issues before deployment.

Security Score as an OKR

Include your Security Hub security score as a team-level OKR or KPI. This creates organizational accountability for security posture and ensures findings are not ignored. Example OKR: “Achieve and maintain 95%+ security score on FSBP standard across all production accounts by end of Q2.” Track progress weekly and report monthly to leadership.

AWS Well-Architected Overview

Summary and Getting Started

AWS Security Hub is the foundational service for cloud security posture management on AWS. It transforms scattered security findings into a unified, actionable view with automated checks against industry standards. Here is how to get started:

  • Day 1: Enable Security Hub in all accounts and all regions with the FSBP standard. Designate a delegated administrator account. Enable GuardDuty and Inspector integrations.
  • Week 1: Review the initial findings. Suppress known acceptable configurations. Identify the top 10 critical findings and assign owners.
  • Month 1: Establish weekly triage meetings. Configure Slack notifications for critical findings. Begin auto-remediating low-risk S3 and encryption findings. Track your security score.
  • Quarter 1: Expand auto-remediation to more finding types. Integrate with Jira for remediation tracking. Define and enforce remediation SLAs. Add CIS standard if needed for compliance.
  • Ongoing: Review suppressed findings quarterly. Tune disabled controls as your environment evolves. Shift left with preventive SCPs and CI/CD scanning. Report security score trends to leadership monthly.

Key Takeaways

Enable Security Hub in all accounts and all regions; the cost is negligible. Start with the AWS Foundational Security Best Practices standard. Aggregate findings in a delegated administrator account. Integrate with GuardDuty, Inspector, and Config for comprehensive coverage. Establish a weekly triage cadence. Automate remediation for well-understood, low-risk issues. Define and enforce remediation SLAs. Security Hub is the central nervous system of your AWS security program. Invest in operating it well, and it will pay for itself many times over.

AWS S3 Storage ClassesAWS VPC Architecture PatternsAWS Route 53 DNS Patterns

Key Takeaways

  1. 1Security Hub aggregates findings from GuardDuty, Inspector, Macie, Firewall Manager, and third-party tools.
  2. 2AWS Foundational Security Best Practices standard provides automated compliance checks.
  3. 3CIS AWS Foundations Benchmark checks cover critical security configurations.
  4. 4Enable Security Hub across all accounts and regions via AWS Organizations.
  5. 5Automated remediation with EventBridge and Lambda reduces mean time to respond.
  6. 6Custom actions and insights help prioritize findings by severity and resource type.

Frequently Asked Questions

What is AWS Security Hub?
Security Hub is a cloud security posture management service that aggregates security findings from AWS services (GuardDuty, Inspector, Macie) and third-party tools into a single dashboard. It runs automated compliance checks against industry standards.
How much does Security Hub cost?
Security Hub charges per security check and per finding ingested. The first 10,000 findings per account per region per month are included in the check pricing. Typical costs are $1-5/month for small accounts and scale with the number of resources.
What compliance standards does Security Hub support?
Built-in standards include AWS Foundational Security Best Practices, CIS AWS Foundations Benchmark (v1.2, v1.4, v3.0), PCI DSS v3.2.1, and NIST 800-53 Rev 5. Each standard runs automated checks against your resources.
How do I set up automated remediation with Security Hub?
Create EventBridge rules that match Security Hub finding events. Trigger Lambda functions or Systems Manager Automation documents to remediate issues automatically. Common automations include enabling encryption, closing public ports, and revoking unused credentials.
Should I enable Security Hub in all regions?
Yes. Enable Security Hub in all regions, even those you do not actively use. An attacker could create resources in an unused region. Use Organizations integration to enable it automatically across all accounts.

Written by CloudToolStack Team

Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.

Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.