Chapter 05: Permission Boundaries and Service Control Policies

Deep dive into AWS permission boundaries, Service Control Policies (SCP) and organization policy advanced permission management mechanisms

Haiyue
18min

Chapter 5: Permission Boundaries and Service Control Policies

Learning Objectives

  1. Understand permission boundary concepts and mechanisms
  2. Master Service Control Policy (SCP) configuration and management
  3. Learn AWS Organizations policy inheritance mechanisms
  4. Implement enterprise-level permission governance strategies
  5. Master permission boundary and SCP best practices

Permission Governance Architecture Diagram

🔄 正在渲染 Mermaid 图表...

5.1 Permission Boundary Fundamentals

5.1.1 Permission Boundary Concepts and Working Principles

Core Permission Boundary Concepts

Permission boundaries are an advanced feature for setting the maximum permissions of IAM entities (users or roles). They don’t grant permissions but define the upper limit of permissions.

  • Mechanism: Permission boundaries intersect with identity policies
  • Scope: Only applies to users and roles, not groups
  • Policy Type: Must use managed policies (cannot use inline policies)
import boto3
import json
from datetime import datetime, timedelta

def understand_permissions_boundary():
    """
    Understand permission boundary working principles
    """

    # Permission boundary working mechanism example
    working_mechanism = {
        "concept": "Permission boundaries define maximum permission scope",
        "formula": "Effective Permissions = Identity Policy Permissions ∩ Boundary Permissions",
        "key_points": [
            "Boundaries don't grant permissions, only limit them",
            "Must satisfy both identity policy and boundary allow conditions",
            "Deny from either side results in final deny",
            "Used to implement permission delegation and governance"
        ]
    }

    # Permission boundary scenario examples
    scenarios = {
        "developer_boundary": {
            "description": "Limit maximum permissions for developers",
            "identity_policy": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Action": "*",  # Identity policy allows all actions
                        "Resource": "*"
                    }
                ]
            },
            "permissions_boundary": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Action": [
                            "s3:*",
                            "dynamodb:*",
                            "lambda:*",
                            "ec2:Describe*",
                            "logs:*"
                        ],  # Boundary only allows specific services
                        "Resource": "*"
                    }
                ]
            },
            "effective_permissions": [
                "s3:*", "dynamodb:*", "lambda:*",
                "ec2:Describe*", "logs:*"
            ],
            "explanation": "Although identity policy allows all, boundary limits available services"
        },
        "service_restriction": {
            "description": "Prevent access to high-risk services",
            "identity_policy": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Action": [
                            "s3:*",
                            "ec2:*",
                            "iam:ListUsers"
                        ],
                        "Resource": "*"
                    }
                ]
            },
            "permissions_boundary": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Action": "*",
                        "Resource": "*"
                    },
                    {
                        "Effect": "Deny",
                        "Action": [
                            "iam:CreateRole",
                            "iam:DeleteRole",
                            "iam:AttachRolePolicy",
                            "organizations:*"
                        ],
                        "Resource": "*"
                    }
                ]
            },
            "effective_permissions": [
                "s3:*", "ec2:*", "iam:ListUsers"
            ],
            "blocked_actions": [
                "iam:CreateRole", "iam:DeleteRole",
                "iam:AttachRolePolicy", "organizations:*"
            ],
            "explanation": "Deny statements in boundary block high-risk IAM operations"
        }
    }

    print("📋 Permission Boundary Working Mechanism:")
    print(f"Concept: {working_mechanism['concept']}")
    print(f"Formula: {working_mechanism['formula']}")
    print("\nKey Points:")
    for point in working_mechanism['key_points']:
        print(f"  • {point}")

    print("\n📝 Permission Boundary Scenario Examples:")
    for scenario_name, scenario_info in scenarios.items():
        print(f"\n{scenario_name}:")
        print(f"  Description: {scenario_info['description']}")
        print(f"  Effective Permissions: {', '.join(scenario_info['effective_permissions'])}")
        if 'blocked_actions' in scenario_info:
            print(f"  Blocked Actions: {', '.join(scenario_info['blocked_actions'])}")
        print(f"  Explanation: {scenario_info['explanation']}")

    return working_mechanism, scenarios

def create_permissions_boundary_manager():
    """
    Create permission boundary manager
    """

    class PermissionsBoundaryManager:
        def __init__(self):
            self.iam = boto3.client('iam')

        def create_boundary_policy(self, policy_name, policy_document, description=""):
            """Create permission boundary policy"""
            try:
                response = self.iam.create_policy(
                    PolicyName=policy_name,
                    PolicyDocument=json.dumps(policy_document),
                    Description=description or f'Permission boundary policy: {policy_name}',
                    Tags=[
                        {
                            'Key': 'Type',
                            'Value': 'PermissionsBoundary'
                        },
                        {
                            'Key': 'CreatedDate',
                            'Value': datetime.now().strftime('%Y-%m-%d')
                        }
                    ]
                )

                policy_arn = response['Policy']['Arn']
                print(f"✅ Permission boundary policy created: {policy_arn}")

                return policy_arn

            except Exception as e:
                print(f"❌ Failed to create boundary policy: {str(e)}")
                return None

        def attach_boundary_to_user(self, username, boundary_policy_arn):
            """Attach permission boundary to user"""
            try:
                self.iam.put_user_permissions_boundary(
                    UserName=username,
                    PermissionsBoundary=boundary_policy_arn
                )

                print(f"✅ Permission boundary attached to user {username}")
                return True

            except Exception as e:
                print(f"❌ Failed to attach boundary: {str(e)}")
                return False

        def attach_boundary_to_role(self, role_name, boundary_policy_arn):
            """Attach permission boundary to role"""
            try:
                self.iam.put_role_permissions_boundary(
                    RoleName=role_name,
                    PermissionsBoundary=boundary_policy_arn
                )

                print(f"✅ Permission boundary attached to role {role_name}")
                return True

            except Exception as e:
                print(f"❌ Failed to attach boundary: {str(e)}")
                return False

    return PermissionsBoundaryManager()

# Usage example
boundary_manager = create_permissions_boundary_manager()

# Create developer permission boundary
developer_boundary = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "dynamodb:*",
                "lambda:*",
                "cloudwatch:*",
                "logs:*",
                "ec2:Describe*",
                "rds:Describe*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Deny",
            "Action": [
                "iam:*",
                "organizations:*",
                "account:*"
            ],
            "Resource": "*"
        }
    ]
}

boundary_policy_arn = boundary_manager.create_boundary_policy(
    "DeveloperPermissionBoundary",
    developer_boundary,
    "Boundary policy for developer roles limiting access to safe services"
)

5.2 Service Control Policies (SCP)

5.2.1 SCP Fundamentals

Service Control Policies (SCPs) are a type of organization policy that you can use to manage permissions in your organization. SCPs offer central control over the maximum available permissions for all accounts in your organization.

def understand_service_control_policies():
    """
    Understand Service Control Policy concepts
    """

    scp_concepts = {
        "definition": "SCPs are organization policies that centrally control maximum permissions",
        "scope": "Applies to all principals in member accounts, including root user",
        "inheritance": "SCPs inherit down the organization tree",
        "permission_model": "SCPs do not grant permissions, only limit them",
        "key_characteristics": [
            "Affects all IAM users and roles in account",
            "Does not affect service-linked roles",
            "Evaluated before identity-based policies",
            "Uses deny-by-default or allow-list approach",
            "Can be attached to organization root, OUs, or accounts"
        ]
    }

    print("📋 Service Control Policy (SCP) Concepts:")
    print(f"Definition: {scp_concepts['definition']}")
    print(f"Scope: {scp_concepts['scope']}")
    print(f"Inheritance: {scp_concepts['inheritance']}")
    print(f"Permission Model: {scp_concepts['permission_model']}")
    print("\nKey Characteristics:")
    for char in scp_concepts['key_characteristics']:
        print(f"  • {char}")

    return scp_concepts

def create_scp_manager():
    """
    Create SCP manager
    """

    class SCPManager:
        def __init__(self):
            self.organizations = boto3.client('organizations')

        def create_scp(self, policy_name, policy_document, description=""):
            """Create Service Control Policy"""
            try:
                response = self.organizations.create_policy(
                    Content=json.dumps(policy_document),
                    Description=description or f'SCP: {policy_name}',
                    Name=policy_name,
                    Type='SERVICE_CONTROL_POLICY',
                    Tags=[
                        {
                            'Key': 'Type',
                            'Value': 'SCP'
                        },
                        {
                            'Key': 'CreatedDate',
                            'Value': datetime.now().strftime('%Y-%m-%d')
                        }
                    ]
                )

                policy_id = response['Policy']['PolicySummary']['Id']
                print(f"✅ SCP created successfully: {policy_id}")

                return response['Policy']

            except Exception as e:
                print(f"❌ Failed to create SCP: {str(e)}")
                return None

        def attach_scp_to_target(self, policy_id, target_id):
            """Attach SCP to organizational target"""
            try:
                self.organizations.attach_policy(
                    PolicyId=policy_id,
                    TargetId=target_id
                )

                print(f"✅ SCP {policy_id} attached to {target_id}")
                return True

            except Exception as e:
                print(f"❌ Failed to attach SCP: {str(e)}")
                return False

    return SCPManager()

# Usage example
scp_manager = create_scp_manager()

# Create deny-list SCP for production accounts
production_scp = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "iam:DeleteRole",
                "iam:DeleteUser",
                "organizations:LeaveOrganization"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Deny",
            "Action": [
                "ec2:TerminateInstances",
                "rds:DeleteDBInstance"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:PrincipalTag/Role": "Administrator"
                }
            }
        }
    ]
}

print("\n📝 Example Production SCP:")
print(json.dumps(production_scp, indent=2))

5.3 Organization Policy Management

5.3.1 AWS Organizations Structure

def manage_organization_structure():
    """
    Manage AWS Organizations structure
    """

    class OrganizationManager:
        def __init__(self):
            self.organizations = boto3.client('organizations')

        def create_organizational_unit(self, parent_id, ou_name):
            """Create Organizational Unit"""
            try:
                response = self.organizations.create_organizational_unit(
                    ParentId=parent_id,
                    Name=ou_name,
                    Tags=[
                        {
                            'Key': 'CreatedBy',
                            'Value': 'OrganizationManager'
                        },
                        {
                            'Key': 'CreatedDate',
                            'Value': datetime.now().strftime('%Y-%m-%d')
                        }
                    ]
                )

                ou_id = response['OrganizationalUnit']['Id']
                print(f"✅ Organizational Unit created: {ou_name} ({ou_id})")

                return response['OrganizationalUnit']

            except Exception as e:
                print(f"❌ Failed to create OU: {str(e)}")
                return None

    return OrganizationManager()

# Usage example
org_manager = manage_organization_structure()

print("\n📋 Organization Structure Example:")
print("  Root")
print("  ├── Production OU")
print("  │   ├── App-Prod Account")
print("  │   └── DB-Prod Account")
print("  ├── Development OU")
print("  │   ├── App-Dev Account")
print("  │   └── DB-Dev Account")
print("  └── Security OU")
print("      ├── Audit Account")
print("      └── Logging Account")

5.4 Best Practices

5.4.1 Permission Governance Best Practices

def implement_governance_best_practices():
    """
    Implement permission governance best practices
    """

    best_practices = {
        "permission_boundaries": [
            "Use boundaries to delegate permission management safely",
            "Apply boundaries to all developer and operator roles",
            "Regular review of boundary effectiveness",
            "Document boundary policies clearly",
            "Test boundaries before production deployment"
        ],
        "service_control_policies": [
            "Start with FullAWSAccess and add deny rules",
            "Test SCPs in non-production first",
            "Use SCPs to enforce organizational standards",
            "Document all SCP changes",
            "Monitor SCP denials in CloudTrail"
        ],
        "organization_design": [
            "Design OU structure based on business needs",
            "Separate production and non-production",
            "Use separate OUs for security functions",
            "Plan for policy inheritance",
            "Regular review of organization structure"
        ]
    }

    print("📋 Permission Governance Best Practices:")
    for category, practices in best_practices.items():
        print(f"\n{category.replace('_', ' ').title()}:")
        for practice in practices:
            print(f"  ✓ {practice}")

    return best_practices

# Execute best practices
governance_best_practices = implement_governance_best_practices()

Summary

This chapter introduced advanced permission governance mechanisms in AWS:

  1. Permission Boundaries: Understand concepts, create and manage boundary policies
  2. Service Control Policies: Master SCP creation, attachment, and inheritance
  3. Organization Management: Design and implement organization structure
  4. Best Practices: Implement enterprise-level permission governance strategies

Through this chapter, you should be able to:

  • Implement permission boundaries for delegation and governance
  • Create and manage Service Control Policies effectively
  • Design scalable organization structures
  • Apply governance best practices in enterprise environments
  • Monitor and audit permission usage across the organization

In the next chapter, we will learn IAM best practices and security principles.