SPIFFE 仕様全部読んでく - SPIFFE ID

SPIFFE に個人的に興味を持ち始めたので、https://github.com/spiffe/spiffe/blob/main/standards/ にある仕様を全部読んで簡単にまとめてく。今回は、SPIFFE-ID についてです。 尚、学習中であるため解釈が間違っている可能性は存分にあります。

ざっくりまとめ

原文: https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md

SPIFFE ID

  • SPIFFE ID
    • RFC 3986 準拠の URI として定義
    • spiffe://trust-domain/path

trust-domain

  • SPIFFE を実行する個人、組織、環境、部門等を示す
    • ※パブリック DNS のようにどこか公な場に登録するようなものではない
  • trust-domain 名の制限
    • 空文字であってはならない
    • 小文字でなければならない
    • a-z0-9.- で構成されなければならない
    • パーセントエンコードされた文字を使ってはいけない
      • i.e. URI として使用できない文字は使用してはいけない
    • IPv4 形式のアドレスは ↑ の制約を満たすが、IPv6 形式のアドレスでは制約を満たさない
      • DNS 名であれば、完全に満たす
  • trust-domain は自由に選択することができるが、規約や登録を行うための中央集権的な機関は存在しない
    • i.e. グローバルに一意であることは全く保証できない
    • 偶発的な衝突を避けるために、グローバルユニークな可能性が高いものを trust-domain として選択することが推奨されている(DNS 名など)
    • trust-domain 名を自動生成する場合は、グローバルに衝突しにくいような UUID 等を用いることが強く推奨されている
    • 衝突が発生した場合は、独立して動作し続けることが可能だが、フェデレート(相互接続)は行うことができない

path

  • path の制限
    • パーセントエンコードされた文字を使ってはいけない
    • パスのコンポーネントには、空のセグメントや相対パスの修飾子(., ..)を使ってはいけない
    • 末尾に / を含んではいけない
    • 個々のパスセグメントは a-z0-9.- で構成されなければならない
    • パスは階層表現してよい
      • 具体的な階層の仕様に関しては、実装者に委ねられる(Istio の場合は、Service Account で埋めている)
  • パスの例
    • サービスを指定する
      • spiffe://staging.example.com/payments/mysql, spiffe://staging.example.com/payments/web-fe
    • サービスの所有者を指定する
      • spiffe://k8s-west.example.com/ns/staging/sa/default
    • 不透明な情報でパスを埋める
      • これが最も一般的な模様
      • spiffe://example.com/9eebccd2-12bf-40a6-b262-65fe0487d453

Maximum SPIFFE ID Length

  • RFC 3986 で定義されているように、URI には長さの制限がない
  • SPIFFE では、相互運用性を考慮しこの長さを 2048 バイトまでに制限している
    • ただし、推奨最大長なので一応これを超過することも可能
  • trust-domain の最大長は 255 バイト
    • これは、RFC 3986 の host 部の最大長で定義がされている

SPIFFE ID Parsing

  • RFC 3986 に従ってパースされる
    • スキーム(spiffe)と trust-domain は大文字と小文字を区別しないが、パスは区別される

SVID(SPIFFE Verifiable Identity Document)

  • SVID
    • ワークロードが SPIFFE ID を呼びだし元/先と通信する仕組み
    • trust-domain 内の CA によって署名された場合、その ID を有効とみなす

SVID Trust

  • 署名機関は、trust-domain 内に存在しなければならず、自身の SVID を有さなければならない
    • 署名機関自身の SPIFFE ID は trust-domain に存在するべきで、パスコンポーネントを持つべきではない
    • 必要に応じて、外部の trust-domain の秘密鍵で署名することもできるが、基本的には自己署名

SVID Components

  • 3 つの要素から構成される
    • SPIFFE ID
    • 有効な署名
    • (オプション)公開鍵
  • SPIFFE ID と(オプション)公開鍵は、署名される Payload の一部に含めなければならない
  • SVID 内には上記の情報以外を含めてもよい
    • JWT-SVID とかはその典型例

SVID Format

  • (2022/07 現在)サポートされているドキュメントタイプ
    • X.509
    • JWT
  • 詳細は、別記事で

Security Considerations

SVID Assertions

Temporal Accuracy

  • SVID は、鍵の漏洩とそれに伴う損害を軽減することを目的として、限られた時間だけ有効なものとなっている
    • アサーションは発行時に真であることが多いが、使用時には必ずしもそうとは限らない
    • 変更される可能性が高い情報
      • SA, Role, Member of group, Access Policy, etc.
    • 変更される可能性が低い情報(i.e. 時間的精度の問題の影響を受けづらい)
      • SPIFFE ID, Region, etc.
  • どのような情報を含めるか?を検討する際は上記のようなことを考慮することが重要

Scope and Influence

  • SVID は、それが存在する trust-domain 内の署名機関によって署名される
    • i.e. SVID の情報全てを検証するのは、署名機関の責任
  • アサーションの有効範囲は、trust-domain に閉じるべき
    • e.g. ある trust-domain A で "admin" というロールを持つエンティティを他の trust-domain B で "admin" として扱うべきではない、etc.

Interpretation

  • 柔軟性を持たせるために SVID 仕様は、任意の情報を含めることを許可している
    • 任意の情報を含めたとしても原則は、意味が合意された trust-domain に限定するべき

Veracity

  • 同じ trust-domain 内で発行された SVID に含まれるアサーション -> 真実であると仮定できる
  • 別の trust-domain で発行された SVID に含まれるアサーション -> 真実だと仮定することに意味なし