EKS Cluster Module - Reference Guide

Overview

The Kosmos EKS Cluster module creates a simple production-ready EKS cluster using the Kosmos Provider, conforming to Samsung Security Checklist requirements.

Requirements

NameVersion
terraform>= 1.13
aws>= 5.95
kosmos>= 0.11

Artifacts

Download the Terraform module from the Terraform Artifacts page:

ArtifactVersion
EKS (Amazon Web Services) Modulev3.2.2

Quick Start

module "eks_cluster" {
  source = "https://srin-s3-terraform-modules.s3.ap-southeast-1.amazonaws.com/terraform-kosmos-eks-v3.2.2.tar.gz"

  fleet_name          = "production-fleet"
  kosmos_owner        = "admin-user"
  aws_region          = "ap-northeast-2"
  cluster_name        = "prod-eks-cluster"
  eks_version         = "1.30"
  oidc_provider_arn   = "arn:aws:iam::123456789:oidc-provider/console.kosmos.spcplatform.com/oidc-name"
  public_access_cidrs = ["210.94.41.89/32"]
}

Inputs

NameTypeRequiredDefaultDescription
fleet_namestring-Target fleet in Kosmos where the cluster will be deployed
kosmos_ownerstring-Kosmos user ID as owner of the cluster
cluster_namestring-EKS cluster name
oidc_provider_arnstring-OIDC ARN for temporary AWS credentials
public_access_cidrslist(string)-List of IP addresses that can access the cluster
aws_regionstring-AWS region target
vpc_cidrstring-"10.0.0.0/16"VPC CIDR block
create_vpcbool-trueWhether to create a new VPC
eks_versionstring-Kubernetes version (e.g., “1.30”)
external_nat_ip_idslist(string)-[]List of Elastic IDs addresses to be used for the NAT Gateway
enable_nat_gatewaybool-trueA Boolean to create a NAT Gateway
cluster_public_accessbool-trueWhether to allow public access to the cluster
bastion_instance_typestring-"t3.micro"Bastion host instance type
bastion_volume_sizenumber-20Bastion host EBS volume size in GB
bastion_ssh_portnumber-4222SSH port for bastion host
bastion_statestring-stoppedState of the Bastion instance. Valid values are stopped, running
bastion_eip_idstring-nullElastic IPs ID to be assigned to the Bastion instance. Create Elastic IP is empty.
ami_typestring-"amazon-linux-2023/x86_64/standard"EKS-optimized AMI type
node_groupsobject-[]Node groups configuration
create_eks_node_security_groupbool-trueWhether to create EKS control plane security group
vpc_idstring-nullVPC ID (required if create_vpc = false)
eks_node_security_group_idsstring-nullEKS security group ID (required if create_eks_control_plane_security_group = false)
eks_subnet_idslist(string)-[]EKS subnet IDs (required if create_vpc = false)
eks_bastion_subnet_idstring-nullBastion subnet ID (required if create_vpc = false)
kosmos_tierstring-nullKosmos environment tier (dev, stg, or null for PRD)
vpc_endpoint_security_group_idsstring-""VPC Endpoint security group ID (required if create_eks_node_security_group = true and create_vpc = false)
enabled_vpc_endpoint_gatewaylist(string)-[]Map of services to enable VPC endpoints for the EKS cluster type Gateway
enabled_vpc_endpoint_interfacelist(string)-[]Map of services to enable VPC endpoints for the EKS cluster type Interface
node_group_security_group_egress_rulemap(object)-{}Map of Egress Rule for the Node Group’s Security Group Rules
node_group_security_group_ingress_rulemap(object)-{}Map of Ingress Rule for the Node Group’s Security Group Rules
create_eks_cluster_security_groupbool-trueWhether to create EKS Cluster security group
eks_cluster_security_group_idsstring-""ID of the AWS security group to associate with eks cluster
cluster_security_group_ingress_rulemap(object)-{}Map of Ingress Rule for the Cluster’s Security Group Rules
cluster_security_group_egress_rulemap(object)-{}Map of Egress Rule for the Cluster’s Security Group Rules
enable_irsabool-trueTo create an IAM OIDC identity provider for the EKS cluster
oidc_provider_audienceslist(string)-[]Audiences for the IAM OIDC identity provider

Examples

Basic Usage

module "eks_cluster" {
  source = "https://srin-s3-terraform-modules.s3.ap-southeast-1.amazonaws.com/terraform-kosmos-eks-v3.2.2.tar.gz"

  fleet_name = "production-fleet"
  cluster_name = "prod-eks-cluster"
  kosmos_owner = "admin"
  oidc_provider_arn = "arn:aws:iam::123456789:oidc-provider/console.kosmos.spcplatform.com/oidc-name"
  public_access_cidrs = ["10.0.0.0/8", "192.168.0.0/16"]
  aws_region = "ap-southeast-1"
  eks_version = "1.30"
}

Custom VPC Usage

module "eks_cluster" {
  source = "https://srin-s3-terraform-modules.s3.ap-southeast-1.amazonaws.com/terraform-kosmos-eks-v3.2.2.tar.gz"

  create_vpc = false
  vpc_id = "vpc-12345678"
  eks_subnet_ids = ["subnet-12345678", "subnet-87654321"]
  eks_bastion_subnet_id = "subnet-11111111"

  fleet_name = "staging-fleet"
  cluster_name = "staging-eks-cluster"
  kosmos_owner = "dev-team"
  eks_version = "1.30"
  oidc_provider_arn = "arn:aws:iam::123456789:oidc-provider/console.kosmos.spcplatform.com/oidc-name"
  public_access_cidrs = ["10.0.0.0/8"]
  aws_region = "ap-southeast-1"
}

Fully Private Cluster

  • Disabled NAT Gateway by setting enable_nat_gateway to false
  • Setting up the minimum Security group permission
  • Setting up the minimum VPC Endpoint requred
module "eks_cluster" {
  source = "https://srin-s3-terraform-modules.s3.ap-southeast-1.amazonaws.com/terraform-kosmos-eks-v3.2.2.tar.gz"

  # EKS Node Group Security Group
  node_group_security_group_egress_rule  = {}
  node_group_security_group_ingress_rule = {}

  # EKS Cluster Security Group
  cluster_security_group_ingress_rule = {}
  cluster_security_group_egress_rule  = {}

  # NAT Gateway
  enable_nat_gateway  = false

  # VPC Endpoint
  enabled_vpc_endpoint_gateway   = ["s3"]
  enabled_vpc_endpoint_interface = ["ec2", "ecr.api", "ecr.dkr", "eks", "kms", "logs", "elasticloadbalancing", "autoscaling", "eks-auth", "sts"]
}

Semi Private Cluster

  • Enabled NAT Gateway by setting enable_nat_gateway to true
  • Defined the Security group permission
  • Setting up the minimum VPC Endpoint requred
module "eks_cluster" {
  source = "https://srin-s3-terraform-modules.s3.ap-southeast-1.amazonaws.com/terraform-kosmos-eks-v3.2.2.tar.gz"

  # EKS Node Group Security Group
  node_group_security_group_egress_rule = {
    allow_all = {
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
      description = "Allow all communication"
    }
    cluster-node = {
      from_port                = 443
      to_port                  = 443
      protocol                 = "all"
      source_security_group_id = module.eks_cluster.aws_security_group_cluster_id
      description              = "Allow all communication from cluster to node"
    }
  }
  node_group_security_group_ingress_rule = {
    cluster-node = {
      from_port                = 443
      to_port                  = 443
      protocol                 = "all"
      source_security_group_id = module.eks_cluster.aws_security_group_cluster_id
      description              = "Allow all communication from node to cluster"
    }
  }

  # EKS Cluster Security Group
  cluster_security_group_ingress_rule = {
    cluster-node = {
      from_port                = 443
      to_port                  = 443
      protocol                 = "all"
      source_security_group_id = module.eks_cluster.aws_security_group_node_id
      description              = "Allow all communication from node to cluster"
    }
  }
  cluster_security_group_egress_rule = {
    allow_all = {
      from_port   = 443
      to_port     = 443
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
      description = "Allow all communication"
    }
    cluster-node = {
      from_port                = 443
      to_port                  = 443
      protocol                 = "all"
      source_security_group_id = module.eks_cluster.aws_security_group_node_id
      description              = "Allow all communication from cluster to node"
    }
  }

  # NAT Gateway
  enable_nat_gateway = true

  # VPC Endpoint
  enabled_vpc_endpoint_gateway   = ["s3"]
  enabled_vpc_endpoint_interface = ["ec2", "ecr.api", "ecr.dkr", "eks", "kms", "logs", "elasticloadbalancing", "autoscaling", "eks-auth", "sts"]
}

Advanced Configuration

module "eks_cluster" {
  source = "https://srin-s3-terraform-modules.s3.ap-southeast-1.amazonaws.com/terraform-kosmos-eks-v3.2.2.tar.gz"

  fleet_name = "advanced-fleet"
  cluster_name = "advanced-eks-cluster"
  kosmos_owner = "platform-team"
  eks_version = "1.30"
  oidc_provider_arn = "arn:aws:iam::123456789:oidc-provider/console.kosmos.spcplatform.com/oidc-name"
  public_access_cidrs = ["10.0.0.0/8"]
  aws_region = "ap-southeast-1"

  # Custom node groups
  node_groups = [
    {
      name = "worker-nodes"
      instance_type = "t3.medium"
      min_size = 2
      max_size = 10
      desired_size = 3
    }
  ]

  # Custom bastion configuration
  bastion_instance_type = "t3.small"
  bastion_volume_size = 30
  bastion_ssh_port = 2222
}

Resources Created

kosmos-eks

AWS Resources

  • VPC: 3 public subnets, 3 private subnets, NAT Gateway, Internet Gateway
  • Bastion Host: EC2 instance for secure cluster access
  • KMS: Dedicated keys for S3 bucket and cluster encryption
  • Security Groups: Default and EKS-specific security groups
  • S3 Bucket: Encrypted bucket for logs with lifecycle policies
  • IAM: Kosmos role and EKS cluster role

Kosmos Resources

  • EKS Cluster: Kubernetes cluster with logging enabled
  • Security Groups: EKS cluster security group

Security Features

This module implements the following security measures:

  • Secrets Encryption: KMS-based encryption for cluster secrets
  • Private Access: API server endpoint access control
  • Network Security: VPC flow logs and security group restrictions
  • Data Protection: S3 bucket encryption and lifecycle policies
  • Access Control: IAM roles and policies for least privilege access

Required Permissions

The following AWS permissions are required to use this module:

KMS

  • kms:CreateKey, kms:DescribeKey, kms:EnableKey, kms:DisableKey
  • kms:ScheduleKeyDeletion, kms:CancelKeyDeletion
  • kms:CreateAlias, kms:DeleteAlias, kms:UpdateAlias
  • kms:ListAliases, kms:PutKeyPolicy, kms:GetKeyPolicy, kms:ListKeys

IAM

  • iam:CreateRole, iam:GetRole, iam:DeleteRole
  • iam:UpdateAssumeRolePolicy, iam:AttachRolePolicy, iam:DetachRolePolicy
  • iam:ListAttachedRolePolicies, iam:PassRole
  • sts:GetCallerIdentity

S3

  • s3:CreateBucket, s3:DeleteBucket, s3:PutBucketAcl, s3:GetBucketAcl
  • s3:PutBucketPolicy, s3:GetBucketPolicy, s3:PutBucketPublicAccessBlock
  • s3:GetBucketPublicAccessBlock, s3:PutBucketVersioning, s3:GetBucketVersioning
  • s3:PutBucketLogging, s3:GetBucketLogging, s3:PutBucketLifecycleConfiguration
  • s3:GetBucketLifecycleConfiguration, s3:PutEncryptionConfiguration
  • s3:GetEncryptionConfiguration, s3:PutBucketTagging, s3:GetBucketTagging

VPC

  • ec2:CreateVpc, ec2:DeleteVpc, ec2:DescribeVpcs, ec2:ModifyVpcAttribute
  • ec2:CreateSubnet, ec2:DeleteSubnet, ec2:DescribeSubnets
  • ec2:CreateRouteTable, ec2:DeleteRouteTable, ec2:AssociateRouteTable
  • ec2:DisassociateRouteTable, ec2:CreateRoute, ec2:DeleteRoute
  • ec2:ReplaceRoute, ec2:ReplaceRouteTableAssociation
  • ec2:CreateInternetGateway, ec2:AttachInternetGateway, ec2:DetachInternetGateway
  • ec2:DeleteInternetGateway, ec2:CreateNatGateway, ec2:DeleteNatGateway
  • ec2:DescribeNatGateways, ec2:AllocateAddress, ec2:ReleaseAddress
  • ec2:CreateSecurityGroup, ec2:DeleteSecurityGroup
  • ec2:AuthorizeSecurityGroupIngress, ec2:RevokeSecurityGroupIngress
  • ec2:AuthorizeSecurityGroupEgress, ec2:RevokeSecurityGroupEgress
  • ec2:CreateNetworkAcl, ec2:DeleteNetworkAcl, ec2:CreateNetworkAclEntry
  • ec2:DeleteNetworkAclEntry, ec2:AssociateNetworkAcl, ec2:DisassociateNetworkAcl
  • ec2:CreateVpcEndpoint, ec2:DeleteVpcEndpoints, ec2:DescribeVpcEndpoints
  • ec2:CreateFlowLogs, ec2:DeleteFlowLogs, ec2:DescribeFlowLogs
  • ec2:DescribeNetworkInterfaces, ec2:DescribeTags, ec2:DescribeRouteTables
  • ec2:DescribeVpcs, ec2:DescribeSecurityGroups, ec2:CreateTags
  • ec2:DescribeAvailabilityZones

EKS

  • eks:*
  • autoscaling:CreateAutoScalingGroup, autoscaling:UpdateAutoScalingGroup
  • autoscaling:DeleteAutoScalingGroup, autoscaling:DescribeAutoScalingGroups
  • logs:CreateLogGroup, logs:PutRetentionPolicy, logs:DescribeLogGroups

Samsung Security Checklist

List of checklist that conform the Samsung Security Checklist

  • EC2
    • Instance metadata Service
      • Ensure that the vulnerable version of Instance metadata service is not in use (only IMDS V2 should be in use, and if not necessary, Instance metadata service should be disabled)
  • EKS
    • Cluster Management
      • Ensure that “Secrets encryption” is turned on
    • Networking Management
      • Ensure the API Server Endpoint Access is private and accept the requests only from the EKS VPC
      • If the value of “API server endpoint access” is ‘Public’, ensure that the required access targets are limited.
    • Logging Management
  • S3 Bucket Data Protection
    • In-Transit Encrypted
      • Ensure that S3 buckets use encrypted communication protocol (HTTPS)
  • S3 Bucket Management
    • S3 Assets Management (Required Tags)
      • Ensure that the required tags are attached to all the S3 buckets.
    • Data Retention Policy
      • Ensure that lifecycle rule is set on confidential/personal information containing S3 buckets to delete the data periodically.
  • Logging Configuration
    • Enabling VPC Flow logs
      • Ensure that the VPC Flow logs is enabled to log.
  • KMS
    • Key generation
      • Ensure that keys are dedicated for the sole purpose
    • Key Rotation Configuration
      • Ensure that the Key Rotation is activated.

List of checklist that does not conform to the Samsung Security Checklist

  • VPC Configuration
    • Private Subnet Access Control
      • Check if nat is connected to routetables of private subnet.

        violation is due to NAT gateway being needed for EKS cluster to connect towards Kosmos' control plane & to pull container images

  • Network ACLs & Security groups
    • Security Group Management
      • Ensure that Security Group’s inbound / outbound rules comply the following management policy.
        • A Policy allowing wide range of CIDR blocks (exceeding 24 bit mask)
        • Do not use anywhere outbound (0.0.0.0/0)
        • A Policy allowing all ports
    • SG Description Management
      • Ensure that Inbound / Outbound rules of the Security Groups have the mandatory description

    The EKS default security group is causing this violation.

  • EKS
    • Security Group Management
      • Ensure that Cluster’s security groups only allow the communications necessary for the EKS Cluster.

      The EKS default security group is not managed by Terraform.

Required Permissions

Download the full assets

Edit this page on GitHub