背景と適用シナリオ
Salesforce 統合エンジニア (Salesforce Integration Engineer) として、私の主な役割は Salesforce と多種多様な外部システムを、安全かつ効率的に接続することです。この目標を達成するために我々が利用するツールの中でも、最も重要かつ強力な機能の一つが Named Credential (指定ログイン情報) です。
かつて、外部サービスへの API コールアウトを実装する際には、多くの課題がありました。エンドポイント URL や認証情報 (ユーザー名、パスワード、API キーなど) を Apex コード内に直接ハードコーディングしたり、カスタム設定 (Custom Settings) やカスタムメタデータ (Custom Metadata) に保存したりする方法が一般的でした。しかし、これらのアプローチには以下のような深刻な問題が伴います。
- セキュリティリスク: パスワードやクライアントシークレットのような機密情報が、コードや設定データとして平文に近い形で保存される可能性があり、セキュリティ上の脆弱性を生み出します。コードリポジトリや組織のメタデータにアクセスできる誰もが、これらの情報を閲覧できてしまいます。
- メンテナンスの煩雑さ: 外部システムの認証情報が変更された場合 (例えば、パスワードの定期変更ポリシーなど)、関連するすべての Apex クラス、トリガー、または設定レコードを特定し、手動で更新する必要がありました。これは非常に手間がかかり、更新漏れによるエラーの原因となり得ます。
- 環境管理の複雑さ: Sandbox から本番環境へデプロイする際、環境ごとに異なるエンドポイント URL や認証情報を手動で再設定する必要がありました。これにより、デプロイプロセスが複雑化し、ヒューマンエラーが発生しやすくなります。
Named Credential は、これらの問題を解決するために設計されました。API 連携における認証管理を一元化し、セキュリティを大幅に向上させ、メンテナンスを簡素化します。例えば、以下のようなシナリオで絶大な効果を発揮します。
- Google や Microsoft 365 のような外部サービスと OAuth 2.0 を用いて連携する。
- Stripe や PayPal などの決済ゲートウェイ API を呼び出す。
- 社内の基幹システム (ERP, SCM) と REST/SOAP API を介してデータ同期を行う。
- 外部の気象情報サービスや株価情報サービスからリアルタイムデータを取得する。
これらのシナリオにおいて、Named Credential は認証情報の安全な保管庫として機能し、開発者は認証プロセスの複雑な詳細を意識することなく、ビジネスロジックの実装に集中できるようになります。
原理説明
Named Credential は、単なる URL の保存場所ではありません。これは、Salesforce が外部システムとの認証を管理するための、洗練されたフレームワークです。その中心的な考え方は、「コールアウトのエンドポイントと認証情報の分離」です。Apex コードは、具体的な URL やパスワードの代わりに、設定された Named Credential の名前を参照するだけです。
近年のリリースにより、このフレームワークはさらに進化し、External Credential (外部ログイン情報) と Principal (プリンシパル) という概念が導入されました。これにより、より柔軟で再利用性の高い設定が可能になりました。
1. External Credential (外部ログイン情報)
External Credential は、認証プロトコルとそのパラメータを定義する中心的なコンポーネントです。これは「どのように認証するか」を定義します。
- Authentication Protocol (認証プロトコル): OAuth 2.0, JWT Bearer Flow, Client Credentials with JWT, Basic Auth (ユーザー名/パスワード), AWS Signature v4, Custom など、多様なプロトコルをサポートします。
- Parameters (パラメータ): 選択したプロトコルに必要な情報 (例: OAuth 2.0 における Client ID, Client Secret, Scope, Auth Provider など) を設定します。
External Credential は再利用可能であり、一つの External Credential を複数の Named Credential から参照することができます。例えば、同じ Google Cloud Platform プロジェクト内の異なる API (Google Drive API と Google Calendar API) にアクセスする場合、同じ OAuth 2.0 設定を共有できます。
2. Named Credential (指定ログイン情報)
新しいフレームワークにおける Named Credential の役割は、主に「どこに接続するか」を定義することです。
- URL: 接続先となる外部システムのベース URL を指定します。(例: `https://api.example.com`)
- External Credential へのリンク: 使用する認証方法として、先ほど作成した External Credential を選択します。
- 認証タイプ:
- Named Principal (指定プリンシパル): 組織全体で単一の認証情報セットを使用する方式です。システム間連携など、特定のユーザーに依存しない場合に適しています。
- Per User (ユーザーごと): API コールアウトを実行する Salesforce ユーザーごとに、個別の認証を行う方式です。例えば、各ユーザーが自身の Google Drive アカウントに接続するようなシナリオで使用します。
この構造により、認証の仕組み (External Credential) と接続先 (Named Credential) が明確に分離され、管理が非常に容易になります。
3. Principal (プリンシパル)
Principal は、認証の主体、つまり「誰として認証するか」を定義します。Named Principal を選択した場合、External Credential で定義されたプロトコルに基づいた具体的な認証情報 (ユーザー名、パスワード、トークンなど) をここで設定します。Per User 認証の場合は、各ユーザーが個別に認証を行い、その結果 (アクセストークンなど) が Salesforce によって安全に管理されます。
Apex からコールアウトを行う際、開発者は以下のようなシンプルな構文を使用します。
`'callout:My_Named_Credential_Name/some_path'`
この `callout:` プレフィックスを見た Salesforce プラットフォームは、`My_Named_Credential_Name` という名前の Named Credential を探し出し、そこに設定されている URL と認証情報 (External Credential 経由で取得) を自動的に付与して、HTTP リクエストを構築します。これにより、Apex コードから全ての機密情報が排除され、安全なコールアウトが実現します。
サンプルコード
以下は、Named Credential を使用して外部の REST API へ GET リクエストを行う標準的な Apex コードの例です。このコードは、`My_API_Credential` という名前の Named Credential が設定済みであることを前提としています。
// My_API_Credential という名前の指定ログイン情報を使用して外部サービスにコールアウトする例
public class ApiCalloutService {
public static String performGetCallout() {
// 1. HttpRequest オブジェクトのインスタンスを作成します。
HttpRequest req = new HttpRequest();
// 2. エンドポイントを設定します。
// 'callout:' プレフィックスに続けて指定ログイン情報の名前を指定し、
// その後に任意のリソースパスを追加します。
// Salesforce は 'callout:My_API_Credential' の部分を、
// 指定ログイン情報に設定された URL (例: https://api.example.com) に自動的に置き換えます。
// さらに、認証ヘッダー (Authorization Header) を自動的に付与します。
req.setEndpoint('callout:My_API_Credential/v1/invoices');
// 3. HTTP メソッドを 'GET' に設定します。
req.setMethod('GET');
// 4. Http オブジェクトのインスタンスを作成し、リクエストを送信します。
Http http = new Http();
HttpResponse res = null;
try {
// 5. send() メソッドを実行して、外部サービスにリクエストを送信し、レスポンスを受け取ります。
res = http.send(req);
// 6. レスポンスのステータスコードを確認します。
if (res.getStatusCode() == 200) {
// 成功した場合、レスポンスボディを返す。
System.debug('成功時のレスポンス: ' + res.getBody());
return res.getBody();
} else {
// エラーが発生した場合、ステータスコードとメッセージをログに出力します。
System.debug('コールアウトエラー: ' + res.getStatusCode() + ' ' + res.getStatus());
// エラー処理をここに追加します。
return null;
}
} catch(System.CalloutException e) {
// 7. コールアウト中に例外が発生した場合の処理 (例: 接続タイムアウト、DNS解決エラーなど)。
System.debug('コールアウト例外が発生しました: ' + e.getMessage());
// 例外処理をここに追加します。
return null;
}
}
}
このコードからわかるように、認証に関する記述 (トークンの取得、ヘッダーへの設定など) は一切ありません。開発者はビジネスロジックに集中でき、コードは非常にクリーンで読みやすくなります。
注意事項
Named Credential は非常に強力ですが、その能力を最大限に引き出し、安全に運用するためには、いくつかの重要な点に注意する必要があります。
権限管理 (Permissions)
新しい External Credential フレームワークを使用する場合、ユーザーがコールアウトを実行するためには適切な権限が必要です。これはプロファイル (Profile) や権限セット (Permission Set) を通じて付与します。
- External Credential Principal Access (外部ログイン情報のプリンシパルアクセス): これが最も重要なシステム権限です。ユーザーが特定の Principal (つまり、特定の認証情報) を使用してコールアウトを行うことを許可します。権限セットを作成し、この権限を有効にした後、アクセスを許可したい External Credential をその権限セットに割り当てる必要があります。
- この仕組みにより、「どのユーザーが、どの認証情報を使って、どのシステムにアクセスできるか」を非常に細かく制御できます。最小権限の原則に従い、必要なユーザーにのみアクセスを許可することが推奨されます。
API 制限 (API Limits)
Named Credential を使用しても、Salesforce のガバナ制限 (Governor Limits) が免除されるわけではありません。特に以下の制限に注意してください。
- Total number of callouts in a transaction (1トランザクションあたりのコールアウト回数): 同期 Apex では通常 100 回までです。
- Total number of callouts in a 24-hour period (24時間あたりのコールアウト回数): 組織のエディションによって異なります。
- Concurrent long-running callouts (同時長時間実行コールアウト): 長時間 (5秒以上) 実行されるコールアウトの同時実行数にも制限があります。
設計段階で、これらの制限を考慮し、API コールアウトを効率的に行うためのアーキテクチャ (一括処理など) を検討することが重要です。
エラー処理 (Error Handling)
外部システムは常に利用可能であるとは限りません。ネットワークの問題、サーバーダウン、認証情報の期限切れなど、様々な理由でコールアウトは失敗する可能性があります。そのため、堅牢なエラー処理は不可欠です。
- `try-catch` ブロック: すべてのコールアウト処理は、必ず `try-catch (System.CalloutException e)` ブロックで囲むべきです。これにより、接続自体に失敗した場合の例外を捕捉できます。
- HTTP ステータスコードの確認: 接続が成功しても、リクエストが正常に処理されたとは限りません。`HttpResponse.getStatusCode()` を確認し、`200` (OK) や `201` (Created) 以外のコード (例: `401` Unauthorized, `404` Not Found, `500` Internal Server Error) に応じた処理を実装する必要があります。
- 再試行ロジック (Retry Logic): 一時的なネットワークエラーの場合に備え、指数バックオフなどのアルゴリズムを用いた再試行ロジックを実装することも有効な場合があります。
名前空間 (Namespaces)
Named Credential を管理パッケージ (Managed Package) に含める場合、Apex コードから参照する際には名前空間プレフィックスが必要になります。
例: `req.setEndpoint('callout:my_namespace__My_API_Credential/v1/data');`
この点に注意しないと、パッケージのインストール先組織でコールアウトが失敗する原因となります。
まとめとベストプラクティス
Named Credential は、現代の Salesforce 統合開発において不可欠な機能です。認証情報をコードから分離することで、セキュリティ、メンテナンス性、そしてコードの可読性を劇的に向上させます。
Salesforce 統合エンジニアとして、Named Credential を最大限に活用するためのベストプラクティスを以下にまとめます。
- 常に Named Credential を使用する: 新規の API 連携を実装する際は、いかなる理由があっても認証情報をハードコーディングしたり、カスタム設定に保存したりせず、必ず Named Credential (および External Credential) を使用してください。
- 新しいフレームワークを活用する: 従来のレガシーな Named Credential ではなく、External Credential と Principal を組み合わせた新しいフレームワークを積極的に採用しましょう。これにより、設定の再利用性と柔軟性が向上します。
- 適切な認証タイプを選択する: システム間連携には `Named Principal` を、ユーザーごとのコンテキストが必要な連携には `Per User` 認証を選択し、要件に最適なアーキテクチャを設計してください。
- 権限を厳格に管理する: 権限セットを使用して、External Credential へのアクセスを必要最小限のユーザーにのみ許可します。これにより、組織のセキュリティ体制が強化されます。
- 堅牢なエラー処理を実装する: すべてのコールアウトには、例外処理とHTTPステータスコードのチェックを含め、失敗した場合の代替パスを考慮したロジックを組み込みます。
- 環境ごとの設定を計画する: Named Credential の URL は Sandbox と本番環境で異なることが多いため、デプロイプロセスの一環として、各環境での URL の設定・更新手順を明確に定義しておきましょう。
これらのベストプラクティスに従うことで、あなたは安全で、スケーラブルかつ保守性の高い、プロフェッショナルな統合ソリューションを構築することができるでしょう。
コメント
コメントを投稿