2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KyvernoでSecretに文字列処理を行う方法

Last updated at Posted at 2024-12-09

Kubernetesクラスタ運用中、Secretの値に特定の処理を施した上で保存・再利用したいケースはしばしば発生します。たとえば、外部システムが投入するSecretに含まれる文字列を大文字化、もしくは一部のパターンを置換して管理したい場合などです。本記事では、KubernetesネイティブなポリシーエンジンKyvernoを用いて、Secret適用時に文字列処理を行う2つのアプローチについて解説します。

Kyverno Secret String Processing.png

Kyvernoとは

Kyvernoは、KubernetesリソースをYAMLベースで記述し、ポリシーとして適用できる強力なポリシーエンジンです。KyvernoはAdmissionコントローラーとして動作し、以下のような機能を提供します:

  • Validate: リソース適用前の条件検証
  • Mutate: リソース適用時にパッチを当ててリソースを変更
  • Generate: あるリソースをトリガーに、別のリソースを自動生成

文字列処理をしたいシナリオ

たとえば、source-secretというSecretが作成された時、その中のdata.usernameを大文字化してtarget-secretという新たなSecretに反映したいと考えます。最初に考えられるアプローチは、Kyvernoのgenerateを使ってsource-secretが作成されたタイミングでtarget-secretを自動生成する、というものです。

しかしここで、Kyvernoのgenerateには「同一Kindのリソースを同時に生成できない場合がある」という制約があります。特に同一のSecretを生成する際など、generateの仕組み上想定しづらいパターンが発生する可能性があります。

generateルールの制約

Kyvernoのgenerateは、たとえばConfigMapが作成されたタイミングで別のConfigMapを生成する、といった使い方に適しています。しかし、generateで「Secretが来たらSecretを生成する」という場合、"generation kind and match resource kind should not be the same"というエラーが発生します。これは同一Kindを生成すると、その生成されたリソースからまたリソースが増えてしまうこと抑制しているものだとおもわれます。

このような状況では、別のアプローチとしてmutateを使用する方法が考えられます。

mutateで同一Secret内のデータ変換を実現

mutateルールを使えば、source-secretが適用される直前にSecretリソース自体を書き換えることが可能です。つまり、同一のSecretリソースのdata.usernameを事前に大文字化してからクラスタに保存できます。これなら、同一Kind生成の問題を回避できます。

Kyvernoで使える文字列処理関数

KyvernoはJMESPath拡張関数を提供しており、文字列操作に便利な関数が多数あります:

  • to_upper(string): 文字列を大文字に変換
  • to_lower(string): 文字列を小文字に変換
  • replace(old, new, string), replaceAll(old, new, string): 文字列置換
  • regex_replaceAll(pattern, replace, string): 正規表現置換
  • base64_decode(string) / base64_encode(string): Base64エンコード/デコード
  • トリム系関数 (trim, trim_prefix, trim_suffix) など

Secretのdata値はBase64エンコードされています。そのため、data.usernameを加工する場合はbase64_decode()で文字列を元に戻し、その後to_upper()等で大文字化。最後にbase64_encode()で再度エンコードし直す流れとなります。

mutateルールの例

以下はdefaultネームスペースのsource-secretが作成される際に、data.usernameを大文字化して上書きするポリシー例です:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: mutate-secret-data
spec:
  rules:
    - name: mutate-secret-username
      match:
        resources:
          kinds:
            - Secret
          namespaces:
            - default
          names:
            - source-secret
      mutate:
        patchStrategicMerge:
          apiVersion: v1
          kind: Secret
          metadata:
            name: "{{ request.object.metadata.name }}"
            namespace: "{{ request.object.metadata.namespace }}"
          data:
            username: "{{ base64_encode(to_upper(base64_decode(request.object.data.username))) }}"

ポリシーの動作確認

  1. 上記ポリシーをkubectl apply -fで適用します。
  2. 以下のSecretをkubectl apply -fで投入します:
apiVersion: v1
kind: Secret
metadata:
  name: source-secret
  namespace: default
type: Opaque
data:
  username: dXNlck5hbWU=  # "userName"をBase64エンコードした値
  1. 適用後にkubectl get secret source-secret -o yamlで中身を確認すると、usernameの値はUSERNAMEに大文字化された文字列のBase64エンコードに置き換わっています。

これで、Admission時に同一Secret内で文字列変換が行われたことが確認できます。

まとめ

当初はgenerate機能を用いて、「あるSecretをトリガーに別のSecretを文字列処理して生成する」シナリオを考えましたが、Kyvernoのgenerateには同一Kind生成が難しい状況があります。そこで、同一リソース上でのデータ変換が必要な場合はmutateを使うことで、Admission時にリソース自体を変換できます。

mutateなら、Secretが保存される直前にdataを任意の文字列処理で加工でき、base64_decode(), to_upper(), base64_encode()などのKyverno拡張関数を組み合わせることで、複雑な文字列変換も実現可能です。

KyvernoはポリシーベースでKubernetesリソースを制御・拡張できる有用なツールです。generateとmutateの使い分けを意識しつつ、SecretやConfigMap、他のKubernetesリソースの管理に役立ててみてください。

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?