SCP Best Practices
Tags: security, aws
Published: 2021-01-06 08:23:15


## What is an SCP? 
Service Control Policies (SCPs) offer central access controls for all IAM entities in AWS accounts.
You can use them to enforce the permissions you want everyone in your business to follow or to be compliant with specific laws which you need to follow (eg.: you can deny regions or services to be DSGVO compliant). If you want to use SCPs you need to create and apply those SCPs through AWS Organizations - SCPs 
can be assigned to AWS accounts or Organizational Units (OUs). 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/13jodalyqtqcyqrnlm2e.png)

### Something you should know about SCPs:

❗️ The Master account of the Organization can't be restricted by using SCPs. </br>
❌ SCPs cannot restrict principals outside of the Organization. </br>
⚠️  SCPs are similar to [IAM boundaries](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html).


In the following section I will introduce some of my and AWS SCP - Best Practices which I am using. 
This SCPs will help you to secure your accounts and resources - plus it will help you to avoid unnecessary costs.

## Avoid unnecessary costs 

#### Deny creation of expensive services
When using an Organization, expensive services should be deployed centrally and shared with all accounts eg. private ACM. That way you can save some costs.

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyACM",
            "Effect": "Deny",
            "Action": [
                "acm-pca:CreateCertificateAuthority",
                "acm-pca:DeleteCertificateAuthority",
                "acm-pca:CreatePermission",
                "acm-pca:DeletePermission",
                "acm-pca:DescribeCertificateAuthorityAuditReport",
                "acm-pca:RestoreCertificateAuthority",
                "acm-pca:TagCertificateAuthority",
                "acm-pca:UntagCertificateAuthority"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:PrincipalArn": "arn:aws:iam::*:role/AWS-CentralCostTeam"
                }
            }
        }
    ]
}

```

  
### Deny purchasing of reserved instances
When using an Organization and your company need to manage reserved instances centrally you should limit the permissions to one team, which ensures that the reserved instances are fully used.

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyAccessToRI",
            "Effect": "Deny",
            "Action": [
                "ec2:PurchaseReservedInstancesOffering",
                "ec2:AcceptReservedInstancesExchangeQuote",
                "ec2:CancelCapacityReservation",
                "ec2:CancelReservedInstancesListing",
                "ec2:CreateCapacityReservation",
                "ec2:CreateReservedInstancesListing"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:PrincipalArn": "arn:aws:iam::*:role/AWS-CentralCostTeam"
                }
            }
        }
    ]
}


```


### Deny creation of savings plans
The same procedure applies for savings plans as for reserved instances in an Organization. 

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyAccessToCreateSavingsPlans",
            "Effect": "Deny",
            "Action": [
                "savingsplans:CreateSavingsPlans"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:PrincipalArn": "arn:aws:iam::*:role/AWS-CentralCostTeam"
                }
            }
        }
    ]
}
```


## Secure resources and accounts

#### Deny all SCP
If your account gets compromised it is recommended to have a deny all SCP to protect your data. This SCP is attached to a quarantine OU, which prohibits every action in the compromised account. 

```
{    
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Quarantine",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*"
    }
  ]
}
```


#### Region enforcement
You need to be sure that your company just uses one region?! The following policy will enforce that your member accounts are using the specified region. <br> ⚠️ You need to define the global services in the NotAction otherwise the accounts are not able to use them.


```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RestrictToOneRegion",
            "Effect": "Deny",
            "NotAction": [
                "a4b:*",
                "artifact:*",
                "aws-portal:*",
                "budgets:*",
                "ce:*",
                "chime:*",
                "cloudfront:*",
                "cur:*",
                "datapipeline:GetAccountLimits",
                "directconnect:",
                "globalaccelerator:*",
                "health:*",
                "iam:*",
                "importexport:*",
                "mobileanalytics:*",
                "organizations:*",
                "resource-groups:*",
                "route53:*",
                "route53domains:*",
                "s3:GetBucketLocation",
                "s3:ListAllMyBuckets",
                "shield:*",
                "support:*",
                "tag:*",
                "trustedadvisor:*",
                "waf:*",
                "wellarchitected:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:RequestedRegion": [
                        "eu-central-1"
                    ]
                }
            }
        }
    ]
}
```

⚠️ If you want to use **Lambda@Edge** you need to add also the service lambda:* to NotAction.  

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RestrictToOneRegion",
            "Effect": "Deny",
            "NotAction": [
                "lambda:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:RequestedRegion": [
                        "eu-central-1"
                    ]
                }
            }
        }
    ]
}
```



#### Secure Security-Baseline: Deny ability to disable GuardDuty
GuardDuty is a threat detection service that continuously monitors for malicious activity and unauthorized behavior in you accounts. In an Organization you should use a master account and connect member accounts to it. The following policy ensures it can’t be turned off, the member can't be disassociated from the master or that a user can't create sample findings.


```
  {
      "Effect": "Deny",
      "Action": [
        "guardduty:DeleteDetector",
        "guardduty:CreateSampleFindings",
        "guardduty:DisassociateFromMasterAccount"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotLike": {
          "aws:PrincipalArn": "arn:aws:iam::*:role/StackSet-GuardDuty-Member-LambdaExecutionRole*"
        }
      }
    }
```


#### Secure Security-Baseline: Deny ability to disable Config
Config is a service to audit and evaluate the configurations in your accounts.
The following SCP prevents users or roles to disable or alter Config, except the specified role which is needed for a Lambda to enable and configure Config in all regions.


```
{
      "Effect": "Deny",
      "Action": [
        "config:DeleteConfigurationRecorder",
        "config:DeleteDeliveryChannel",
        "config:StopConfigurationRecorder",
        "config:PutDeliveryChannel",
        "config:StartConfigurationRecorder"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotLike": {
          "aws:PrincipalArn": "arn:aws:iam::*:role/StackSet-Enable-Config-*"
        }
      }
    }
```
 
#### Secure Security-Baseline: Deny leaving the Organization
Secure your Organization that no accounts can leave your Organization, where they would no longer be restricted by your SCPs.

```
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Deny",
        "Action": "organizations:LeaveOrganization",
        "Resource": "*"
    }
}
```

#### Deny root access
AWS recommends a SCP for denying use of the root user. The following policy enforces that the root user can't be used.

```
{
  "Version": "2012-10-17",
  "Statement": {
    "Sid": "DenyRootUser",
    "Effect": "Deny",
    "Action": "*",
    "Resource": "*",
    "Condition": {
      "StringLike": { "aws:PrincipalArn": "arn:aws:iam::*:root" }
    }
  }
}
```
## How to test SCPs or how to handle SCPs without breaking things? 

Lets start with the bad news, unfortunately there is no audit mode for SCPs, but you can use the API - [GetOrganizationsAccessReport](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetOrganizationsAccessReport.html) from the IAM Access Advisor to identify unused services. This API will help you to see whether services are used in an account or OU. I always use a separate OU to test new SCPs by moving a test account to see, if my SCP works as desired.