Installing a connector on EKS Using Terraform

This guide is intended for admins managing a Connector in the environment

📘 You have chosen the advanced installation method

You can also easily connect AWS in Apono following this UI guide here

How to install the Connector on EKS Using Terraform

Prerequisites

  • Required CLI: terraform

Step 1 - Create Connector

Important: before you start, copy the connector Terraform params and export them in the terminal.

Step 2 - Configure Variables

variable "eks_cluster_name" {
  type    = string
  default = "PLEASE_REPLACE_WITH_CLUSTER_NAME"
}

variable "CONNECTOR_ID" {
  type    = string
  description = "Apono Connector ID"
}

variable "APONO_TOKEN" {
  type    = string
  description = "Apono authoriozatrion token"
  sensitive = true
}

variable "APONO_WEBSOCKET_URL" {
  type    = string
  description = "Apono websocket URL"
}

variable "aws_region" {
  type    = string
  default = "us-east-1"
}

variable "service_account_name" {
  type    = string
  default = "apono"
}

variable "namespace" {
  type    = string
  default = "apono"
}

Step 3 - Add necessary Terraform providers

** if you already use your own providers, you can skip this step

provider "aws" {
  alias  = "apono"
  region = var.aws_region
}

data "aws_eks_cluster" "cluster" {
  name     = var.eks_cluster_name
}

data "aws_eks_cluster_auth" "eks_cluster_auth" {
  name     = var.eks_cluster_name
}

data "aws_caller_identity" "aws_account" {
}

locals {
  aws_account_id = data.aws_caller_identity.aws_account.account_id
  oidc_provider = replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, "https://", "")
  config_path = "~/.kube/config"
  config_context = "my-context" 
}

provider "kubernetes" {
  config_path = local.config_path
  config_context = local.config_context
}

provider "helm" {
  kubernetes {
    config_path = local.config_path
    config_context = local.config_context
  }
}

Run terraform init to validate it works

Step 4 - Add EKS cluster OIDC provider to your IAM

It's required that your EKS cluster OIDC provider will be added to your IAM. &#xNAN;This step is required only once, and you may have already done it.

data "aws_eks_cluster" "eks_cluster" {
  name = var.eks_cluster_name
}

data "tls_certificate" "tls_cert" {
  url = data.aws_eks_cluster.eks_cluster.identity[0].oidc[0].issuer
}

resource "aws_iam_openid_connect_provider" "eks-oidc-provider" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.tls_cert.certificates[0].sha1_fingerprint]
  url             = data.aws_eks_cluster.eks_cluster.identity[0].oidc[0].issuer
}

Step 5 - Create the Connector IAM role

The Connector is deployed using helm and requires an IAM Role to be able to access tagged ASM secrets in the future.

// IAM role and access policy for apono tagged secrets
resource "aws_iam_role" "apono-connector" {
  name     = "${var.service_account_name}-${var.CONNECTOR_ID}"

  assume_role_policy = jsonencode({
    "Version" : "2012-10-17",
    "Statement" : [
      {
        "Effect" : "Allow",
        "Principal" : { "Federated" : "arn:aws:iam::${local.aws_account_id}:oidc-provider/${local.oidc_provider}" },
        "Action" : "sts:AssumeRoleWithWebIdentity",
        "Condition" : {
          "StringEquals" : { "${local.oidc_provider}:sub" : "system:serviceaccount:${var.namespace}:${var.service_account_name}" }
        }
      }
    ]
  })
  
  inline_policy {
    name = "apono-tagged-keys-access-policy"

    policy = jsonencode({
      Version = "2012-10-17"
      Statement = [
        {
          Effect = "Allow"
          Action = [ "kms:Sign" ]
          Resource = "*"
          Condition = { "StringEquals": {"aws:ResourceTag/apono-connector-read": "true"} }
        },
      ]
    })
  }
  
  inline_policy {
    name = "apono-tagged-secrets-access-policy"

    policy = jsonencode({
      Version = "2012-10-17"
      Statement = [
        {
          Effect = "Allow"
          Action = [ "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret"]
          Resource = "arn:aws:secretsmanager:*:${local.aws_account_id}:secret:*"
          Condition = { "StringEquals": {"aws:ResourceTag/apono-connector-read": "true"} }
        },
      ]
    })
  }

  // for IAM Managment
  inline_policy {
    name = "iam-access-policy"
    policy = jsonencode({
      Version = "2012-10-17"
      Statement = [
        {
            Effect = "Allow"
            Action = [
                "iam:ListPolicies",
                "iam:CreateInstanceProfile",
                "iam:ListGroups",
                "iam:ListInstanceProfiles"
            ],
            Resource = "*"
        },
        {
            Effect = "Allow"
            Action = [
                "iam:CreateInstanceProfile",
                "iam:GetRole",
                "iam:UpdateAssumeRolePolicy",
                "iam:ListRoleTags",
                "iam:TagRole",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:AttachRolePolicy",
                "iam:PutRolePolicy",
                "iam:AddRoleToInstanceProfile",
                "iam:ListInstanceProfilesForRole",
                "iam:DetachRolePolicy",
                "iam:ListAttachedRolePolicies",
                "iam:DeleteRolePolicy",
                "iam:ListAttachedGroupPolicies",
                "iam:ListRolePolicies",
                "iam:GetRolePolicy",
                "iam:PassRole",
                "iam:GetInstanceProfile",
                "iam:CreateUser",
                "iam:CreateAccessKey",
                "iam:DeleteAccessKey",
                "iam:PutUserPolicy",
                "iam:DeleteUserPolicy",
                "iam:GetUser",
                "iam:GetUserPolicy",
                "iam:ListAttachedUserPolicies",
                "iam:ListUserPolicies",
                "iam:UpdateLoginProfile",
                "iam:ListAccessKeys",
                "iam:AttachUserPolicy",
                "iam:DetachUserPolicy",
                "iam:CreateLoginProfile"
            ]
            Resource = [
                "arn:aws:iam::*:instance-profile/*",
                "arn:aws:iam::*:role/*",
                "arn:aws:iam::*:group/*",
                "arn:aws:iam::*:user/*"
            ]
        }
      ]
    })
  }
  
  inline_policy {
    name = "ec2-policy"
    policy = jsonencode({
      Version = "2012-10-17"
      Statement = [{
        "Effect": "Allow",
        "Action": [ "ec2:DescribeInstances","ec2:DescribeTags","ec2:AssociateIamInstanceProfile" ],
        "Resource": "*"
      }]
    })
  }
}

data "aws_iam_policy" "SecurityAudit" {
  arn = "arn:aws:iam::aws:policy/SecurityAudit"
}

resource "aws_iam_role_policy_attachment" "connector-security-audit" {
  role       = "${aws_iam_role.apono-connector.name}"
  policy_arn = "${data.aws_iam_policy.SecurityAudit.arn}"
}

Step 6 - Deploy Apono Connector

locals {
  connector_helm_repo = "https://apono-io.github.io/apono-helm-charts/"
  connector_helm_chart = "apono-connector"
  connector_helm_chart_version = "<<helmVersion>>"
}

// agent deployment
resource "kubernetes_namespace_v1" "apono-namespace" {
  metadata {
    name = var.namespace
  }
}

resource "helm_release" "apono-connector" {
  name             = "apono-connector"
  repository       = local.connector_helm_repo
  chart            = local.connector_helm_chart
  version          = local.connector_helm_chart_version
  namespace        = kubernetes_namespace_v1.apono-namespace.metadata[0].name


  set {
    name = "serviceAccount.name"
    value = var.service_account_name
  }
  
  set {
    name = "serviceAccount.awsRoleAccountId"
    value = local.aws_account_id
  }
  
  set {
    name = "serviceAccount.awsRoleName"
    value = "${var.service_account_name}-${var.CONNECTOR_ID}"
  }

  set {
    name = "image.tag"
    value = "<<connectorVersion>>"
  }

  set {
    name  = "apono.token"
    value = var.APONO_TOKEN
  }

  set {
    name  = "apono.url"
    value = var.APONO_WEBSOCKET_URL
  }

  set {
    name  = "apono.connectorId"
    value = var.CONNECTOR_ID
  }
}

Validate the Connector is Connected

You can validate the Connector is installed in the Connector status page.

Last updated