Salesforce 統合エンジニア (Salesforce Integration Engineer) の視点から、Salesforce プラットフォームにおける API 連携の要とも言える「指定ログイン情報 (Named Credentials)」について、その基本から応用、ベストプラクティスまでを深く掘り下げて解説します。
背景と応用シナリオ
現代のビジネスアプリケーションは、単体で完結することは稀です。顧客データを管理する Salesforce、経理情報を扱う ERP システム、マーケティングオートメーションツール、外部の天気情報 API など、様々なシステムが連携することで、より大きな価値を生み出します。Salesforce 統合エンジニアとして、これらのシステム間を安全かつ効率的に接続することが私たちの重要な責務です。
このシステム間連携の中核をなすのが API コールアウト (Callout) です。しかし、従来の方法にはいくつかの課題がありました。例えば、API のエンドポイント URL や認証情報(API キー、パスワードなど)を Apex コード内に直接書き込む「ハードコーディング」は、セキュリティリスクが非常に高く、また環境ごとに URL を書き換える必要があるため、メンテナンス性も著しく低いものでした。あるいは、カスタム設定 (Custom Settings) やカスタムメタデータ (Custom Metadata) に認証情報を保存する方法もありますが、パスワードなどの機密情報を平文に近い形で保存することになり、依然としてセキュリティ上の懸念が残ります。
こうした課題を解決するために Salesforce が提供しているのが、指定ログイン情報 (Named Credentials) です。指定ログイン情報を使用することで、以下のメリットを享受できます。
- セキュリティの強化: パスワードやアクセストークンなどの機密情報を Salesforce の安全な保管庫で管理します。Apex コードからはこれらの情報に直接アクセスできず、Salesforce プラットフォームが裏側で認証処理を代行するため、認証情報が漏洩するリスクを大幅に低減できます。
- メンテナンス性の向上: 連携先システムのエンドポイント URL や認証情報が変更された場合でも、Apex コードを修正する必要がありません。管理画面から指定ログイン情報の設定を変更するだけで、すべての関連するコールアウトに即座に反映されます。これにより、開発・運用の手間が大幅に削減されます。
- コードの簡素化: Apex コード内で面倒な認証処理(OAuth 2.0 のトークン取得・更新など)を実装する必要がなくなります。シンプルな URL を指定するだけで、Salesforce が自動的に認証ヘッダーを付与してくれるため、開発者はビジネスロジックの実装に集中できます。
- リモートサイト設定の不要化: 指定ログイン情報を使用するコールアウトでは、従来必要だった「リモートサイトの設定 (Remote Site Settings)」が不要になります。これにより、設定管理がさらにシンプルになります。
具体的な応用シナリオとしては、以下のようなケースが考えられます。
- 外部の REST/SOAP API(Google Maps API, Slack API, 各種SaaSサービスなど)との連携
- オンプレミス環境で稼働する ERP やデータベースとの連携 (MuleSoft や Heroku Connect との組み合わせ)
- 別の Salesforce 組織との組織間連携 (Org-to-Org Integration)
原理説明
指定ログイン情報は、一見すると単なる URL と認証情報の設定に見えますが、その裏側では巧妙な仕組みが動いています。特に近年のアップデートで導入された外部ログイン情報 (External Credential) との組み合わせにより、その柔軟性と再利用性は飛躍的に向上しました。
旧来の指定ログイン情報 (Legacy Named Credentials)
初期の指定ログイン情報は、一つの設定の中にエンドポイント URL と認証情報の両方を含んでいました。これはシンプルで分かりやすい反面、例えば同じ認証情報を使いながらエンドポイントのパスだけが異なる複数の API を呼び出す場合に、それぞれ別の指定ログイン情報を作成する必要があるなど、再利用性に課題がありました。
新しいモデル:外部ログイン情報 + 指定ログイン情報
現在の推奨モデルでは、役割が明確に分離されています。
1. 外部ログイン情報 (External Credential)
これは「認証」に関する設定をカプセル化するコンポーネントです。具体的には、以下の要素を定義します。
- 認証プロトコル (Authentication Protocol): 連携先システムが要求する認証方式を選択します。主なものに `OAuth 2.0`、`パスワード認証 (Password Authentication)`、`JWT`、`AWS Signature V4` などがあります。
- プリンシパル (Principals): 認証に使用する具体的なユーザ情報やパラメータを定義します。例えば、パスワード認証であればユーザ名とパスワード、OAuth であればクライアント ID やクライアントシークレットなどを設定します。
外部ログイン情報を作成することで、「どのシステムに」「どの方式で」「どの資格情報を使って」認証するのか、という部分を一つの再利用可能なコンポーネントとして定義できます。
2. 指定ログイン情報 (Named Credential)
新しいモデルの指定ログイン情報は、「どこに」接続するのか、つまりエンドポイント URL のみを定義する役割に特化しています。そして、作成した外部ログイン情報をこの指定ログイン情報に関連付けます。
この分離により、例えば一つの外部ログイン情報(例:Google API への OAuth 認証)を、複数の指定ログイン情報(例:Google Maps API 用、Google Calendar API 用)で共有することが可能になり、設定の重複を排除し、管理を大幅に簡素化できます。
コールアウトの処理フロー
Apex から指定ログイン情報を使ってコールアウトを行う際の内部的なフローは以下のようになります。
- Apex コードが `callout:MyNamedCredential/api/resource` のような特殊な URL 形式でリクエストを送信します。
- Salesforce プラットフォームが `callout:` プレフィックスを検知し、このリクエストをインターセプトします。
- `MyNamedCredential` という名前の指定ログイン情報を検索し、設定されているエンドポイント URL (`https://api.example.com` など) を取得します。
- 次に関連付けられた外部ログイン情報を参照し、定義された認証プロトコルとプリンシパルに従って認証処理を実行します。(例:OAuth 2.0 の場合、必要であればアクセストークンをリフレッシュし、有効なトークンを取得します。)
- 取得したアクセストークンなどを用いて、適切な形式の認証ヘッダー(例:`Authorization: Bearer
`)を自動的に生成し、HTTP リクエストに付与します。 - 最終的に、エンドポイント URL (`https://api.example.com/api/resource`) と認証ヘッダーがすべて設定された完全な HTTP リクエストが、外部システムへ送信されます。
この一連の流れがすべて Salesforce プラットフォーム内部で処理されるため、開発者は認証の詳細を一切意識する必要がないのです。
サンプルコード
ここでは、`My_ERP_System` という名前の指定ログイン情報を使用して、外部の ERP システムから商品情報を取得する、というシナリオを想定した Apex コードの例を示します。このコードは Salesforce の公式ドキュメントで紹介されている標準的な記述方法に基づいています。
// 商品情報を取得する Apex クラス public class ProductIntegrationService { // 指定ログイン情報を使用して商品情報を取得するメソッド public static String getProductDetails(String productId) { // 1. HttpRequest オブジェクトをインスタンス化 HttpRequest req = new HttpRequest(); // 2. エンドポイントを設定 // 'callout:' プレフィックスに続けて指定ログイン情報の API 参照名、 // その後に連携先システムのリソースパスを指定します。 // Salesforce は 'callout:My_ERP_System' の部分を、指定ログイン情報に設定された // URL (例: https://api.my-erp.com) に自動的に置き換えます。 req.setEndpoint('callout:My_ERP_System/products/' + productId); // 3. HTTP メソッドを設定 (GET, POST, PUT, DELETE など) // ここでは商品情報を取得するため 'GET' を使用します。 req.setMethod('GET'); // 4. (オプション) ヘッダーを設定 // Content-Type などの認証以外のヘッダーはここで設定します。 // Authorization ヘッダーは Salesforce が自動で付与するため、絶対に設定しないでください。 req.setHeader('Content-Type', 'application/json'); // 5. Http オブジェクトをインスタンス化してリクエストを送信 Http http = new Http(); HttpResponse res = null; try { // 実際にコールアウトを実行 res = http.send(req); // 6. レスポンスを処理 if (res.getStatusCode() == 200) { // 成功した場合、レスポンスボディ (JSON 文字列など) を返す System.debug('成功時のレスポンス: ' + res.getBody()); return res.getBody(); } else { // エラーレスポンスの場合 System.debug('エラー: ' + res.getStatusCode() + ' ' + res.getStatus()); System.debug('エラーボディ: ' + res.getBody()); // ここでカスタム例外をスローするなどのエラーハンドリングを行う throw new CalloutException('ERP システムへの接続に失敗しました。ステータスコード: ' + res.getStatusCode()); } } catch(System.CalloutException e) { // ネットワークエラーやタイムアウトなど、コールアウト自体の例外をキャッチ System.debug('コールアウト例外が発生しました: ' + e.getMessage()); // エラーを再スローするか、適切なデフォルト値を返す throw e; } } }
このコードの最も重要な点は `req.setEndpoint('callout:My_ERP_System/products/' + productId);` の行です。URL を直接記述する代わりに、指定ログイン情報を参照することで、コードと環境設定が完全に分離され、安全でメンテナンス性の高い連携が実現できています。
注意事項
指定ログイン情報を利用する際には、以下の点に注意が必要です。
権限 (Permissions)
- 指定ログイン情報や外部ログイン情報を作成・編集するには、プロファイルまたは権限セットで「アプリケーションのカスタマイズ」権限、および「すべてのデータの参照」権限が必要です。より詳細な制御として、「指定ログイン情報を管理」権限を付与することもできます。
- 認証の ID 種別 (Identity Type) を「ユーザごと (Per User)」に設定した場合、各ユーザは自身の個人設定画面から外部システムへの認証を個別に行う必要があります。管理者はこの設定を強制することはできず、ユーザが認証を完了するまでそのユーザのコンテキストでのコールアウトは失敗します。
API 制限 (API Limits)
- 指定ログイン情報を使用したコールアウトも、Salesforce のガバナ制限 (Governor Limits) の対象となります。トランザクションあたりのコールアウト回数(同期 Apex では 100 回)や、合計タイムアウト時間(120 秒)などの制限に抵触しないよう設計する必要があります。
- OAuth 2.0 のトークンリフレッシュなど、Salesforce がバックグラウンドで行う認証処理も、場合によってはコールアウト回数を消費することがあります。複雑な連携処理を実装する際は、デバッグログで実際のコールアウト回数を確認することが推奨されます。
エラー処理 (Error Handling)
- 外部システムがダウンしている、認証情報が失効している、ネットワークに問題があるなど、コールアウトは様々な理由で失敗する可能性があります。サンプルコードに示したように、必ず `try-catch` ブロックで `System.CalloutException` を捕捉し、適切なエラーハンドリング(ユーザへの通知、再試行ロジック、ログ記録など)を実装してください。
- HTTP ステータスコードが 2xx 以外(4xx や 5xx)の場合も、例外はスローされません。`res.getStatusCode()` を確認し、業務要件に応じたエラー処理を実装することが不可欠です。
テスト (Testing)
- 指定ログイン情報を使用したコールアウトを含む Apex コードをテストする場合、実際に外部システムへ接続するわけにはいきません。`HttpCalloutMock` インターフェースを実装したテストクラスを使用して、擬似的なレスポンスを返すように設定する必要があります。モックを設定する際は、`setEndpoint` で指定した指定ログイン情報の URL (`callout:My_ERP_System/...`) をリクエストのエンドポイントとして指定します。
まとめとベストプラクティス
指定ログイン情報は、Salesforce と外部システムを連携させる際のデファクトスタンダードと言える機能です。統合エンジニアとしてこの機能を使いこなすことは、堅牢で、安全で、スケーラブルなソリューションを構築するための必須スキルです。
最後に、指定ログイン情報を活用するためのベストプラクティスをまとめます。
- 常に指定ログイン情報を使用する: コードやカスタム設定に認証情報をハードコーディングすることは避け、すべての API 連携で指定ログイン情報の利用を第一に検討してください。
- 新しいモデル(外部ログイン情報 + 指定ログイン情報)を活用する: 新規の連携を構築する際は、認証とエンドポイントを分離できる新しいモデルを積極的に採用しましょう。これにより、設定の再利用性が高まり、管理が効率化されます。
- 環境ごとに設定を管理する: Sandbox と本番環境では、接続先のエンドポイントや認証情報が異なるのが一般的です。変更セットや DevOps ツールで移行する際は、指定ログイン情報のエンドポイント URL などの値が環境ごとに適切に設定されるように注意深く管理してください。
- 命名規則を定める: `[連携先システム名]_[認証方式]_[環境]`(例: `Google_OAuth_PROD`, `ERP_Password_UAT`)のような、分かりやすい命名規則をチームで定めることで、設定の可読性と管理性が向上します。
- 最小権限の原則を適用する: 連携に必要な最小限の権限を持つ専用の連携ユーザを外部システム側に作成し、その認証情報を指定ログイン情報に設定することを推奨します。これにより、万が一認証情報が侵害された場合の影響を最小限に抑えることができます。
Salesforce プラットフォームが提供するこの強力な機能を最大限に活用し、ビジネスの成長を支えるシームレスなシステム連携を実現していきましょう。
コメント
コメントを投稿