IAM to Kubernetes RBAC integration through aws-auth ConfigMap management and OIDC provider configuration for secure cluster access control.
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");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.ioOIDC 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",
},
}
),
});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"// 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 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"],
});