ServerlessBase Blog
  • Understanding Cloud IAM: Identity and Access Management

    Learn how cloud IAM controls access to resources and protects your infrastructure from unauthorized access.

    Understanding Cloud IAM: Identity and Access Management

    You've probably deployed a service to the cloud and immediately realized you need to give someone else access. You open the console, find the right user, click "Add permissions," and assign a role. It works, but you're not entirely sure what you just did. You granted access, but did you grant too much? Too little? Is there a way to see who can do what and when?

    Cloud IAM (Identity and Access Management) is the system that answers these questions. It's the foundation of cloud security, determining who can access what resources and under what conditions. Without proper IAM, your cloud infrastructure is essentially an open door. With it, you have fine-grained control over every action.

    What Is IAM and Why Does It Matter

    IAM is the mechanism that maps identities to permissions. An identity is anything that can request access: a user, a service account, or an application. Permissions define what that identity can do: read, write, delete, or manage resources. The core principle is simple: grant the minimum necessary permissions to perform a task.

    Cloud providers implement IAM differently, but the concepts remain consistent. AWS uses roles and policies. Google Cloud uses IAM roles and bindings. Azure uses role-based access control (RBAC) with built-in and custom roles. All three systems share the same fundamental problem: managing permissions at scale across hundreds or thousands of resources.

    The complexity grows quickly. A single application might need access to a database, a storage bucket, a compute instance, and a messaging queue. Each of these resources has its own permission model. IAM provides the glue that ties these permissions together into a coherent security model.

    Core IAM Concepts

    Identities

    Identities are the actors in your IAM system. Users are human beings who need access to resources. Service accounts are non-human identities used by applications to authenticate. Groups collect users together for easier permission management. Roles define permissions that can be assumed by identities.

    Service accounts are particularly important in cloud environments. Unlike users, service accounts don't have passwords or multi-factor authentication. They authenticate using keys, certificates, or workload identity federation. This makes them ideal for automated systems that need consistent, reliable access.

    Permissions and Policies

    Permissions are the actual actions allowed on resources. Policies are the documents that define permissions. A policy is a JSON document that lists allowed actions, resources, and conditions. The simplest policy grants full access to a single resource:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::my-bucket/*"
        }
      ]
    }

    This policy allows any identity with it to read objects from the specified S3 bucket. The Effect field can be Allow or Deny. The Action field specifies the operation. The Resource field targets the specific resource. The Condition field adds time-based or IP-based restrictions.

    Roles and Principals

    Roles are temporary credentials that can be assumed by identities. A role contains a set of permissions but no persistent credentials. When an identity assumes a role, it receives temporary credentials valid for a limited time. This pattern is ideal for cross-account access and least privilege.

    Principals are the identities that can assume a role. A principal can be a user, a service account, or another role. When you attach a policy to a role, you're defining what the role can do. When you assign a role to a principal, you're defining what the principal can become.

    Trust Policies

    Trust policies define which principals can assume a role. They're attached to the role itself, not to the principal. A trust policy for a cross-account role might look like this:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::123456789012:root"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }

    This trust policy allows any identity in account 123456789012 to assume the role. The Action field restricts the operation to sts:AssumeRole. The Principal field specifies the trusted account. You can also restrict this to specific users or roles within the account.

    IAM vs Authentication vs Authorization

    These three concepts are often confused, but they serve different purposes. Authentication is the process of verifying an identity. Authorization is the process of determining what an identity can do. IAM handles both, but the distinction matters for security design.

    Authentication answers "who are you?" Authorization answers "what can you do?" IAM provides the authorization layer, while authentication is typically handled by a separate system like Okta, Auth0, or the cloud provider's identity service. In AWS, this separation is explicit: IAM handles authorization, while Cognito or other services handle authentication.

    This separation enables flexible authentication strategies. You can use a third-party identity provider for authentication while keeping IAM as the authorization layer. This pattern is common in enterprise environments where you need to integrate with existing identity systems.

    IAM Models Across Cloud Providers

    AWS IAM

    AWS IAM is the most mature and feature-rich system. It supports fine-grained permissions, resource-based policies, permission boundaries, and service control policies. AWS also provides organizations and accounts for multi-account management.

    AWS IAM uses the concept of managed policies and inline policies. Managed policies are reusable policies published by AWS or created in your account. Inline policies are attached directly to a user, group, or role. Managed policies are preferred for consistency and ease of management.

    Google Cloud IAM

    Google Cloud IAM uses roles and bindings. Roles are collections of permissions. Bindings associate identities with roles. The binding syntax is simpler than AWS policies but less flexible. Google Cloud also provides conditional IAM policies for time-based and IP-based restrictions.

    Google Cloud's approach is more declarative. You define what you want to allow, and the system enforces it. This reduces the chance of configuration errors but limits the ability to express complex permission requirements.

    Azure RBAC

    Azure RBAC uses built-in and custom roles. Built-in roles provide common permission sets like Owner, Contributor, and Reader. Custom roles allow you to create roles with specific permissions. Azure also supports role assignments at the resource, resource group, and subscription levels.

    Azure RBAC is integrated deeply with Azure's resource model. This integration makes it easy to manage permissions but can lead to permission sprawl as you create custom roles for every use case.

    IAM Best Practices

    Principle of Least Privilege

    Grant the minimum permissions required to perform a task. This is the golden rule of IAM. Start with the Reader role and add permissions only as needed. Regularly review permissions and remove those that are no longer required.

    The principle of least privilege is easy to state but hard to implement consistently. It requires ongoing maintenance as your infrastructure evolves. A common pattern is to create a dedicated IAM user for each application or service. This user should have only the permissions the application needs.

    Use Roles Instead of Users for Services

    Service accounts should use roles, not users. Roles provide temporary credentials that can be rotated automatically. Users require manual credential management and are more prone to security issues.

    When deploying applications to the cloud, always use roles. If your application needs access to a database, create a role with database permissions and assign it to the application's service account. This pattern works consistently across all cloud providers.

    Regular Permission Audits

    Review your IAM policies regularly. Look for overly permissive policies, unused permissions, and orphaned identities. Most cloud providers offer tools to help with this process, such as AWS Trusted Advisor or Azure Security Center.

    An audit should answer three questions: Who has access to what? What permissions do they have? Are these permissions still necessary? The answers to these questions should drive your permission changes.

    Enable MFA for All Users

    Multi-factor authentication adds a layer of security to user accounts. Even if a user's credentials are compromised, an attacker cannot access the account without the second factor. Most cloud providers require MFA for privileged accounts.

    MFA should be enabled for all user accounts, especially those with administrative privileges. This simple measure significantly reduces the risk of account compromise.

    Use IAM Roles for Cross-Account Access

    Cross-account access should always use roles, not direct user access. Roles provide temporary credentials that can be revoked instantly. Direct user access requires managing credentials across accounts, which is error-prone and insecure.

    When you need to grant access to another account, create a role in the target account with the necessary permissions. In the source account, create a trust policy that allows the source account to assume the role. This pattern is secure, auditable, and easy to manage.

    IAM Security Considerations

    Privilege Escalation

    Privilege escalation is the process of gaining higher permissions than you initially had. Attackers often target IAM policies to escalate privileges. Common vectors include misconfigured trust policies, overly permissive roles, and unused permissions.

    Prevent privilege escalation by regularly reviewing trust policies, limiting the permissions in roles, and removing unused permissions. Use tools like AWS IAM Access Analyzer or Azure Privileged Identity Management to detect and prevent privilege escalation attempts.

    Credential Rotation

    IAM credentials should be rotated regularly. For users, this means changing passwords and rotating access keys. For roles, rotation is automatic but should be monitored. Stale credentials are a common security vulnerability.

    Enable automatic credential rotation for all users and roles. Monitor for failed authentication attempts and credential usage anomalies. If a credential is compromised, rotate it immediately and investigate the source of the compromise.

    Audit Logging

    Enable IAM audit logging to track who did what and when. Most cloud providers offer detailed logs of IAM operations. These logs are essential for incident response and compliance.

    Configure logs to be sent to a secure, immutable storage location. Regularly review logs for suspicious activity. Set up alerts for unusual patterns, such as a user accessing resources outside their normal working hours.

    IAM in Practice: A Step-by-Step Example

    Let's walk through creating a secure IAM setup for a web application. We'll use AWS as an example, but the concepts apply to any cloud provider.

    Step 1: Create an IAM User for the Application

    First, create a dedicated IAM user for your application. This user should have no other permissions. Navigate to the IAM console, create a new user, and attach no policies. Save the access keys and store them securely.

    # Create the IAM user (this would be done in the AWS console)
    aws iam create-user --user-name my-web-app
     
    # Create access keys for the user
    aws iam create-access-key --user-name my-web-app

    Step 2: Create an IAM Role with Database Permissions

    Create a role that your application can assume. This role should have only the permissions the application needs. For a web application, this might include read access to a database and write access to a log bucket.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "rds-db:connect",
            "rds-db:sql"
          ],
          "Resource": "arn:aws:rds-db:us-east-1:123456789012:db:my-db"
        },
        {
          "Effect": "Allow",
          "Action": [
            "s3:PutObject",
            "s3:GetObject"
          ],
          "Resource": "arn:aws:s3:::my-app-logs/*"
        }
      ]
    }

    Step 3: Create a Trust Policy for the Role

    Define which principals can assume the role. In this case, we want the application user to assume the role.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::123456789012:user/my-web-app"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }

    Step 4: Assign the Role to the Application

    Attach the trust policy to the role and assign the role to the application user. This allows the application to assume the role and use the permissions defined in the role's policy.

    # Attach the trust policy to the role
    aws iam put-role-policy \
      --role-name my-web-app-role \
      --policy-name trust-policy \
      --policy-document file://trust-policy.json
     
    # Attach the permissions policy to the role
    aws iam put-role-policy \
      --role-name my-web-app-role \
      --policy-name db-access-policy \
      --policy-document file://db-access-policy.json

    Step 5: Configure the Application to Assume the Role

    Update your application to assume the role and use the temporary credentials. Most SDKs provide built-in support for this pattern.

    // Assume the role and get temporary credentials
    const sts = new STSClient({ region: 'us-east-1' });
     
    const assumeRoleCommand = new AssumeRoleCommand({
      RoleArn: 'arn:aws:iam::123456789012:role/my-web-app-role',
      RoleSessionName: 'my-web-app-session',
      DurationSeconds: 3600,
    });
     
    const { Credentials } = await sts.send(assumeRoleCommand);
     
    // Use the temporary credentials to access resources
    const rds = new RDSClient({
      region: 'us-east-1',
      credentials: {
        accessKeyId: Credentials.AccessKeyId,
        secretAccessKey: Credentials.SecretAccessKey,
        sessionToken: Credentials.SessionToken,
      },
    });

    Step 6: Verify and Test

    Test the configuration by running a simple query against the database. Verify that the application can access the resources it needs and cannot access resources it shouldn't.

    # Test the database connection
    aws rds-db execute-sql \
      --db-instance-identifier my-db \
      --db-name mydb \
      --db-user admin \
      --sql "SELECT 1"

    Common IAM Mistakes

    Overly Permissive Policies

    Creating policies with broad permissions like : is a common mistake. This grants unlimited access to all resources and services. Overly permissive policies increase your attack surface and make it harder to track who did what.

    Always start with the principle of least privilege. Grant only the specific permissions needed for the task. Use resource-specific policies to limit access to particular resources rather than all resources of a type.

    Forgetting to Rotate Credentials

    Access keys and passwords should be rotated regularly. Stale credentials are a security risk. If a credential is compromised, an attacker can access your resources until you discover the compromise.

    Enable automatic credential rotation for all users and roles. Set up alerts for failed authentication attempts. Monitor for unusual activity patterns that might indicate a compromised credential.

    Not Using Roles for Cross-Account Access

    Direct user access between accounts is insecure and difficult to manage. Roles provide temporary credentials that can be revoked instantly. They also provide better audit trails and easier permission management.

    Always use roles for cross-account access. Create a role in the target account with the necessary permissions. In the source account, create a trust policy that allows the source account to assume the role.

    Ignoring Service Control Policies

    Service control policies (SCPs) restrict the permissions available to IAM principals. They're useful for implementing organizational boundaries and preventing privilege escalation. Ignoring SCPs can lead to permission sprawl and security issues.

    Use SCPs to define the maximum permissions available to principals in an organization. This prevents users from creating overly permissive policies and helps maintain a consistent security posture.

    IAM and Platform Engineering

    Modern platform engineering practices rely heavily on IAM. Internal developer platforms (IDPs) use IAM to manage access to self-service infrastructure. Developers request access to environments and resources through a self-service portal. The platform team reviews and grants access using IAM policies.

    Platforms like ServerlessBase automate much of this process. They provide pre-configured environments with minimal permissions. Developers can request access to specific resources through a UI. The platform team approves requests and grants temporary access. This pattern reduces the burden on platform engineers while maintaining security.

    Conclusion

    IAM is the foundation of cloud security. It determines who can access what resources and under what conditions. The principles of least privilege, role-based access, and regular audits are essential for maintaining a secure cloud environment.

    The key takeaways are: grant the minimum necessary permissions, use roles instead of users for services, enable MFA for all users, and regularly audit your IAM policies. These practices will help you maintain a secure and manageable cloud environment.

    The next step is to audit your current IAM setup. Identify overly permissive policies, unused permissions, and orphaned identities. Make incremental changes to improve security without disrupting operations. Remember that IAM is an ongoing process, not a one-time configuration task.

    Platforms like ServerlessBase can simplify IAM management by providing automated permission controls and self-service access management. This reduces the administrative burden while maintaining security and compliance.

    Leave comment