Overview

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.

Configure & Deploy

Configuration Presets

  • Package contains most common SCPs for protecting:
    • AWS Security and Logging Services: GuardDuty, CloudTrail and AWS Config
    • AWS Account Billing and Support Settings (and membership in AWS Organizations)
    • Restict the Root User in an AWS Account
    • Prevent creation of IAM users or Access Keys in an AWS Account

Configuration Template

EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
EDIT
Items
9
Size
7.8 KB
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: nodejs8.10
      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"],"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_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:
      - ScpPolicy4
  ScpPolicy6:
    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:
      - ScpPolicy5
  ScpPolicy7:
    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:
      - ScpPolicy6
Parameters: {}
Metadata: {}
Conditions: {}