Table of Contents

  1. Introduction
  2. IAM Concepts
  3. Provider Comparison
  4. AWS IAM
  5. Azure Entra ID
  6. Google Cloud IAM
  7. Secrets Management
  8. Encryption Services
  9. Compliance & Governance
  10. Best Practices
  11. Conclusion
Back to Technology

Cloud Identity & Security Guide

January 25, 2026 Wasil Zafar 50 min read

Master cloud security with AWS IAM, Azure Entra ID, and GCP IAM. Learn roles, policies, encryption, secrets management, and compliance.

Introduction

Cloud security is a shared responsibility between cloud providers and customers. This guide covers identity and access management (IAM), encryption, secrets management, and compliance across all major cloud platforms.

What We'll Cover:
  • Identity Management - Users, groups, roles, service accounts
  • Access Control - Policies, permissions, RBAC
  • Secrets Management - Key Vault, Secrets Manager, Secret Manager
  • Encryption - KMS, data encryption at rest and in transit
  • Compliance - Frameworks, auditing, governance

IAM Concepts

Key Terminology

Concept Description Example
Principal Entity that can request access (user, service, application) IAM user, service account, Lambda function
Identity Unique representation of a principal user@domain.com, arn:aws:iam::123:user/john
Authentication Verifying identity (who you are) Password, MFA, certificate, token
Authorization Determining permissions (what you can do) Policy evaluation, role assignment
Role Set of permissions that can be assumed EC2 instance role, Azure RBAC role
Policy Document defining permissions JSON policy allowing S3 read access
Service Account Identity for applications/services GCP service account, Azure managed identity
Least Privilege Grant only minimum required permissions Read-only access to specific S3 bucket
Security Principle:

Always follow the principle of least privilege. Grant only the permissions necessary to perform a task, and remove permissions when no longer needed.

Provider Comparison

Feature AWS Azure GCP
Identity Service IAM Entra ID (Azure AD) Cloud Identity / IAM
User Management IAM Users Entra ID Users Google Workspace / Cloud Identity
Service Identity IAM Roles Managed Identity Service Account
Permission Model Policy-based (JSON) RBAC + Azure Policy IAM Policies + Org Policies
Secrets Manager Secrets Manager / SSM Parameter Store Key Vault Secret Manager
Key Management KMS Key Vault Keys Cloud KMS
MFA Virtual MFA, Hardware MFA Microsoft Authenticator, FIDO2 Google Authenticator, Security Keys
SSO IAM Identity Center Entra ID SSO Cloud Identity SSO

AWS IAM

AWS Identity and Access Management

  • Global service - IAM is not region-specific
  • Free to use - No additional charges for IAM
  • Policy types - Identity-based, resource-based, permissions boundaries
  • Organizations - Multi-account management with SCPs

IAM Users and Groups

# Create IAM user
aws iam create-user --user-name developer1

# Create access keys for user
aws iam create-access-key --user-name developer1

# Create IAM group
aws iam create-group --group-name Developers

# Add user to group
aws iam add-user-to-group --user-name developer1 --group-name Developers

# List users
aws iam list-users --output table

# List groups for user
aws iam list-groups-for-user --user-name developer1

# Enable MFA for user (after creating virtual MFA device)
aws iam enable-mfa-device \
    --user-name developer1 \
    --serial-number arn:aws:iam::123456789012:mfa/developer1 \
    --authentication-code1 123456 \
    --authentication-code2 789012

IAM Policies

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowS3ReadAccess",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket",
                "arn:aws:s3:::my-bucket/*"
            ]
        },
        {
            "Sid": "DenyDeleteBucket",
            "Effect": "Deny",
            "Action": "s3:DeleteBucket",
            "Resource": "*"
        }
    ]
}
# Create policy from JSON file
aws iam create-policy \
    --policy-name S3ReadOnlyPolicy \
    --policy-document file://s3-readonly-policy.json

# Attach policy to user
aws iam attach-user-policy \
    --user-name developer1 \
    --policy-arn arn:aws:iam::123456789012:policy/S3ReadOnlyPolicy

# Attach policy to group
aws iam attach-group-policy \
    --group-name Developers \
    --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

# List attached policies for user
aws iam list-attached-user-policies --user-name developer1

# Get policy document
aws iam get-policy-version \
    --policy-arn arn:aws:iam::123456789012:policy/S3ReadOnlyPolicy \
    --version-id v1

IAM Roles

# Create role trust policy (for EC2)
cat > trust-policy.json << 'EOF'
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF

# Create IAM role
aws iam create-role \
    --role-name EC2S3AccessRole \
    --assume-role-policy-document file://trust-policy.json

# Attach policy to role
aws iam attach-role-policy \
    --role-name EC2S3AccessRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

# Create instance profile (for EC2)
aws iam create-instance-profile --instance-profile-name EC2S3Profile

# Add role to instance profile
aws iam add-role-to-instance-profile \
    --instance-profile-name EC2S3Profile \
    --role-name EC2S3AccessRole

# Assume role (get temporary credentials)
aws sts assume-role \
    --role-arn arn:aws:iam::123456789012:role/EC2S3AccessRole \
    --role-session-name MySession

# Cross-account role trust policy
cat > cross-account-trust.json << 'EOF'
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::987654321098:root"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "sts:ExternalId": "unique-external-id"
                }
            }
        }
    ]
}
EOF

Service Control Policies (SCPs)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyLeaveOrganization",
            "Effect": "Deny",
            "Action": "organizations:LeaveOrganization",
            "Resource": "*"
        },
        {
            "Sid": "RequireIMDSv2",
            "Effect": "Deny",
            "Action": "ec2:RunInstances",
            "Resource": "arn:aws:ec2:*:*:instance/*",
            "Condition": {
                "StringNotEquals": {
                    "ec2:MetadataHttpTokens": "required"
                }
            }
        },
        {
            "Sid": "DenyRegionsOutsideUS",
            "Effect": "Deny",
            "Action": "*",
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "aws:RequestedRegion": [
                        "us-east-1",
                        "us-west-2"
                    ]
                }
            }
        }
    ]
}

Azure Entra ID

Microsoft Entra ID (formerly Azure AD)

  • Cloud-based identity - Comprehensive identity platform
  • Hybrid identity - Sync with on-premises Active Directory
  • Conditional Access - Context-aware access policies
  • Privileged Identity Management - Just-in-time access

Users and Groups

# Create user
az ad user create \
    --display-name "John Developer" \
    --user-principal-name john@contoso.onmicrosoft.com \
    --password "SecureP@ssw0rd!"

# List users
az ad user list --output table

# Create security group
az ad group create \
    --display-name "Developers" \
    --mail-nickname "developers"

# Add user to group
az ad group member add \
    --group "Developers" \
    --member-id $(az ad user show --id john@contoso.onmicrosoft.com --query id -o tsv)

# List group members
az ad group member list --group "Developers" --output table

# Create service principal
az ad sp create-for-rbac \
    --name "myapp-sp" \
    --role Contributor \
    --scopes /subscriptions/xxx/resourceGroups/myRG

Azure RBAC

# List built-in roles
az role definition list --output table

# Get role definition details
az role definition list --name "Contributor" --output json

# Assign role to user at resource group scope
az role assignment create \
    --assignee john@contoso.onmicrosoft.com \
    --role "Contributor" \
    --resource-group myResourceGroup

# Assign role to service principal at subscription scope
az role assignment create \
    --assignee-object-id $(az ad sp show --id myapp-sp --query id -o tsv) \
    --role "Reader" \
    --scope /subscriptions/xxx

# List role assignments
az role assignment list \
    --resource-group myResourceGroup \
    --output table

# Create custom role
az role definition create --role-definition '{
    "Name": "Custom VM Operator",
    "Description": "Can start and stop VMs",
    "Actions": [
        "Microsoft.Compute/virtualMachines/start/action",
        "Microsoft.Compute/virtualMachines/powerOff/action",
        "Microsoft.Compute/virtualMachines/restart/action",
        "Microsoft.Compute/virtualMachines/read"
    ],
    "NotActions": [],
    "AssignableScopes": ["/subscriptions/xxx"]
}'

# Remove role assignment
az role assignment delete \
    --assignee john@contoso.onmicrosoft.com \
    --role "Contributor" \
    --resource-group myResourceGroup

Managed Identities

# Create user-assigned managed identity
az identity create \
    --resource-group myResourceGroup \
    --name myManagedIdentity

# Get managed identity details
az identity show \
    --resource-group myResourceGroup \
    --name myManagedIdentity

# Assign managed identity to VM
az vm identity assign \
    --resource-group myResourceGroup \
    --name myVM \
    --identities myManagedIdentity

# Enable system-assigned managed identity on VM
az vm identity assign \
    --resource-group myResourceGroup \
    --name myVM

# Assign role to managed identity
az role assignment create \
    --assignee $(az identity show -g myResourceGroup -n myManagedIdentity --query principalId -o tsv) \
    --role "Storage Blob Data Reader" \
    --scope /subscriptions/xxx/resourceGroups/myRG/providers/Microsoft.Storage/storageAccounts/mystorageaccount

Conditional Access (via Portal/Graph API)

# List conditional access policies (requires Graph API)
az rest --method GET \
    --url "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies"

# Example policy structure (create via Portal or Graph API)
# {
#   "displayName": "Require MFA for admins",
#   "state": "enabled",
#   "conditions": {
#     "users": {
#       "includeRoles": ["62e90394-69f5-4237-9190-012177145e10"]
#     },
#     "applications": {
#       "includeApplications": ["All"]
#     }
#   },
#   "grantControls": {
#     "operator": "OR",
#     "builtInControls": ["mfa"]
#   }
# }

Google Cloud IAM

Google Cloud IAM

  • Resource hierarchy - Organization ? Folders ? Projects ? Resources
  • Policy inheritance - Permissions inherit down the hierarchy
  • Predefined roles - Curated sets of permissions
  • Custom roles - Define exact permissions needed

Service Accounts

# Create service account
gcloud iam service-accounts create my-service-account \
    --display-name="My Service Account" \
    --description="Service account for my application"

# List service accounts
gcloud iam service-accounts list

# Create key for service account
gcloud iam service-accounts keys create key.json \
    --iam-account=my-service-account@my-project.iam.gserviceaccount.com

# Grant role to service account
gcloud projects add-iam-policy-binding my-project \
    --member="serviceAccount:my-service-account@my-project.iam.gserviceaccount.com" \
    --role="roles/storage.objectViewer"

# Enable service account impersonation
gcloud iam service-accounts add-iam-policy-binding \
    my-service-account@my-project.iam.gserviceaccount.com \
    --member="user:admin@example.com" \
    --role="roles/iam.serviceAccountUser"

# Impersonate service account
gcloud auth print-access-token \
    --impersonate-service-account=my-service-account@my-project.iam.gserviceaccount.com

IAM Policies

# Get current IAM policy
gcloud projects get-iam-policy my-project --format=json > policy.json

# Grant role to user
gcloud projects add-iam-policy-binding my-project \
    --member="user:developer@example.com" \
    --role="roles/viewer"

# Grant role with condition
gcloud projects add-iam-policy-binding my-project \
    --member="user:developer@example.com" \
    --role="roles/storage.objectViewer" \
    --condition='expression=request.time < timestamp("2026-12-31T00:00:00Z"),title=temporary-access,description=Access until end of year'

# Remove role from user
gcloud projects remove-iam-policy-binding my-project \
    --member="user:developer@example.com" \
    --role="roles/viewer"

# List all roles
gcloud iam roles list

# Describe a role
gcloud iam roles describe roles/storage.objectAdmin

Custom Roles

# Create custom role definition file
cat > custom-role.yaml << 'EOF'
title: "Custom Storage Reader"
description: "Can read storage objects but not list buckets"
stage: "GA"
includedPermissions:
  - storage.objects.get
  - storage.objects.list
EOF

# Create custom role
gcloud iam roles create customStorageReader \
    --project=my-project \
    --file=custom-role.yaml

# Update custom role
gcloud iam roles update customStorageReader \
    --project=my-project \
    --add-permissions=storage.buckets.get

# Delete custom role
gcloud iam roles delete customStorageReader --project=my-project

Workload Identity Federation

# Create workload identity pool
gcloud iam workload-identity-pools create my-pool \
    --location="global" \
    --display-name="My Identity Pool"

# Add AWS provider
gcloud iam workload-identity-pools providers create-aws my-aws-provider \
    --location="global" \
    --workload-identity-pool="my-pool" \
    --account-id="123456789012" \
    --attribute-mapping="google.subject=assertion.arn"

# Add OIDC provider (GitHub Actions)
gcloud iam workload-identity-pools providers create-oidc github-actions \
    --location="global" \
    --workload-identity-pool="my-pool" \
    --issuer-uri="https://token.actions.githubusercontent.com" \
    --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository"

# Grant access to service account
gcloud iam service-accounts add-iam-policy-binding \
    my-service-account@my-project.iam.gserviceaccount.com \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/my-pool/attribute.repository/my-org/my-repo"

Secrets Management

AWS Secrets Manager

# Create secret
aws secretsmanager create-secret \
    --name MyDatabaseSecret \
    --description "Database credentials" \
    --secret-string '{"username":"admin","password":"MySecureP@ss123"}'

# Get secret value
aws secretsmanager get-secret-value \
    --secret-id MyDatabaseSecret \
    --query SecretString --output text

# Update secret
aws secretsmanager update-secret \
    --secret-id MyDatabaseSecret \
    --secret-string '{"username":"admin","password":"NewP@ssword456"}'

# Enable automatic rotation
aws secretsmanager rotate-secret \
    --secret-id MyDatabaseSecret \
    --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:SecretsRotation \
    --rotation-rules AutomaticallyAfterDays=30

# List secrets
aws secretsmanager list-secrets --output table

# Delete secret (with recovery window)
aws secretsmanager delete-secret \
    --secret-id MyDatabaseSecret \
    --recovery-window-in-days 7

AWS SSM Parameter Store

# Create SecureString parameter
aws ssm put-parameter \
    --name "/myapp/database/password" \
    --value "SecureP@ssword123" \
    --type SecureString \
    --key-id alias/aws/ssm

# Create parameter with tags
aws ssm put-parameter \
    --name "/myapp/config/api-key" \
    --value "abc123xyz" \
    --type SecureString \
    --tags "Key=Environment,Value=Production"

# Get parameter value
aws ssm get-parameter \
    --name "/myapp/database/password" \
    --with-decryption \
    --query "Parameter.Value" --output text

# Get parameters by path
aws ssm get-parameters-by-path \
    --path "/myapp/" \
    --recursive \
    --with-decryption

# Delete parameter
aws ssm delete-parameter --name "/myapp/database/password"

Azure Key Vault

# Create Key Vault
az keyvault create \
    --resource-group myResourceGroup \
    --name myKeyVault \
    --location eastus \
    --sku standard

# Set secret
az keyvault secret set \
    --vault-name myKeyVault \
    --name DatabasePassword \
    --value "SecureP@ssword123"

# Get secret
az keyvault secret show \
    --vault-name myKeyVault \
    --name DatabasePassword \
    --query value -o tsv

# List secrets
az keyvault secret list --vault-name myKeyVault --output table

# Set secret with expiration
az keyvault secret set \
    --vault-name myKeyVault \
    --name TempApiKey \
    --value "temp-key-123" \
    --expires "2026-12-31T23:59:59Z"

# Grant access to managed identity
az keyvault set-policy \
    --name myKeyVault \
    --object-id $(az identity show -g myRG -n myManagedIdentity --query principalId -o tsv) \
    --secret-permissions get list

# Enable soft delete and purge protection
az keyvault update \
    --resource-group myResourceGroup \
    --name myKeyVault \
    --enable-soft-delete true \
    --enable-purge-protection true

# Delete secret (soft delete)
az keyvault secret delete --vault-name myKeyVault --name DatabasePassword

# Recover deleted secret
az keyvault secret recover --vault-name myKeyVault --name DatabasePassword

Google Secret Manager

# Create secret
gcloud secrets create my-database-password \
    --replication-policy="automatic"

# Add secret version
echo -n "SecureP@ssword123" | gcloud secrets versions add my-database-password --data-file=-

# Access secret (latest version)
gcloud secrets versions access latest --secret=my-database-password

# Access specific version
gcloud secrets versions access 1 --secret=my-database-password

# List secrets
gcloud secrets list

# List secret versions
gcloud secrets versions list my-database-password

# Grant access to service account
gcloud secrets add-iam-policy-binding my-database-password \
    --member="serviceAccount:my-sa@my-project.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

# Disable secret version
gcloud secrets versions disable 1 --secret=my-database-password

# Delete secret
gcloud secrets delete my-database-password

Encryption Services

AWS KMS

# Create KMS key
aws kms create-key \
    --description "My encryption key" \
    --key-usage ENCRYPT_DECRYPT \
    --origin AWS_KMS

KEY_ID=$(aws kms list-keys --query "Keys[0].KeyId" --output text)

# Create alias for key
aws kms create-alias \
    --alias-name alias/my-key \
    --target-key-id $KEY_ID

# Encrypt data
aws kms encrypt \
    --key-id alias/my-key \
    --plaintext fileb://plaintext.txt \
    --output text --query CiphertextBlob | base64 -d > encrypted.bin

# Decrypt data
aws kms decrypt \
    --ciphertext-blob fileb://encrypted.bin \
    --output text --query Plaintext | base64 -d > decrypted.txt

# Generate data key for client-side encryption
aws kms generate-data-key \
    --key-id alias/my-key \
    --key-spec AES_256

# Enable automatic key rotation
aws kms enable-key-rotation --key-id $KEY_ID

# Create key policy
aws kms put-key-policy \
    --key-id $KEY_ID \
    --policy-name default \
    --policy '{
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "Enable IAM User Permissions",
                "Effect": "Allow",
                "Principal": {"AWS": "arn:aws:iam::123456789012:root"},
                "Action": "kms:*",
                "Resource": "*"
            },
            {
                "Sid": "Allow use of the key",
                "Effect": "Allow",
                "Principal": {"AWS": "arn:aws:iam::123456789012:role/MyAppRole"},
                "Action": ["kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey"],
                "Resource": "*"
            }
        ]
    }'

# List keys
aws kms list-keys --output table

Azure Key Vault Keys

# Create RSA key
az keyvault key create \
    --vault-name myKeyVault \
    --name myRSAKey \
    --kty RSA \
    --size 2048

# Create EC key
az keyvault key create \
    --vault-name myKeyVault \
    --name myECKey \
    --kty EC \
    --curve P-256

# List keys
az keyvault key list --vault-name myKeyVault --output table

# Encrypt data (requires SDK - example using Azure CLI)
az keyvault key encrypt \
    --vault-name myKeyVault \
    --name myRSAKey \
    --algorithm RSA-OAEP \
    --value "SGVsbG8gV29ybGQ="

# Decrypt data
az keyvault key decrypt \
    --vault-name myKeyVault \
    --name myRSAKey \
    --algorithm RSA-OAEP \
    --value ""

# Enable key rotation policy
az keyvault key rotation-policy update \
    --vault-name myKeyVault \
    --name myRSAKey \
    --value '{
        "lifetimeActions": [{
            "action": {"type": "rotate"},
            "trigger": {"timeAfterCreate": "P90D"}
        }],
        "attributes": {"expiryTime": "P1Y"}
    }'

# Backup key
az keyvault key backup \
    --vault-name myKeyVault \
    --name myRSAKey \
    --file myRSAKey.backup

Google Cloud KMS

# Create key ring
gcloud kms keyrings create my-keyring \
    --location=global

# Create symmetric encryption key
gcloud kms keys create my-key \
    --keyring=my-keyring \
    --location=global \
    --purpose=encryption \
    --rotation-period=90d \
    --next-rotation-time=$(date -d "+90 days" --iso-8601)

# Encrypt data
gcloud kms encrypt \
    --keyring=my-keyring \
    --key=my-key \
    --location=global \
    --plaintext-file=plaintext.txt \
    --ciphertext-file=encrypted.bin

# Decrypt data
gcloud kms decrypt \
    --keyring=my-keyring \
    --key=my-key \
    --location=global \
    --ciphertext-file=encrypted.bin \
    --plaintext-file=decrypted.txt

# Create asymmetric signing key
gcloud kms keys create my-signing-key \
    --keyring=my-keyring \
    --location=global \
    --purpose=asymmetric-signing \
    --default-algorithm=ec-sign-p256-sha256

# List keys
gcloud kms keys list --keyring=my-keyring --location=global

# Grant encrypt/decrypt permissions
gcloud kms keys add-iam-policy-binding my-key \
    --keyring=my-keyring \
    --location=global \
    --member="serviceAccount:my-sa@my-project.iam.gserviceaccount.com" \
    --role="roles/cloudkms.cryptoKeyEncrypterDecrypter"

Compliance & Governance

Common Compliance Frameworks:
  • SOC 2 - Security, Availability, Processing Integrity, Confidentiality, Privacy
  • ISO 27001 - Information Security Management
  • GDPR - EU Data Protection Regulation
  • HIPAA - Healthcare data protection (US)
  • PCI DSS - Payment card data security
  • FedRAMP - US Federal cloud security

AWS Config & Security Hub

# Enable AWS Config
aws configservice put-configuration-recorder \
    --configuration-recorder name=default,roleARN=arn:aws:iam::123456789012:role/ConfigRole

# Enable Config rule (S3 bucket encryption)
aws configservice put-config-rule \
    --config-rule '{
        "ConfigRuleName": "s3-bucket-server-side-encryption-enabled",
        "Source": {
            "Owner": "AWS",
            "SourceIdentifier": "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
        }
    }'

# Check compliance
aws configservice get-compliance-details-by-config-rule \
    --config-rule-name s3-bucket-server-side-encryption-enabled

# Enable Security Hub
aws securityhub enable-security-hub --enable-default-standards

# Get findings
aws securityhub get-findings \
    --filters '{"SeverityLabel": [{"Value": "CRITICAL", "Comparison": "EQUALS"}]}'

# Enable GuardDuty
aws guardduty create-detector --enable

# List GuardDuty findings
aws guardduty list-findings --detector-id $(aws guardduty list-detectors --query DetectorIds[0] -o text)

Azure Policy & Defender

# List built-in policy definitions
az policy definition list \
    --query "[?policyType=='BuiltIn'].{Name:displayName, Category:metadata.category}" \
    --output table

# Assign policy (require encryption on storage accounts)
az policy assignment create \
    --name "require-storage-encryption" \
    --policy "/providers/Microsoft.Authorization/policyDefinitions/7c322315-e26d-4174-a99e-f49d351b4688" \
    --scope "/subscriptions/xxx"

# Check compliance
az policy state summarize \
    --filter "policyAssignmentName eq 'require-storage-encryption'"

# Enable Microsoft Defender for Cloud
az security pricing create \
    --name VirtualMachines \
    --tier Standard

# List security recommendations
az security assessment list --output table

# Enable Azure Blueprints (for governance)
az blueprint create \
    --name "SecurityBaseline" \
    --target-scope subscription \
    --description "Security baseline for new subscriptions"

GCP Organization Policies

# List available constraints
gcloud org-policies list-available-constraints \
    --organization=123456789012

# Set organization policy (disable external IPs on VMs)
gcloud org-policies set-policy \
    --organization=123456789012 \
    policy.yaml

# Example policy.yaml:
# name: organizations/123456789012/policies/compute.vmExternalIpAccess
# spec:
#   rules:
#     - denyAll: true

# Enable Security Command Center
gcloud services enable securitycenter.googleapis.com

# List findings
gcloud scc findings list organizations/123456789012 \
    --filter="state=\"ACTIVE\" AND severity=\"HIGH\""

# Create notification config for findings
gcloud scc notification-configs create my-config \
    --organization=123456789012 \
    --pubsub-topic=projects/my-project/topics/scc-findings \
    --filter="state=\"ACTIVE\""

# Enable Cloud Asset Inventory
gcloud asset search-all-resources \
    --scope=projects/my-project \
    --query="state:ACTIVE"

Best Practices

Identity Security:
  • Never use root/owner accounts for daily tasks
  • Enable MFA for all human users
  • Use service accounts/roles for applications
  • Rotate credentials regularly
  • Review access periodically and remove unused permissions

Security Checklist

  1. Least Privilege - Grant minimum required permissions
  2. Defense in Depth - Multiple security layers
  3. Encrypt Everything - Data at rest and in transit
  4. Audit Logging - Enable CloudTrail, Activity Logs, Audit Logs
  5. Secrets Management - Never hardcode secrets in code
  6. Network Security - Use private subnets, security groups
  7. Incident Response - Have a plan and test it
  8. Compliance - Understand and meet regulatory requirements
Secrets Best Practices:
  • Use dedicated secrets management services (Secrets Manager, Key Vault, Secret Manager)
  • Enable automatic rotation for database credentials
  • Use managed identities/IAM roles instead of access keys when possible
  • Never commit secrets to version control
  • Use environment variables or secrets injection at runtime

Conclusion

Cloud security requires a comprehensive approach covering identity, encryption, and compliance. Key takeaways:

Component AWS Azure GCP
Start With IAM roles over users Managed Identities Service Accounts + WIF
Secrets Secrets Manager + rotation Key Vault + RBAC Secret Manager + IAM
Compliance Config + Security Hub Policy + Defender Org Policies + SCC
Technology