C 用の許可 API
許可 API を使用すると、カスタム アクセス制御機能を実装できます。カスタム アクセス制御機能を実装するには、以下を行う必要があります。
sm1252sp1jjp
許可 API を使用すると、カスタム アクセス制御機能を実装できます。カスタム アクセス制御機能を実装するには、以下を行う必要があります。
- 許可 API をサポートし、必要なカスタム機能を提供する共有ライブラリを開発します。共有ライブラリには、エクスポート可能な記号として定義された 1 つ以上の関数が含まれる必要があります。SmApi.h はカスタム ポリシー、ルールおよびレスポンス プラグインを作成するのに必要なデータ構造をすべて定義します。
- 共有ライブラリを以下のいずれかのデフォルトの場所にインストールします。
- UNIX プラットフォームでは、CA Single Sign-onlib ディレクトリ
- Windows プラットフォームでは、CA Single Sign-onbin ディレクトリ
- 管理 UI で以下の 1 つ以上を定義します。
- アクティブ ポリシー -- 外部のビジネス ロジックに基づいて動的な認可を提供するポリシー。たとえば、ユーザがアクティブなポリシー式のパラメータ(param)フィールドで定義されるような LDAP ディレクトリ内の特定の組織単位(ou)に属する場合に真を返すアクティブなポリシーを定義することができます。
- アクティブ レスポンス -- 共有ライブラリから返されたカスタム レスポンス。アクティブ レスポンスの使用は、ユーザに固有の権限情報を定義できる 1 つの方法です。たとえば、ユーザがアクティブなレスポンス表現のparamフィールドで指定された ou に属する場合、ユーザの共通名(cn)を返すアクティブなレスポンスを定義することができます。
- アクティブ ルール--外部のビジネス ロジックに基づいて動的な認可を提供するルール。たとえば、ユーザがレルムを表示する権限があるディレクトリ管理者など、グループのメンバである場合に真を返すアクティブなルールを定義することができます。
認可 API を拡張する場合、SmApi.h ヘッダ ファイルを含めます。
#include "SmApi.h"
許可 API には、ポリシー サーバへのローカル アクセス タイプがあります。
アクティブな式
アクティブな式
は、アクティブなポリシー、ルールまたはレスポンスを含む変数定義の文字列です。アクティブな式は以下の構文を使用して、管理 UI で作成されます。<@ lib=<lib-spec> func=<func-spec> param=<func-params>@>
この構文例において、
- lib-specはカスタム共有ライブラリへのパスです。この節は必須です。ライブラリをデフォルトの場所に配置する場合、指定する必要があるのはライブラリ ファイル名のみでパスは不要です。また、拡張子 .dll または .so はオプションです。
- func-specは、共有ライブラリで定義されたユーザ定義の、外部的に表示できる関数の名前です。この節は必須です。
- func-paramsは関数に渡されるパラメータ文字列です。この節はオプションです。
CA Single Sign-on
は、[アクティブ ルール エディタ]、[アクティブ ポリシー エディタ]、または[アクティブ レスポンス属性エディタ]ダイアログ ボックスで提供される情報からアクティブな式を組み立てます。CA Single Sign-on
がアクティブな式を解釈する方法アプリケーションのアクティブな式は、以下のタスクを開始します。
- アクティブな式で指定された共有ライブラリをロードします。
- アクティブな式で指定されたユーザ定義関数を呼び出します。
- ユーザ定義関数に、オプションのパラメータ文字列とコンテキスト情報、すなわち API コンテキスト(Sm_Api_Context_t)、要求コンテキスト(Sm_Api_RequestContext_t)、およびユーザ コンテキスト(Sm_Api_UserContext_t)を渡します。
共有ライブラリ内の指定されたユーザ定義関数は、結果を lpszOutBuf パラメータ内の
CA Single Sign-on
に返します。CA Single Sign-on
は、アクティブな式のタイプに従って以下のようにこの結果を解釈します。- アクティブ ポリシー -- 関数の呼び出しが失敗した場合や、lpszOutBufで返された結果が空の場合、認可が拒否されます。lpszOutBufで返された結果が次の文字列(大文字と小文字を区別しない)のいずれかに一致する場合、ポリシーは開始しません。FALSE、F または 0。他の結果値の場合ポリシーが開始します。
- アクティブ ルール -- 関数の呼び出しが失敗した場合や、lpszOutBufで返された結果が空の場合、以下の動作が発生します。
- アクセス許可ルールでは、ルールが起動しません。
- アクセス拒否ルールでは、ルールが起動します。
これ以外の場合は、動作はアクティブ ポリシーと同じです。 - アクティブ レスポンス -- 結果はレスポンス属性値を表す文字列です。CA Single Sign-onがどのようにこの値を使用するかは、管理 UI で指定されたレスポンス属性によって決定されます。例:
- WebAgent-OnReject-Redirect。この属性を与えられると、CA Single Sign-onは、レスポンス値がリソースへのアクセスを拒否されたユーザをリダイレクトするために URL など場所を指定すると予測します。たとえば、アクティブな式のオプションのparam変数でグループ名を指定し、次に、パスを戻す URL を決定するために関数内のグループ名の検査を行うことができます。
- WebAgent-HTTP-Cookie-Variable。この属性を与えられると、CA Single Sign-onは、ユーザの共通名などのレスポンス値が Cookie 変数に割り当てられることになっていると予期します。フォームをパーソナライズするためにユーザの共通名を表示するなどのように、レスポンス値を好きなように使用できます。CA Single Sign-onレスポンス属性エディタで Cookie 名を指定します。
アクティブ ルールの定義
アクティブ ルールは、アクティブ ルール エディタ ダイアログ ボックスを使用して管理 UI で定義されます。[ルール プロパティ]ダイアログ ボックスからこのエディタにアクセスするには、[詳細]グループ ボックス内の[アクティブ ルール]タブを選択し、次に、[編集]をクリックします。
アクティブ レスポンスの定義
アクティブ レスポンスは、レスポンス属性エディタ ダイアログ ボックスを使用して管理 UI で定義されます。
[レスポンス プロパティ]ダイアログ ボックスから、[作成]をクリックしてエディタにアクセスし、[属性のセットアップ]タブ上の[属性の種類]グループ ボックス内の[アクティブ レスポンス]ボタンを選択します。
アクティブ ポリシーの定義
アクティブ ポリシーは、アクティブ ポリシー エディタ ダイアログ ボックスを使用して管理 UI で定義されます。
[ポリシー プロパティ]ダイアログ ボックスから、[詳細]タブを選択し[編集]をクリックしてこのエディタにアクセスします。
ポリシー サーバへの HTTP ヘッダおよび Cookie のパス
任意のカスタム キー/値ペアを現在のセッションに追加して、HTTP ヘッダおよび Cookie をポリシー サーバに渡すことができます。これらのキー/値ペアはセッション ストアに保持され、有効期間はセッションと同じです。名前/値ペアは、セッション ストア データベース内の Expiry Data テーブルに保存されます。1 つのセッションに対し最大 5 つのエントリが可能です。アクティブ プラグイン コードは、UserContext 構造(Sm_Api_UserContext_t* lpUserContext)を使用して fSetProp と fGetProp をそれぞれ呼び出すことによりこれらの名前/値ペアを設定し取得することができます。値を設定するには、fSetProp は値として SM_SESSIONVAR(<name>) および lpszValueBuf として lpszPropName で呼び出されます。値を取得するには、fGetProp は SM_SESSIONVAR(<name>)/ SM_SESSIONVAR として lpszPropName で呼び出され、値/値は lpszValueBuf で返されます。
以下の点に注意してください。
- Expiry Data テーブルで名前/値ペアを設定するには、名前は SM_SESSIONVAR(<name>) 形式のみで渡される必要があります。名前は最大 32 文字の長さで、文字またはアンダースコアで始まることができ、文字、数字またはアンダースコアのみが使用できます。設定できる値の長さは最大 4000 文字です。
- 名前の値を取得するには、名前は SM_SESSIONVAR(<name>) 形式で渡される必要があります。<name> に対応する Expiry Data テーブル内の値が返されます。SM_SESSIONVAR のみが渡される場合(名前は含まれない)、そのセッションの名前がすべてキャレットで区切られた形式で返されます。
- Expiry Data テーブル内の名前/値ペアを削除する場合、名前は SM_SESSIONVAR(<name>) として渡されます。また値はブランクとして渡される必要があります。
認可関数宣言
共有ライブラリには、適切なエントリ ポイントが必要です。共有ライブラリ内のエントリ ポイントはそれぞれ 1 つ以上のアクティブな式を表し、指定された構文に従って定義される必要があります。
注:
Microsoft Visual Studio を使用している場合は、関数アドレスをモジュール定義ファイル(.DEF ファイル)にエクスポートします。関数アドレスをエクスポートするには、.DEF ファイルを作成し、.DEF ファイルのエクスポート セクションに、アクティブ ルールまたはアクティブ ポリシーから呼び出す関数をリストアップします。.DEF ファイルを作成した後、Microsoft Visual Studio プロジェクトにそれを追加します。ユーザ定義関数
ポリシー サーバは、ユーザ定義関数を呼び出しカスタム ポリシー、ルールまたはレスポンス操作を実行します。
任意の名前の関数を割り当てることができます。管理 UI で定義するアクティブな式によって、
CA Single Sign-on
に関数名および関数が存在する共有ライブラリの名前を知らせます。構文
int SM_EXTERN <func-spec> (const Sm_Api_Context_t*lpApiContext,const Sm_Api_UserContext_t*lpUserContext,const Sm_Api_RequestContext_t*lpReqContext,const char*lpszParam,const intnBytesOutBuf,char*lpszOutBuf,const intnBytesErrBuf,char*lpszErrBuf);
パラメータ | I/O | 説明 |
lpApiContext
| I | API コンテキスト構造へのポインタ。 |
lpUserContext
| I | ユーザ コンテキスト構造へのポインタ。 |
lpReqContext
| I | 要求コンテキスト構造へのポインタ。 |
lpszParam
| I | で指定された NULL で終 わるパラメータ文字列が含まれるバッファへのポインタ。 |
nBytesOutBuf
| I | 出力結果バッファ(4097 バイト)の最大サイズ。 |
lpszOutBuf
| O | CA Single Sign-on に送信する結果の出力バッファ。 |
nBytesErrBuf
| I | 出力エラー バッファ(4097 バイト)の最大サイズ。 |
lpszErrBuf
| O | エラー テキストを受信するための出力バッファ。 CA Single Sign-on は、デバッグ ログ ファイルにエラー テキストを表示します。 |
戻り値
- 実行が成功すると、関数は 0 より大きい値、すなわち結果バッファlpszOutBuf内のバイトの総数を返します。
- エラーが発生した場合、関数は -1 を返し、エラー バッファlpszErrBufに適用可能なエラー メッセージを保存します。
- アクティブ ルールに対して使用される場合、0 の戻り値(空の文字列は、lpszOutbufに戻されました)は、以下のいずれかのアクションをもたらします。
- アクセス許可ルールでは、ルールが起動しません。
- アクセス拒否ルールでは、ルールが起動します。
SmQueryVersion()
ポリシー サーバは、この関数を呼び出し、カスタム ライブラリが準拠している許可 API のバージョンを決定します。
構文
int SmQueryVersion (const Sm_Api_Context_t* lpApiContext);
パラメータ | I/O | 説明 |
lpApiContext
| I | API コンテキスト構造へのポインタ。 |
戻り値
許可 API のバージョン番号を返します。現在、サポートされたバージョンは Sm_Api_Version_V3 です。この定数は SmApi.h で定義されています。
アクティブな式の例
以下のセクションで提供されるこのサンプルは以下にあります。
sdk\samples\smazapi\smazapi.cpp
以下に示すような各サンプルに先行する構文は、
<@ lib="SmAzAPI" func="activeRule" param="" @>
CA Single Sign-on
の[アクティブ ルール エディタ]、[アクティブ ポリシー エディタ]または[アクティブ レスポンス属性エディタ]ダイアログ ボックスにおいてダイアログ ボックスでユーザが提供する情報から CA Single Sign-on
が作成する生成されたスクリプトの例です。UNIX 用のサンプルのアクティブな式を作るには、<install_path>\sdk\samples\smazapi\makefile にある makefile を使用します。
アクティブ ルールの例
以下の例では、ユーザがレルムを表示する特別なアクセス許可がある場合、真を返します。ユーザにディレクトリ管理者権限がある場合、ユーザはレルムを表示できます。
<@ lib="SmAzAPI" func="activeRule" param="" @>*************************************************************int SM_EXTERN activeRule(const Sm_Api_Context_t* lpApiContext,// the structure that provides API contextconst Sm_Api_UserContext_t* lpUserContext,// the structure that provides user contextconst Sm_Api_RequestContext_t* lpReqContext,// the structure that provides request contextconst char* lpszParam,// the parameter string (null-terminated)const int nBytesOutBuf,// the maximum size of the output bufferchar* lpszOutBuf,// the output buffer to hold the null-terminated resultconst int nBytesErrBuf,// the maximum size of the error message bufferchar* lpszErrBuf)// the output buffer to hold the null-terminated error message{/* User Context is required to use the functions like fGetProp, fSetProp.. */if(!lpUserContext->bIsUserContext){strncpy (lpszErrBuf, "No User Context ", nBytesErrBuf);lpszErrBuf[nBytesErrBuf-1] = '\0';return -1;}/*// The DN to look for the attribute "uniquemember"// If the user is listed as the member of the above attribute,// it has directory manager privileges.*/char lpszDn[] = "cn=Directory Administrators,ou=Groups,o=airius.com";char lpszDnvalue[256];memset(lpszDnvalue, 0, sizeof(lpszDnvalue));/*// fGetDnProp function is used to retrieve an attribute value// in a directory entry.*/int getResult = lpUserContext->fGetDnProp(lpUserContext->lpParam,lpszDn,"uniquemember",sizeof(lpszDnvalue),lpszDnvalue);/*// If no error occurs, fGenDnProp will return the length of the// buffer lpszDnvalue. Otherwise the function returns 0.*/if(getResult > 0){/* Check to see if the user is present in the list. */if(strpbrk(lpszDnvalue, lpUserContext->lpszUserName) != NULL){/* The result "true" is placed in the output buffer. */strncpy(lpszOutBuf, "true", nBytesOutBuf);lpszOutBuf[nBytesOutBuf-1] = '\0';return strlen(lpszOutBuf);}else{strncpy(lpszOutBuf, "false", nBytesOutBuf);lpszOutBuf[nBytesOutBuf-1] = '\0';return strlen(lpszOutBuf);}}else{strncpy(lpszErrBuf, "Failed to get attribute value for the DN ",nBytesErrBuf);strncat( (lpszErrBuf + strlen(lpszErrBuf)), lpszDn,(nBytesErrBuf-strlen(lpszErrBuf)));lpszErrBuf[nBytesErrBuf-1] = '\0';return -1;}/* everything failed.... */return 0;}
アクティブ レスポンスの例
このアクティブ レスポンスは、ユーザがアクティブなレスポンス表現のパラメータ(param)フィールドで指定された組織単位に属する場合、ユーザの共通名(cn)を返します。
<@ lib="SmAzAPI" func="activeResponse" param="Human Resources" @>***********************************************************int SM_EXTERN activeResponse(const Sm_Api_Context_t* lpApiContext,/* the structure that provides API context */const Sm_Api_UserContext_t* lpUserContext,/* the structure that provides user context */const Sm_Api_RequestContext_t* lpReqContext,/* the structure that provides request context */const char* lpszParam,/* the parameter string (null-terminated) */const int nBytesOutBuf,/* the maximum size of the output buffer */char* lpszOutBuf,/* the output buffer to hold the null-terminated attribute value */const int nBytesErrBuf,/* the maximum size of the error message buffer */char* lpszErrBuf)/* the output buffer to hold the null-terminated error message */{memset(lpszOutBuf, 0, sizeof(lpszOutBuf));if(!lpUserContext->bIsUserContext){strncpy (lpszErrBuf, "No User Context ", nBytesErrBuf);lpszErrBuf[nBytesErrBuf-1] = '\0';return -1;}/* Store all the organizational units to which the user belongs. */char lpszOrgUnit[30];memset(lpszOrgUnit, 0, sizeof(lpszOrgUnit));/* store the common name of the user. */char lpszCN[30];memset(lpszCN, 0, sizeof(lpszCN));/* Check to see if a parameter is requested. */if(lpszParam == NULL || strlen(lpszParam) == 0){strncpy (lpszErrBuf, "Organizational unit is not entered ",nBytesErrBuf);lpszErrBuf[nBytesErrBuf-1] = '\0';return -1;}/* Get all the organization units to which the user belongs. */int getResult = lpUserContext->fGetProp (lpUserContext->lpParam,"ou", /* Attribute name */sizeof (lpszOrgUnit), lpszOrgUnit);if (getResult < 0){strncpy (lpszErrBuf,"Failed to get organization unit for the user's profile ",nBytesErrBuf);strncat( (lpszErrBuf + strlen(lpszErrBuf)),lpUserContext->lpszUserName,(nBytesErrBuf-strlen(lpszErrBuf)));lpszErrBuf[nBytesErrBuf-1] = '\0';return -1;}else{/* Check if the user belongs to the organization unit that is requested. */if(strstr(lpszOrgUnit, lpszParam) != NULL){if((lpUserContext->fGetProp(lpUserContext->lpParam,"cn",sizeof(lpszCN),lpszCN)) > 0){strncpy(lpszOutBuf, lpszCN, nBytesOutBuf);lpszOutBuf[nBytesOutBuf-1] = '\0';return strlen(lpszOutBuf);} /* end of fGetProp */else{strncpy (lpszErrBuf,"Failed to get user common name from user's profile attribute ",nBytesErrBuf);strncat( (lpszErrBuf + strlen(lpszErrBuf)),lpUserContext->lpszUserName,(nBytesErrBuf-strlen(lpszErrBuf)));lpszErrBuf[nBytesErrBuf-1] = '\0';return -1;}} /* end of strstr */else{strncpy (lpszErrBuf,"The user does not belong to the requested organizational unit ",nBytesErrBuf);lpszErrBuf[nBytesErrBuf-1] = '\0';return -1;}}/* everything failed.... */return 0;}#ifndef _WIN32}#endif