Categories
Security & Monitoring

Improve Your SCP Foundation In AWS Organizations

AWS Organizations now supports the full IAM policy language in Service Control Policies (SCPs). In this post, learn how to use the new features safely along with some examples.

(Oh, and for those unclear on the niche image header. – Ed)

Table of Contents

Introduction

On 19 September 2025, AWS announced and posted that AWS Organizations now offers full IAM policy language support for service control policies (SCPs):

AWS Organizations now offers full IAM policy language support for service control policies (SCPs), enabling you to write SCPs with the same flexibility as IAM managed policies. With this launch, SCPs now support use of conditions, individual resource ARNs, and the NotAction element with Allow statements. Additionally, you can now use wildcards at the beginning or middle of Action element strings and the NotResource element.

In this post, I’ll explain what this change means in practice, provide examples from my AWS accounts, and share patterns to help adopt the new features safely. Whether implementing organization-wide guardrails, securing sandbox accounts or preventing accidental outages, this guidance will show how to get the most from SCPs after this update.

Service Control Policies

This section examines SCPs in closer detail. What are they? What do they do? And what benefits do they offer?

What Are SCPs?

Service Control Policies (SCPs) are an AWS Organizations feature that apply permission guardrails across multiple AWS accounts. To use SCPs, the AWS Organization must have all features enabled.

SCPs do not grant permissions. Instead, they define the maximum available permissions that IAM users and roles in an account can receive. Any action not permitted by an SCP is implicitly denied, even if an IAM policy within the account allows it. SCP syntax is similar to that used by IAM permission policies and resource-based policies (such as S3 bucket policies).

SCPs can be attached to the root of an AWS Organization, to an Organizational Unit (OU), or to individual accounts.

What Do SCPs Do?

SCPs use IAM policies and resource policies to determine whether to permit an action. The evaluation process consists of three parts:

Hierarchy & Inheritance

SCPs flow down through an AWS Organization. Attach a policy at the root, and everything underneath, including both OUs and accounts, inherits it. Each account ends up with the combined effect of every SCP above it.

Testing policies in a non-production OU before using them more widely helps to prevent unexpected lockouts!

Interaction with IAM and Resource Policies

SCPs define the boundaries within which IAM and resource policies operate. If either an SCP or IAM policy denies the action, then the request will be rejected. SCPs apply to all IAM users in an account, including the root user. Service-linked roles are usually exempt, allowing AWS services to function properly.

AWS have great documentation regarding how SCPs and IAM are evaluated.

Allow and Deny Approaches

By default, each account inherits the AWS-managed FullAWSAccess SCP that imposes no restrictions. Administrators can then apply additional policies using one of two strategies:

  • Deny list: Retain FullAWSAccess and add explicit Deny statements for disallowed services or actions.
  • Allow list: Remove FullAWSAccess and explicitly allow only the required services and actions. Everything else is implicitly denied.

In both models, explicit Deny statements always take priority.

Benefits Of SCPs

SCPs provide several advantages for organizations operating at scale or under compliance requirements:

  • Centralised Governance: Policies can be applied uniformly across all accounts from a single, central location. This reduces configuration drift and ensures consistent governance.
  • Enforcing Least Privilege: SCPs support least privilege by limiting available services and actions to only those that are approved. Additionally, newly launched AWS services can be blocked until they are approved.
  • Compliance & Risk Management: SCPs can implement controls like restricting access, requiring encryption or preventing the deletion of critical resources. These measures help reduce the risks associated with accidental misconfigurations and malicious actions.
  • Scalability & Efficiency: Managing IAM policies across multiple accounts is inefficient. SCPs streamline management by allowing the implementation of guardrails at both the OU and root levels.
  • Autonomy With Boundaries: SCPs create a secure outer boundary, allowing account teams to manage IAM policies within that boundary. This approach strikes a balance between enabling self-service and maintaining organizational controls.

Useful SCP & IAM Sites

This section has sites that I frequently hunt for when researching or writing SCPs for my AWS Organizations. This can be a struggle, as I usually forget what they’re called or what to search for! So for all the times I’ve remembered that these sites exist but couldn’t find them, they are here. This one’s for you Future Damo.

aws.permissions.cloud

aws.permissions.cloud compiles and organises a comprehensive collection of AWS IAM actions, managed policies, and permission metadata. This is presented in a searchable and structured format that includes tables and visualisations. The website uses the IAM Dataset created by AWS Community Hero Ian Mckay. Users can navigate the site using the left sidebar or by searching for a specific managed policy, IAM permission, or API method using the search bar at the top.

When comparing permissions.cloud‘s S3 Permissions Reference to the AWS S3 Service Authorization Reference, the two have many similarities. However, permissions.cloud features a better layout and includes a Used By column that indicates which AWS APIs use that IAM action.

In some cases this may be obvious, like the S3.AbortMultipartUpload API call using the s3:AbortMultipartUpload IAM action. Where this shines is with less obvious cases, like the FSx.CreateAndAttachS3AccessPoint API‘s use of the s3:CreateAccessPoint IAM action. While this information is all available in the documentation, having it all together in a searchable table is highly convenient.

2025 09 30 permissionscloud

asecure.cloud

asecure.cloud is a cloud security and compliance platform that aggregates AWS-recommended security configurations, automates environment assessments and enables rapid infrastructure-as-code remedial deployment.

The platform includes a library of security controls for numerous AWS services, IAM policies, cost controls and a configuration builder. While some content is premium-only, the free resources are substantial. Examples can be deployed using CloudFormation (and Terraform in many cases) custom templates, as well as AWS CLI scripts. For example, this page has a repository for Service Control Policy templates in several formats.

2025 09 28 asecurecloudSCPs

Speaking of which…

SCPs I Use

This section has some SCPs I use in my previously discussed AWS Organization. Each SCP has a policy and a brief description of what it does.

Deny LeaveOrganization

This policy, included in the AWS example SCPs, stops member account administrators from removing their accounts from an AWS Organization:

JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "organizations:LeaveOrganization"
            ],
            "Resource": "*"
        }
    ]
}
  • Actions: Targets organizations:LeaveOrganization.
  • EffectDeny – Blocks the specified action
  • Condition: None – applies unconditionally to all accounts
  • Result: The account cannot leave an AWS Organization.

Restrict EC2 Instance Type

This asecurecloud policy prevents the launch of any EC2 instance type that isn’t allowed. I’m no big user of EC2, so this is currently set to t3.micro:

JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ec2:RunInstances"
            ],
            "Resource": "*",
            "Effect": "Deny",
            "Condition": {
                "StringNotEquals": {
                    "ec2:InstanceType": "t3.micro"
                }
            }
        }
    ]
}
  • Action: Targets ec2:RunInstances
  • EffectDeny – blocks the action when conditions are met
  • ConditionStringNotEquals with ec2:InstanceType: "t3.micro"
  • Result: Denies launching any EC2 instance that is NOT a t3.micro

Restrict Lambda Python Runtime

This policy prevents the deployment of Lambda functions using the specified runtimes. This ensures that an account’s Lambda functions are consistent:

JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnsupportedLambdaRuntimes",
      "Effect": "Deny",
      "Action": [
        "lambda:CreateFunction",
        "lambda:UpdateFunctionConfiguration"
      ],
      "Resource": "*",
      "Condition": {
        "ForAllValues:StringEquals": {
          "lambda:Runtime": [
            "python3.11",
            "python3.10",
            "python3.9"
          ]
        }
      }
    }
  ]
}

How it works:

  • Actions: Targets both lambda:CreateFunction and lambda:UpdateFunctionConfiguration
  • EffectDeny – blocks actions when conditions are met.
  • ConditionForAllValues:StringEquals with denied runtimes.
  • Result: Users can’t create or update Lambda functions using Python 3.9, 3.10, or 3.11.

Restrict AWS Service Use

This policy restricts AWS service usage to only specified services in approved regions.

JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowServicesBasedOnRegion",
      "Effect": "Allow",
      "Action": [
        "ec2:*",
        "s3:*",
        "states:*",
        "lambda:*",
        "cloudformation:*",
        "iam:*",
        "cloudwatch:*"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": [
            "AWS-REGION-1",
            "AWS-REGION-2"
          ]
        }
      }
    }
  ]
}

Actions:

  • ec2:* – All EC2 operations
  • s3:* – All S3 operations
  • states:* – All Step Functions operations
  • lambda:* – All Lambda operations
  • cloudformation:* – All CloudFormation operations
  • iam:* – All IAM operations
  • cloudwatch:* – All CloudWatch operations
  • EffectAllow – Permits the specified actions when conditions are met.
  • ConditionsStringEquals with aws:RequestedRegion matching “AWS-REGION-1” or “AWS-REGION-2”

Result:

  • Only the seven specified service categories are allowed.
  • These services only work in the two specified regions.
  • All other AWS services are implicitly denied.
  • All other regions are blocked for any service.

Summary

In this post, we learned how to use the new AWS Organizations SCP features safely along with some examples.

Full support for IAM policy language in SCPs greatly enhances the governance capabilities of AWS Organizations. This allows for resource-level constraints, conditional logic and advanced action matching. To implement these features effectively, follow clear change control processes:

  • Validate policies in isolated OUs
  • Run representative simulations.
  • Stage deployments.
  • Ensure that centralised documentation and incident recovery plans are established.

Like this post? Click the button below for links to contact, socials, projects and sessions:

SharkLinkButton 1

Thanks for reading ~~^~~

Categories
Security & Monitoring

Building Strong Fundamentals With Microsoft’s SC-900

In this post, I will talk about my recent experience with Microsoft’s SC-900 certification and the resources I used to study for it.

Table of Contents

Introduction

On 23 May 2022 I earned the Microsoft Certified Security, Compliance, and Identity Fundamentals certification. This is my third Microsoft certification, joining my other badges on Credly.

I wanted to take the time to write about my experience in the hope that it may help others who are looking at the certification. I also wanted to address the elephant in the room – why did I take a Microsoft certification when my blog is called amazonwebshark?

First, I’ll talk about my motivation for studying for Microsoft’s SC-900 certification. Then I’ll talk about the resources I used, and finally I’ll cover my takeaways from the experience.

Motivation

In this section I’ll talk about my reasons for studying for Microsoft’s SC-900 certification.

Security Is Job Zero

While I’m a Data Engineer by trade, security is still a big part of my job. I need to make sure that any S3 objects and EBS volumes I create are encrypted. Any AWS resources using servers need security groups and NACLs that only allow certain levels of access. Also, SQL Server objects like logins and linked servers must have appropriate scopes and follow principles of least privilege.

Then I have my own resources to consider. My AWS account needs to use appropriate IAM and S3 bucket policies to control access to resources and data. I need to consider multi-factor authentication and access keys. Monitoring is needed for any hacking attempts or costs resulting from malicious activity.

In addition, this blog also presents security challenges. My site backups must be hardened and kept up to date. I need to consider attacks such as Cross-Site Scripting and SQL Injection. There are also plugins to consider. Are they up to date? Are they fit for purpose?

These factors are only the tip of the iceberg. The security landscape is ever-changing and needs constant vigilance.

Validation Of Knowledge

While security is a vital job, many security certifications test at a high level. Examples include the AWS Certified Security – Specialty certification and the CompTIA Security+. These usually recommend many years of industry experience and in-depth knowledge of the exam provider’s services.

Microsoft’s SC-900 is aimed at people who are getting to know the fundamentals of security, compliance, and identity. While the exam is Microsoft-branded, the topics tested are broadly the same across all cloud providers. This makes the SC-900 useful beyond Microsoft’s platform.

Speaking of which…

Security Is Security Is Security

Having earned my AWS Developer Associate Certification at the end of March, I currently hold all of the AWS Associate certifications. Each of these exams requires some security knowledge.

The Solutions Architect exam can ask about securing access to resources and data using services including IAM, subnets and NACLs. Meanwhile, the SysOps Administrator exam looks at implementing and managing security policies and strategies. It includes services like AWS CloudTrail, AWS Control Tower and AWS SSO.

Finally, the Developer exam covers authentication, authorisation and encryption with services like Amazon Cognito, API Gateway and AWS KMS. In short, the three exams cover a wide range of AWS services offering different types of security.

The major cloud providers all have their own version of common security products. Microsoft maintains a comparison list, offering examples like:

Studying for the SC-900 forced me to check that I understood the various services conceptually. The challenge was less about remembering names, and more about recognising what the services did. In other words, what do I know outside of AWS?

Resources

In this section I’ll talk about the resources I used to study for the Microsoft SC-900 certification.

John Savill

John Savill’s Technical Training YouTube channel started in 2008. Since then he’s created a wide range of videos from deep dives to weekly updates. In addition, he has study cram videos for many Microsoft certifications including the SC-900.

I found John’s channel while studying for other Microsoft certifications in 2021. John’s DP-900 video was a big help in checking what I was happy with and what needed attention.

Since then I’ve kept an eye on John’s channel as I enjoy his style, and he publishes videos on other topics including PowerShell and DevOps. So when I committed to taking Microsoft’s SC-900 certification he was my first port of call.

Thanks John! You’re a great human!

Microsoft Learn

Microsoft’s education platform provides learning via guided paths and individual modules depending on the desired result. Microsoft Learn has options for casual and in-depth learning, exam certification and on-demand streaming. It also includes a gamified experience system to drive user engagement.

Microsoft Learn has a free learning path with four modules tailed for the SC-900 exam. These modules offer a wide range of learning resources. Some sections are text-based. Others include videos and screenshots of the Azure portal. Some sections also include interactive sections that allow the use of a sandbox.

Microsoft Learn is a great resource and I look forward to seeing what else it has to offer.

Summary

In this post, I talked about my recent experience with Microsoft’s SC-900 certification and the resources I used to study for it.

In my opinion, Microsoft’s SC-900 has found a great niche for itself. Microsoft’s investment in this certification highlights the importance of security at a fundamental level. And despite the exam’s branding, the knowledge required to earn the certification is useful for many platforms and roles.

Microsoft’s SC-900 helped me prove my familiarity with security fundamentals. It also demonstrated to me that my security knowledge goes beyond the AWS cloud. It was a good experience and well worth taking on!

If this post has been useful, please feel free to follow me on the following platforms for future updates:

Thanks for reading ~~^~~

Categories
Security & Monitoring

Unexpected CloudWatch In The Billing Area

In this post I will investigate an unexpected CloudWatch charge on my April 2022 AWS bill, and explain how to interpret the bill and find the resources responsible.

Table of Contents

Introduction

My April 2022 AWS bill has arrived. The total wasn’t unusual – £4.16 is a pretty standard charge for me at the moment, most of which is S3. Then I took a closer look at the services and found an unexpected cost for CloudWatch, which is usually zero.

But not this month:

While $0.30 isn’t bank-breaking, it is unexpected and worth investigating. More importantly, nothing should be running in EU London! And there were no CloudWatch changes at all on my March 2022 bill. So what’s going on here?

Let’s start with the bill itself.

The April 2022 Bill

Looking at the bill, the rows with unexpected CloudWatch charges all mention alarms. Since nothing else has generated any charges, let’s take a closer look at all of the rows referring to alarms.

$0.00 Per Alarm Metric Month – First 10 Alarm Metrics – 10.000 Alarms

The AWS Always Free Tier includes ten CloudWatch alarms.

$0.10 Per Alarm Metric Month (Standard Resolution) – EU (Ireland) – 2.000002 Alarms

In EU Ireland, each standard resolution alarm after the first ten costs $0.10. The bill says there are twelve alarms in EU Ireland – ten of these are free and the other two cost $0.10 each – $0.20 in total.

$0.10 Per Alarm Metric Month (Standard Resolution) – EU (London) – 1.000001 Alarms

CloudWatch standard resolution alarms also cost $0.10 in EU London. As all my free alarms are seemingly in EU Ireland, the one in EU London costs a further $0.10.

So the bill is saying I have thirteen alarms – twelve in EU Ireland and one in EU London. Let’s open CloudWatch and see what’s going on there.

CloudWatch Alarm Dashboard

It seems I have thirteen CloudWatch alarms. Interesting, because I could only remember the four security alarms I set up in February.

CloudWatch says otherwise. This is my current EU Ireland CloudWatch dashboard:

Closer inspection finds eight alarms with names like:

  • TargetTracking-table/Rides-ProvisionedCapacityHigh-a53f2f67-9477-45a6-8197-788d2c7462b3
  • TargetTracking-table/Rides-ProvisionedCapacityLow-a36cf02f-7b3c-4fb0-844e-cf3d03fa80a9

Two of these are constantly In Alarm, and all have Last State Update values on 2022-03-17. The alarm names led me to suspect that DynamoDB was involved, and this was confirmed by viewing the Namespace and Metric Name values in the details of one of the alarms:

At this point I had an idea of what was going on. To be completely certain, I wanted to check my account history for 2022-03-17. That means a trip to CloudTrail!

CloudTrail Event History

CloudTrail’s Event History shows the last 90 days of management events. I entered a date range of 2022-03-17 00:00 > 2022-03-18 00:01 into the search filter, and it didn’t take long to start seeing some familiar-looking Resource Names:

Alongside the TargetTracking-table resource names linked to monitoring.amazonaws.com, there are also rows on the same day for other Event Sources including:

  • dynamodb.amazonaws.com
  • apigateway.amazonaws.com
  • lambda.amazonaws.com
  • cognito-idp.amazonaws.com

I now know with absolute certainty where the unexpected CloudWatch alarms came from. Let me explain.

Charge Explanations

So far I’ve reviewed my bills, found the CloudWatch alarms and established what was happening in my account when they were added. Now I’ll explain how this all led to charges on my bill.

The $0.20 EU Ireland Charge

When I was recently studying for the Developer Associate certification, I followed an AWS tutorial on how to Build a Serverless Web Application with AWS Lambda, Amazon API Gateway, AWS Amplify, Amazon DynamoDB, and Amazon Cognito. This was to top up my serverless knowledge before the exam.

The third module involves creating a DynamoDB table for the application. A table that I provisioned with auto-scaling for read and write capacity:

These auto-scaling policies rely on CloudWatch alarms to function, as demonstrated by some of the alarm conditions:

The DynamoDB auto-scaling created eight CloudWatch alarms. Four for Read Capacity Units:

  • ConsumedReadCapacityUnits > 42 for 2 datapoints within 2 minutes
  • ConsumedReadCapacityUnits < 30 for 15 datapoints within 15 minutes
  • ProvisionedReadCapacityUnits > 1 for 3 datapoints within 15 minutes
  • ProvisionedReadCapacityUnits < 1 for 3 datapoints within 15 minutes

And four for Write Capacity Units:

  • ConsumedWriteCapacityUnits > 42 for 2 datapoints within 2 minutes
  • ConsumedWriteCapacityUnits < 30 for 15 datapoints within 15 minutes
  • ProvisionedWriteCapacityUnits > 1 for 3 datapoints within 15 minutes
  • ProvisionedWriteCapacityUnits < 1 for 3 datapoints within 15 minutes

These eight alarms joined the existing four. The first ten were free, leaving two accruing charges.

This also explains why two alarms are always In Alarm – the criteria for scaling in are being met but the DynamoDB table can’t scale down any further.

I could have avoided this situation by destroying the resources after finishing the tutorial. The final module of the tutorial covers this. Instead I decided to keep everything around so I could take a proper look at everything under the hood.

No resources accrued any charges in March, so I left everything in place during April. I’ll go into why there was nothing on the March bill shortly, but first…

The $0.10 EU London Charge

Remember when I said that I shouldn’t be running anything in EU London? Turns out I was!

I found a very old CloudWatch alarm from 2020. It’s been there ever since. Never alerting so I didn’t know it was there. Included in the Always Free tier, so never costing me anything or triggering an AWS Budget alert. Appearing on my bill, but always as a free entry so never drawing attention.

When I exceeded my ten free CloudWatch alarms, the one in EU London became chargeable for the first time. A swift delete later and that particular problem is no more.

No CloudWatch Charge On The March 2022 Bill

That only leaves the question of why there were no CloudWatch charges on my March 2022 bill, despite there being thirteen alarms on my account for almost half of that month:

I wanted to understand what was going on, so I reached out to AWS Support.

In what must have been a first for them, I asked why no money had been billed for CloudWatch in March:

On my April 2022 bill I was charged $0.30 for CloudWatch. $0.20 in Ireland and $0.10 in London. I understand why.

What I want to understand is why I didn’t see a charge for them on my March 2022 bill. The alerts were added to the account on March 17th, so from that moment on I had thirteen alerts which is three over the free tier.

Can I get confirmation on why they don’t appear on March but do on April please?

I soon received a reply from AWS Support that explained the events in full:

…although you enabled all 13 Alarms in March, the system only calculated a pro-rated usage value, since the Alarms were only enabled on 17th March. The pro-rated Alarm usage values only amounted to 7.673 Alarms in the EU (Ireland) region, and 1.000003 Alarms in the EU (London) region.

The total pro-rated Alarm usage calculated for March (8.673003 Alarms) is thus within the 10 Alarm Free Tier threshold and thus incurred no charges, whereas in April the full 13 Alarm usage came into play for the entire month…

To summarise, I hadn’t been charged for the alarms in March because they’d only been on my account for almost half a month. Thanks for the help folks!

Summary

In this post I investigated an unexpected CloudWatch charge on my April 2022 AWS bill. I showed what the bill looked like, demonstrated how to find the resources generating the charges and explained how those resources came to be on my AWS account.

If this post has been useful, please feel free to follow me on the following platforms for future updates:

Thanks for reading ~~^~~