or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

alb-controller.mdauth.mdcluster.mdfargate.mdindex.mdkubectl-provider.mdkubernetes-resources.mdnode-groups.mdservice-accounts.mdutilities.md
tile.json

auth.mddocs/

Authentication & Authorization

IAM to Kubernetes RBAC integration through aws-auth ConfigMap management and OIDC provider configuration for secure cluster access control.

Capabilities

AwsAuth Class

Manage IAM to Kubernetes RBAC mapping via aws-auth ConfigMap.

/**
 * Manage IAM to Kubernetes RBAC mapping via aws-auth ConfigMap
 */
class AwsAuth extends Construct {
  constructor(scope: Construct, id: string, props: AwsAuthProps);
  
  /** Add IAM role with masters permissions */  
  addMastersRole(role: iam.IRole, username?: string): void;
  /** Add IAM role mapping to Kubernetes RBAC */
  addRoleMapping(role: iam.IRole, mapping: AwsAuthMapping): void;
  /** Add IAM user mapping to Kubernetes RBAC */
  addUserMapping(user: iam.IUser, mapping: AwsAuthMapping): void;
  /** Add AWS account for cross-account access */
  addAccount(accountId: string): void;
}

/**
 * AwsAuth properties
 */
interface AwsAuthProps {
  /** EKS cluster */
  readonly cluster: ICluster;
}

/**
 * IAM to Kubernetes RBAC mapping
 */
interface AwsAuthMapping {
  /** Kubernetes username */
  readonly username: string;
  /** Kubernetes groups */
  readonly groups: string[];
}

Usage Examples:

import * as eks from "@aws-cdk/aws-eks";
import * as iam from "@aws-cdk/aws-iam";

// Get cluster's aws-auth
const awsAuth = new eks.AwsAuth(this, "AwsAuth", {
  cluster: cluster,
});

// Add developer role with limited permissions
const developerRole = new iam.Role(this, "DeveloperRole", {
  assumedBy: new iam.AccountRootPrincipal(),
});

awsAuth.addRoleMapping(developerRole, {
  username: "developer",
  groups: ["developer-group"],
});

// Add admin role with cluster admin permissions
const adminRole = new iam.Role(this, "AdminRole", {
  assumedBy: new iam.AccountRootPrincipal(),
});

awsAuth.addMastersRole(adminRole, "admin-user");

// Add read-only user
const readOnlyUser = new iam.User(this, "ReadOnlyUser");
awsAuth.addUserMapping(readOnlyUser, {
  username: "readonly",
  groups: ["system:authenticated", "readonly-group"],
});

// Add cross-account access
awsAuth.addAccount("123456789012");

RBAC Integration

Create Kubernetes RBAC resources to work with aws-auth mappings:

# ClusterRole for developers
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: developer-role
rules:
- apiGroups: [""]
  resources: ["pods", "services", "configmaps", "secrets"]
  verbs: ["get", "list", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets"]
  verbs: ["get", "list", "create", "update", "patch", "delete"]

---
# ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: developer-binding
subjects:
- kind: Group
  name: developer-group
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: developer-role
  apiGroup: rbac.authorization.k8s.io

OpenIdConnectProvider Class

OIDC identity provider for EKS cluster integration with IAM.

/**
 * OIDC identity provider for EKS cluster integration
 */
class OpenIdConnectProvider extends iam.OpenIdConnectProvider {
  constructor(scope: Construct, id: string, props: OpenIdConnectProviderProps);
}

/**
 * OIDC provider properties
 */
interface OpenIdConnectProviderProps {
  /** OIDC issuer URL */
  readonly url: string;
  /** Client IDs */
  readonly clientIds?: string[];
  /** Server certificate thumbprints */
  readonly thumbprints?: string[];
}

Usage Examples:

// Manual OIDC provider creation (usually automatic with cluster)
const oidcProvider = new eks.OpenIdConnectProvider(this, "OidcProvider", {
  url: cluster.clusterOpenIdConnectIssuer,
  clientIds: ["sts.amazonaws.com"],
});

// Use OIDC provider for service account trust relationships
const serviceAccountRole = new iam.Role(this, "ServiceAccountRole", {
  assumedBy: new iam.WebIdentityPrincipal(
    oidcProvider.openIdConnectProviderArn,
    {
      "StringEquals": {
        [`${cluster.clusterOpenIdConnectIssuer}:sub`]: "system:serviceaccount:default:my-service-account",
        [`${cluster.clusterOpenIdConnectIssuer}:aud`]: "sts.amazonaws.com",
      },
    }
  ),
});

AWS Auth ConfigMap Structure

The aws-auth ConfigMap has the following structure:

apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: arn:aws:iam::123456789012:role/NodeGroupRole
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
    - rolearn: arn:aws:iam::123456789012:role/DeveloperRole
      username: developer
      groups:
        - developer-group
  mapUsers: |
    - userarn: arn:aws:iam::123456789012:user/ReadOnlyUser  
      username: readonly
      groups:
        - system:authenticated
        - readonly-group
  mapAccounts: |
    - "123456789012"

Common RBAC Patterns

// Pattern 1: Namespace-scoped access
const namespaceRole = new iam.Role(this, "NamespaceRole", {
  assumedBy: new iam.AccountRootPrincipal(),
});

awsAuth.addRoleMapping(namespaceRole, {
  username: "namespace-user",
  groups: ["namespace-group"],
});

// Deploy namespace-scoped RBAC
cluster.addManifest("NamespaceRBAC", {
  apiVersion: "rbac.authorization.k8s.io/v1",
  kind: "Role",
  metadata: {
    namespace: "development",
    name: "namespace-role",
  },
  rules: [{
    apiGroups: [""],
    resources: ["pods", "services"],
    verbs: ["get", "list", "create", "delete"],
  }],
}, {
  apiVersion: "rbac.authorization.k8s.io/v1", 
  kind: "RoleBinding",
  metadata: {
    name: "namespace-binding",
    namespace: "development",
  },
  subjects: [{
    kind: "Group",
    name: "namespace-group",
    apiGroup: "rbac.authorization.k8s.io",
  }],
  roleRef: {
    kind: "Role",
    name: "namespace-role",
    apiGroup: "rbac.authorization.k8s.io",
  },
});

// Pattern 2: Read-only cluster access  
const readOnlyRole = new iam.Role(this, "ReadOnlyRole", {
  assumedBy: new iam.AccountRootPrincipal(),
});

awsAuth.addRoleMapping(readOnlyRole, {
  username: "readonly-user",
  groups: ["system:authenticated"],
});

cluster.addManifest("ReadOnlyRBAC", {
  apiVersion: "rbac.authorization.k8s.io/v1",
  kind: "ClusterRole", 
  metadata: { name: "readonly-role" },
  rules: [{
    apiGroups: [""],
    resources: ["*"],
    verbs: ["get", "list"],
  }, {
    apiGroups: ["apps", "extensions"],
    resources: ["*"],
    verbs: ["get", "list"],
  }],
}, {
  apiVersion: "rbac.authorization.k8s.io/v1",
  kind: "ClusterRoleBinding",
  metadata: { name: "readonly-binding" },
  subjects: [{
    kind: "User",
    name: "readonly-user",
    apiGroup: "rbac.authorization.k8s.io",
  }],
  roleRef: {
    kind: "ClusterRole",
    name: "readonly-role", 
    apiGroup: "rbac.authorization.k8s.io",
  },
});

Best Practices

  1. Principle of Least Privilege: Grant minimum required permissions
  2. Use Groups: Map IAM roles to Kubernetes groups, not individual users
  3. Namespace Isolation: Use namespace-scoped roles when possible
  4. Audit Access: Regularly review aws-auth mappings and RBAC policies
  5. Service Accounts: Use IRSA for pod-level AWS access instead of node-level permissions
// Best practice example: Environment-specific access
const prodRole = new iam.Role(this, "ProdRole", {
  assumedBy: new iam.AccountRootPrincipal(),
  roleName: "EKSProdAccess",
});

const devRole = new iam.Role(this, "DevRole", {
  assumedBy: new iam.AccountRootPrincipal(), 
  roleName: "EKSDevAccess",
});

awsAuth.addRoleMapping(prodRole, {
  username: "prod-user",
  groups: ["prod-admins"],
});

awsAuth.addRoleMapping(devRole, {
  username: "dev-user", 
  groups: ["dev-users"],
});