cloudbees / terraform-aws-cloudbees-ci-eks-addon

CloudBees CI Add-on for AWS EKS
https://registry.terraform.io/modules/cloudbees/cloudbees-ci-eks-addon/aws
MIT License
8 stars 10 forks source link

[Blueprints, 02-at-scale] Replace Instance Profile by Pod Identities #56

Open carlosrodlop opened 5 months ago

carlosrodlop commented 5 months ago

After discussions with @Vlatombe it seems a better approach to use Pod Identity

Than current instances profile configuration (Obsolete). Ref:

carlosrodlop commented 3 weeks ago

Configuration

Pod Identities Tested successfully by

1.- Removing Instance Profile configuration

data "aws_iam_policy_document" "managed_ng_assume_role_policy" {
  statement {
    sid = "EKSWorkerAssumeRole"

    actions = [
      "sts:AssumeRole",
    ]
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "managed_ng" {
  name                  = local.cbci_iam_role
  description           = "EKS Managed Node group IAM Role"
  assume_role_policy    = data.aws_iam_policy_document.managed_ng_assume_role_policy.json
  path                  = "/"
  force_detach_policies = true
  # Mandatory for EKS Managed Node Group
  managed_policy_arns = [
    "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
    "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
    "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",
    "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
  ]
  # Additional Permissions for for EKS Managed Node Group per https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html
  inline_policy {
    name = "${local.name}-iam_inline_policy"
    policy = jsonencode(
      {
        "Version" : "2012-10-17",
        #https://docs.cloudbees.com/docs/cloudbees-ci/latest/pipelines/cloudbees-cache-step#_s3_configuration
        "Statement" : [
          {
            "Sid" : "cbciS3BucketputGetDelete",
            "Effect" : "Allow",
            "Action" : [
              "s3:PutObject",
              "s3:GetObject",
              "s3:DeleteObject"
            ],
            "Resource" : "${local.cbci_s3_location}/*"
          },
          {
            "Sid" : "cbciS3BucketList",
            "Effect" : "Allow",
            "Action" : "s3:ListBucket",
            "Resource" : module.cbci_s3_bucket.s3_bucket_arn
            "Condition" : {
              "StringLike" : {
                "s3:prefix" : "cbci/*"
              }
            }
          },
        ]
      }
    )
  }
  tags = var.tags
}

resource "aws_iam_instance_profile" "managed_ng" {
  name = local.cbci_instance_profile
  role = aws_iam_role.managed_ng.name
  path = "/"

  lifecycle {
    create_before_destroy = true
  }

  tags = var.tags
}  

2.- Enable Pod Identity Agent Addon

module "eks_blueprints_addons" {
  source = "aws-ia/eks-blueprints-addons/aws"
  #vEKSBpAddonsTFMod#
  version = "1.15.1"

  cluster_name      = module.eks.cluster_name
  cluster_endpoint  = module.eks.cluster_endpoint
  oidc_provider_arn = module.eks.oidc_provider_arn
  cluster_version   = module.eks.cluster_version

  eks_addons = {
    ...
    eks-pod-identity-agent = {}
  }
}

3.- Adding Pod Identity

data "aws_iam_policy_document" "assume_role" {
  statement {
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["pods.eks.amazonaws.com"]
    }

    actions = [
      "sts:AssumeRole",
      "sts:TagSession"
    ]
  }
}

resource "aws_iam_role" "s3" {
  name               = "eks-pod-identity-s3-role"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
  inline_policy {
    name = "${local.name}-iam_inline_policy"
    policy = jsonencode(
      {
        "Version" : "2012-10-17",
        #https://docs.cloudbees.com/docs/cloudbees-ci/latest/pipelines/cloudbees-cache-step#_s3_configuration
        "Statement" : [
          {
            "Sid" : "cbciS3BucketputGetDelete",
            "Effect" : "Allow",
            "Action" : [
              "s3:PutObject",
              "s3:GetObject",
              "s3:DeleteObject"
            ],
            "Resource" : "${local.cbci_s3_location}/*"
          },
          {
            "Sid" : "cbciS3BucketList",
            "Effect" : "Allow",
            "Action" : "s3:ListBucket",
            "Resource" : module.cbci_s3_bucket.s3_bucket_arn
            "Condition" : {
              "StringLike" : {
                "s3:prefix" : "cbci/*"
              }
            }
          },
        ]
      }
    )
  }
}

resource "aws_eks_pod_identity_association" "cjoc" {
  cluster_name    = module.eks.cluster_name
  namespace       = module.eks_blueprints_addon_cbci.cbci_namespace
  service_account = "cjoc"
  role_arn        = aws_iam_role.s3.arn
}

resource "aws_eks_pod_identity_association" "controllers" {
   cluster_name    = module.eks.cluster_name
   namespace       = module.eks_blueprints_addon_cbci.cbci_namespace
   service_account = "jenkins"
   role_arn        = aws_iam_role.s3.arn
 }

4.- Uploading manually the following version of the plugins (thanks @Vlatombe). The aws-java-sdk related plugins required an updated. It is expected to by in CB CAP by the next release (Until then it is not possible to configure Pod Identity for CBCI)

Proposal design: Include the configuration of the Identity Pods within the Terraform Module, not in the blueprints

Points to validate

1.-Check EKS Cluster > Access > Pod Identity associations

image

2.- Pod Manifest (OC or Controllers) includes Env and Vol configuration as explained in https://docs.aws.amazon.com/eks/latest/userguide/pod-id-how-it-works.html

kubectl get pod team-b-0 -n cbci -o yaml | grep -i aws
        -DMASTER_ENDPOINT="https://team-b.crl.aws.ps.beescloud.com/" -DMASTER_WEBSOCKET="false"
        -Dcom.cloudbees.networking.hostname="crl.aws.ps.beescloud.com" -Dcom.cloudbees.networking.port=443
    - name: AWS_STS_REGIONAL_ENDPOINTS
    - name: AWS_DEFAULT_REGION
    - name: AWS_REGION
    - name: AWS_CONTAINER_CREDENTIALS_FULL_URI
    - name: AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE
      value: /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token
    - mountPath: /var/run/secrets/pods.eks.amazonaws.com/serviceaccount
          audience: pods.eks.amazonaws.com

Issue : Within the same identity configuration than Controllers, OC does not fetch credentials from AWS

resource "kubectl_manifest" "test_association" {

  yaml_body = <<YAML
apiVersion: v1
kind: Pod
metadata:
  name: aws-cli
  namespace: cbci
spec:
  serviceAccount: cjoc
  containers:
    - name: aws-cli
      image: amazon/aws-cli:latest
      command: ["sleep", "infinity"]
YAML
}