【入門編】 KubernetesにおけるSecretのメモリ内保護と外部シークレット管理 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

こんにちは!国内外でサイバーセキュリティの最前線に立ち、日々システムをクラッカー(悪意ある攻撃者)の手から守っているCISSPのセキュリティオフィサーです。

突然ですが、みなさんはご自宅の「予備の鍵」をどこに保管していますか?
「まさか、玄関の植木鉢の下や、郵便受けの裏に隠してはいませんよね?」

実は、今大人気のシステム管理ツール「Kubernetes(クーバネティス、以下K8s)」を使っている開発現場で、これと全く同じ「危ない鍵の隠し方」をしてしまっているケースが後を絶ちません。

今回は、K8sの中で大切なパスワードやAPIキー(これらを「シークレット」と呼びます)を、泥棒から完璧に守り抜くための方法を解説します。小難しいセキュリティ用語が出てきても、身近な防犯の仕組みに例えて丁寧に紐解いていきますので、一歩ずつ対策を学んでいきましょう!

—

1. なぜ標準の「Kubernetes Secret」は植木鉢の下の鍵なのか?

K8sには、標準機能として Secret という「パスワードを保存するための専用の箱」が用意されています。これを聞くと、「専用の箱なんだから安全だろう」と思いますよね。

しかし、ここに大きな落とし穴があります。

Base64は「暗号」ではなく「ただの並び替え」

標準の Secret にパスワードを登録するとき、データは「Base64(ベースロクヨン)」という形式に変換されます。
これは一見すると YWRtaW4= のような意味不明な文字列に見えるため、暗号化されているように錯覚してしまいます。

ですが、これは「日本語をローマ字表記に変えただけ」のようなものです。知識がある人なら、一瞬で元のパスワード(この場合は admin)に戻せてしまいます。泥棒にしてみれば、「ちょっと紙を裏返したら、そこに暗号の答えが書いてあった」というレベルの、非常に簡単な仕掛けなのです。

すべてのデータが集まる「etcd」という名の物置

K8sの裏側には、システム全体のあらゆる設定情報を保管する etcd(エトセディー)というデータベース(物置)があります。
標準の Secret を使うと、先ほどの「Base64で変換しただけのパスワード」が、そのままこの物置に放り込まれます。

もし攻撃者が何らかの方法でこの etcd にアクセスできてしまったら、あなたの家の「すべての部屋の鍵」が一瞬で盗まれてしまうことになるのです。

—

2. 泥棒(攻撃者)が狙う「3つの侵入ルート」

プロのハッカーや泥棒は、力任せに玄関を破るようなことはしません。もっと賢く、泥臭いルートを狙ってきます。K8sの環境において、彼らがシークレットを盗み出す主なルートは以下の3つです。

1. 物置(etcd)の直接ハッキング:
暗号化されていない etcd から、直接パスワードのデータを引っこ抜く。
2. コンテナの「環境変数」を覗き見る:
多くの開発者は、プログラムにパスワードを渡すために「環境変数」を使います。しかし、攻撃者がコンテナに一瞬でも侵入すると、env という簡単なコマンドを実行するだけで、画面にパスワードが丸見えになってしまいます。
3. ハードディスクの「残骸」を漁る:
サーバーのハードディスク(ストレージ)に一時的に書き込まれたパスワードのファイルを、サーバーが破棄された後に復元して盗み出す。

「じゃあ、一体どうすればいいの?」と不安になりますよね。
そこで登場するのが、「外部のプロの金庫番(シークレットマネージャー)」を雇うという方法です!

—

3. 解決策:プロの金庫番を雇い「必要なときだけ使い捨ての鍵」を渡してもらう

標準の Secret が頼りないなら、世界最高峰の頑丈な金庫を使えばいいのです。
具体的には、「HashiCorp Vault(ボルト)」や「AWS Secrets Manager」といった、セキュリティ専用の超強力な金庫サービスを利用します。

そして、ここからがプロの知恵です。
「金庫からパスワードを持ってきて、K8sの中にずっと置いておく」のでは、結局そこを狙われてしまいますよね。

そこで、「必要なときだけ、その瞬間だけ使える『使い捨ての鍵』をメモリ(脳内)にだけ覚えさせて、使い終わったら綺麗さっぱり忘れる」という仕組みを作ります。これを「動的シークレット注入(Dynamic Secret Injection)」と呼びます。

この仕組みを使えば、万が一サーバーのハードディスクを盗まれても、そこには鍵のデータ(足跡)が一切残っていないため、泥棒は手も足も出なくなります。

—

4. 【実践】External Secrets Operator (ESO) で安全に鍵を届ける

では、実際にこの「プロの金庫番」から安全に鍵を受け取る仕組みを、K8sの上に構築してみましょう!
今回は、現場で非常によく使われている External Secrets Operator(ESO) というツールを使って、AWS Secrets Manager(外部の金庫)から安全にパスワードを引っ張ってくる設定例(YAML)をご紹介します。

まずは、金庫の場所と、そこに入るための身分証明書を指定する「ストア」を設定します。

設定例1:金庫の場所を教えてあげる設定(SecretStore)

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secrets-manager-store
  namespace: default
spec:
  provider:
    aws:
      service: SecretsManager
      # どの地域のAWS金庫を使うかを指定します(例:東京リージョン)
      region: ap-northeast-1
      auth:
        # 金庫を開けるための鍵(認証情報)を安全に渡すための設定です
        jwt:
          serviceAccountRef:
            name: my-safe-service-account

次に、「この金庫の中にある、あのパスワードを持ってきて!」とお願いする設定を作ります。

設定例2:特定のパスワードを安全に取り出す設定(ExternalSecret)

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: my-database-secret
  namespace: default
spec:
  # 30秒ごとに金庫の中身が更新されていないか確認に行きます(常に最新の鍵に保ちます)
  refreshInterval: "30s"
  
  # 先ほど設定した「金庫の場所(SecretStore)」を指定します
  secretStoreRef:
    name: aws-secrets-manager-store
    kind: SecretStore
    
  # 取り出した鍵を、K8sの中で一時的にどういう名前で扱うかを決めます
  target:
    name: k8s-dynamic-db-secret
    creationPolicy: Owner
    
  # 実際に金庫(AWS)に保管されているデータの名前と、取り出したい項目を指定します
  data:
    - secretKey: db_password # K8s内での変数名
      remoteRef:
        key: production/database/credentials # AWS Secrets Manager上の金庫の箱の名前
        property: password # その箱の中にある「password」という項目を指定

この設定(マニフェスト)を適用すると、ESOという執事のようなシステムが裏側で動いてくれて、AWSの頑丈な金庫から自動的にパスワードを安全に持ってきてくれます。

—

5. さらに強力な防犯:メモリの中だけで鍵を扱う「メモリ内保護」

ここまでの対策で、かなり安全になりました。しかし、最高峰のホワイトハッカーを目指すなら、もう一歩踏み込んでみましょう。

「いくら安全に持ってきても、コンテナの中に一時ファイルとしてパスワードが保存されたら、それが漏れるかもしれない…」

その心配、大正解です!
これを防ぐために、「ハードディスクには一切書き込まず、パソコンのメモリ(脳内・一時記憶領域)の上だけで鍵を扱う」という高度な設定を行います。

K8sでは、一時的なメモリ空間である emptyDir(ミディアム:Memory)という仕組みを使って、コンテナの中に「脳内専用の引き出し」を作ることができます。

設定例3:ファイルに痕跡を残さない「メモリ共有」のポッド設定

apiVersion: v1
kind: Pod
metadata:
  name: secure-web-app
  namespace: default
spec:
  containers:
    - name: web-container
      image: nginx:alpine
      # 脳内専用の引き出し(メモリ)を、アプリから見える場所にマウント(接続)します
      volumeMounts:
        - name: in-memory-vault
          mountPath: /run/secrets/app # アプリはこのフォルダからパスワードを読み取ります
          readOnly: true # 泥棒に書き換えられないように「読み取り専用」にします
  
  # ここで「絶対にハードディスクに書き込まない、メモリだけの引き出し」を定義します
  volumes:
    - name: in-memory-vault
      emptyDir:
        medium: Memory # これが「ハードディスクではなく、メモリ(RAM)の上に作れ!」という魔法の命令です

この設定を行うことで、コンテナが動いている間だけメモリ上にパスワードが存在し、コンテナが停止したり再起動したりした瞬間に、パスワードのデータは宇宙の彼方へ完全に消え去ります。泥棒が後からサーバーのストレージを盗み見ても、そこには1文字のパスワードすら残っていません。

—

まとめ:セキュリティは「めんどくさい」を乗り越えた先にある安心

今回は、Kubernetesにおけるシークレット管理の危険性と、外部の金庫(VaultやSecrets Manager)を使った「動的シークレット注入」、そして「メモリ内保護」の仕組みについて解説しました。

最後に、今回学んだ防犯ポイントをおさらいしましょう!

  • 標準の Secret(Base64)は、植木鉢の下の鍵と同じ。過信は禁物!
  • プロの金庫番(外部マネージャー)と連携して、鍵は外で一括管理する。
  • 鍵は「必要なときだけ使い捨て」を徹底する(動的注入)。
  • サーバーのハードディスクに足跡を残さず、メモリ(Memory)の上だけで鍵を扱う。

セキュリティの対策は、最初は少し設定が面倒に感じるかもしれません。しかし、泥棒に家に入られてから後悔しても遅いのです。

「うちのシステムは大丈夫かな?」と気になった方は、ぜひ今回ご紹介したYAML設定を参考に、一歩ずつ安全なシステムづくりを進めてみてくださいね。

一歩ずつ、安全な開発ライフを一緒に歩んでいきましょう!

コメント

タイトルとURLをコピーしました