AccessGuard: Setup Guide
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)
- A Lambda function runs on a schedule (default: every 5 minutes).
- 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
).
- 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).
- Creates/updates an SCP named
- Optional exceptions:
BypassPrincipalArns
(comma‑separated ARNs/patterns)BypassTagKey
+BypassTagValue
- Optional workload toggle:
AllowAwsServices=true
ensures AWS services aren’t blocked by lack of SourceIp context.
- 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 provideTargetOuId
.FraudGuardUser
/FraudGuardPass
— Basic Auth for FraudGuard whitelist API.
Common Optional
TargetOuId
— Attach SCP to a specific OU instead of Root.PolicyName
— Defaults toAccessGuard-WhitelistOnly
.
Whitelist & Pagination
WhitelistApiBase
— Base URL (https://api.fraudguard.io/whitelist
). Lambda appends/<offset>
.PageOffsetStep
— Pagination step (default1000
).MaxPages
— Safety ceiling on pages (default100
).MaxCidrs
— Cap CIDRs in the SCP (default10000
) 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
).Mode
—DryRun
(preview) orEnforce
(apply).
4) Testing Enforcement
Important: SCPs do not apply to the management account. Test with a member account.
- Assume a role into a member account (console “Switch Role” or
aws sts assume-role
).- SCPs apply to assumed roles in member accounts.
- 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
- 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
- Period:
- 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.
- Confirm the SNS subscription. Alarms notify on state change only. Force a flip (set
- “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
andAlarmEmail
set; confirm SNS email - (Optional) Apply “2 of 3 @ 60s” tuning CLI
- Set
- 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.