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

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

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

Codex で使用する場合は、このページの手順に従って Oracle トークンを取得し、内容を確認します。その後、Codex のワークロード ID を設定し、トークンをファイルに書き込んで Codex から参照できるようにします。このページのサービスアカウントのマッピングと SDK の例は、OpenAI API 向けです。

この設定では、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 ID トークンのリクエスト

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 に置き換えないでください。OpenAI プロバイダーには、実際の Oracle トークンに含まれるオーディエンスを設定します。

トークンの確認

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_instanceipst_compartmentdomain_idca_ocid を優先して使用してください。

ワークロード ID フェデレーションのセットアップ

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

ワークロード ID プロバイダーのセットアップ

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

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

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

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

Oracle の OpenID Connect ディスカバリーリファレンスは、カスタムディスカバリーが重要な理由を示しています。ディスカバリードキュメントでは、グローバルな発行者として https://identity.oraclecloud.com/ を宣言しながら、トークンエンドポイントと jwks_uri をテナント固有のアイデンティティドメインで公開できます。 OIDC 発行者 URL にはグローバルな発行者を設定したままにし、 カスタム OIDC ディスカバリー URLにはテナントのドメインを使用してください。

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

サービスアカウントのマッピングのセットアップ

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

  2. 安定して識別できる、範囲が最も狭い OCI ID を照合条件にします。 1 つのインスタンスにアクセスを許可するには、 キーipst_instance に設定し、 には確認済みのトークンに含まれるインスタンス OCID を正確に設定します。1 つのコンパートメント内のインスタンスにアクセスを許可するには、 キーipst_compartment に設定し、 にはコンパートメント OCID を正確に設定します。

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

  4. OpenAI 側の対象を選択します。 プロジェクト には、サービスアカウントが属するプロジェクトを設定します。次に、信頼する OCI ワークロードが使用できる サービスアカウント を選択します。

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

標準のインスタンスプリンシパル署名機能を使用する OKE ワークロードは、ワーカーノードの ID を継承します。インスタンス単位のマッピングで認可されるのは、1 つの 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_IDOPENAI_SERVICE_ACCOUNT_ID には、OpenAI プロバイダーとサービスアカウントのマッピングから取得した 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 で 1 つのインスタンスをマッピングします。
  • コンパートメント内の対象となるすべてのインスタンスでマッピングを共有する場合にのみ、ipst_compartment を使用します。
  • domain_id または ca_ocid を追加して、アイデンティティドメインとテナンシーの境界による制限を適用します。
  • アプリケーションと環境ごとに、別々の OpenAI サービスアカウントを使用します。
  • Pod 単位の分離を前提にする前に、OKE トークンがワーカーノードを表しているかどうかを確認してください。
  • OpenAI 固有のオーディエンスを想定せず、発行された Oracle トークンに含まれるオーディエンスを使用します。
  • アイデンティティドメインで OIDC ディスカバリーを使用できない場合は、Oracle が署名鍵をローテーションする際に、アップロードした公開鍵もローテーションしてください。