argocd-vault-pluginを触ってみた
k8s外の機密情報をk8sへ埋め込むためにはいくつかの方法がありますが、その中から今回はargocd-vault-pluginについて軽く触ったのでまとめてみました。
AWS(EKS) x argocd-vault-plugin の組み合わせを前提としています。
※他の方法としてExternal Secrets Operatorもあります
argocd-vault-plugin
argocd-vault-pluginというのは、簡単にいうとk8s外にある機密情報をk8sにinjectしてくれる君です。
ArgoCDのpluginとして入れられるので、ArgoCDをすでに利用している人たちにとってはお手軽に機密情報管理までできちゃう代物です。
Secret取得する対象のバックエンドにはAWS Secret Manager, Hashicorp Vault, GCP Secret Managerなどに対応しています。
ざっくり仕組み
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
の組み合わせを取れます(初見だとまぁまぁややこしい..)。
- pluginのインストール方法
a.RepoServerのimageにpluginを混ぜる
b.RepoServerのinitContainerでpluginをインストールする
- pluginをArgoCD内で実際に利用できるようにする方法
a.argocd-cm ConfigMapからpluginを登録する
b.sidecarで注入する
具体的な手順
今回は 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