Installing a connector on Kubernetes with AWS permissions
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 Kubernetes
Prerequisite
It's required that you have your Cloud Account connected to your Kubernetes Cluster In this example we use Kube2Iam solution for kubernetes on EC2
Deploying the Connector
The Connector is deployed using helm and requires and IAM Role to be able to access tagged ASM secrets in the future. You can choose to install the Connector using either your CLI or Terraform:
CLI
Create a IAM role to allow Connector read access for apono tagged secrets
Get AWS Account
Replace
#EKS_CLUSTER_NAME
ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text) && OIDC_PROVIDER=$(aws eks describe-cluster --name "#EKS_CLUSTER_NAME" --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
Create Connector Role
aws iam create-role --role-name "{{K8S_SERVICE_ACCOUNT}}-{{CONNECTOR_ID}}" --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}'
Assign Role Policies
aws iam put-role-policy --role-name "{{K8S_SERVICE_ACCOUNT}}-{{CONNECTOR_ID}}" --policy-name "apono-tagged-secrets-access-policy" --policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [ "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret"],
"Resource": "arn:aws:secretsmanager:*:'"${ACCOUNT_ID}"':secret:*",
"Condition": { "StringEquals": {"aws:ResourceTag/apono-connector-read": "true"} }
}]
}'
aws iam put-role-policy --role-name "{{K8S_SERVICE_ACCOUNT}}-{{CONNECTOR_ID}}" --policy-name "apono-tagged-kms-keys-access-policy" --policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "kms:Sign",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/apono-connector-read": "true"
}
}
}
]
}'
aws iam put-role-policy --role-name "{{K8S_SERVICE_ACCOUNT}}-{{CONNECTOR_ID}}" --policy-name "apono-iam-policy" --policy-document '{
"Version": "2012-10-17",
"Statement": [{"Action":["iam:ListPolicies","iam:CreateInstanceProfile","iam:ListGroups","iam:ListInstanceProfiles"],
"Effect":"Allow",
"Resource":"*"},
{"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"],
"Effect":"Allow",
"Resource":["arn:aws:iam::*:instance-profile/*","arn:aws:iam::*:role/*","arn:aws:iam::*:group/*","arn:aws:iam::*:user/*"]}]
}'
aws iam put-role-policy --role-name "{{K8S_SERVICE_ACCOUNT}}-{{CONNECTOR_ID}}" --policy-name "apono-read-objects-policy" --policy-document '{
"Version": "2012-10-17",
"Statement": [{"Action":["rds:DescribeDBInstances","rds:ListTagsForResource"],
"Effect":"Allow",
"Resource":"arn:aws:rds:*:*:db:*"},
{"Action":["ssm:GetParameters*"],
"Effect":"Allow",
"Resource":"arn:aws:ssm:*:*:parameter/*"},
{"Action":["ssm:DescribeParameters"],
"Effect":"Allow",
"Resource":"*"},
{"Action":["s3:GetBucketTagging","s3:ListAllMyBuckets","s3:ListBucket","s3:GetBucketLocation"],
"Effect":"Allow",
"Resource":"arn:aws:s3:::*"}]
}'
aws iam put-role-policy --role-name "{{K8S_SERVICE_ACCOUNT}}-{{CONNECTOR_ID}}" --policy-name "apono-read-resource-tags" --policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "tag:GetResources",
"Resource": "*"
}]
}'
Deploy Apono Connector
helm install apono-connector {{CONNECTOR_CHART_REPO}}/{{CONNECTOR_CHART_NAME}}/{{CONNECTOR_CHART_NAME}}-<<helmVersion>>.tgz \
--namespace "{{K8S_NAMESPACE}}" \
--set image.repository="{{CONNECTOR_IMAGE_REPO}}" \
--set image.tag="<<connectorVersion>>" \
--set gitSyncImage="{{GIT_SYNC_IMAGE}}" \
--set githubAccessToken="{{GITHUB_ACCESS_TOKEN}}" \
--set serviceAccount.name="{{K8S_SERVICE_ACCOUNT}}" \
--set podAnnotations."iam\.amazonaws\.com/role"="{{K8S_SERVICE_ACCOUNT}}-{{CONNECTOR_ID}}" \
--set apono.token="{{TOKEN}}" \
--set apono.url="{{APONO_WEBSOCKET_URL}}" \
--set apono.websocketSsl="{{APONO_WEBSOCKET_SSL}}" \
--set apono.connectorId="{{CONNECTOR_ID}}" \
--create-namespace
Terraform
Required providers:
helm
(v2.5.1),aws
,kubernetes
locals {
apono_token = "{{TOKEN}}"
apono_websocket_url = "{{APONO_WEBSOCKET_URL}}"
apono_websocket_ssl = "{{APONO_WEBSOCKET_SSL}}"
connector_id = "{{CONNECTOR_ID}}"
connector_helm_repo = "{{CONNECTOR_CHART_REPO}}"
connector_helm_chart = "{{CONNECTOR_CHART_NAME}}"
connector_helm_chart_version = "<<helmVersion>>"
connector_image_repo = "{{CONNECTOR_IMAGE_REPO}}"
connector_image_tag = "<<connectorVersion>>"
git_sync_image = "{{GIT_SYNC_IMAGE}}"
github_access_token = "{{GITHUB_ACCESS_TOKEN}}"
service_account_name = "{{K8S_SERVICE_ACCOUNT}}"
namespace = "{{K8S_NAMESPACE}}"
}
data "aws_caller_identity" "aws_account" {
}
locals {
aws_account_id = data.aws_caller_identity.aws_account.account_id
}
// agent deployment
resource "kubernetes_namespace_v1" "apono-namespace" {
metadata {
name = local.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 = "image.repository"
value = local.connector_image_repo
}
set {
name = "image.tag"
value = local.connector_image_tag
}
set {
name = "gitSyncImage"
value = local.git_sync_image
}
set {
name = "githubAccessToken"
value = local.github_access_token
}
set {
name = "serviceAccount.name"
value = local.service_account_name
}
set {
name = "serviceAccount.awsRoleAccountId"
value = local.aws_account_id
}
set {
name = "podAnnotations."iam\.amazonaws\.com/role""
value = "${local.service_account_name}-${local.connector_id}"
}
set {
name = "apono.token"
value = local.apono_token
}
set {
name = "apono.url"
value = local.apono_websocket_url
}
set {
name = "apono.websocketSsl"
value = local.apono_websocket_ssl
}
set {
name = "apono.connectorId"
value = local.connector_id
}
}
// IAM role and access policy for apono tagged secrets
resource "aws_iam_role" "apono-connector" {
name = "${local.service_account_name}-${local.connector_id}"
assume_role_policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Principal": { "Service": "ec2.amazonaws.com"},
"Action" : "sts:AssumeRole"
}
]
})
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 s3-iam-role resources
inline_policy {
name = "s3-list-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["s3:GetBucketTagging", "s3:ListAllMyBuckets", "s3:ListBucket", "s3:GetBucketLocation"]
Resource = "arn:aws:s3:::*"
},
]
})
}
// for mysql-rds resources
inline_policy {
name = "rds-list-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["rds:DescribeDBInstances", "rds:ListTagsForResource"]
Resource = "arn:aws:rds:*:*:db:*"
},
]
})
}
// for ssm-iam-role resources
inline_policy {
name = "ssm-params-list-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["ssm:GetParameters*"]
Resource = "arn:aws:ssm:*:*:parameter/*"
},
{
Effect = "Allow"
Action = ["ssm:DescribeParameters"]
Resource = "*"
},
]
})
}
// for iam manipulation
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 = "apono-read-resource-tags"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
"Effect": "Allow",
"Action": [ "tag:GetResources" ],
"Resource": "*"
}]
})
}
inline_policy {
name = "ec2-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
"Effect": "Allow",
"Action": [ "ec2:DescribeInstances","ec2:DescribeTags","ec2:AssociateIamInstanceProfile" ],
"Resource": "*"
}]
})
}
}
Validate the Connector is Connected
You can validate the Connector is installed in the Connector status page.
Last updated