AccessGuard is a fully automated IAM control system that syncs your FraudGuard.io real-time IP whitelist into your AWS Organizations Service Control Policy (SCP). It enforces a simple, powerful SCP rule across your entire AWS Organization: only requests from trusted, explicitly whitelisted IPs are allowed. Everything else involving human interaction with your AWS Organization is denied — protecting your cloud from stolen laptops, leaked credentials, or coffee-shop hackers.

Highlights

  • Whitelist‑Only IAM Access — deny by default; allow only your corporate VPNs, secure egress proxies, and other owned IPs/CIDRs.
  • Org‑wide Enforcement — attach at the Root OU to cover every member account consistently. This policy applies equally to AWS Management Console logins, AWS CLI usage, and API requests, ensuring that all human access is gated by trusted IPs.
  • Automated Sync — A Lambda living in your own AWS account fetches FraudGuard’s whitelist and updates the SCP on a schedule.
  • Safe by Design — SCPs do not apply to the Organizations management account. You always have a way back in should anything go wrong.
  • No Agents. No Proxies. — Deployed with CloudFormation, runs entirely in your AWS. All logic is executed entirely within the customer’s AWS environment — FraudGuard does not store or process any customer data, aside from the customer-managed whitelist itself.
  • Practical Exceptions — optional easy BypassPrincipalArns and BypassTagKey/Value options for break‑glass access.
  • Workload‑Safe Toggle — optional AllowAwsServices=true keeps AWS service principals running.

0) Prerequisites

  • An AWS Organization where you are signed in to the management account.
  • SCPs enabled in your Organization (one‑time):
    • Console: AWS Organizations → Policies → Service control policies → Enable
    • CLI:
      aws organizations enable-policy-type --root-id r-xxxx --policy-type SERVICE_CONTROL_POLICY
      
  • Your FraudGuard.io API credentials with access to the whitelist API. 👉 AccessGuard CloudFormation Template

🔐 Safety net: SCPs never apply to the management account. Even if your IP isn’t whitelisted, you cannot lock yourself out of the management account.


1) How AccessGuard Works (Architecture)

  1. A Lambda function runs on a schedule (default: every 5 minutes).
  2. It fetches your FraudGuard whitelist via the paginated endpoint:
    • https://api.fraudguard.io/whitelist/<offset> (defaults: PageOffsetStep=1000, MaxPages=100)
    • IPv4/IPv6 and bare IPs are normalized to CIDRs (/32 and /128).
  3. The function rebuilds the SCP from the current whitelist and:
    • Creates/updates an SCP named AccessGuard-WhitelistOnly (configurable).
    • Attaches it to your Root OU (or a specific OU if you prefer).
  4. Optional exceptions:
    • BypassPrincipalArns (comma‑separated ARNs/patterns)
    • BypassTagKey + BypassTagValue
  5. Optional workload toggle:
    • AllowAwsServices=true ensures AWS services aren’t blocked by lack of SourceIp context.
  6. Optional monitoring:
    • A CloudWatch Logs Metric Filter counts SCP denials from CloudTrail logs.
    • An optional CloudWatch Alarm notifies via SNS email when denial volume crosses a threshold.

2) Quick Start (DryRun → Enforce)

A. Deploy in DryRun (safe preview — no Org changes)

aws cloudformation deploy \
  --stack-name accessguard \
  --template-file ./accessguard.yml \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameter-overrides \
    OrgRootId=r-xxxx \
    FraudGuardUser='YOUR_USER' \
    FraudGuardPass='YOUR_PASS' \
    WhitelistApiBase='https://api.fraudguard.io/whitelist' \
    AllowAwsServices=true \
    Mode='DryRun'

👉 AccessGuard CloudFormation Template

Invoke once and inspect logs:

FN=$(aws cloudformation describe-stacks --stack-name accessguard \
  --query "Stacks[0].Outputs[?OutputKey=='FunctionName'].OutputValue" --output text)

aws lambda invoke --function-name "$FN" /tmp/out.json >/dev/null && cat /tmp/out.json
aws logs tail "/aws/lambda/$FN" --follow

You’ll see "mode":"DryRun" plus the exact SCP JSON that would be enforced.

B. Flip to Enforce

aws cloudformation deploy \
  --stack-name accessguard \
  --template-file ./accessguard.yml \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameter-overrides \
    OrgRootId=r-xxxx \
    FraudGuardUser='YOUR_USER' \
    FraudGuardPass='YOUR_PASS' \
    WhitelistApiBase='https://api.fraudguard.io/whitelist' \
    AllowAwsServices=true \
    Mode='Enforce'

👉 AccessGuard CloudFormation Template

Verify the SCP exists and is attached to your Root (or target OU):

aws organizations list-policies-for-target --target-id r-xxxx --filter SERVICE_CONTROL_POLICY
aws organizations describe-policy --policy-id <PolicyIdFromList> --query 'Policy.Content' --output text

3) Parameter Reference

Required

  • OrgRootId — Root OU ID (e.g., r-2zjz). Used if you don’t provide TargetOuId.
  • FraudGuardUser / FraudGuardPass — Basic Auth for FraudGuard whitelist API.

Common Optional

  • TargetOuId — Attach SCP to a specific OU instead of Root.
  • PolicyName — Defaults to AccessGuard-WhitelistOnly.

Whitelist & Pagination

  • WhitelistApiBase — Base URL (https://api.fraudguard.io/whitelist). Lambda appends /<offset>.
  • PageOffsetStep — Pagination step (default 1000).
  • MaxPages — Safety ceiling on pages (default 100).
  • MaxCidrs — Cap CIDRs in the SCP (default 10000) to respect AWS policy size limits.

Exceptions & Toggle

  • AllowAwsServices"true" (default) keeps AWS service principals operating. Set to "false" only for absolute lockdown.
  • BypassPrincipalArns — Comma‑separated ARNs/patterns for break‑glass access:
    arn:aws:iam::123456789012:role/Admin,arn:aws:iam::*:role/SRE-*
    
  • BypassTagKey + BypassTagValue — Tag a principal to bypass (e.g., AccessGuardBypass=true).

Monitoring

  • CloudTrailLogGroupName — Name of the CloudTrail log group in CloudWatch Logs (e.g., /aws/cloudtrail/your-trail). If empty, metrics/alarms aren’t created.
  • CreateSCPDeniedAlarm"true" to create an alarm on SCP denials.
  • AlarmEmail — Email for SNS subscription (confirm via email after deploy).

Ops Defaults

  • ScheduleExpression — Sync cadence (default: rate(5 minutes)).
  • LogRetentionDays — CloudWatch Logs retention (default: 14).
  • ModeDryRun (preview) or Enforce (apply).

4) Testing Enforcement

Important: SCPs do not apply to the management account. Test with a member account.

  1. Assume a role into a member account (console “Switch Role” or aws sts assume-role).
    • SCPs apply to assumed roles in member accounts.
  2. From a non‑whitelisted IP, run:
    aws ec2 describe-instances
    

    Expect an error like:

    ... is not authorized to perform: ec2:DescribeInstances with an explicit deny in a service control policy
    
  3. From a whitelisted IP, the same call should succeed.

Removing an IP from FraudGuard? The next sync rebuilds the SCP, so removed IPs are automatically dropped.


5) Monitoring & Alerting

A) Metric + Alarm (built into the template)

If you set CloudTrailLogGroupName, the stack creates a metric filter that counts SCP denials:

  • FilterPattern
    { ($.errorCode = "AccessDenied") && ($.errorMessage = "*explicit deny in a service control policy*") }
    
  • Metric: AccessGuard/Org :: SCPDeniedCount (Sum per period)

Optional alarm (when CreateSCPDeniedAlarm=true):

  • Default tuning (recommended): “2 of 3 @ 60s”
    • Period: 60s
    • EvaluationPeriods: 3
    • DatapointsToAlarm: 2
    • Threshold: 1 (Sum)
    • TreatMissingData: notBreaching
    • Actions: SNS email on ALARM and OK
  • Confirm the email subscription sent by SNS after deploy.

CLI to (re)apply this tuning

TOPIC_ARN=$(aws sns list-topics --query "Topics[?ends_with(TopicArn,'accessguard-scp-denied')].TopicArn" --output text)

aws cloudwatch put-metric-alarm \
  --alarm-name accessguard-scp-denied \
  --alarm-description "AccessGuard SCP denials >=1 in 2 of 3 minutes" \
  --namespace "AccessGuard/Org" --metric-name SCPDeniedCount \
  --statistic Sum --period 60 \
  --evaluation-periods 3 --datapoints-to-alarm 2 \
  --threshold 1 --comparison-operator GreaterThanOrEqualToThreshold \
  --treat-missing-data notBreaching --actions-enabled \
  --alarm-actions "$TOPIC_ARN" --ok-actions "$TOPIC_ARN"

CloudWatch emails only on state changes (OK→ALARM, ALARM→OK). If you confirmed SNS while the alarm was already ALARM, you will not get an email until it flips state again.

B) CloudWatch Logs Insights — ready‑to‑use queries

Ad‑hoc SCP denial search

fields @timestamp,
       recipientAccountId,
       userIdentity.arn as principal_arn,
       sourceIPAddress,
       eventSource,
       eventName,
       errorMessage
| filter errorCode = "AccessDenied"
| filter errorMessage like /explicit deny in a service control policy/
| sort @timestamp desc
| limit 200

Top blocked principals

fields userIdentity.arn
| filter errorCode = "AccessDenied"
| filter errorMessage like /explicit deny in a service control policy/
| stats count() as scp_denies by userIdentity.arn
| sort scp_denies desc
| limit 20

C) CloudTrail Lake (no log group needed)

SELECT eventTime, eventSource, eventName, userIdentity.arn, sourceIPAddress, errorMessage
FROM $EDS_ID
WHERE errorCode = 'AccessDenied'
  AND errorMessage LIKE '%explicit deny in a service control policy%'
ORDER BY eventTime DESC
LIMIT 200;

6) Troubleshooting

  • No events?
    • Make sure CloudTrail is enabled in the right region and (ideally) as an organization trail so member accounts are captured.
  • No email?
    • Confirm the SNS subscription. Alarms notify on state change only. Force a flip (set 1 of 1 temporarily) to test.
  • “It applies to my console?”
    • Yes — SCPs evaluate both console and CLI/API actions in member accounts.
    • Management account remains exempt.

7) Rollback / Safety

  • Detach only (keep policy for later):
    aws organizations detach-policy --policy-id <PolicyId> --target-id r-xxxx
    
  • Delete policy:
    aws organizations delete-policy --policy-id <PolicyId>
    
  • Remove the stack:
    aws cloudformation delete-stack --stack-name accessguard
    
  • Pause enforcement without teardown: redeploy with Mode=DryRun.

8) FAQ

Q: Will new accounts be protected automatically?
A: Yes, if you attach at the Root OU. New member accounts inherit the SCP.

Q: Can I exempt a specific admin role?
A: Yes. Add its ARN to BypassPrincipalArns, or tag it with BypassTagKey/BypassTagValue.

Q: Can I lock down AWS services too?
A: Set AllowAwsServices=false. Be careful — some service‑initiated calls may fail if they lack a Source IP.

Q: What about huge whitelists?
A: AccessGuard paginates with /<offset> (configurable) and caps entries with MaxCidrs. It also deduplicates and supports IPv4 & IPv6.

Q: How fast do changes take effect?
A: On the next scheduled run (default 5 minutes) or when you manually invoke the Lambda.


9) Launch Checklist (copy/paste)

  • Enable SCPs in AWS Organizations (one‑time).
  • Deploy** the stack in DryRun; verify logs show the SCP preview.
  • Flip to Enforce; confirm policy is attached at Root (or target OU).
  • Test from a member account:
    • Non‑whitelisted IP → explicit SCP deny
    • Whitelisted IP → allowed
  • Monitoring:
    • Set CloudTrailLogGroupName (if using Logs‑based metric)
    • (Optional) CreateSCPDeniedAlarm=true and AlarmEmail set; confirm SNS email
    • (Optional) Apply “2 of 3 @ 60s” tuning CLI
  • Docs & Runbook:
    • Record your whitelist owners and review cadence
    • Keep a management account recovery path in your SOP

That’s it — AccessGuard is live and available today with a FraudGuard.io Professional plan starting at $99/month. If you have questions or want help reviewing your SCP preview before enforcement, reach out to the team at hello@fraudguard.io.