🦑

argocd-vault-pluginを触ってみた

2022/08/28に公開

k8s外の機密情報をk8sへ埋め込むためにはいくつかの方法がありますが、その中から今回はargocd-vault-pluginについて軽く触ったのでまとめてみました。
AWS(EKS) x argocd-vault-plugin の組み合わせを前提としています。

※他の方法としてExternal Secrets Operatorもあります
https://zenn.dev/nameless_gyoza/articles/external-secrets-operator

argocd-vault-plugin

argocd-vault-pluginというのは、簡単にいうとk8s外にある機密情報をk8sにinjectしてくれる君です。
ArgoCDのpluginとして入れられるので、ArgoCDをすでに利用している人たちにとってはお手軽に機密情報管理までできちゃう代物です。

https://github.com/argoproj-labs/argocd-vault-plugin

Secret取得する対象のバックエンドにはAWS Secret Manager, Hashicorp Vault, GCP Secret Managerなどに対応しています。

https://argocd-vault-plugin.readthedocs.io/en/stable/backends/

ざっくり仕組み

k8s Secreに対して以下のように特定のannotationと <placeholder> を置いておくと、argocd-vault-plugin君が該当のSecret backendからデータを取得し、その値を <placeholder> にinjectしてくれます。

kind: Secret
apiVersion: v1
metadata:
  name: example-secret
  annotations:
    avp.kubernetes.io/path: "path/to/secret"
type: Opaque
data:
  # `<password-vault-key>` に対して、AWSなどで登録されている値がinjectされる
  password: <password-vault-key>

導入のためのざっくり流れ

以下2つのポイントに対してそれぞれ a or b の組み合わせを取れます(初見だとまぁまぁややこしい..)。

  1. pluginのインストール方法
    a. RepoServerのimageにpluginを混ぜる
    b. RepoServerのinitContainerでpluginをインストールする
  2. pluginをArgoCD内で実際に利用できるようにする方法
    a. argocd-cm ConfigMapからpluginを登録する
    b. sidecarで注入する

https://argocd-vault-plugin.readthedocs.io/en/stable/installation/

具体的な手順

今回は RepoServerのimageにpluginを混ぜる + argocd-cm ConfigMapからpluginを登録する の組み合わせを利用します。
今回はTerraformからargocdを建て、argocd-vault-pluginを使ってSecret Managerに登録した値を取得できることを確認します。

  • ArgoCDの構築
resource "helm_release" "argocd" {
  name             = "argocd"
  create_namespace = "true"
  chart            = "argo-cd"
  namespace        = "argocd"
  version          = "5.3.6"
  repository       = "https://argoproj.github.io/argo-helm"

  // HCLでvalues.yamlをゴリゴリ書くのは大変すぎるのでファイルを分ける
  values = [
    file("${path.module}/values.yaml")
  ]
}

resource "kubernetes_secret" "argocd_vault_plugin" {
  metadata {
    name      = "argocd-vault-plugin-credentials"
    namespace = "argocd"
  }

  // see: https://argocd-vault-plugin.readthedocs.io/en/stable/backends/#aws-secrets-manager
  data = {
    "AVP_TYPE"   = "awssecretsmanager"
    "AWS_REGION" = "ap-northeast-1"
  }

  type = "Opaque"
}
  • values.yaml
server:
  config:
    configManagementPlugins: |-
      - name: argocd-vault-plugin
        generate:
          command: ["argocd-vault-plugin"]
          args: ["generate", "./"]
repoServer:
  volumes:
    - name: custom-tools
      emptyDir: {}
  volumeMounts:
    - name: custom-tools
      mountPath: /usr/local/bin/argocd-vault-plugin
      subPath: argocd-vault-plugin
  initContainers:
    - name: download-tools
      image: alpine:3.8
      command: [sh, -c]
      args:
        - >-
          wget -O argocd-vault-plugin
          https://github.com/IBM/argocd-vault-plugin/releases/download/v1.12.0/argocd-vault-plugin_1.12.0_linux_amd64 &&
          chmod +x argocd-vault-plugin &&
          mv argocd-vault-plugin /custom-tools/
      volumeMounts:
        - mountPath: /custom-tools
          name: custom-tools
  envFrom:
    # argo-helmの都合上、secretRefで渡す必要がある
    - secretRef:
        name : argocd-vault-plugin-credentials
  serviceAccount:
    annotations:
      # argocd-repo-server用にIRSAを用意し、SecretManagerへのアクセスをできるようにしておく
      "eks.amazonaws.com/role-arn": "arn:aws:iam::xxxxxx:role/argocd-repo-server"

Secret Managerに適当なSecretを登録します。

Secretを利用するApplicationに対して、vault-pluginを指定します。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd-vault-plugin
  namespace: argocd
spec:
  project: default
  source:
    path: .
    repoURL: 'https://github.com/yu-croco/arogcd-vault-plugin-demo.git' 
    targetRevision: HEAD
    # ここ!!
    plugin:
      name: argocd-vault-plugin
  destination:
    namespace: default
    server: 'https://kubernetes.default.svc'

Applicationに紐づくリソースの一つとして、Secret Managerに対応するSecretリソースを定義します。
※今回の場合は repoURL: 'https://github.com/yu-croco/arogcd-vault-plugin-demo.git' の先にSecretリソースを定義しています。

kind: Secret
apiVersion: v1
metadata:
  name: example-secret
  annotations:
    # Secret Managerのpath
    avp.kubernetes.io/path: "avp/data/test"
type: Opaque
stringData:
  # Secret ManagerのSecret Keyを `<>` で囲む
  sample-secret: <sample-secret>

Secret ManagerのSecret Keyを <> で囲むことで、ArgoCD Vault plugin側でSecret Managerから取得した値をk8s Secretに対してInjectしてくれます。
Secretの中の値を見ると、以下のようにSecret Managerで登録した値が入っていることがわかります。

$ kubectl get secret example-secret -o jsonpath='{.data.sample-secret}' | base64 --decode
hello-world

雑感

  • Secret管理のために完全新規のツールを用意しなくても良いという点では導入のハードルは低そう
  • 一方で思ったよりも準備のための設定が多く、これメンテするのめんどそうだなとも思った

Discussion