背景と応用シナリオ
Salesforce 開発者 (Salesforce Developer) として、私たちは日常的に Salesforce プラットフォームを外部システムと連携させるためのインテグレーションを構築します。例えば、外部の在庫管理システムから商品情報を取得したり、決済代行サービスの API を呼び出して支払いを処理したり、地理情報サービスに住所を送信して緯度経度を取得したりするなど、その応用範囲は多岐にわたります。
これらの連携を実装する際、最も重要な課題の一つが「認証情報の管理」です。外部サービスへ接続するためには、API キー、ユーザー名とパスワード、OAuth トークンなどの認証情報が必要になります。従来、これらの機密情報を Apex コード内に直接ハードコーディングしたり、カスタム設定やカスタムメタデータに平文で保存したりする方法が取られることがありました。しかし、このアプローチには深刻な問題が伴います。
・セキュリティリスク:コードやメタデータ内に認証情報が存在すると、ソースコード管理システムや組織のメタデータへのアクセス権を持つ誰もがその情報を閲覧できてしまい、情報漏洩のリスクが非常に高まります。
・メンテナンス性の低下:API キーやエンドポイント URL が変更された場合、コードや設定を修正し、再度デプロイする必要があります。特に、複数のクラスで同じエンドポイントが参照されている場合、修正漏れが発生するリスクもあります。また、Sandbox と本番環境で異なるエンドポイントや認証情報を管理するのも煩雑になります。
これらの課題を解決するために Salesforce が提供しているのが、Named Credentials (指定ログイン情報) という強力な機能です。Named Credentials は、外部サービスのコールアウト先エンドポイント URL と、それに必要な認証情報を一元的に、かつ安全に管理するための仕組みです。開発者は実際の認証情報を意識することなく、Apex コードから安全に外部 API を呼び出すことが可能になります。
原理说明
Named Credentials の中核的なコンセプトは「抽象化」と「認証の委任」です。開発者はコード内で実際のエンドポイント URL や認証情報を直接記述する代わりに、設定画面で定義した Named Credential の名前を指定します。
Apex がコールアウトを実行しようとすると、Salesforce プラットフォームがそのリクエストを検知し、指定された Named Credential の設定に基づいて、以下の処理を自動的に実行します。
1. エンドポイントの解決:Apex コード内で指定された `callout:My_Named_Credential` のような特別な URL を、Named Credential に設定されている実際の URL (例: `https://api.example.com`) に置き換えます。
2. 認証情報の付与:Named Credential に設定された認証プロトコル(例: Basic 認証、OAuth 2.0 など)に従い、Salesforce が安全に保管している認証情報(パスワードやアクセストークンなど)を取得します。そして、HTTP リクエストのヘッダーに必要な認証情報(例: `Authorization` ヘッダー)を自動的に付与します。
3. コールアウトの実行:認証情報が付与された HTTP リクエストが、実際に外部サービスのエンドポイントへ送信されます。
この仕組みにより、開発者は認証プロセスの複雑な実装(特に OAuth 2.0 のトークンリフレッシュ処理など)から解放され、ビジネスロジックの実装に集中できます。また、認証情報は Salesforce によって暗号化されて安全に保管されるため、コードやメタデータには一切露出しません。
Named Credentials の主要な設定項目
・URL:コールアウト先のベースとなる URL を指定します。例: `https://api.example.com`。
・Identity Type (ID 種別):認証情報を誰の権限で管理するかを定義します。Named Principal (指定ユーザ) は、システム全体で共有される一つの認証情報を使用する方式です。一方、Per User (ユーザ別) は、コールアウトを実行する Salesforce ユーザごとに個別の認証情報(通常は OAuth を利用)を使用する方式です。
・Authentication Protocol (認証プロトコル):外部サービスの認証方式に合わせて選択します。「No Authentication」「Password Authentication (Basic 認証)」「OAuth 2.0」「JWT」など、主要なプロトコルをサポートしています。
開発者にとって最も大きな利点は、Apex コードが非常にシンプルかつクリーンになることです。環境ごとにエンドポイントを書き換える必要がなくなり、認証ロジックがコードから分離されることで、コードの可読性と保守性が劇的に向上します。
示例代码
以下に、Named Credential を使用して外部の REST API に GET リクエストを送信する Apex コードの例を示します。この例では、`My_Awesome_API` という名前の Named Credential が事前に設定されていることを前提とします。この Named Credential には、ターゲットのエンドポイント URL と必要な認証情報がすべて含まれています。
このコードは、Salesforce Developer ドキュメントの `HttpRequest` クラスの標準的な使用法に基づいています。
// Apex コントローラーまたはサービスクラス内での実装例 public class ExternalApiService { public static String getApiData() { // 1. HttpRequest オブジェクトのインスタンスを作成します。 HttpRequest req = new HttpRequest(); // 2. エンドポイントを設定します。 // 'callout:' プレフィックスに続けて Named Credential の API 参照名を指定します。 // Salesforce は 'My_Awesome_API' を解決し、設定された実際の URL と認証情報を自動的に付与します。 // '/items/123' は、Named Credential のベース URL に追加される相対パスです。 req.setEndpoint('callout:My_Awesome_API/items/123'); // 3. HTTP メソッドを 'GET' に設定します。 req.setMethod('GET'); // 4. Http オブジェクトのインスタンスを作成し、リクエストを送信します。 Http http = new Http(); HttpResponse res = null; try { // 5. send メソッドでリクエストを外部サービスに送信し、レスポンスを受け取ります。 // ここで Salesforce プラットフォームが認証処理をバックグラウンドで実行します。 res = http.send(req); // 6. レスポンスのステータスコードを確認します。 if (res.getStatusCode() == 200) { // 成功した場合、レスポンスボディを返す。 System.debug('成功レスポンス: ' + res.getBody()); return res.getBody(); } else { // エラーレスポンスを処理します。 System.debug('エラーレスポンス: ' + res.getStatusCode() + ' ' + res.getStatus()); System.debug('エラーボディ: ' + res.getBody()); // ここでカスタム例外をスローするなどのエラーハンドリングを実装します。 return 'Error: ' + res.getStatusCode(); } } catch(System.CalloutException e) { // 7. ネットワーク接続の問題やタイムアウトなど、コールアウト例外をキャッチします。 System.debug('コールアウトエラー: ' + e.getMessage()); // 適切なエラーハンドリングを行います。 return 'Callout failed: ' + e.getMessage(); } } }
このコードからわかるように、認証情報を扱うための記述(API キーをヘッダーに追加するなど)が一切ありません。`setEndpoint` メソッドに `callout:My_Awesome_API` と指定するだけで、残りの複雑な処理はすべて Salesforce が担当してくれます。これにより、コードは非常にシンプルになり、本来のビジネスロジックに集中できるのです。
注意事項
Named Credentials を利用する際には、いくつかの重要な点に注意する必要があります。
・権限管理:Apex コードを実行するユーザは、そのコードが参照する Named Credential へのアクセス権を持っている必要があります。これはプロファイルや権限セットで制御します。具体的には、External Credential Principal Access (外部ログイン情報プリンシパルアクセス) を通じて、どのユーザがどの Named Credential を使用できるかを定義します。権限がないユーザがコールアウトを実行しようとすると、エラーが発生します。
・ガバナ制限:Named Credentials を使用したコールアウトも、Salesforce の標準的なガバナ制限(1 トランザクションあたりのコールアウト回数や、合計コールアウト時間など)の対象となります。大量のデータを扱うバッチ処理などでコールアウトを行う場合は、これらの制限に抵触しないように設計する必要があります。
・エラーハンドリング:サンプルコードにも示した通り、コールアウトは常に成功するとは限りません。外部サービスの障害、ネットワークの問題、認証情報の誤りなど、様々な原因で失敗する可能性があります。そのため、`HttpRequest` を実行するコードは必ず `try-catch` ブロックで囲み、`System.CalloutException` を捕捉するようにしてください。また、レスポンスを受け取った後は、`res.getStatusCode()` を確認し、`200` 番台以外のステータスコードに対する処理を適切に実装することが不可欠です。
・URL のマージフィールド:Named Credentials の URL フィールドでは、`{!$Api.Partner_Server_URL_290}` のようなグローバル変数のマージフィールドを使用できます。これにより、組織のインスタンスに依存しない動的な URL 構築が可能ですが、意図しない挙動を避けるため、その仕様を正しく理解して使用することが重要です。
・コールアウトの許可:Apex から外部サイトへコールアウトを行うには、そのエンドポイント URL を事前に Remote Site Settings (リモートサイトの設定) に登録する必要があります。しかし、Named Credentials を使用する場合、その Named Credential の URL は自動的に信頼されるため、リモートサイトの設定への登録は不要です。これは Named Credentials を利用する大きなメリットの一つです。
まとめとベストプラクティス
Named Credentials は、Salesforce 開発者が外部システム連携を実装する上で、もはや不可欠と言える機能です。認証情報をコードから分離することで、セキュリティを劇的に向上させ、メンテナンスコストを大幅に削減します。
以下に、開発者としてのベストプラクティスをまとめます。
・ハードコーディングの撲滅:外部 API へのコールアウトを実装する際は、常に Named Credentials の使用を第一の選択肢とし、認証情報やエンドポイント URL のハードコーディングは絶対に避けてください。
・環境ごとの設定:開発、ステージング、本番といった環境ごとに、それぞれ対応する Named Credential を作成してください(例: `MyAPI_DEV`, `MyAPI_UAT`, `MyAPI_PROD`)。コード内では、これらの Named Credential 名を直接記述するのではなく、カスタムメタデータなどから動的に取得する設計にすると、デプロイ後の手動設定変更が不要になり、さらに柔軟性が増します。
・適切な ID 種別の選択:システムとして単一の認証情報で接続する場合は `Named Principal` を、各ユーザが自身の外部アカウントで認証する必要がある場合は `Per User` を選択します。ユースケースに応じて適切な方式を選択してください。
・堅牢なエラーハンドリングの実装:すべてのコールアウト処理に、例外処理とステータスコードの検証を含めることを徹底してください。これにより、システムの安定性が向上し、問題発生時のトラブルシューティングが容易になります。
・最小権限の原則:Named Credential へのアクセス権は、それを必要とするユーザやプロファイルにのみ付与するように権限セットを設計し、セキュリティを確保してください。
Named Credentials を正しく理解し活用することで、私たちはより安全で、保守しやすく、拡張性の高いインテグレーションを迅速に構築することができます。これは Salesforce 開発者にとって必須のスキルセットの一つです。
コメント
コメントを投稿