トークン交換権限付与タイプ: UPSTのためのKerberosトークンの交換

Kerberosが認証プロバイダであり、KerberosトークンをIAMトークンまたはプリンシパルと交換してOCIサービスにアクセスする必要がある場合に、Kerberosトークン交換を使用します。IAMでKerberosトークンをOCIユーザー・プリンシパル・セッション・トークン(UPST)と交換します。

Kerberosトークンの用語
用語 説明
Kerberos

クロス・プラットフォーム認証のシングル・サインオン・システム。Kerberosプロトコルを使用すると、共有の秘密キー(対称キー)に依存する2つのエンティティ間で相互認証を実行できます。Kerberos認証では、クライアント、サーバーおよびそれらを仲介するための、キー配布センター(KDC)と呼ばれる信頼されたパーティが必要です。

次も必要です:

  • プリンシパル: ユーザーのアイデンティティ(ユーザーにプリンシパルが割り当てられます)、またはKerberosサービスを提供するアプリケーションのアイデンティティ。

  • レルム: Kerberosサーバー環境。example.comなどのドメイン名にすることもできます。各Kerberosレルムには、少なくとも1つのWebサービス・セキュリティKDCがあります。

WS-SecurityのKerberos Token Profileを使用すると、ビジネス・パートナがサービス指向アーキテクチャ(SOA)でKerberosトークンを使用できるようになります。

Kerberosキー配布センター(KDC) サードパーティーの認証サーバー。
Active Directory (AD) KDCサーバーのリポジトリ。
Keytab

特定のプリンシパルのパスワード・チャレンジのかわりに使用できる実際の暗号化キーを格納するファイル。キータブ・ファイルは、非対話型のユース・ケースに役立ちます。

ヒント: KDC管理ツールを使用してキータブ・ファイルを作成できます。keytabの作成時に、暗号化タイプを指定できます。次の暗号化タイプを使用します: aes256-cts-hmac-sha1-96

シンプルで保護されたGSSAPIネゴシエーション・メカニズム(SPNEGO)

Simple and Protected GSSAPI Negotiation Mechanism(SPNEGO)は、クライアント/サーバー・ソフトウェアがセキュリティ・テクノロジの選択をネゴシエーションするために使用するGSSAPIの疑似メカニズムです。

Kerberosチケットは、トークンがHTTPベースのアプリケーション・レイヤーで動作するように、SPNEGOトークンの一部としてラップされます。

SPNEGOトークンのフォーマットと詳細

SPNEGOトークン形式は、RFC 4178で定義されています。トークンは、次のフィールドを含むシリアライズされたデータ構造です。

  • mechTypes: サポートされている認証メカニズムをリストする一連のオブジェクト識別子(OID)。
  • mechToken: オプティミスティック・メカニズム・トークン。これは、使用される実際の認証メカニズムのネゴシエーションに使用されるトークンです。
  • krb5Creds: Kerberos BLOB。これは、Kerberos認証情報を含むバイナリBLOBです。

SPNEGOトークンはASN.1でエンコードされます。次に、SPNEGOトークンの例を示します。

NegTokenInit ::= SEQUENCE
{
mechTypes SEQUENCE OF Oid,
mechToken OCTET STRING,
krb5Creds [0] KerberosCreds OPTIONAL
}
グサピ 一般セキュリティ・サービス・アプリケーション・プログラム・インタフェース
IAMトークン交換Service API IAMアイデンティティ・ドメインOAuthサービス: /oauth2/v1/token。APIは、標準のOAuthベースの認証ヘッダー/ペイロードとOCI署名の両方を受け入れます。アイデンティティ・ドメインでOAuthクライアントを使用してREST APIにアクセスする方法を学習するには、OAuth 2を使用したREST APIへのアクセスを参照してください。
アイデンティティ伝播の信頼構成 アイデンティティ伝播信頼構成を使用して、OCIアイデンティティと外部アイデンティティ・プロバイダ間の信頼を確立し、外部アイデンティティ・プロバイダ・トークンと、外部アイデンティティ・プロバイダのユーザー・アイデンティティとIAMのユーザー・アイデンティティのマッピングを検証します。また、アイデンティティ伝播の信頼によって、外部アイデンティティ・プロバイダからOCIへのアイデンティティ伝播も容易になります。/IdentityPropagationTrustエンドポイント設計は汎用であり、任意のクラウド・プロバイダと連携します。アイデンティティ伝播信頼構成を作成するには、ステップ6: アイデンティティ伝播信頼構成の作成を参照してください。
サービス・ユーザー 対話型ログイン権限のないユーザー。これらのサービス・ユーザーは、グループおよびサービス・ロールに付与できます。アプリケーションは、これらのサービス・ユーザーを使用することも、ログイン・ユーザーがそれらのユーザーを偽装して一時的なUPSTを取得することもできます。サービス・ユーザーの使用はオプションです。サービス・ユーザーの使用の詳細は、ステップ5: サービス・ユーザーの使用(オプション)を参照してください。
ユーザー・プリンシパル・セッション・トークン(UPST) IAM生成トークン。セキュリティ・トークンとも呼ばれます。認証済サービス・ユーザーを表します。

Kerberosトークンの交換ステップ

次のステップを使用して、KerberosトークンをUPSTと交換します。

  1. ステップ1: Vaultの作成およびKeytabファイルの内容の追加
  2. ステップ2: 必要なIAMポリシーの作成
  3. ステップ3: アイデンティティ・ドメイン・アプリケーションの作成
  4. ステップ4: 特定のユーザー・プリンシパルのSPNEGOトークンの生成
  5. ステップ5: サービス・ユーザーの使用(オプション)
  6. ステップ6: アイデンティティ伝播信頼構成の作成
  7. ステップ7: OCIを最新の状態に

ステップ1: Vaultの作成およびKeytabファイルの内容の追加

Vaultを作成し、キータブ・ファイルのコンテンツをbase64エンコード文字列として追加します。ノート: IAMは、keytabファイルをファイル・システムに格納しません。

ガイドとして次のステップを実行します。

  1. Vaultの作成Vaultの作成を参照してください。
  2. keytabの内容をBase64形式で読み取ります。
  3. Vaultに移動し、そのまま格納します。シークレットの作成時に、必ずBase64をシークレット・タイプ・テンプレートとして確認してください。Vaultでのシークレットの作成を参照してください。

ステップ2: 必要なIAMポリシーの作成

アイデンティティ・ドメイン・リソースがVaultにアクセスできるように、テナンシにIAMポリシーを作成します。これにより、IAMはVaultからkeytab構成を取得できます。次の例をガイドとして使用できます。

allow resource iam-domain <domain_displayName> to read secrets from vault in compartment <compartment_ocid> where all {target.secret.id = <secret_ocid_where_the_keytab_is_present>}

ステップ3: アイデンティティ・ドメイン・アプリケーションの作成

アイデンティティ・ドメインの機密アプリケーションを作成します。アプリケーションを作成したら、クライアントIDクライアントシークレットをセキュアな場所に保存します。機密アプリケーションの追加に関する項を参照してください。

ステップ4: 特定のユーザー・プリンシパルのSPNEGOトークンの生成

  1. Javaコードを使用してKDCサーバーに接続し、SPNEGOトークンを生成します。
  2. そのSPNEGOトークンをコピーして、トークン・リクエストを形成します。

次のJavaコード例をガイドとして使用します。

package com.oracle;

import com.sun.security.auth.module.Krb5LoginModule;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;

import javax.security.auth.Subject;
import java.io.IOException;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.Base64;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class GenerateSpnegoToken {
    static String servicePrincipal = "HTTP/iamtesp@WINDOWSKDCSERVER.COM";
    static String userPrincipal = "HTTP/<sample-job>@WINDOWSKDCSERVER.COM";
    static String userPrincipalKeyTab = "keytabs/ms/<sample-job>.keytab";
    public static void main(String[] args) throws IOException {
        System.setProperty("sun.security.krb5.debug", "true");
        System.setProperty("sun.security.spnego.debug", "true");
        System.setProperty("java.security.krb5.conf", "ms_krb5.conf");

        String spnegoToken = generateSpnegoToken();
    }
    private static String generateSpnegoToken() {
        Subject subject = getAuthenticateSubject();
        return Subject.doAs(
                subject,
                (PrivilegedAction<String>)
                        () -> {
                            String SPNEGO_OID = "1.3.6.1.5.5.2";
                            String KRB5_MECHANISM_OID = "1.2.840.113554.1.2.2";
                            String KRB5_PRINCIPAL_NAME_OID = "1.2.840.113554.1.2.2.1";

                            try {
                                // Create GSS context for the service principal and the logged-in user
                                Oid krb5Mechanism = new Oid(KRB5_MECHANISM_OID);
                                Oid krb5PrincipalNameType = new Oid(KRB5_PRINCIPAL_NAME_OID);
                                Oid spnegoOid = new Oid(SPNEGO_OID);
                                GSSManager manager = GSSManager.getInstance();
                                GSSName gssServerName =
                                        manager.createName(servicePrincipal, krb5PrincipalNameType, krb5Mechanism);
                                GSSContext gssContext =
                                        manager.createContext(
                                                gssServerName, spnegoOid, null, 240000);
                                gssContext.requestMutualAuth(true);
                                gssContext.requestCredDeleg(true);
                                gssContext.requestLifetime(10);

                                // Generate the SPNEGO token
                                byte[] token = new byte[0];
                                token = gssContext.initSecContext(token, 0, token.length);
                                return Base64.getEncoder().encodeToString(token);
                            } catch (GSSException e) {
                                throw new RuntimeException(e);
                            }
                        });
    }

    private static Subject getAuthenticateSubject() {
        final Map<String, String> options = new HashMap<>();
        options.put("keyTab", userPrincipalKeyTab);
        options.put("principal", userPrincipal);
        options.put("doNotPrompt", "true");
        options.put("isInitiator", "true");
        options.put("refreshKrb5Config", "true");
        options.put("storeKey", "true");
        options.put("useKeyTab", "true");

        // Execute the login
        Subject subject = new Subject();
        Krb5LoginModule krb5LoginModule = new Krb5LoginModule();
        krb5LoginModule.initialize(subject, null, new HashMap<String, String>(), options);
        try {
            krb5LoginModule.login();
            krb5LoginModule.commit();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        Set<Principal> principals = (Set<Principal>) subject.getPrincipals();
        Iterator<Principal> iterator = principals.iterator();
        while (iterator.hasNext()) {
            System.out.println("\nprincipal : " + ((Principal) iterator.next()));
        }

        return subject;

    }
}

ステップ5: サービス・ユーザーの使用(オプション)

サービス・ユーザーは、属性serviceUsertrueに設定されているアイデンティティ・ドメイン・ユーザーです。

ノート

サービス・ユーザーの使用はオプションです。ユーザーの偽装を信頼構成の一部として使用する場合は、サービス・ユーザーが必要です。それ以外の場合は、他のアイデンティティ・ドメイン・ユーザーが使用されます。サービス・ユーザーを作成、置換、更新または削除できるのは、アイデンティティ・ドメイン管理者のみです。他の管理者は、サービス・ユーザーとその属性を読み取ることができます。

サービス・ユーザーを使用するには、対話型ログイン権限のないユーザーを作成します。これらのサービス・ユーザーは、グループおよびサービス・ロールに付与できます。アプリケーションでこれらのサービス・ユーザーを使用することも、ログイン・ユーザーがそれらを偽装して一時的なUPSTトークンを取得することもできます。

サービス・ユーザーには、次の特徴があります。

  • userNameが必要です。名および姓は必要ありません。
  • 電子メール・アドレスを指定できます(オプション)。
  • グループおよびアプリケーション・ロールのメンバーにできます。
  • APIキーを使用できません。
  • セルフサービス・エンドポイントを使用できません。
  • パスワードおよびパスワード・ポリシーを適用できません。

リクエストの例: サービス・ユーザーの作成

次に、サービス・ユーザーの作成に必要な最小属性を持つリクエストの例を示します。

## POST on https://<domainURL>/admin/v1/Users
## Payload:
{
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User"
    ],
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User": {
        "serviceUser": true
    },
    "userName": "myServiceUserName"
}

レスポンスの例: サービス・ユーザーの作成

次に、サービス・ユーザー作成時のレスポンスの例を示します。

{
    "idcsCreatedBy": {
        "type": "App",
        "display": "idcsadmin"
    },
    "id": "<user_id>",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User": {
        "isFederatedUser": false,
        "isGroupMembershipSyncedToUsersGroups": true,
        "serviceUser": true
    },
    "meta": {
        "created": "2023-12-07T06:52:55.380Z",
        "lastModified": "2023-12-07T06:52:55.380Z",
        "version": "<version>",
        "resourceType": "User",
        "location": "https://<domainURL>/admin/v1/Users/<user_id>"
    },
    "active": true,
    "idcsLastModifiedBy": {
        "display": "idcsadmin",
        "type": "App"
    },
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User": {
        "locked": {
            "on": false
        }
    },
    "ocid": "ocid1.user.region1...<ocid>",
    "userName": "myServiceUserName",
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User",
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User",
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:capabilities:User",
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User"
    ]
}

ステップ6: アイデンティティ伝播信頼構成の作成

アイデンティティ伝播の信頼構成は、OCIアイデンティティと外部クラウド・プロバイダ間の信頼、クラウド・プロバイダ・トークンの検証、およびクラウド・プロバイダのユーザー・アイデンティティとアイデンティティ・ドメインのserviceユーザー・アイデンティティのマッピングを確立するために使用されます。

アイデンティティ伝播の信頼構成の詳細な説明
属性 必須? 説明と例
名前 はい

信頼の名前。

はい

トークン・タイプ:

  • 脊索動物
  • jwt
  • saml
  • AWS資格証明
発行者 はい

発行者を使用して、信頼の識別情報を検索します。たとえば、サービス・プリンシパルIAMSpを使用してSPNEGOトークンが生成される場合、IAMSpが発行者値です。

例: IAMTokenExchangeServicePrincipal

アクティブ はい

有効な場合は、true

無効な場合、false

oauthClients はい

特定の信頼できるパートナのトークンの取得を許可されているOAuthクライアントのリスト。

例:
"oauthClients": [
 "oauthclient-id"
 ],
allowImpersonation (serviceUserを使用) いいえ

ブール値。結果のUPSTにサブジェクトとして認証済ユーザーを含めるか、IAMでサービス・ユーザーを偽装するかを指定します。

impersonatingServiceUser

はい(allowImpersonationtrueに設定されている場合)。

トークン要求名および値条件に基づいて、結果として生成されるプリンシパルが偽装されるかどうかを指定します。次のことができます:

  • すべてのアイデンティティ・プロバイダ(IdP)認証済ユーザーに対して、特定の偽装プリンシパルを許可します。
  • 偽装条件を定義するルールを設定します。
    • トークン要求名に基づく
    • 条件: 次を含む(co)または等しい(eq)
    • 値:
      • 文字列を指定できます。
      • 値の配列および複合/複合値はサポートされていません。
      • equals条件の場合: wild card (*) is allowed
      • 「次を含む」条件の場合: ワイルドカード(*)はサポートされていません
    • 主体になりすます。

例:

  • ルール: "username" eq kafka*
  • マップ済サービス・ユーザー: kafka
  • 結果: kafka接頭辞で始まるすべての認証済ユーザーは、IAMサービス・ユーザーkafkaに偽装されます。結果のUPSTには、認証されたユーザー・プリンシパルとしてkafkaが含まれます。

偽装が許可されている場合、結果のOCIセキュリティ・トークン(UPST)には、元の認証済ユーザー関連クレーム(source_authn_prin)と、代理で偽装が行われたユーザーを示します。

  • サブジェクト要求名が構成されている場合、その要求値の抽出に使用されます。
  • サブジェクト・クレーム名が構成されていない場合、受信トークンのデフォルトはsubです。subクレーム自体が存在しない場合、無視されます。
評価は最初に一致したルールで停止し、対応する結果のプリンシパルは表示名属性を使用して返されます。一致するルールがない場合、トークン・リクエストはエラーで失敗します。
keytab

はい(トークン・タイプがSPNEGOの場合)。

Vaultからkeytab構成を取得します。

重要:
  • トークン交換サービスは、シークレットOCIDおよびシークレット・バージョンに基づいてシークレット情報を取得します。

  • KDCサーバーでkeytabがローテーションされている場合、アイデンティティ伝播の信頼構成でシークレット情報を更新する必要があります。

  • keytabがVaultでローテーションされる場合、アイデンティティ伝播の信頼構成でシークレット情報を更新する必要があります。

リクエストの例: アイデンティティ伝播信頼構成の作成

次に、アイデンティティ伝播信頼構成を作成するリクエストの例を示します。
## POST on https://<domainURL>/admin/v1/IdentityPropagationTrusts
## Payload:
{
 "active": true,
 "allowImpersonation": false,
 "issuer": "idcs_psr_itp",
 "name": "<identity_propagation_trust_name>",
 "oauthClients": [
 "<oauthclient-id>"
 ],
 "keytab": {
 "secretOcid": "<secret_ocid>"
 },
 "subjectMappingAttribute": "userName",
 "subjectType": "User",
 "type": "SPNEGO",
 "schemas": [
 "urn:ietf:params:scim:schemas:oracle:idcs:IdentityPropagationTrust"
 ]
}

レスポンスの例: アイデンティティ伝播信頼構成の作成

次に、アイデンティティ伝播信頼構成の作成時のレスポンスの例を示します。
  "response": {
    "name": "<identity_propagation_trust_name>",
    "type": "<token_type>",
    "issuer": "idcs_psr_itp",
    "accountId": "<example_account_id>",
    "subjectClaimName": "cognito:username",
    "subjectMappingAttribute": "username",
    "subjectType": "User",
    "clientClaimName": "appId",
    "clientClaimValues": ["<client_claim_value>"],
    "active": true,
    "publicKeyEndpoint": "https://example.identityprovider.com/publickey/<publickey_value>",
    "publicCertificate": "<public_certificate_value>",
    "oauthClients": ["<oauthclient-id>"],

    "allowImpersonation": true,
    "impersonationServiceUsers": [
      {
        "rule": "groups co \"network-admin\"",
        "userId": "<user_id>"
      },
      {
        "rule": "groups co \"tenancy-admin\"",
        "userId": "<user_id>"
      }
    ],
    "keytab": {
      "secretOcid": "<secret_ocid>",
      "secretVersion": "<secret_version>"
    },
    "clockSkewSeconds": 60,
    "id": "<identity_propagation_trust_id>",
    "meta": {
      "created": "2023-11-09T23:26:53.224Z",
      "lastModified": "2023-11-09T23:26:53.224Z",
      "resourceType": "IdentityPropagationTrust",
      "location": "http://example.hostname.com:8990/admin/v1/IdentityPropagationTrusts/<identity_propagation_trust_id>"
    },
    "schemas": [
      "urn:ietf:params:scim:schemas:oracle:idcs:IdentityPropagationTrust"
    ],
    "idcsCreatedBy": {
      "value": "<app_id>",
      "display": "admin",
      "type":"App",
      "$ref": "http://example.hostname.com:8990/admin/v1/Apps/<app_id>"
    },
    "idcsLastModifiedBy": {
      "value": "<app_id>",
      "display": "admin",
      "type":"App",
      "$ref": "http://example.hostname.com:8990/admin/v1/Apps/<app_id>"
    }
  }

ステップ7: OCIを最新の状態に

UPSTトークン・リクエスト・ペイロードの詳細説明
リクエスト・パラメータ 有効な値

grant_type

'grant_type=urn:ietf:params:oauth:grant-type:token-exchange'

requested_token_type

'requested_token_type=urn:oci:token-type:oci-upst'

public_key

'public_key=<public-key-value>'

公開キー・ワークフロー:

  1. ワークロードはキー・ペアを生成します。
  2. 公開キーはトークン交換リクエストの一部として送信され、これはクレームjwkとして結果のUPSTに追加されます。
  3. 秘密キーは、OCIネイティブ・サービスAPI呼出しのOCI署名をUPSTとともに生成するために使用されます。
  4. OCIサービス認証では、UPSTが検証され、UPSTからjwkクレームが抽出されてから、OCI署名の検証に使用されます。

subject_token_type

'subject_token_type=spnego'

  • 脊索動物
  • jwt
  • saml
  • AWS資格証明

subject_token

'subject_token=<subject-token>'

トークン・タイプ:

  • spnego: 不透明な暗号化トークン。
  • jwtまたはsaml: jwtまたはsamlアサーション値(そのまま)。
  • aws-credential: XML形式で表示されるAWS資格証明のbase64エンコード値。

issuer

トークン・タイプがspnegoの場合は必須です。

例:

IAMTokenExchangeServicePrincipal

UPSTトークン・リクエストの例: OCI署名ベース

OCI署名ベースのcURLリクエストの例を次に示します。

## OCI Signature Based Request
curl  -X POST -sS https://<domainURL>/oauth2/v1/token -i 
-H 'date: Wed, 06 Dec 2023 01:17:33 GMT' 
-H 'x-content-sha256: <key>' 
-H 'content-type: application/x-www-form-urlencoded;charset=utf-8' 
-H 'content-length: 197' 
-H 'Authorization: Signature version="1",keyId="<key_id>",algorithm="rsa-sha256",headers="(request-target) date host x-content-sha256 content-type content-length",signature="a+aH0b...TLtPA=="'  --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'requested_token_type=urn:oci:token-type:oci-upst' \
--data-urlencode 'public_key=<public_key>' \
--data-urlencode 'subject_token=<subject_token>' \
--data-urlencode 'subject_token_type=spnego' \
--data-urlencode 'issuer=<Issuer stored in the Identity Trust Propagation. For example, examplead@kdcserver.com>' -k
{
   "token": "<token_id>"
}

UPSTトークンのリクエストの例: アイデンティティ・ドメイン・アプリケーションベース

次に、OCIアイデンティティ・ドメイン・アプリケーションベースのcURLリクエストの例を示します。

## IAM Domain App Based Request. Note that client credentials can be sent as part of basic authn header or in the payload.  
curl --location ' https://<domainURL>/oauth2/v1/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic <auth_code>' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'requested_token_type=urn:oci:token-type:oci-upst' \
--data-urlencode 'public_key=<public_key>' \
--data-urlencode 'subject_token=<subject_token>' \
--data-urlencode 'subject_token_type=spnego' \
--data-urlencode 'issuer=<Issuer stored in the Identity Trust Propagation. For example, examplead@kdcserver.com>' -k
{
   "token": "<token_id>"
}