At a glance

VendorAmazon Web Services — Security Hub (primary) + GuardDuty, IAM, S3, EC2, CloudTrail
Source typecloud
Vendor ID (slug)aws-security-hub
Base URLRegional AWS endpoint, e.g. https://securityhub.us-east-1.amazonaws.com. Draxis parses the region from the hostname.
Auth methodIAM access key pair. The Draxis integration form shows this as "Client ID" / "Client Secret" (OAuth-style) — map them to AWS Access Key ID and Secret Access Key respectively. Secret is encrypted server-side with encryption.key before storage.
Schedule defaultdaily — the KRIs with time windows (GuardDuty 7d, root usage 7d) self-reset each run.
Regional scopeSecurity Hub, GuardDuty, and Security Groups: home region only by default. IAM and S3: global (any region works). CloudTrail logging gaps: all enabled regions, via DescribeRegions. For cross-region Security Hub / GuardDuty coverage, enable the Security Hub aggregator — see Quirks.
AvailabilityNew in 2026.04.

Required scopes & roles

Draxis authenticates as a dedicated IAM user with access-key credentials. Attach one of these policies:

  • Simplest — AWS managed policy arn:aws:iam::aws:policy/SecurityAudit. Broad read-only coverage across security-relevant services. Recommended if you don't need a tighter audit trail.
  • Least-privilege — a custom policy with exactly the Read/Describe/List/Get actions the connector calls. Snippet below; attach via IAM → Policies → Create policy → JSON, then assign to the Draxis user.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DraxisAwsSecurityRead",
      "Effect": "Allow",
      "Action": [
        "sts:GetCallerIdentity",

        "securityhub:GetFindings",

        "guardduty:ListDetectors",
        "guardduty:ListFindings",

        "s3:ListAllMyBuckets",
        "s3:GetBucketPolicyStatus",

        "iam:ListUsers",
        "iam:ListAccessKeys",

        "ec2:DescribeSecurityGroups",
        "ec2:DescribeRegions",

        "cloudtrail:DescribeTrails",
        "cloudtrail:GetTrailStatus",
        "cloudtrail:LookupEvents"
      ],
      "Resource": "*"
    }
  ]
}

All Read, List, Describe, or Get verbs. Do not grant any Put, Update, Delete, or Create action. Do not use the ReadOnlyAccess managed policy unless you specifically want broader coverage — SecurityAudit is already the read-only policy scoped to security services.

Setup steps

  1. Decide on your home region. This is the region Draxis will query for Security Hub, GuardDuty, and Security Groups findings. If you only operate in one region, pick it. If you're multi-region, pick the region where your Security Hub aggregator lives (or create one — see Quirks). The region string goes into the API Base URL in step 5.
  2. Create a dedicated IAM user. In the AWS console, IAM → Users → Create user. Name it draxis-connector. Do not enable console access — programmatic access only. Skip group membership; we'll attach the policy directly.
  3. Attach the IAM policy. Either attach the AWS managed policy SecurityAudit (simplest) or create a custom policy from the JSON above (least-privilege) and attach it. On the user's Permissions tab, click Add permissions → Attach policies directly.
  4. Create an access key. On the user's Security credentials tab, click Create access key. Use case: Third-party service. AWS will show the Access Key ID and Secret Access Key once — copy both into your password manager immediately. The secret cannot be retrieved later; if you lose it, rotate the key and create a new one.
  5. Build your regional API Base URL. Use the format https://securityhub.<region>.amazonaws.com — substitute your home region (e.g. us-east-1, eu-west-2, ap-southeast-1). Draxis parses the region from the hostname so the connector can route per-service calls correctly.
  6. (Recommended) Enable Security Hub and GuardDuty in your home region if you haven't already. Security Hub: Services → Security Hub → Enable. GuardDuty: Services → GuardDuty → Get started. These are the sources behind the two headline KRIs; without them, those KRIs report 0.
  7. (Optional) Enable the Security Hub cross-region aggregator for single-pane-of-glass findings. In Security Hub: Settings → Region aggregation → Configure. Pick your home region as the aggregation region and all linked regions you want covered. Findings from every linked region then appear when Draxis queries Security Hub in the home region — no connector changes needed.

Wire it into Draxis

  1. Open Settings → Integrations in your tenant.
  2. Click Add integration and pick Cloud Security as the source type.
  3. Pick AWS Security Hub + GuardDuty from the vendor dropdown. Draxis auto-fills the default US-1 base URL, the OAuth auth method, and the daily schedule.
  4. In API Base URL, replace the region with yours from step 5 of the setup (e.g. https://securityhub.eu-west-2.amazonaws.com).
  5. In Client ID, paste the AWS Access Key ID (starts with AKIA).
  6. In Client Secret, paste the AWS Secret Access Key. Draxis encrypts it server-side before storage.
  7. Click Test. Green means Draxis called sts:GetCallerIdentity successfully — the message includes the AWS account ID and the IAM principal ARN so you can verify the right user is wired up.
  8. Under KRIs to import, tick the KRIs you want Draxis to manage. All seven aws_* KRIs are checked by default; uncheck any you don’t need (for instance, drop the GuardDuty KRI if GuardDuty isn't enabled — the connector would just report 0 but a zero could be mistaken for a clean posture). Selected rows are created on save with the seeded thresholds. Unchecking a previously-imported KRI deletes it on save.
  9. Save. The connector runs daily by default; use Run now from run history to trigger the first sync immediately.

KRIs produced

SlugMeaningDerivation
aws_security_hub_critical_high_open Security Hub findings at CRITICAL or HIGH severity that are still open GetFindings with filter SeverityLabel in ('CRITICAL','HIGH') and WorkflowStatus in ('NEW','NOTIFIED') and RecordState='ACTIVE', paginated & summed (cap 50 pages).
aws_guardduty_high_severity_7d GuardDuty findings at severity ≥ 7.0 updated in the last 7 days ListDetectors then per-detector ListFindings with severity.Gte=7.0 and updatedAt.Gte=<now-7d>, summed.
aws_s3_public_buckets S3 buckets AWS considers publicly accessible via bucket policy ListBuckets → per-bucket GetBucketPolicyStatus; count buckets where PolicyStatus.IsPublic === true. Buckets with no policy (NoSuchBucketPolicy) are not counted.
aws_iam_access_keys_gt_90d Active IAM access keys whose CreateDate is older than 90 days ListUsers → per-user ListAccessKeys; count keys where Status='Active' and CreateDate < now-90d.
aws_root_account_usage_7d CloudTrail events in the last 7 days performed by the Root user LookupEvents with LookupAttributes: [{ AttributeKey: 'Username', AttributeValue: 'Root' }] and StartTime=<now-7d>.
aws_security_groups_open_to_world Security group rules allowing 0.0.0.0/0 (or ::/0) on sensitive TCP ports DescribeSecurityGroups; count rules where IpRanges contains 0.0.0.0/0 (or Ipv6Ranges ::/0) AND the port range overlaps {22, 3389, 445, 135, 1433, 3306, 5432, 27017, 6379, 9200, 9300, 5984, 11211, 2375, 10250} OR the rule is all-ports / protocol=-1. 80/443/21 are explicitly excluded — legitimately public.
aws_cloudtrail_logging_gaps Enabled AWS regions without any active CloudTrail trail If ≥1 active multi-region trail exists, returns 0. Otherwise: DescribeRegions + per-region DescribeTrails + GetTrailStatus; count of regions with no trail where IsLogging=true.

Each row is a slug the connector writes to. Draxis creates the matching kri rows automatically when you check them in the KRIs to import section of the integration form — no manual API call or seed script needed. Thresholds shown in the table are the seeded defaults; you can edit them freely in the KRIs tab afterwards.

Vendor quirks

  • "Client ID" and "Client Secret" are reused for AWS access keys. The Draxis form reuses the OAuth2 two-field shape (Client ID / Client Secret) because the underlying storage encrypts the second field correctly. For AWS integrations, map them to Access Key ID and Secret Access Key. The UI labels are a known mismatch — the pill under the header reads IAM access key (via oauth2 form) to remind you.
  • Region is parsed from the API Base URL. Whatever service you put in the hostname, Draxis extracts the middle component as the region (securityhub.us-east-1.amazonaws.comus-east-1). Using sts.<region>.amazonaws.com works equally well. What matters is getting the region right — a wrong region fails Test with a credential or connectivity error.
  • Security Hub, GuardDuty, and Security Groups are queried in the home region only. For multi-region coverage without code changes: enable the Security Hub region aggregator (see step 7 of Setup). GuardDuty has a similar cross-account delegated-admin model — run it from your home region's delegated admin account and its findings surface to that region's API.
  • Root-account detection requires CloudTrail logging in the home region. LookupEvents returns events from the region it's called in. If your CloudTrail trail is multi-region and writes to the home region, you see root events from any region. If you only have regional trails, the KRI misses root activity outside the home region — a gap your own aws_cloudtrail_logging_gaps KRI will surface.
  • Security-group scanning is sensitive-port gated. A rule opening TCP 443 to 0.0.0.0/0 is almost always intentional; we don't count it. A rule opening TCP 22 or 3389 to 0.0.0.0/0 almost never is. The port set is hardcoded in the connector (see KRIs produced row for the list); request changes via a support ticket if your environment has service-specific ports to add.
  • S3 public-access detection is bucket-policy-based. The KRI counts buckets whose BucketPolicyStatus.IsPublic=true — AWS's own determination of public access from the policy. Buckets made public via ACL-only permissions, or via a permissive account-level Public Access Block, aren't necessarily caught. For the strongest coverage, enable Block Public Access at the account level and let Security Hub control S3.1/S3.8 surface any residual public buckets — those show up in the aws_security_hub_critical_high_open KRI.
  • IAM key age check iterates all users. Capped at 2000 users (20 pages × 100). Orgs with more than 2000 IAM users should either slim the user list (most shouldn't have human IAM users at all — use SSO + roles) or open a support ticket for a bigger cap.
  • CloudTrail logging-gap computation can be slow. Without a multi-region trail, the connector enumerates every enabled region and probes trails in each — 17+ API calls just for this one KRI. Enable a multi-region trail (CloudTrail → Trails → Create → Multi-region) and the KRI drops to a single call and reports 0 gaps.
  • Access key rotation. AWS best practice is quarterly. When rotating, create the new key on the same IAM user, update Draxis, then deactivate (not delete) the old key for 24h to confirm nothing breaks, then delete it. This prevents a race where the runner uses the old key after you've already rotated.
  • No Role-based (STS assume-role) auth in Phase 1. Static access keys only. An OIDC-backed assume-role flow is on the roadmap — if you're security-averse to long-lived access keys, open a feature request.

Troubleshooting

  • Test returns InvalidClientTokenId — the access key is wrong, deleted, or inactive. Mint a new key on the IAM user and update Draxis.
  • Test returns SignatureDoesNotMatch — the secret access key has a copy-paste error (usually a leading/trailing space or a truncated value). Mint a new key and paste carefully.
  • Test returns AccessDenied on sts:GetCallerIdentity — extremely unusual; this action is generally unrestricted. Check whether your account has an SCP (AWS Organizations Service Control Policy) blocking the Draxis user.
  • A specific KRI is 0 but shouldn't be — check the run log (Run history → Details). Per-KRI errors are logged as aws.kri failed with the error name. Common causes:
    • AccessDenied → the IAM policy is missing that service's Read/Describe action. Compare with the least-privilege policy above.
    • BadRequestException on securityhub:GetFindings → Security Hub isn't enabled in the home region.
    • BadRequestException on guardduty:ListDetectors → GuardDuty isn't enabled, or the IAM user lacks GuardDuty permissions.
  • aws_s3_public_buckets warns "s3.policy_status skipped" a lot — some buckets live in regions other than your home region, and cross-region introspection can fail with AccessDenied even though ListBuckets works. The KRI still reports counts for the buckets it could check; the warn log tells you which ones were skipped.
  • aws_cloudtrail_logging_gaps = (most regions) — you likely have only regional trails, or no trail at all. Create a multi-region trail in the CloudTrail console; the KRI collapses to 0 on the next run.
  • rowsSkipped > 0 and rowsWritten = 0 — your tenant hasn't imported any KRIs for this integration yet. Open the integration in Settings → Integrations, tick the KRIs under KRIs to import, and save.
  • Still stuck? Open a support ticket with the run ID (from Run history) and we'll dig in.