A configuration package to deploy common Service Control Policies (SCPs) in the master account of an AWS Organization. The package includes common SCPs to protect security and logging services (CloudTrail, GuardDuty, Config, CloudWatch, VPC Flow Logs), network connectivity settings, S3 and EC2 security measures, and more.
See full SCP Repository to browse individual SCP policies.
AWSTemplateFormatVersion: '2010-09-09'
Description: ''
Resources:
ScpPolicy1:
Type: 'Custom::ServiceControlPolicy'
Properties:
PolicyName: scp_root_account
PolicyDescription: >-
This SCP prevents restricts the root user in an AWS account from taking
any action, either directly as a command or through the console.
PolicyContents: >-
{"Version":"2012-10-17","Statement":[{"Action":"*","Resource":"*","Effect":"Deny","Condition":{"StringLike":{"aws:PrincipalArn":["arn:aws:iam::*:root"]}}}]}
ServiceToken:
'Fn::GetAtt':
- ScpResourceLambda
- Arn
ScpResourceLambdaRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
Policies:
- PolicyName: scp-access
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 'organizations:UpdatePolicy'
- 'organizations:DeletePolicy'
- 'organizations:CreatePolicy'
- 'organizations:ListPolicies'
Resource: '*'
ScpResourceLambda:
Type: 'AWS::Lambda::Function'
Properties:
Code:
ZipFile: |-
'use strict';
const AWS = require('aws-sdk');
const response = require('cfn-response');
const organizations = new AWS.Organizations({region: 'us-east-1'});
exports.handler = (event, context, cb) => {
console.log('Invoke:', JSON.stringify(event));
const done = (err, data) => {
if (err) {
console.log('Error: ', err);
response.send(event, context, response.FAILED, {}, 'CustomResourcePhysicalID');
} else {
response.send(event, context, response.SUCCESS, {}, 'CustomResourcePhysicalID');
}
};
const updatePolicies = (policyName, policyAction) => {
organizations.listPolicies({
Filter: "SERVICE_CONTROL_POLICY"
}, function(err, data){
if (err) done(err);
else {
const policy = data.Policies.filter((policy) => (policy.Name === policyName))
let policyId = ''
if (policy.length > 0)
policyId = policy[0].Id
else
done('policy not found')
if (policyAction === 'Update'){
organizations.updatePolicy({
Content: event.ResourceProperties.PolicyContents,
PolicyId: policyId
}, done)
}
else {
organizations.deletePolicy({
PolicyId: policyId
}, done)
}
}
})
}
if (event.RequestType === 'Update' || event.RequestType === 'Delete') {
updatePolicies(event.ResourceProperties.PolicyName, event.RequestType)
} else if (event.RequestType === 'Create') {
organizations.createPolicy({
Content: event.ResourceProperties.PolicyContents,
Description: event.ResourceProperties.PolicyDescription,
Name: event.ResourceProperties.PolicyName,
Type: "SERVICE_CONTROL_POLICY"
}, done);
} else {
cb(new Error('unsupported RequestType: ', event.RequestType));
}
};
Handler: index.handler
MemorySize: 128
Role:
'Fn::GetAtt':
- ScpResourceLambdaRole
- Arn
Runtime: nodejs12.x
Timeout: 120
ScpPolicy2:
Type: 'Custom::ServiceControlPolicy'
Properties:
PolicyName: scp_cloudtrail
PolicyDescription: >-
This SCP prevents users or roles in any affected account from disabling
a CloudTrail log, either directly as a command or through the console.
PolicyContents: >-
{"Version":"2012-10-17","Statement":[{"Action":["cloudtrail:StopLogging","cloudtrail:DeleteTrail"],"Resource":"*","Effect":"Deny"}]}
ServiceToken:
'Fn::GetAtt':
- ScpResourceLambda
- Arn
DependsOn:
- ScpPolicy1
ScpPolicy3:
Type: 'Custom::ServiceControlPolicy'
Properties:
PolicyName: scp_config
PolicyDescription: >-
This SCP prevents users or roles in any affected account from running
AWS Config operations that could disable AWS Config or alter its rules
or triggers.
PolicyContents: >-
{"Version":"2012-10-17","Statement":[{"Action":["config:DeleteConfigRule","config:DeleteConfigurationRecorder","config:DeleteDeliveryChannel","config:StopConfigurationRecorder"],"Resource":"*","Effect":"Deny"}]}
ServiceToken:
'Fn::GetAtt':
- ScpResourceLambda
- Arn
DependsOn:
- ScpPolicy2
ScpPolicy4:
Type: 'Custom::ServiceControlPolicy'
Properties:
PolicyName: scp_guardduty
PolicyDescription: >-
This SCP prevents users or roles in any affected account from disabling
or modifying Amazon GuardDuty settings, either directly as a command or
through the console.
PolicyContents: >-
{"Version":"2012-10-17","Statement":[{"Action":["guardduty:DeleteDetector","guardduty:DeleteInvitations","guardduty:DeleteIPSet","guardduty:DeleteMembers","guardduty:DeleteThreatIntelSet","guardduty:DisassociateFromMasterAccount","guardduty:DisassociateMembers","guardduty:StopMonitoringMembers"],"Resource":"*","Effect":"Deny"}]}
ServiceToken:
'Fn::GetAtt':
- ScpResourceLambda
- Arn
DependsOn:
- ScpPolicy3
ScpPolicy5:
Type: 'Custom::ServiceControlPolicy'
Properties:
PolicyName: scp_securityhub
PolicyDescription: >-
This SCP prevents users or roles in any affected account from disabling
AWS Security Hub, deleting member accounts or disassociating an account
from a master Security Hub account.
PolicyContents: >-
{"Version":"2012-10-17","Statement":[{"Action":["securityhub:DeleteInvitations","securityhub:DisableSecurityHub","securityhub:DisassociateFromMasterAccount","securityhub:DeleteMembers","securityhub:DisassociateMembers"],"Resource":"*","Effect":"Deny"}]}
ServiceToken:
'Fn::GetAtt':
- ScpResourceLambda
- Arn
DependsOn:
- ScpPolicy4
ScpPolicy6:
Type: 'Custom::ServiceControlPolicy'
Properties:
PolicyName: scp_organizations
PolicyDescription: >-
This SCP prevents users or roles in any affected account from leaving
AWS Organizations, either directly as a command or through the console.
PolicyContents: >-
{"Version":"2012-10-17","Statement":[{"Action":["organizations:LeaveOrganization"],"Resource":"*","Effect":"Deny"}]}
ServiceToken:
'Fn::GetAtt':
- ScpResourceLambda
- Arn
DependsOn:
- ScpPolicy5
ScpPolicy7:
Type: 'Custom::ServiceControlPolicy'
Properties:
PolicyName: scp_account_billing
PolicyDescription: >-
This SCP prevents users or roles in any affected account from modifying
the account and billing settings, either directly as a command or
through the console.
PolicyContents: >-
{"Version":"2012-10-17","Statement":[{"Action":["aws-portal:ModifyAccount","aws-portal:ModifyBilling","aws-portal:ModifyPaymentMethods"],"Resource":"*","Effect":"Deny"}]}
ServiceToken:
'Fn::GetAtt':
- ScpResourceLambda
- Arn
DependsOn:
- ScpPolicy6
ScpPolicy8:
Type: 'Custom::ServiceControlPolicy'
Properties:
PolicyName: scp_deny_iam_user_creation
PolicyDescription: >-
This SCP restricts IAM principals from creating new IAM users or IAM
Access Keys in an AWS account.
PolicyContents: >-
{"Version":"2012-10-17","Statement":[{"Action":["iam:CreateUser","iam:CreateAccessKey"],"Resource":["*"],"Effect":"Deny"}]}
ServiceToken:
'Fn::GetAtt':
- ScpResourceLambda
- Arn
DependsOn:
- ScpPolicy7
Parameters: {}
Metadata: {}
Conditions: {}