{"id":5691,"date":"2023-03-31T12:00:15","date_gmt":"2023-03-31T10:00:15","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=5691"},"modified":"2023-03-31T15:07:52","modified_gmt":"2023-03-31T13:07:52","slug":"iam-policies-and-service-control-policies-scps-how-to-master-and-secure-access-and-permissions-in-an-aws-landing-zone","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/iam-policies-and-service-control-policies-scps-how-to-master-and-secure-access-and-permissions-in-an-aws-landing-zone\/","title":{"rendered":"IAM policies and Service Control Policies (SCPs): How to master and secure access and permissions in an AWS Landing Zone"},"content":{"rendered":"\n
Today we are proud to welcome a special guest post<\/em>: straight from<\/em> the IAM- focused Noovolari Leapp’s blog<\/a>, Nicol\u00f2 Marchesi – Nico for friends \ud83d\ude09 – will guide us deep into one of the key aspects of a successful multi-account strategy on AWS. <\/em><\/p>\n\n\n\n As already covered in this blog post series<\/a>, implementing a Landing Zone is the starting point for a future-proof scalable, secure, and dynamic AWS environment. Within a Landing Zone,<\/em> some tricky aspects have to be handled with extreme care. That’s why we asked Nico to help us understand more about secure cloud access and permissions management in AWS. <\/p>\n\n\n\n How to use IAM Policies and Service Control Policies (SCPs) effectively? And how this can help companies to keep up with every organization’s security and governance needs?<\/p>\n\n\n\n Let’s find out!<\/em><\/p>\n\n\n\n Hello cloud fellows! Today we\u2019ll build up on the cloud landing zone series to explore a fascinating but often ignored context\u2026 Service Control Policies! SCPs are powerful, but there are a few caveats and tricks to make them work efficiently with every different kind of IAM policy<\/strong>. In this blog post, we will see how the whole IAM ecosystem interacts and how we can effectively leverage the tools to deploy a strong IAM strategy in our Cloud Landing Zone.<\/p>\n\n\n\n There is a lot of ground to cover, so let\u2019s start immediately!<\/p>\n\n\n\n I don\u2019t want to bother you with all the details about AWS Organizations so that we can keep our focus on permissions. If that\u2019s not the case, refer to one of the thousands of articles on the web or check THIS<\/a> one I wrote.<\/em><\/p>\n\n\n\n So, let\u2019s get the foundations covered (for the laziest of you, skip after the graph, there\u2019s a neat bullet-point recap). Before jumping directly to the interactions, we need to understand what we have at our disposal in our IAM strategy and all the different kind of tools in IAM to make it work:<\/p>\n\n\n\n As you may be starting to get, there is a fundamental difference between those policies, and it’s laid out in the diagram by the action that connects the policy to the actual permissions.<\/p>\n\n\n\n NOTE: Permission boundaries and Service control policies do NOT grant ANY permission<\/em><\/p>\n\n\n\n An Identity can access a Resource only through Identity-based and Resource-based policies. Permission boundaries and SCPs can only limit the aforementioned permissions. That means we need an Identity-based or Resource-based policy that explicitly allows permission to let the policy evaluation engine.<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n In short, Identity-based and Resource-based policies define who can access resources and what actions they can perform. Permission boundaries and Service Control Policies limit the scope of those permissions, ensuring that entities cannot perform unauthorized actions.<\/p>\n\n\n\n So let\u2019s get a visual representation of our policies: start by seeing how it works in a single account, and then see how things change by adding AWS Organizations to the equation.<\/p>\n\n\n\n Yeah, I know the icons differ from the AWS framework but bear with me; I want to highlight the differences and that we\u2019re working with fundamentally different policies.<\/p>\n\n\n\n As you can see, the three elements we can leverage are Identity-based, Resource-based policies, and Permission boundaries:<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n We can see that while the policies going in and out of the Identity and the Resource grants access, the Permission Boundaries limit that set of permission instead.<\/p>\n\n\n\n It\u2019s impossible to grant additional permissions through the use of Permission Boundaries.<\/p>\n\n\n\n When integrating the AWS Organization service, we gain the ability to use Service control policies to have better control over our environment:<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n The behavior is practically the same as Permission Boundaries, but we\u2019ll see soon that it has a slight difference. So, to briefly recap:<\/p>\n\n\n\n Behind all these definitions, a policy evaluation engine goes through all the policies we have seen before and evaluates if the specific action performed has to be allowed or denied.<\/p>\n\n\n\n Here I condensed the logic to understand the decision flow better:<\/p>\n\n\n\n It\u2019s interesting to note that Resource and Identity-based permissions are evaluated at the center of the evaluation flow. Around them, SCPs and PBs are evaluated, which we clustered in control policies.<\/p>\n\n\n\n <\/p>\n\n\n\n <\/p>\n\n\n\n Aside from Resource-based and Session policies, it turns out that it\u2019s pretty straightforward; the trick here is to focus on the edge cases.<\/p>\n\n\n\n Resource-based policies result in a deny when the Principal making the request is different than the Principal we\u2019re granting access to through the Resource-based policy. I\u2019ve highlighted the affected case in the schema proposed by AWS at this link<\/a>.<\/p>\n\n\n\n <\/p>\n\n\n\n <\/p>\n\n\n\n Even in this case, it\u2019s simpler than it looks. Session policies kick in only when they are present.<\/p>\n\n\n\n If you\u2019re not using them in your request, you shouldn’t care, but when the time comes that you\u2019re leveraging them, you need to remember the following:<\/p>\n\n\n\n Until now, we\u2019ve considered only access within the same account, but what would happen if we need to evaluate also cross-account access? It\u2019s simpler than it looks: request is evaluated on policies and permission from the perspective of both the trusted and trusting account and allowed only if both are evaluated as an allow!<\/p>\n\n\n\n If you think about this, it\u2019s more restrictive than single access. Since AWS permission starts with an implicit deny, you must explicitly set the permissions on both accounts before evaluating the request as an allow.<\/p>\n\n\n\n After understanding what is involved in deciding when a request is allowed, we can move on to how they interact.<\/p>\n\n\n\n This led to two practical scenarios, one with and one without Resource-based policies. The main point here is to understand that the only case in which one\u2019s effective permissions can exceed that of the whole intersection is when Resource-based policies are involved.<\/strong><\/p>\n\n\n\n <\/p>\n\n\n\n <\/p>\n\n\n\n When Resource-based policies are involved, if they evaluate as an allow, you\u2019re taking the final decision before the policy evaluation flow would evaluate Identity-based, Permission Boundaries, and Session policies. This results in permissions granted that can exceed the ones explicitly allowed by those policies.<\/p>\n\n\n\n The last thing to say is about Service Control Policies and the fact that they can be inherited.<\/p>\n\n\n\n Strangely, this doesn\u2019t work as one should expect (but it\u2019s for the better, trust me).<\/p>\n\n\n\n When one thinks about inheritance, usually in programming, but even in other fields, one thinks about getting the parent’s configurations to the child. If we apply this to SCPs, Organizational Units, and accounts, one can define the SCPs at the root level and then inherit everything. Well, that\u2019s NOT how it works.<\/p>\n\n\n\n Since DENY statements are evaluated first, in practice, only DENY statements are inherited<\/strong>.<\/p>\n\n\n\n If you deny a service in an SCP, there is no way to grant it in a lower-level OU or Account.<\/p>\n\n\n\n So, when an SCP is evaluated, there are actually only two SCPs that concur with the outcome:<\/p>\n\n\n\n <\/p>\n\n\n\n <\/p>\n\n\n\n From this perspective, you can see that ALLOW statements are not inherited but need to be explicitly set in the SCP of the Account or Organization Unit. This is for security purposes, as we want to explicitly set the boundaries of accounts and organizational units to avoid implicit significant permissions.<\/p>\n\n\n\n With a deny strategy, actions are allowed by default through a FullAccess SCP managed directly by AWS. You attach that SCP to all Accounts and OU and you need to specify what services and actions are prohibited:<\/p>\n\n\n\n <\/p>\n\n\n\n <\/p>\n\n\n\n This is the default configuration of AWS Organizations so that account admins can delegate all services and actions until you create and attach an SCP that denies a specific service.<\/p>\n\n\n\n The benefit of this approach is that deny statements require less maintenance<\/strong> because you don’t need to update them when AWS adds new services, and it\u2019s supported out of the box. You can also restrict access to specific resources or define conditions for when SCPs are in effect.<\/p>\n\n\n\n This is a great way to start for smaller organizations that need to act fast and don\u2019t have strict requirements over governance and security.<\/p>\n\n\n\n With an allow strategy, you must remove the AWS-managed FullAWSAccess SCP. Now all actions for all services are implicitly denied, and you need to create an SCP that explicitly permits only those services and actions you want to allow. This case is the same schema as the inheritance evaluation.<\/p>\n\n\n\n The benefit of this approach is that you have more control over what is allowed<\/strong>. Since everything is implicitly denied, this way is easier to scope down the actual boundaries of an account. Since deny permissions are inherited, you don\u2019t have to specify it everywhere.<\/p>\n\n\n\n However, it requires more maintenance since you have to manually allow each service (and this includes new services). And it comes with some limitations on the allow statements: Resource elements can only have a \u201d*\u201d entry,<\/strong> and they can’t have a Condition.<\/strong><\/p>\n\n\n\n This approach’s value shines when services may not be needed by a large portion of the organization but may still be required for specific use cases. In this scenario, it\u2019s simpler to elevate permissions and satisfy security and governance concerns while allowing flexibility and exceptions.<\/p>\n\n\n\n So let\u2019s see those SCPs in action; here, I put some examples so you can better picture what an SCP looks like in a real-world scenario.<\/p>\n\n\n\n In this case, we\u2019ve created an SCP to deny everything except changes that run through pipelines. The use case is to create an automation-only account where no manual action is allowed, but changes are always deployed through pipelines.<\/p>\n\n\n\n In this SCP, we implemented a way to protect all backups made through AWS backup by deletion. Notice that both S3 and Backup vaults are protected and the service cannot be turned down.<\/p>\n\n\n\n Congratulations, you\u2019ve managed to get to the end of the blog post! We\u2019ve gone from the policy evaluation flow to the actual implementation of SCPs, passing through the understanding of all the details that concur in policy and boundary interaction.<\/p>\n\n\n\n From seeing the SCP examples, as with any governance tool, their implementation is extremely tied to how your organization is structured and works. So I truly believe this knowledge should be well internalized and widely understood within the organization.<\/p>\n\n\n\n Now you\u2019re on your way to mastery; see you next time, and let me know how your cloud journey is going!<\/p>\n\n\n\n <\/p>\n\n\n\n Time to thank Nico and the rest of the Leapp team for this complete blog post! <\/em><\/p>\n\n\n\n How was your trip through Service Control Policies? <\/em>Let us know in the comments!<\/p>\n\n\n\n Curious about this open-source project? Visit the GitHub repository<\/a> (and drop a star if you like it!), and the website<\/a><\/em> or read more about IAM and Cloud Access Management on their blog<\/a><\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":" Today we are proud to welcome a special guest post: straight from the IAM- focused Noovolari Leapp’s blog, Nicol\u00f2 Marchesi […]<\/p>\n","protected":false},"author":1,"featured_media":5719,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[472],"tags":[278,586,566,582,633,635],"yoast_head":"\nIntroduction<\/h3>\n\n\n\n
\n\n\n\n
\n\n\n\nPolicies<\/h2>\n\n\n\n
\n
The caveat<\/h2>\n\n\n\n
<\/figure><\/div>\n\n\n
A visual representation of policy interaction<\/h2>\n\n\n\n
Single account (without Organizations)<\/h3>\n\n\n\n
<\/figure><\/div>\n\n\n
Organization structure<\/h3>\n\n\n\n
<\/figure><\/div>\n\n\n
\n
\n
\n
\n
\n
\n
The policy evaluation flow<\/h1>\n\n\n\n
<\/figure>\n\n\n\n
With resource-based policies<\/h3>\n\n\n\n
<\/figure>\n\n\n\n
With session policies<\/h3>\n\n\n\n
\n
A side note on cross-account access<\/h2>\n\n\n\n
Permission intersections<\/h2>\n\n\n\n
<\/figure>\n\n\n\n
About SCPs inheritance<\/h2>\n\n\n\n
\n
<\/figure>\n\n\n\n
Deny strategy<\/h3>\n\n\n\n
<\/figure>\n\n\n\n
Allow strategy<\/h3>\n\n\n\n
Just a few examples<\/h2>\n\n\n\n
Pipeline only account<\/h3>\n\n\n\n
{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"DenyAllExceptPipelines\",\n \"Effect\": \"Deny\",\n \"NotAction\": [\n \"codepipeline:*\",\n \"codebuild:*\",\n \"codecommit:*\",\n \"codedeploy:*\",\n \"codestar:*\",\n \"cloudformation:*\",\n \"iam:*\",\n \"s3:*\",\n \"logs:*\",\n \"cloudwatch:*\",\n \"cloudtrail:*\",\n \"codestar:*\",\n \"codestar-notification:*\",\n \"codeartifact:*\",\n \"kms:*\",\n \"tag:*\",\n \"access-analyzer:*\",\n \"codestar-connections:*\",\n \"ssm:GetParameter*\",\n \"sts:*\",\n \"events:*\"\n ],\n \"Resource\": \"*\",\n \"Condition\": {\n \"StringNotLike\": {\n \"aws:PrincipalArn\": [\n \"arn:aws:iam::MY-ACCOUNT-ID:role\/MY-ROLE\"\n ]\n }\n }\n }\n ]\n}<\/code><\/pre>\n\n\n\n
Backup protection<\/h3>\n\n\n\n
{\n\t\"Version\": \"2012-10-17\",\n\t\"Statement\": [\n\t\t{\n\t\t\t\"Sid\": \"DenyS3BackupDelete\",\n\t\t\t\"Action\": [\n\t\t\t\t\"s3:DeleteObject\",\n\t\t\t\t\"s3:DeleteObjectVersion\",\n\t\t\t\t\"s3:DeleteObjectTagging\",\n\t\t\t\t\"s3:DeleteBucket\"\n\t\t\t],\n\t\t\t\"Resource\": [\n\t\t\t\t\"arn:aws:s3:::MY-S3-BACKUP*\/*\"\n\t\t\t],\n\t\t\t\"Effect\": \"Deny\"\n\t\t},\n\t\t{\n\t\t\t\"Sid\": \"DenyBackupDelete\",\n\t\t\t\"Action\": [\n\t\t\t\t\"backup:DeleteBackupVault\",\n\t\t\t\t\"backup:DeleteBackupVaultAccessPolicy\",\n\t\t\t\t\"backup:PutBackupVaultAccessPolicy\"\n\t\t\t],\n\t\t\t\"Resource\": [\n\t\t\t\t\"arn:aws:backup:*:*:backup-vault:MY-BACKUP-VAULT\"\n\t\t\t],\n\t\t\t\"Effect\": \"Deny\",\n\t\t\t\"Condition\": {\n\t\t\t\t\"StringNotLike\": {\n\t\t\t\t\t\"aws:PrincipalARN\": \"arn:aws:iam::*:role\/MY-EXECUTION-ROLE\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"Sid\": \"DenyBackupTurnoffService\",\n\t\t\t\"Action\": [\n\t\t\t\t\"backup:UpdateRegionSettings\"\n\t\t\t],\n\t\t\t\"Resource\": [\n\t\t\t\t\"*\"\n\t\t\t],\n\t\t\t\"Effect\": \"Deny\",\n\t\t\t\"Condition\": {\n\t\t\t\t\"StringNotLike\": {\n\t\t\t\t\t\"aws:PrincipalARN\": [\n\t\t\t\t\t\t\"arn:aws:iam::*:role\/MY-EXECUTION-ROLE\"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}<\/code><\/pre>\n\n\n\n
Conclusion<\/h2>\n\n\n\n