For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
メインナビゲーション
Theme

Oracle Cloud Infrastructure 向けワークロード ID フェデレーションの設定

Oracle Identity Cloud Service(IDCS)のアクセストークンを有効期間の短い OpenAI アクセストークンに交換することで、Oracle Cloud Infrastructure(OCI)をワークロード ID プロバイダーとして使用できます。OCI のインスタンス・プリンシパルは、同じテナンシ内のアイデンティティ・ドメインに送るトークン交換リクエストに署名します。OpenAI は、発行されたトークンを検証し、OCI ワークロードがマッピング先の OpenAI サービスアカウントとして動作することを許可します。

この構成では、OpenAI API キーや Oracle のカスタム OAuth リソースアプリケーションは不要です。カスタムアプリケーションにアクセスする権限を動的グループに付与する必要もありません。

OCI ワークロードの設定

インスタンス・プリンシパルを使用する OCI Compute インスタンス上でワークロードを実行します。Oracle Kubernetes Engine(OKE)を使用する場合は、どの ID でリクエストに署名するかを確認してください。標準のインスタンス・プリンシパル署名器が識別するのは、通常、個々の Kubernetes Pod ではなくワーカーノードです。

署名器は OCI インスタンス・メタデータ・サービスから認証情報を取得します。ワークロードからリンクローカルのメタデータエンドポイントにアクセスできることを確認します。

curl --fail --silent \
  --header "Authorization: Bearer Oracle" \
  http://169.254.169.254/opc/v2/instance/id

ワークロードからは、同じテナンシ内のアイデンティティ・ドメインに HTTPS リクエストを送信できる必要もあります。メタデータエンドポイント自体へのアクセスには、NAT ゲートウェイもインターネット接続も不要です。

Oracle アイデンティティトークンの取得

OCI Python SDK の InstancePrincipalsSecurityTokenSigner を使用して、アイデンティティ・ドメインに送る OAuth トークン交換リクエストに署名します。

POST https://<identity-domain>/oauth2/v1/token
Content-Type: application/x-www-form-urlencoded;charset=utf-8

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
scope=urn:opc:idm:__myscopes__
requested_token_type=urn:ietf:params:oauth:token-type:access_token

urn:opc:idm:__myscopes__ スコープでは、インスタンス・プリンシパルにすでに付与されている権限が使われます。返された IDCS アクセストークンを、OpenAI のワークロード ID フェデレーションのサブジェクトトークンとして使用します。Oracle トークンのオーディエンスを https://api.openai.com/v1 に置き換えないでください。実際の Oracle トークンに含まれるオーディエンスを OpenAI 側のプロバイダーに設定します。

トークンの確認

TOKEN に実際の OCI ワークロードで取得したアクセストークンを設定し、既存のローカル JWT デコーダーでクレームを確認します。

const parts = process.env.TOKEN?.split(".") ?? [];
if (parts.length !== 3) {
  throw new Error("Expected a compact JWT with three segments");
}
if (!/^[A-Za-z0-9_-]+$/.test(parts[1]) || parts[1].length % 4 === 1) {
  throw new Error("JWT payload is not valid Base64URL");
}

const bytes = Buffer.from(parts[1], "base64url");
if (bytes.toString("base64url") !== parts[1]) {
  throw new Error("JWT payload is not valid Base64URL");
}
const decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
const claims = JSON.parse(decoded);
if (claims === null || Array.isArray(claims) || typeof claims !== "object") {
  throw new Error("JWT payload is not a JSON object");
}
console.log(decoded);

このデコーダーではトークンの内容を確認できますが、署名は検証されません。トークンは機密情報として扱い、トークンそのものをログに記録しないでください。本番環境のトークンをサードパーティ製の JWT デコーダーに貼り付けないでください。

デコードした Oracle アクセストークンには、次のようなクレームが含まれる場合があります。

{
  "iss": "https://identity.oraclecloud.com/",
  "aud": [
    "https://idcs-example.us-phoenix-1.identity.oraclecloud.com",
    "https://idcs-example.identity.oraclecloud.com"
  ],
  "sub_type": "instance",
  "ipst_instance": "ocid1.instance.oc1.phx.<instance-id>",
  "ipst_compartment": "ocid1.compartment.oc1..<compartment-id>",
  "domain_id": "ocid1.domain.oc1..<domain-id>",
  "ca_ocid": "ocid1.tenancy.oc1..<tenancy-id>",
  "tenant": "idcs-example",
  "exp": 1782369434,
  "iat": 1782365834
}

設定値は、ご利用のアイデンティティ・ドメインが発行したトークンを基準にしてください。iss の値を正確に指定し、同じトークンの aud の値を 1 つ選んで設定します。ワークロードにアクセスを許可する際は、値が変わらないクレーム ipst_instance、ipst_compartment、domain_id、ca_ocid を優先して使用してください。

ワークロード ID フェデレーションの設定

Oracle のアイデンティティ・ドメインに対応するワークロード ID プロバイダーを作成し、対象の OpenAI サービスアカウントの使用を許可する OCI インスタンスまたはコンパートメントのマッピングを追加します。

ワークロード ID プロバイダーの設定

  1. ワークロード ID プロバイダーを作成します。 名前には oracle-cloud-prod などの一意の値を設定します。説明には Production OCI instance principal など、信頼するワークロードを識別できる内容を入力します。

  2. 発行者とオーディエンスを設定します。 OIDC 発行者 URL には、トークンの iss クレームの値(例:https://identity.oraclecloud.com/)を設定します。オーディエンスには、同じトークンの aud の値を 1 つ選んで設定します。

  3. 利用可能な場合は、テナント固有の OIDC ディスカバリーを設定します。 OIDC ディスカバリーにカスタム URL を使用が詳細設定に表示されている場合は、有効にします。カスタム OIDC ディスカバリー URL には、https://idcs-example.identity.oraclecloud.com など、テナント固有のアイデンティティ・ドメインの URL を設定します。OpenAI は https://idcs-example.identity.oraclecloud.com/.well-known/openid-configuration からディスカバリードキュメントを取得し、その jwks_uri を使ってテナントの署名検証用の公開鍵を取得します。カスタムディスカバリーの設定項目が表示されない場合は、代わりにトークンの検証にアップロードした JWKS を使用を有効にし、https://<identity-domain>/admin/v1/SigningCert/jwk から取得した公開 JWKS をアップロードします。

  4. 派生属性が必要な場合にのみ、属性変換を追加します。 サービスアカウントのマッピング条件には、ipst_instance、ipst_compartment、domain_id、ca_ocid などの Oracle クレームをそのまま使用できます。インスタンスの派生属性を明示的に定義するには、属性名に instance、式に assertion.ipst_instance を入力して openai.instance を作成します。

Oracle の OpenID Connect ディスカバリーのリファレンスには、カスタムディスカバリーが重要な理由が示されています。ディスカバリードキュメントでは、グローバルな発行者として https://identity.oraclecloud.com/ が指定されていても、トークンエンドポイントと jwks_uri はテナント固有のアイデンティティ・ドメインで公開されている場合があります。OIDC 発行者 URL にはグローバルな発行者の URL を指定したまま、カスタム OIDC ディスカバリー URL にテナントのドメインを指定します。

アイデンティティ・ドメインがトークン発行者の URL でディスカバリーメタデータを公開している場合は、カスタムディスカバリーを無効のままにし、標準の OIDC ディスカバリーを使用します。OpenAI からテナントのディスカバリードキュメントまたは署名鍵のエンドポイントにアクセスできない場合は、カスタムディスカバリーを無効にし、トークンの検証にアップロードした JWKS を使用を有効にします。そのうえで、https://<identity-domain>/admin/v1/SigningCert/jwk から取得したテナントの公開 JWKS をアップロードします。カスタムディスカバリーとアップロードした JWKS の使用は同時に有効にできません。Oracle が署名証明書を更新した際は、アップロードした鍵も更新してください。

サービスアカウントのマッピングの設定

  1. サービスアカウントのマッピングを作成します。 名前には oracle-instance-prod などの一意の値を設定し、信頼する OCI ワークロードを識別できる説明を追加します。

  2. 対象を最も狭く限定できる安定した OCI ID を照合します。 単一のインスタンスにアクセスを許可するには、キーに ipst_instance を設定し、値に検証済みトークンのインスタンス OCID を正確に指定します。1 つのコンパートメント内のインスタンスにアクセスを許可するには、キーに ipst_compartment を設定し、値にコンパートメントの正確な OCID を指定します。

  3. 必要に応じて、ドメインとテナンシを限定します。 domain_id または ca_ocid をマッピングの行として追加すると、対象のワークロードを特定の Oracle アイデンティティ・ドメインまたはテナンシに限定できます。トークンに sub_type クレームが含まれ、インスタンス・プリンシパルを必須にしたい場合は、このクレームを追加し、値に instance を指定します。マッピングのすべての行で条件が一致する必要があります。

  4. OpenAI 側のマッピング先を選択します。 プロジェクトにはサービスアカウントが属するプロジェクトを設定し、信頼する OCI ワークロードに使用を許可するサービスアカウントを選択します。

  5. 必要に応じて API 権限を絞り込みます。 ワークロードに必要な権限だけを選択します。マッピングの権限設定で、選択したサービスアカウントの権限を制限できますが、そのサービスアカウントが持っていない権限を付与することはできません。

標準のインスタンス・プリンシパル署名器を使用する OKE ワークロードは、ワーカーノードの ID を引き継ぎます。インスタンス単位のマッピングでは、アクセス許可はそのノード全体に適用され、単一の Pod には限定されません。同じワーカーノード上の Pod を相互に分離する必要がある場合は、OCI がサポートする、より細かい単位のワークロード ID を使用してください。

コードでのトークンの使用

OpenAI、OCI、Requests の Python パッケージをインストールします。

pip install openai oci requests

Ruby の場合は、OpenAI と OCI の gem をインストールします。

gem install openai oci

OCI_IDENTITY_DOMAIN_URL には、ワークロードと同じテナンシ内にあるアイデンティティ・ドメインのベース URL を設定します。OPENAI_IDENTITY_PROVIDER_ID と OPENAI_SERVICE_ACCOUNT_ID には、それぞれ OpenAI 側で設定したプロバイダーの ID と、マッピング先のサービスアカウントの ID を設定します。

次の例では、OCI のインスタンス・プリンシパルで Oracle のトークン交換リクエストに署名し、取得した IDCS アクセストークンを OpenAI SDK に返します。SDK は必要に応じて、このトークンを有効期間の短い OpenAI アクセストークンに交換します。

OCI インスタンス・プリンシパルによる認証
import os

import oci
import requests
from openai import OpenAI
from openai.auth import SubjectTokenProvider


def oracle_instance_principal_token_provider(
    identity_domain_url: str,
) -> SubjectTokenProvider:
    def get_token() -> str:
        signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
        response = requests.post(
            f"{identity_domain_url.rstrip('/')}/oauth2/v1/token",
            data={
                "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
                "scope": "urn:opc:idm:__myscopes__",
                "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
            },
            headers={
                "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
            },
            auth=signer,
            timeout=30,
        )
        response.raise_for_status()

        token = response.json().get("access_token")
        if not isinstance(token, str) or not token:
            raise RuntimeError("Oracle IDCS did not return an access token.")

        return token

    return {"token_type": "jwt", "get_token": get_token}


client = OpenAI(
    workload_identity={
        "identity_provider_id": os.environ["OPENAI_IDENTITY_PROVIDER_ID"],
        "service_account_id": os.environ["OPENAI_SERVICE_ACCOUNT_ID"],
        "provider": oracle_instance_principal_token_provider(
            os.environ["OCI_IDENTITY_DOMAIN_URL"]
        ),
    },
)

response = client.responses.create(
    model="gpt-5.6-terra",
    input="Say hello from Oracle Cloud Infrastructure workload identity federation.",
)

print(response.output_text)

OpenAI SDK がワークロード ID の認証情報を更新する必要があるときに、サブジェクトトークンのプロバイダーが新しい Oracle トークンをリクエストします。Oracle のサブジェクトトークンや、交換して得られた OpenAI アクセストークンは、決して出力したり永続化したりしないでください。

OCI のセキュリティに関する推奨事項

  • 1 つのワークロードだけにアクセスを許可する場合は、ipst_instance で単一のインスタンスをマッピングします。
  • ipst_compartment は、そのコンパートメント内で条件を満たすすべてのインスタンスに同じマッピングを適用する場合にのみ使用します。
  • domain_id または ca_ocid を追加し、アクセスできる範囲をアイデンティティ・ドメインやテナンシの境界内に制限します。
  • アプリケーションや環境ごとに個別の OpenAI サービスアカウントを使用します。
  • Pod 単位の分離を前提にする前に、OKE トークンがワーカーノードを表しているかどうかを確認します。
  • OpenAI 固有のオーディエンスを想定せず、発行された Oracle トークンに含まれるオーディエンスを使用します。
  • アイデンティティ・ドメインで OIDC ディスカバリーを使用できない場合は、Oracle が署名鍵を更新するタイミングで、アップロードした公開鍵も更新します。