Skip to content

NimTechnology

Trình bày các công nghệ CLOUD một cách dễ hiểu.

  • Kubernetes & Container
    • Docker
    • Kubernetes
      • Ingress
      • Pod
    • Helm Chart
    • OAuth2 Proxy
    • Isito-EnvoyFilter
    • Apache Kafka
      • Kafka
      • Kafka Connect
      • Lenses
    • Vault
    • Longhorn – Storage
    • VictoriaMetrics
    • MetalLB
    • Kong Gateway
  • CI/CD
    • ArgoCD
    • ArgoWorkflows
    • Argo Events
    • Spinnaker
    • Jenkins
    • Harbor
    • TeamCity
    • Git
      • Bitbucket
  • Coding
    • DevSecOps
    • Terraform
      • GCP – Google Cloud
      • AWS – Amazon Web Service
      • Azure Cloud
    • Golang
    • Laravel
    • Python
    • Jquery & JavaScript
    • Selenium
  • Log, Monitor & Tracing
    • DataDog
    • Prometheus
    • Grafana
    • ELK
      • Kibana
      • Logstash
  • BareMetal
    • NextCloud
  • Toggle search form

[AWS] EKS IAM Roles for Service Accounts (IRSA) using Terraform

Posted on September 9, 2022May 13, 2024 By nim No Comments on [AWS] EKS IAM Roles for Service Accounts (IRSA) using Terraform

Tình huống là như thế này:
Bạn có 1 workload(deployment, statefulSet, Job) trên k8s
Bạn muốn là workload trên k8s cũng có thể access các resources trên AWS thì làm sao?
Cách 1: add access key và secret key vào workload thông qua Secret và Environment.
Cách 2: sử dụng Service Account đã được cấp quyền access và gắn vào workload(ở bài này thì mình dùng cách 2)

Contents

Toggle
  • 1) Introduction to IRSA
  • 2) Practice configuring IRSA to access S3, resources on AWS.
  • 3) Use eks-irsa terraform module to create IRSA easily
  • 4) Use cross-account IAM roles in IRSA
    • 4.1) Try hard.
    • 4.2) Using IRSA Module.

1) Introduction to IRSA

Nếu là 1 pod bất kì trong k8s thì không thể access S3 được!
Đây là những lý do mà workload trên k8s cần access vào resource aws
Những thử bạn cần làm để có 1 IRSA
Bạn sẽ cần nhớ Issuer URL bạn cần nhớ
Bạn có thể lấy link rồi thêm đuôi /.well-known/openid-configuration
Bạn sẽ cần tạo 1 oidc bằng link Issuer URL

2) Practice configuring IRSA to access S3, resources on AWS.

Extract OIDC provider thumbprint for all AWS Region with EKS support
oidc-thumbprint-regions.sh

#!/bin/bash

set -e

if [ ! -z "$DEBUG" ] ; then
    set -x
fi

REGIONS="us-east-2
    us-east-1 
    us-west-1
    us-west-2
    ap-east-1
    ap-northeast-2
    ap-southeast-1
    ap-southeast-2
    ap-northeast-1
    eu-central-1
    eu-west-1
    eu-west-2
    eu-west-3
    eu-north-1
    me-south-1
    sa-east-1"

for REGION in $REGIONS ; do
    JWKS_URI="oidc.eks.${REGION}.amazonaws.com"

    # Extract all certificates in separate files
    # https://unix.stackexchange.com/questions/368123/how-to-extract-the-root-ca-and-subordinate-ca-from-a-certificate-chain-in-linux
    TEMP=$(mktemp -d -t oidc-eks-XXXX)
    openssl s_client -servername $JWKS_URI -showcerts -connect $JWKS_URI:443 < /dev/null 2>/dev/null | awk -v dir="$TEMP" '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/{ if(/BEGIN/){a++}; out=dir"/cert00"a".crt"; print >out }'

    # Assume last found certificate in chain is the ROOT_CA
    ROOT_CA=$(ls -1 $TEMP/* | tail -1)

    # Extract fingerprint in desired format (no header, no colons)
    THUMBPRINT=$(openssl x509 -fingerprint -noout -in $ROOT_CA | sed 's/^.*=//' | sed 's/://g')
    printf '{"%s": "%s"}\n' $REGION $THUMBPRINT
    rm -rf $TEMP
done

Kiểm tra OIDC provider thumbprint khi nào thì hết hạn

# Enable IAM Roles for EKS Service-Accounts (IRSA).

# The Root CA Thumbprint for an OpenID Connect Identity Provider is currently
# Being passed as a default value which is the same for all regions and
# Is valid until (Jun 28 17:39:16 2034 GMT).
# https://crt.sh/?q=9E99A48A9960B14926BB7F3B02E22DA2B0AB7280
# https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
# https://github.com/terraform-providers/terraform-provider-aws/issues/10104

Bên terraform của cluster EKS mình sẽ tạo ra 2 file nữa

c6-01-iam-oidc-connect-provider-variables.tf
>>>>>>>>>>

# Input Variables - AWS IAM OIDC Connect Provider


# EKS OIDC ROOT CA Thumbprint - valid until 2037
variable "eks_oidc_root_ca_thumbprint" {
  type        = string
  description = "Thumbprint of Root CA for EKS OIDC, Valid until 2037"
  default     = "9e99a48a9960b14926bb7f3b02e22da2b0ab7280"
}
c6-02-iam-oidc-connect-provider.tf
>>>>>>
>>>>>

# Datasource: AWS Partition
# Use this data source to lookup information about the current AWS partition in which Terraform is working
data "aws_partition" "current" {}

# Resource: AWS IAM Open ID Connect Provider
resource "aws_iam_openid_connect_provider" "oidc_provider" {
  client_id_list  = ["sts.${data.aws_partition.current.dns_suffix}"]
  thumbprint_list = [var.eks_oidc_root_ca_thumbprint]
  url             = aws_eks_cluster.eks_cluster.identity[0].oidc[0].issuer

  tags = merge(
    {
      Name = "${var.cluster_name}-eks-irsa"
    },
    local.common_tags
  )
}

# Output: AWS IAM Open ID Connect Provider ARN
output "aws_iam_openid_connect_provider_arn" {
  description = "AWS IAM Open ID Connect Provider ARN"
  value = aws_iam_openid_connect_provider.oidc_provider.arn 
}

# Extract OIDC Provider from OIDC Provider ARN
locals {
    aws_iam_oidc_connect_provider_extract_from_arn = element(split("oidc-provider/", "${aws_iam_openid_connect_provider.oidc_provider.arn}"), 1)
}

# Output: AWS IAM Open ID Connect Provider
output "aws_iam_openid_connect_provider_extract_from_arn" {
  description = "AWS IAM Open ID Connect Provider extract from ARN"
   value = local.aws_iam_oidc_connect_provider_extract_from_arn
}

# Sample Outputs for Reference
/*
aws_iam_openid_connect_provider_arn = "arn:aws:iam::180789647333:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/A9DED4A4FA341C2A5D985A260650F232"
aws_iam_openid_connect_provider_extract_from_arn = "oidc.eks.us-east-1.amazonaws.com/id/A9DED4A4FA341C2A5D985A260650F232"
*/

Manifest đầy đủ ở đây:
https://github.com/mrnim94/terraform-aws/tree/master/eks/AWS-EKS-Cluster-Basics

Chúng ta có 1 resource
khi run terraform apply thì: aws_iam_openid_connect_provider
==> tạo 1 IAM access vào nhà cung cấp OpenID
trong resource trên có 1 field: url = aws_eks_cluster.eks_cluster.identity[0].oidc[0].issuer
thì nó lấy ở đây:

Làm sao để lấy được cài OpenID connect Provider URL thông qua terraform thì tham khảo ở đây:
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#enabling-iam-roles-for-service-accounts

output khi run command
Mình kiểm tra trong IAM -> Identity providers
Chúng ta đã tạo được

Còn cái: client_id_list = [“sts.${data.aws_partition.current.dns_suffix}”]
thường nó sẽ là client_id_list = [“sts.amazonaws.com”]
Hoặc bạn lấy động như mình
tham khảo link: dns_suffix – Base DNS domain name for the current partition (e.g. amazonaws.com in AWS Commercial, amazonaws.com.cn in AWS China).

Ở đâu mình có sử dụng merge map

  tags = merge(
    {
      Name = "${var.cluster_name}-eks-irsa"
    },
    local.common_tags
  )

Tham khảo link này: https://www.terraform.io/language/functions/merge

Ngoài ra mình có sử dụng spit function
https://www.terraform.io/language/functions/split

EKS OpenID Connect Well Known Configuration URL

  • We can also call it as OpenID Connect Discovery URL
  • Discovery: Defines how Clients dynamically discover information about OpenID Providers
# Get OpenID Connect provider URL for EKS Cluster
Go to Services -> EKS -> hr-dev-eksdemo1 -> Configuration -> Details -> OpenID Connect provider URL

# EKS OpenID Connect Well Known Configuration URL
<EKS OpenID Connect provider URL>/.well-known/openid-configuration

# Sample
https://oidc.eks.us-east-1.amazonaws.com/id/EC973221A6C1BC248C79CFD5455EEECC/.well-known/openid-configuration

https://github.com/mrnim94/terraform-aws/blob/master/eks-iam_roles_for_services_account/EKS-IRSA/02-eks-irsa-demo-terraform-manifests

Acquiring state lock. This may take a few moments...
╷
│ Error: AccessDenied: Access Denied
│       status code: 403, request id: BK8EFDSKVEYMW37W, host id: VIfTThsTvogmR4nLHcvBsEfbKnNQ7ecVpfxftkgjn4jFU5P5vpT+n5O71LM+gsfrv9xbW3X+kOg=
│
│
╵
Releasing state lock. This may take a few moments...

Bạn nên tìm đến terraform_remote_state và sửa config bucket

Bạn tạo role để mấy thanh niên mà kết nối đến oidc của EKS và có service account là irsa-demo-sa

permission là nó được access vào S3

Dùng terraform tạo 1 service account trong k8s

c4-03-irsa-k8s-service-account.tf
>>>>
>>

# Resource: Kubernetes Service Account
resource "kubernetes_service_account_v1" "irsa_demo_sa" {
  depends_on = [ aws_iam_role_policy_attachment.irsa_iam_role_policy_attach ]
  metadata {
    name = "irsa-demo-sa"
    annotations = {
      "eks.amazonaws.com/role-arn" = aws_iam_role.irsa_iam_role.arn
      }
  }
}

Đây là Service account mà get được trong k8s

root@LP11-D7891:~# kubectl get sa/irsa-demo-sa -o yaml
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::250887682577:role/SAP-dev-irsa-iam-role
  creationTimestamp: "2022-09-08T05:39:20Z"
  name: irsa-demo-sa
  namespace: default
  resourceVersion: "208932"
  uid: 4c6298b9-d888-4212-8a71-67a242b24b1f
secrets:
- name: irsa-demo-sa-token-vdstw

Tiếp đến là mình tạo Job rồi gắn service account vào
Cuối cùng là run lệnh s3 ls sem có list được ss3 trên aws ko?

# Resource: Kubernetes Job
resource "kubernetes_job_v1" "irsa_demo" {
  metadata {
    name = "irsa-demo"
  }
  spec {
    template {
      metadata {
        labels = {
          app = "irsa-demo"
        }
      }
      spec {
        service_account_name = kubernetes_service_account_v1.irsa_demo_sa.metadata.0.name 
        container {
          name    = "irsa-demo"
          image   = "amazon/aws-cli:latest"
          args = ["s3", "ls"]
          #args = ["ec2", "describe-instances", "--region", "${var.aws_region}"] # Should fail as we don't have access to EC2 Describe Instances for IAM Role
        }
        restart_policy = "Never"
      }
    }
  }
}

Giờ mình tiến hành list job, pod và show logs pods.

root@LP11-D7891:~# kubectl get job
NAME        COMPLETIONS   DURATION   AGE
irsa-demo   1/1           11s        14s

root@LP11-D7891:~# kubectl get pod
NAME              READY   STATUS      RESTARTS   AGE
irsa-demo-dsjzr   0/1     Completed   0          44s

root@LP11-D7891:~# kubectl logs pod/irsa-demo-dsjzr
2022-09-04 16:46:10 codepipeline-us-east-1-95999394200
2022-07-12 16:44:47 elasticbeanstalk-eu-west-1-250887682577
2022-09-07 09:14:06 terraform-on-aws-eks-nim
Ngon nhé!

3) Use eks-irsa terraform module to create IRSA easily

https://registry.terraform.io/modules/mrnim94/eks-irsa/aws/latest

4) Use cross-account IAM roles in IRSA

4.1) Try hard.

Cách này chúng ta hơi manual 1 tý.

Pods của cluster A muốn access vào resource AWS của account B

Đầu tiền bạn cần lấy OpenID Connect Provider của EKS trong accunt A.
https://oidc.eks.us-west-2.amazonaws.com/id/AAAAAAAAAAAAAAAAAA

Tiếp đến bạn run terraform bên dưới ở account của Cluster B.

resource "aws_iam_openid_connect_provider" "oidc_issuer" {
  url             = "https://oidc.eks.us-west-2.amazonaws.com/id/AAAAAAAAAAAAAAAAAA"
  thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"]
  client_id_list  = ["sts.amazonaws.com"]
}

data "aws_iam_policy_document" "irsa" {
 statement {
   effect  = "Allow"
   actions = ["sts:AssumeRoleWithWebIdentity"]
   principals {
     type        = "Federated"
     identifiers = [aws_iam_openid_connect_provider.oidc_issuer.arn]
   }
   condition {
     test     = "StringLike"
     variable = "oidc.eks.us-west-2.amazonaws.com/id/AAAAAAAAAAAAAAAAAA:sub"
     values   = ["system:serviceaccount:kube-system:zeus-rotations"]
   }
 }
}

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

    actions = [
      "iam:CreateAccessKey",
      "iam:ListAccessKeys",
      "iam:DeleteAccessKey",
    ]
    resources = ["*"]
  }
}

resource "aws_iam_role" "iam" {
 name               = "irsa"
 assume_role_policy = data.aws_iam_policy_document.irsa.json
}

resource "aws_iam_policy" "iam" {
  name   = "iam"
  policy = data.aws_iam_policy_document.iam.json
}

resource "aws_iam_role_policy_attachment" "s3" {
  role       = aws_iam_role.iam.name
  policy_arn = aws_iam_policy.iam.arn
}

output "irsa_iam_role_arn" {
  description = "IRSA Demo IAM Role ARN. You need add this values to serviceAccount.annotations with key `eks.amazonaws.com/role-arn`"
  value = aws_iam_role.iam.arn
}

Khi nó print cái output irsa_iam_role_arn thì bạn set nó vào service account của deployment của aws account A.

4.2) Using IRSA Module.

Cũng như các bước trên bạn cần lấy được
https://oidc.eks.us-west-2.amazonaws.com/id/AAAAAAAAAAAAAAAAAA

resource "aws_iam_openid_connect_provider" "oidc_issuer" {
  url             = "https://oidc.eks.us-west-2.amazonaws.com/id/AAAAAAAAAAAAAAAAAA"
  thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"]
  client_id_list  = ["sts.amazonaws.com"]
}

module "eks-irsa-nim-devsecops" {
  source  = "mrnim94/eks-irsa/aws"
  version = "1.0.0"
  depends_on = [
    aws_iam_openid_connect_provider.oidc_issuer
  ]

  aws_region = var.aws_region
  environment = "dev"
  business_divsion = "irsa-zeus-rotations-nim-devsecops"

  k8s_namespace = "kube-system"
  k8s_service_account = "zeus-rotations"
  json_policy = <<EOT
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:CreateAccessKey",
        "iam:ListAccessKeys",
        "iam:DeleteAccessKey"
      ],
      "Resource": "*"
    }
  ]
}
EOT

  aws_iam_openid_connect_provider_arn = aws_iam_openid_connect_provider.oidc_issuer.arn
}

output "irsa_iam_role_arn_nim_devsecops" {
  description = "aws_iam_openid_connect_provider_arn"
  value = module.eks-irsa-nim-devsecops.irsa_iam_role_arn
}
AWS - Amazon Web Service

Post navigation

Previous Post: [Verdaccio] Creating a Local Private NPM registry
Next Post: [Github] How to fix “Large files detected. You may want to try Git Large File Storage”

More Related Articles

[Bitbucket Pipeline] Design bitbucket-pipeline and eksctl to upgrade EKS cluster AWS - Amazon Web Service
[AWS] Creating AWS Certificate Manager (ACM) AWS - Amazon Web Service
[S3] You will naturally see files on S3 being deleted AWS - Amazon Web Service
[AWS] Login Argocd via Cognito in AWS ArgoCD
[AWS] – Terraform Beginner – Lesson 1: Create a Free Account of AWS AWS - Amazon Web Service
[eks] Kubernetes Cluster-AutoScaler error: Failed to watch *v1.CSIDriver AWS - Amazon Web Service

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Tham Gia Group DevOps nhé!
Để Nim có nhiều động lực ra nhiều bài viết.
Để nhận được những thông báo mới nhất.

Recent Posts

  • [Azure] The subscription is not registered to use namespace ‘Microsoft.ContainerService’ May 8, 2025
  • [Azure] Insufficient regional vcpu quota left May 8, 2025
  • [WordPress] How to add a Dynamic watermark on WordPress. May 6, 2025
  • [vnet/Azure] VNet provisioning via Terraform. April 28, 2025
  • [tracetcp] How to perform a tracert command using a specific port. April 3, 2025

Archives

  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • June 2021

Categories

  • BareMetal
    • NextCloud
  • CI/CD
    • Argo Events
    • ArgoCD
    • ArgoWorkflows
    • Git
      • Bitbucket
    • Harbor
    • Jenkins
    • Spinnaker
    • TeamCity
  • Coding
    • DevSecOps
    • Golang
    • Jquery & JavaScript
    • Laravel
    • NextJS 14 & ReactJS & Type Script
    • Python
    • Selenium
    • Terraform
      • AWS – Amazon Web Service
      • Azure Cloud
      • GCP – Google Cloud
  • Kubernetes & Container
    • Apache Kafka
      • Kafka
      • Kafka Connect
      • Lenses
    • Docker
    • Helm Chart
    • Isito-EnvoyFilter
    • Kong Gateway
    • Kubernetes
      • Ingress
      • Pod
    • Longhorn – Storage
    • MetalLB
    • OAuth2 Proxy
    • Vault
    • VictoriaMetrics
  • Log, Monitor & Tracing
    • DataDog
    • ELK
      • Kibana
      • Logstash
    • Fluent
    • Grafana
    • Prometheus
  • Uncategorized
  • Admin

Copyright © 2025 NimTechnology.