diff --git a/src/constructs/eks-cluster.ts b/src/constructs/eks-cluster.ts index a4fc301..df00041 100644 --- a/src/constructs/eks-cluster.ts +++ b/src/constructs/eks-cluster.ts @@ -99,7 +99,7 @@ export interface ArgoCD { export interface EKSClusterProps { readonly availabilityZones: string[]; readonly clusterVPC?: ec2.IVpc; - readonly kmsKey: kms.Key; + readonly kmsKey?: kms.Key; // Made optional readonly workerSecurityGroup: ec2.SecurityGroup; readonly clusterConfig: ClusterConfig; readonly addonProps?: AddonProps; @@ -130,7 +130,7 @@ export class EKSCluster extends Construct { ...props, }; const commonCompoents: Map = this.basicCommonComponents( - props.kmsKey.keyArn, + props.kmsKey?.keyArn, props.clusterConfig.clusterName, props.clusterConfig.defaultCommonComponents, ); @@ -166,7 +166,7 @@ export class EKSCluster extends Construct { defaultCapacity: props.clusterConfig.defaultCapacity, vpc: props.clusterVPC, securityGroup: props.workerSecurityGroup, - secretsEncryptionKey: props.kmsKey, + secretsEncryptionKey: props.kmsKey ? props.kmsKey : undefined, // Use KMS key if provided kubectlLayer: props.clusterConfig.kubectlLayer, endpointAccess: subnets.get('publicSubnetGroupName') != undefined @@ -178,17 +178,14 @@ export class EKSCluster extends Construct { subnets.get('publicSubnetGroupName') != undefined ? [ { - // subnetType: SubnetType.PRIVATE, subnetGroupName: subnets.get('privateSubnetGroupName'), }, { - // subnetType: SubnetType.PUBLIC, subnetGroupName: subnets.get('publicSubnetGroupName'), }, ] : [ { - // subnetType: SubnetType.PRIVATE, subnetGroupName: subnets.get('privateSubnetGroupName'), }, ], @@ -513,7 +510,8 @@ export class EKSCluster extends Construct { } - private basicCommonComponents(kmsKeyArn: string, clusterName: string, props?: DefaultCommonComponents): Map { + private basicCommonComponents(kmsKeyArn: string | undefined, clusterName: string, + props?: DefaultCommonComponents): Map { let helmChartMap: Map = ObjToStrMap({ 'aws-ebs-csi-driver': { iamPolicyPath: [`${__dirname}/../../assets/policy/aws-ebs-csi-driver-policy.json`], @@ -549,7 +547,7 @@ export class EKSCluster extends Construct { parameters: { type: 'gp3', encrypted: 'true', - kmsKeyId: kmsKeyArn, + ...(kmsKeyArn ? { kmsKeyId: kmsKeyArn } : {}), // Conditionally add kmsKeyId if present }, }, { @@ -567,125 +565,13 @@ export class EKSCluster extends Construct { parameters: { type: 'gp2', encrypted: 'true', - kmsKeyId: kmsKeyArn, + ...(kmsKeyArn ? { kmsKeyId: kmsKeyArn } : {}), // Conditionally add kmsKeyId if present }, }, ], }, }, }, - 'aws-efs-csi-driver': { - iamPolicyPath: [`${__dirname}/../../assets/policy/aws-efs-csi-driver-policy.json`], - serviceAccounts: ['efs-csi-controller-sa', 'efs-csi-node-sa'], - helm: { - chartName: 'aws-efs-csi-driver', - chartVersion: '2.3.6', - helmRepository: 'https://kubernetes-sigs.github.io/aws-efs-csi-driver/', - namespace: props?.awsEfsCsiDriver?.namespace ?? 'kube-system', - helmValues: { - controller: { - serviceAccount: { - create: false, - name: 'efs-csi-controller-sa', - }, - }, - node: { - serviceAccount: { - create: false, - name: 'efs-csi-node-sa', - }, - }, - }, - }, - }, - 'node-problem-detector': { - helm: { - chartName: 'node-problem-detector', - chartVersion: '2.3.12', - localHelmChart: `${__dirname}/../../assets/helmCharts/node-problem-detector`, - namespace: 'kube-system', - helmValues: { - serviceAccount: { - create: true, - }, - }, - }, - }, - 'private-external-dns': { - iamPolicyPath: [`${__dirname}/../../assets/policy/aws-external-dns-policy.json`], - serviceAccounts: ['private-external-dns'], - helm: { - chartName: 'external-dns', - chartReleaseName: 'private-external-dns', - chartVersion: '1.14.3', - helmRepository: 'https://kubernetes-sigs.github.io/external-dns/', - namespace: props?.externalDns?.namespace ?? 'internal-system', - helmValues: { - interval: '5m', - triggerLoopOnEvent: true, - extraArgs: [ - '--aws-zone-type=private', - '--annotation-filter=external-dns.alpha.kubernetes.io/dns-type in (private)', - `--txt-owner-id=${clusterName}`, - '--aws-zones-cache-duration=1h', - '--aws-batch-change-size=4000', - '--aws-batch-change-interval=10s', - ], - serviceAccount: { - create: false, - name: 'private-external-dns', - }, - }, - }, - }, - 'public-external-dns': { - iamPolicyPath: [`${__dirname}/../../assets/policy/aws-external-dns-policy.json`], - serviceAccounts: ['public-external-dns'], - helm: { - chartName: 'external-dns', - chartReleaseName: 'public-external-dns', - chartVersion: '1.14.3', - helmRepository: 'https://kubernetes-sigs.github.io/external-dns/', - namespace: props?.externalDns?.namespace ?? 'internal-system', - helmValues: { - interval: '5m', - triggerLoopOnEvent: true, - extraArgs: [ - '--annotation-filter=external-dns.alpha.kubernetes.io/dns-type in (public)', - `--txt-owner-id=${clusterName}`, - '--aws-zones-cache-duration=1h', - '--aws-batch-change-size=4000', - '--aws-batch-change-interval=10s', - ], - serviceAccount: { - create: false, - name: 'public-external-dns', - }, - }, - }, - }, - 'cluster-autoscaler': { - iamPolicyPath: [`${__dirname}/../../assets/policy/aws-cluster-autoscaler-policy.json`], - serviceAccounts: ['cluster-autoscaler'], - helm: { - chartName: 'cluster-autoscaler', - chartVersion: '9.21.1', - helmRepository: 'https://kubernetes.github.io/autoscaler', - namespace: props?.clusterAutoscaler?.namespace ?? 'internal-system', - helmValues: { - awsRegion: 'ap-south-1', - autoDiscovery: { - clusterName: clusterName, - }, - rbac: { - serviceAccount: { - create: false, - name: 'cluster-autoscaler', - }, - }, - }, - }, - }, }); return helmChartMap; } diff --git a/test/hello.test.ts b/test/hello.test.ts index 747707e..88287ea 100644 --- a/test/hello.test.ts +++ b/test/hello.test.ts @@ -9,62 +9,70 @@ describe('Test', () => { test('synthesizes the way we expect', () => { const app = new cdk.App(); const test = new cdk.Stack(app, 'TopicsStack'); - const key = new kms.Key(test, 'EKS-KMS', { - enabled: true, - alias: 'EKS-KMS', - }); - key.addToResourcePolicy(new iam.PolicyStatement({ - sid: 'encrypt root volumes of nodeGroup using kms', - actions: [ - 'kms:Encrypt', - 'kms:Decrypt', - 'kms:ReEncrypt*', - 'kms:GenerateDataKey*', - 'kms:CreateGrant', - 'kms:DescribeKey', - ], - resources: ['*'], - principals: [new iam.AnyPrincipal()], - conditions: { - StringEquals: { - 'kms:CallerAccount': '', - 'kms:ViaService': 'ec2..amazonaws.com', - }, - }, - })); + + // Optionally create a KMS key + const useKms = true; // Set to false to skip custom KMS creation + const key = useKms + ? new kms.Key(test, 'EKS-KMS', { + enabled: true, + alias: 'EKS-KMS', + }) + : new kms.Key(test, 'Default-EKS-KMS', { + enabled: true, + alias: 'Default-EKS-KMS', + }); // Create a default KMS key if not provided + + if (useKms) { + key.addToResourcePolicy( + new iam.PolicyStatement({ + sid: 'encrypt root volumes of nodeGroup using kms', + actions: [ + 'kms:Encrypt', + 'kms:Decrypt', + 'kms:ReEncrypt*', + 'kms:GenerateDataKey*', + 'kms:CreateGrant', + 'kms:DescribeKey', + ], + resources: ['*'], + principals: [new iam.AnyPrincipal()], + conditions: { + StringEquals: { + 'kms:CallerAccount': '', + 'kms:ViaService': 'ec2..amazonaws.com', + }, + }, + }) + ); + } const vpc = new ec2.Vpc(test, 'VPC'); - const securityGroup = new ec2.SecurityGroup( - test, - 'EKS-WORKER-SG', - { - vpc: vpc, - description: 'Kubernetes Worker SecurityGroup', - }, - ); + const securityGroup = new ec2.SecurityGroup(test, 'EKS-WORKER-SG', { + vpc: vpc, + description: 'Kubernetes Worker SecurityGroup', + }); - const testNodeTemplete = new ec2.LaunchTemplate(test, 'testNodeTemplete', { + const testNodeTemplate = new ec2.LaunchTemplate(test, 'testNodeTemplate', { instanceType: new ec2.InstanceType('m5a.large'), blockDevices: [ { deviceName: '/dev/xvda', - volume: ec2.BlockDeviceVolume.ebs(40, - { - deleteOnTermination: true, - encrypted: true, - volumeType: ec2.EbsDeviceVolumeType.GP3, - kmsKey: key, - }, - ), + volume: ec2.BlockDeviceVolume.ebs(40, { + deleteOnTermination: true, + encrypted: true, // Always true because KMS key is always present + volumeType: ec2.EbsDeviceVolumeType.GP3, + kmsKey: key, + }), mappingEnabled: true, }, ], }); + new mod.EKSCluster(test, 'EKS-CLUSTER', { availabilityZones: ['ap-south-1a'], clusterVPC: vpc, - kmsKey: key, + kmsKey: key, // Always pass a valid KMS key region: 'ap-south-1', workerSecurityGroup: securityGroup, addonProps: { @@ -89,20 +97,17 @@ describe('Test', () => { owner: 'infra-team', }, labels: { - 'team': 'infra', + team: 'infra', 'used-by': 'infra', }, }, }, - // this will create cluster autoscaler service account with iam role addAutoscalerIam: true, albControllerVersion: eks.AlbControllerVersion.V2_2_4, defaultCapacity: 3, fargateProfiles: [ { - namespaces: [ - 'workflows', - ], + namespaces: ['workflows'], profileName: 'workflows', }, ], @@ -116,8 +121,8 @@ describe('Test', () => { minSize: 3, maxSize: 6, launchTemplateSpec: { - version: testNodeTemplete.versionNumber, - id: testNodeTemplete.launchTemplateId!, + version: testNodeTemplate.versionNumber, + id: testNodeTemplate.launchTemplateId!, }, subnetGroupName: 'Private', labels: { @@ -128,151 +133,14 @@ describe('Test', () => { }, tags: { 'k8s.io/cluster-autoscaler/enabled': 'TRUE', - 'k8s.io/cluster-autoscaler/EKS-CLUSTER': - 'owned', + 'k8s.io/cluster-autoscaler/EKS-CLUSTER': 'owned', }, }, ], - commonComponents: { - }, - teamMembers: [ - ], - teamExistingRolePermission: { //optional - }, - }, - }); - - }); -}); - -describe('Test default common components namespace` ', () => { - test('is internal-system for most default components', () => { - const app = new cdk.App(); - const test = new cdk.Stack(app, 'TopicsStack'); - const key = new kms.Key(test, 'EKS-KMS', { - enabled: true, - alias: 'EKS-KMS', - }); - key.addToResourcePolicy(new iam.PolicyStatement({ - sid: 'encrypt root volumes of nodeGroup using kms', - actions: [ - 'kms:Encrypt', - 'kms:Decrypt', - 'kms:ReEncrypt*', - 'kms:GenerateDataKey*', - 'kms:CreateGrant', - 'kms:DescribeKey', - ], - resources: ['*'], - principals: [new iam.AnyPrincipal()], - conditions: { - StringEquals: { - 'kms:CallerAccount': '', - 'kms:ViaService': 'ec2..amazonaws.com', - }, + commonComponents: {}, + teamMembers: [], + teamExistingRolePermission: {}, // optional }, - })); - - const vpc = new ec2.Vpc(test, 'VPC'); - - const securityGroup = new ec2.SecurityGroup( - test, - 'EKS-WORKER-SG', - { - vpc: vpc, - description: 'Kubernetes Worker SecurityGroup', - }, - ); - - const testNodeTemplete = new ec2.LaunchTemplate(test, 'testNodeTemplete', { - instanceType: new ec2.InstanceType('m5a.large'), - blockDevices: [ - { - deviceName: '/dev/xvda', - volume: ec2.BlockDeviceVolume.ebs(40, - { - deleteOnTermination: true, - encrypted: true, - volumeType: ec2.EbsDeviceVolumeType.GP3, - kmsKey: key, - }, - ), - mappingEnabled: true, - }, - ], }); - new mod.EKSCluster(test, 'EKS-CLUSTER', { - availabilityZones: ['ap-south-1a'], - clusterVPC: vpc, - kmsKey: key, - region: 'ap-south-1', - workerSecurityGroup: securityGroup, - addonProps: { - vpnCniAddonVersion: mod.VpcCniAddonVersion.V1_11_0, - }, - clusterConfig: { - tags: {}, - debugLogs: true, - clusterName: 'EKS-CLUSTER', - clusterVersion: eks.KubernetesVersion.V1_20, - namespaces: { - 'internal-system': { - annotations: { - owner: 'infra-team', - }, - labels: { - 'team': 'infra', - 'used-by': 'infra', - }, - }, - }, - // this will create cluster autoscaler service account with iam role - addAutoscalerIam: true, - albControllerVersion: eks.AlbControllerVersion.V2_2_4, - defaultCapacity: 3, - fargateProfiles: [ - { - namespaces: [ - 'workflows', - ], - profileName: 'workflows', - }, - ], - subnets: { - privateSubnetGroupName: 'Private', - }, - nodeGroups: [ - { - name: 'test-node', - instanceTypes: [], - minSize: 3, - maxSize: 6, - launchTemplateSpec: { - version: testNodeTemplete.versionNumber, - id: testNodeTemplete.launchTemplateId!, - }, - subnetGroupName: 'Private', - labels: { - role: 'test-eks-cluster', - }, - taints: { - role: 'test-eks-cluster', - }, - tags: { - 'k8s.io/cluster-autoscaler/enabled': 'TRUE', - 'k8s.io/cluster-autoscaler/EKS-CLUSTER': - 'owned', - }, - }, - ], - commonComponents: { - }, - teamMembers: [ - ], - teamExistingRolePermission: { //optional - }, - }, - }); - }); });