執筆者:Salesforce 連携エンジニア
背景と応用シナリオ
Salesforce 連携エンジニアとして、私は日々、Salesforce プラットフォームと外部システムとの間でデータをやり取りする仕組みを構築しています。会計システム、ERP、マーケティングオートメーションツール、カスタム API など、連携先は多岐にわたります。これらの連携を実装する上で最も重要な課題の一つが、「いかにしてセキュアかつメンテナンス性の高い方法で外部システムの認証情報を管理し、API コールアウトを実行するか」という点です。
過去には、API のエンドポイント URL や認証情報(API キー、ユーザー名、パスワードなど)を Apex コード内に直接ハードコーディングしたり、カスタム設定やカスタムメタデータに保存したりする方法が取られていました。しかし、これらのアプローチには以下のような深刻な問題が伴います。
- セキュリティリスク:コードや設定内に平文で認証情報を保存することは、情報漏洩の大きなリスクとなります。特に、コードがバージョン管理システムで共有される場合、意図せず機密情報が外部に流出する可能性があります。
- メンテナンス性の低下:連携先のシステムがサンドボックス環境から本番環境へ移行する際や、API のエンドポイント URL、認証情報が変更された際に、コードや設定の複数箇所を修正する必要が生じます。これにより、修正漏れやデプロイミスが発生しやすくなります。
- 認証処理の複雑化:OAuth 2.0 のような複雑な認証フローを Apex で自前で実装する場合、アクセストークンの取得、リフレッシュ、管理など、多くの定型的ながらも複雑なコードを記述する必要があり、開発工数が増大します。
これらの課題を解決するために Salesforce が提供しているのが、Named Credential (指定ログイン情報) です。Named Credential は、API 連携におけるエンドポイントの URL と認証情報を一つの定義にまとめ、安全かつ宣言的に管理するためのフレームワークです。これにより、開発者は認証情報の管理という煩雑な作業から解放され、ビジネスロジックの実装に集中できるようになります。
具体的な応用シナリオとしては、以下のようなものが挙げられます。
- Google や Microsoft 365 の API と連携し、カレンダー情報やファイルデータを Salesforce に同期する。
- 外部の気象情報 API を呼び出し、取引先責任者の住所に基づいて最新の天候情報を取得する。
- Stripe や PayPal などの決済ゲートウェイと連携し、Salesforce 上で決済処理を完結させる。
- 社内のオンプレミスシステムで公開されている REST API と接続し、在庫情報や顧客マスタをリアルタイムで同期する。
私たち連携エンジニアにとって、Named Credential は、堅牢でスケーラブルな連携ソリューションを構築するための必須のツールと言えるでしょう。
原理説明
Named Credential の核心的な機能は、「API コールアウトの宛先 (Endpoint) と認証 (Authentication) の分離」です。これにより、Apex コードは具体的な URL や認証情報を意識することなく、単に Named Credential の名前を指定するだけで外部システムへのコールアウトを実行できます。
この仕組みを支える主要なコンポーネントは、Named Credential (指定ログイン情報) と External Credential (外部ログイン情報) です。最近の Salesforce のアップデートにより、この二つの役割分担がより明確になりました。
1. External Credential (外部ログイン情報)
External Credential は、認証プロトコルの詳細と、それに必要な権限セットを管理する役割を担います。いわば「認証情報の金庫」です。
- Authentication Protocol (認証プロトコル): OAuth 2.0, JWT, Basic Auth, Custom など、連携先システムが要求する認証方式を定義します。
- Principals (プリンシパル): 認証情報を誰が、どのように使用するかを定義します。例えば、特定の API ユーザーの情報(Named Principal)や、コールアウトを実行する Salesforce ユーザー自身の情報(Per-User Principal)を設定し、それらを権限セットを通じてユーザーに割り当てることができます。
これにより、認証に関する設定を一元管理し、異なる Named Credential から再利用することが可能になります。
2. Named Credential (指定ログイン情報)
Named Credential は、連携先の具体的な Endpoint URL (エンドポイント URL) と、使用する External Credential を紐づける役割を持ちます。
- URL: 連携先のベース URL を指定します。(例: `https://api.example.com`)
- External Credential Link: 上記で作成した External Credential を選択し、この Named Credential がどの認証情報を使用するかを定義します。
- Callout Options (コールアウトオプション): 必要に応じて、すべてのリクエストに含めるカスタムヘッダー(例: `Content-Type: application/json`)などを設定できます。
この二段構成により、例えば同じ API プロバイダー(例: Google)に対して、異なるサービス(Google Calendar API, Google Drive API)へ接続する場合、一つの External Credential を作成し、それを参照する複数の Named Credential を作成する、といった柔軟な構成が可能になります。
Apex コードから Named Credential を使用する場合、以下のような特別な URL 形式を用います。
`callout:[Named Credential の API 参照名]/[パス]`
例えば、「My_External_API」という名前の Named Credential を作成し、`/users/123` というパスにアクセスしたい場合、Apex コード内で指定するエンドポイントは `callout:My_External_API/users/123` となります。Salesforce プラットフォームは、この `callout:` プレフィックスを認識すると、自動的に以下の処理を実行します。
- 「My_External_API」という Named Credential の定義を検索します。
- 定義された URL (`https://api.example.com`) とコード内のパス (`/users/123`) を結合し、完全なリクエスト URL (`https://api.example.com/users/123`) を生成します。
- 紐づけられた External Credential の定義に基づき、必要な認証処理(例: OAuth トークンの取得・付与)をバックグラウンドで実行し、`Authorization` ヘッダーなどをリクエストに自動的に追加します。
- 認証情報が付与されたリクエストを、最終的な URL に送信します。
この一連のプロセスが Salesforce によって自動化されるため、開発者は認証の詳細を一切コードに記述する必要がなくなります。これが Named Credential の強力な点です。
サンプルコード
ここでは、`My_Named_Credential` という名前で設定された Named Credential を使用して、外部の REST API からユーザー情報を取得する Apex コードの例を示します。このコードは、Salesforce の公式ドキュメントで推奨されている標準的な実装方法です。
// UserInfoService クラス: 外部 API との通信を担う public class UserInfoService { // ユーザー情報を取得する静的メソッド // @param userId 取得対象のユーザーID // @return API からのレスポンスボディ(JSON 文字列) @future(callout=true) // コールアウトは非同期実行が推奨されるため @future アノテーションを付与 public static void fetchUserInfo(String userId) { // 1. HttpRequest オブジェクトのインスタンスを作成 HttpRequest req = new HttpRequest(); // 2. HTTP メソッドを 'GET' に設定 req.setMethod('GET'); // 3. エンドポイントを Named Credential を使用して設定 // 'callout:' プレフィックスに続けて Named Credential の API 参照名を指定 // その後に API の具体的なパスを追加する // Salesforce は自動的に Named Credential に設定された URL とこのパスを結合する req.setEndpoint('callout:My_Named_Credential/users/' + userId); // 4. (任意) カスタムヘッダーの設定 // Named Credential 側で設定することも可能だが、リクエストごとに動的に変えたい場合はここで設定 req.setHeader('Accept', 'application/json'); // 5. Http オブジェクトのインスタンスを作成し、リクエストを送信 Http http = new Http(); HttpResponse res = null; try { // 6. API コールアウトを実行 // ここで Salesforce が認証処理を自動的に行い、リクエストを送信する res = http.send(req); // 7. レスポンスのステータスコードをチェック if (res.getStatusCode() == 200) { // 成功した場合: レスポンスボディをデバッグログに出力 System.debug('Success! Response Body: ' + res.getBody()); // ここで JSON のパースや、取得したデータを使ったビジネスロジックを実装する } else { // エラーの場合: ステータスコードとメッセージをログに出力 System.debug('Request failed. Status: ' + res.getStatus() + ', Status Code: ' + res.getStatusCode()); // エラーハンドリング処理を実装する (例: カスタムオブジェクトにエラーログを記録) } } catch(System.CalloutException e) { // 8. コールアウト例外のハンドリング // ネットワーク接続の問題やタイムアウトなどで発生 System.debug('Callout error: '+ e.getMessage()); // 例外発生時のフォールバック処理を実装 } } }
このコードを実行するには、匿名実行ウィンドウなどで以下のように呼び出します。
// '12345' は外部システム上のユーザーIDの例 UserInfoService.fetchUserInfo('12345');
ご覧の通り、コード内には URL のホスト名や API キー、トークンといった機密情報が一切含まれていません。すべて `callout:My_Named_Credential` という抽象的な名前に隠蔽されており、高いセキュリティとメンテナンス性を実現しています。
注意事項
Named Credential は非常に強力なツールですが、連携エンジニアとして、その利用にあたっては以下の点に注意する必要があります。
権限 (Permissions)
- 設定時の権限: Named Credential や External Credential を作成・編集するには、「アプリケーションのカスタマイズ」および「設定・定義の参照」権限が必要です。
- 実行時の権限: External Credential では、プリンシパルへのアクセスを権限セットを通じて制御します。Per-User 認証(ユーザー単位認証)の場合、コールアウトを実行するユーザーに適切な権限セットを割り当てなければ、認証に失敗します。この権限モデルを正しく設計することが、セキュアな連携の鍵となります。
API 制限 (API Limits)
- Named Credential 自体に直接的な制限はありませんが、それを利用して行われる Apex コールアウトは、Salesforce のガバナ制限に従います。
- 1 トランザクションあたりのコールアウト回数(同期 Apex では 100 回)、累積タイムアウト時間(120 秒)などの制限を常に意識する必要があります。大量のデータを扱う連携処理では、Queueable Apex や Batch Apex を使用して、処理を分割・非同期化することが不可欠です。
エラー処理 (Error Handling)
- サンプルコードにも示した通り、コールアウト処理は必ず `try-catch` ブロックで囲み、`System.CalloutException` を捕捉してください。これにより、接続タイムアウトや DNS 解決エラーなどのネットワークレベルの問題に対応できます。
- API が正常に応答を返しても、それが成功を意味するとは限りません。`res.getStatusCode()` を必ずチェックし、2xx 以外のステータスコード(例: 401 Unauthorized, 404 Not Found, 500 Internal Server Error)に対する処理を適切に実装することが、安定した連携システムの構築には不可欠です。
パッケージ化とデプロイ
- Named Credential はメタデータ API を通じてデプロイ可能ですが、URL などの環境固有の情報を含むため、注意が必要です。本番環境とサンドボックスで URL が異なる場合は、デプロイ後の手動設定や、デプロイスクリプトによる更新が必要になります。
- External Credential に含まれる認証情報(パスワードやクライアントシークレットなど)は、セキュリティ上の理由からメタデータに含まれず、デプロイされません。したがって、デプロイ先の組織でこれらの値を再設定する必要があります。
まとめとベストプラクティス
Named Credential は、Salesforce と外部システムを連携させる際のセキュリティ、メンテナンス性、開発効率を劇的に向上させるための基本かつ最も重要な機能です。連携エンジニアとして、以下のベストプラクティスを遵守することを強く推奨します。
- ハードコーディングの撲滅: いかなる理由があっても、Apex コードやカスタム設定にエンドポイント URL や認証情報をハードコーディングしてはいけません。常に Named Credential を使用してください。
- External Credential との分離: 最新のベストプラクティスとして、認証ロジックは External Credential に、エンドポイント定義は Named Credential に分離して管理しましょう。これにより、設定の再利用性と管理性が向上します。
- 適切な Identity Type の選択: 連携の要件に応じて、`Named Principal`(システム間連携など、単一の固定ユーザーで認証)と `Per User`(各 Salesforce ユーザーが自身の外部システムアカウントで認証)を正しく使い分けましょう。
- 堅牢なエラーハンドリングとロギング: API 連携は常に失敗する可能性があるという前提に立ち、包括的なエラーハンドリングと、問題発生時に原因を特定できるような詳細なロギング機構を実装してください。
- 環境差分の考慮: 開発、テスト、本番環境で異なるエンドポイント URL や認証情報をどのように管理するか、デプロイ戦略をあらかじめ計画しておくことが重要です。
Named Credential を正しく理解し、活用することで、私たちはより安全で、信頼性が高く、将来の変化にも柔軟に対応できる連携ソリューションを顧客に提供することができます。これは、Salesforce 連携エンジニアとしての価値を最大限に発揮するための、基本的なスキルセットの一つです。
コメント
コメントを投稿