Salesforce CLI で JWT を使って安全に接続するための設定方法

Salesforce 組織への接続をするための方法には様々あります。
Salesforce CLIを使ってバッチ処理を行うような場合には、安全な接続方法と外部に情報が漏れない仕組み作りが必要です。そのためのSalesforceの設定と、証明書の準備をまとめました。

# 証明書の作成

JWTで接続を行う場合、SSL証明書が必要になります。まず、そのための証明書を作成しましょう。

`openssl`を使って証明書を作成していきます。
普通に自己署名証明書を作成していきましょう。
証明書署名要求には証明書の識別名を入れる必要がありますが、オレオレ証明書なので好きに作ってしまって構いません。
豊島区在住のしょっさんの作成サンプルは次の通りです。

`openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr`

```bash:識別名作成のサンプル
> openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr
..+......+........+.+++++++++++++++++++++++++++++++++++++++*...+..+............+...+.+.....+.+......+++++++++++++++++++++++++++++++++++++++*........+..+......+...+.+....................+.+.................+...+.......+.....+...+....+.....+..........+..............+....+...+..+...+...+.......+.....+...+.......+...+..+.......+.....+..........+......+..+...+.+........+.+......+.....+....+.....+......+...+......+.+.........+..+...+....+..+...+..........+.....+......+.+.........+.....+......+..........+......+..+..........+...+........+...............+......+.+...+......+.........+......+........+...+...+....+..+....+...........+...+..........+...+..+......+.+...+..+......+...++++++
...+...............+.+..+...+++++++++++++++++++++++++++++++++++++++*.+.+..+..........+..+.........+....+...+.....+..................+............+.........+.+..+...+...+....+..+.+...+..+............+.+..+.......+......+..............+...+...+.+......+...+......+....................+...+...+...+.+.........+............+++++++++++++++++++++++++++++++++++++++*..........+...+............+...........................+..+......+..........+...+......+...+..+....+.....+....+........+...+......+...+.+.....+...............+.+...+.....+...+....+...........+...+......+.+.........+...+..+...+.+.........+.....+.+.....+....+.....+.+......+..................+.....+...+.........+................+..+.+..+.........+......+....+..................+..+...+.......+.....+.............+...+..+...+...+.......+............+......+......+........+.......+...........+...+....+..+.........+.........+...+...+.+...+...+..+.......+...+......+.........+..+.+...+..+....+...+......+.....+.........+...+.......+.....+......................+...........+....+.....+.+...+.........+......+......+...+.....+.+.................+...+..........+............+..+.+......+...+........+...............+.......+..+.+..+.+......+........+......+.+........+...+..........+.........+.....+...+......+.......+.........+...+...............+.....+...+....+...+..++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Toshima
Organization Name (eg, company) [Internet Widgits Pty Ltd]:oshiire
Organizational Unit Name (eg, section) []:tako
Common Name (e.g. server FQDN or YOUR name) []:oshiire.to
Email Address []:sho@oshiire.to

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

```
challenge password は入れてません。

では、この秘密鍵で自己署名した証明書を作成しましょう。今回はテスト用なので期間を10年(3650days)としていますが、実際の運用では1年未満にしましょう。

`openssl x509 -req -sha256 -days 3650 -in server.csr -signkey server.key -out server.crt`

```bash: openssl x509 -req の実行結果
> openssl x509 -req -sha256 -days 3650 -in server.csr -signkey server.key -out server.crt
Certificate request self-signature ok
subject=C=JP, ST=Tokyo, L=Toshima, O=oshiire, OU=tako, CN=oshiire.to, emailAddress=tak@oshiire.to
```

これでSalesforce組織とのJWTを利用した証明書の準備は完了です。

# Salesforce 組織の接続アプリケーションの作成

何はともあれ、Salesforce組織と接続するためには「接続アプリケーション」が必要です。ここで設定した内容にしたがったユーザと接続方式のみが利用可能です。

Salesforce組織の「設定」画面から "**アプリケーションマネージャー**" を選択しましょう。恐れることは何もありません。この設定をまちがえてもSalesforce組織への影響はありません。多分。
![CleanShot 2023-12-23 at 15.31.21@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/41407751-3b7f-9886-c966-2ff3468f599e.png)

右上にある「新規接続アプリケーション」ボタンを押すと、「接続アプリケーション」の作成画面になります。ここで、必要な情報を入れていきましょう。

今回の設定条件は、次の通りです。

- Salesforce CLI からのみ接続する
- Salesforce CLI を使って、自動的なデプロイ&リリースを実現する
- JWTを利用した安全かつバッチ処理にあつらえた接続方法を利用する

利用用途によって設定するAPIなどは変わってきますが、基本的な設定部分に変わりはありません。
最低限設定が必要な部分は次の通りです。

- 接続アプリケーション名 ... 判別できる好きな名前を付けてください。今回は CircleCIで自動テストするための用とで考えているので`circleci`という安直な前にしています
- API 参照名 ... メタデータAPIを利用するときの参照名です、ユニークで判別できればなんでも良いです
- 取引先責任者 メール ... とりあえず利用者のメールアドレスを入れておきましょう
- OAuth 設定の有効化 ... ここにチェックを入れねばなりません
- デバイスフローで有効化 ... CLIなどの限定的な利用の場合は付けておくと効果があるかもしれません。付けなくても平気です
- コールバックURL ... 今回のような用途の時は、無心で`http://localhost:1717/OauthRedirect`を入れておきましょう
- デジタル署名を使用 ... 先ほど作成した証明書が必要です。`server.crt`ファイルがあるでしょうから、それをアップロードします。
- 選択した OAuth 範囲 ... 最小限必要なのが、次の3つです。(web)を忘れがち。
    1. API を使用してユーザーデータを管理 (API)
    1. Web ブラウザーを使用してユーザーデータを管理 (web)
    1. いつでも要求を実行 (refresh_token, offline_access)

その他はdefaultのままで良いですが、設定してみるとこのような画面になります。ご参考に。
![CleanShot 2023-12-24 at 10.04.51@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/25f87753-3673-13ac-e1e2-fde2418e3087.png)

作成して「保存」したら、この接続アプリケーションで利用するコンシューマーキーを入手しましょう。
`コンシューマーの詳細を管理`ボタンをクリックします。
![CleanShot 2023-12-23 at 15.42.38@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/378fcc13-93fc-a9d5-5318-0e5a920603d3.png)

システム管理者宛に確認コードが送られるので、その確認コードを入れて「検証」しましょう。そうです、システム管理者の人じゃないとこの設定はできません。当たり前ですけれども。
![CleanShot 2023-12-24 at 10.30.19@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/06eb4978-6637-b5a7-844c-93d4e4bc0278.png)

「顧客の詳細」画面になりますから、ここで`コンシューマー鍵`の情報をコピーしておきます。あとで使いますから忘れずに。
![CleanShot 2023-12-23 at 15.43.26@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/43a50756-3b0e-764c-56a7-4fbb1ceb1934.png)

左上の「`接続アプリケーションを管理する`に戻る」をクリックして管理画面に戻ります。
戻ったら`Manage`ボタンをクリックしましょう。ここでいくつかの推奨設定があります。

- 許可されているユーザー ... `管理者が承認したユーザーは事前承認済み` にする
- 「更新トークンポリシー」 ... `次の時間が経過したら更新トークンを期限切れにする → 90日以下がオススメ

この二つを設定したら保存します。
![CleanShot 2023-12-23 at 15.53.36@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/da14968c-eb0b-bdec-42c1-c8b25ed3bfca.png)

今回利用するユーザーのプロファイルを追加しておきます。管理画面の下の方に「プロファイル」という項目がありますから、そこで`プロファイルを管理する`ボタンをクリックして、Salesforce CLIを利用するユーザーのプロファイルを設定しておきます。システム管理者なら「システム管理者」を追加しておきましょう。
![CleanShot 2023-12-23 at 15.53.57@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37263/3542e709-b010-2fe6-8524-4934d4f69a02.png)

参考 : [組織の接続アプリケーションの作成 | Salesforce DX 開発者ガイド | Salesforce Developers](https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth_connected_app.htm)

# 接続テスト

では、この証明書を使ってJWTで接続可能かどうか、接続テストをしてみましょう。
先ほど準備した「コンシューマー鍵」と`server.key`を使ってアクセスしてみます。

```bash:JWTを利用したSalesforceへの接続-実行結果
> sf force auth jwt grant -i <コンシューマー鍵> -f ./server.key --username xxxxxxx@xxxxxxx.com -d
Successfully authorized xxxxxx@xxxxxxx.com with org ID 00XxX000001XXXXXX2
```

このように `Successfully`と出てくればOKです。やったぜ。