IBM API Connect 関連メモ - (6)API Connect-z/OS Connect間TLS接続

# はじめに
IBM Cloud上のAPI Connectを試してみた時の作業ログです。
今回はバックエンドのサービスとしてz/OS Connect,CICSにアクセスする構成で、API Connect - z/OS Connect間をTLS(HTTPS)で接続するための構成を試してみます。


## 関連記事

[IBM API Connect 関連メモ - (1)既存REST APIの取り込み](https://qiita.com/tomotagwork/private/d02f8e6092740b0e782f)
[IBM API Connect 関連メモ - (2)API Connectツールキットを使用したNode.jsアプリ作成(Loopback)](https://qiita.com/tomotagwork/private/7872ec8f99de57d7819a)
[IBM API Connect 関連メモ - (3)カタログ、開発者ポータルの構成](https://qiita.com/tomotagwork/private/da577551d7f4c50c4fd2)
[IBM API Connect 関連メモ - (4)各種APIの管理](https://qiita.com/tomotagwork/private/99e9b35227a0f80b2a91)
[IBM API Connect 関連メモ - (5)Secure Gateway経由でのz/OS Connectとの連携](https://qiita.com/tomotagwork/private/59e88b782bb72f1d0c1a)
[IBM API Connect 関連メモ - (6)API Connect-z/OS Connect間TLS接続](https://qiita.com/tomotagwork/private/c70b8566129e51c92423)
[IBM API Connect 関連メモ - (7)z/OS Connect 基本認証 + ID伝播](https://qiita.com/tomotagwork/private/38d41cbc01f92352f649)
[IBM API Connect 関連メモ - (8)z/OS Connect 連携におけるインターフェースの浄化](https://qiita.com/tomotagwork/private/0ec8d2224ad141756510)
[IBM API Connect 関連メモ - (9)z/OS Connect 連携まとめ](https://qiita.com/tomotagwork/private/a9fae53f02773a0c67b1)

# 参考情報

z/OS Connect側: [How to configure TLS with RACF key rings](https://www.ibm.com/support/knowledgecenter/en/SS4SVW_3.0.0/securing/config_tls_racf.html)
API Connect側: [TLSプロファイル](https://www.ibm.com/support/knowledgecenter/ja/SSMNED_5.0.0/com.ibm.apic.cmc.doc/ssl.html)

ちなみに、証明書の有効期間短縮の動きが出てきているのでニュース記事引用しておきます。
https://www.itmedia.co.jp/enterprise/articles/2006/30/news064.html
>Googleは2020年9月1日以降に発行されるTLSサーバ証明書について、有効期間を398日以下に短縮する方針を示した。既に同様の変更を表明しているAppleやMozillaに追随する措置だ。これで証明書の有効期間を13カ月とする措置が主要Webブラウザで出そろうことになり、Webサイト運営者は証明書更新の際に対応が必要になる。
>...
>　Google傘下のChromiumプロジェクトページに掲載された情報によると、2020年9月1日以降に発行されたTLSサーバ証明書については、有効期間が398日を超える場合は不正な証明書として扱われることになる。こうした証明書を使っているWebサイトはエラー表示が出て、アクセスできなくなる可能性がある。


# 全体像

z/OS Connect が提供するセキュリティー関連機能は各種ありますが、ここではz/OS Connectをプロバイダーとした時の、API Connect-z/OS Connect間通信にHTTPS(TLS)を使用する構成をやってみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/bd426e2d-3e01-b99e-2a26-771c10caa69a.png)

今回API Connectとz/OS Connect間はSecure Gatewayを使用して暗号化はされているはずですが、SecureGatewayを使っていない場合や、サーバー認証、クライアント認証が必要なケースも想定して、当構成をやってみます。

HTTPS(TLS)の認証のパターンとしては、(1)サーバー認証のみ、(2)サーバー認証&クライアント認証、2つのケースの構成例を示します。
また、TLSで使用する証明書にてては、RACFを認証局(CA)としてRACFから発行されたものを使用することにします。CA証明書は自己署名証明書を使います。


# (1) TLS/サーバー認証のみ

サーバー認証のみの構成の場合に必要な証明書を整理するとこんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/9769cf1b-b253-8fef-da54-3dc316390c99.png)


【サーバー側(z/OS Connect側)】
CA証明書を使って署名されたサーバー証明書をキーストアに保持している必要があります。

【クライアント側(API Connect側】
サーバーから送られてきたサーバー証明書が信頼されたものかを検証するために、CA証明書をトラストストアに保持している必要があります。

## サーバー側(z/OS Connect側)設定
今回z/OS Connect側の証明書関連で作成するオブジェクトのイメージを、ネーミングも含めてもう少し具体化すると以下のようなイメージとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/8a1357d1-72e8-d1fc-d799-bcd0c109b34f.png)

証明書は、z/OS Connectインスタンス実行ユーザー(LIBSRV)に関連付いたKeyRing(Keyring.ZOSCONN)に保持するようにします。
また、CA証明書はクライアント側に転送する必要があるので、SAMにExportします。
以下、具体的な手順を示します。

### キーリング作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/23653853-16ac-8774-07a7-6b23bfa18256.png)

```sh:01_createKeyRing.sh
#!/bin/sh
tsocmd "RACDCERT ID(LIBSRV) ADDRING(Keyring.ZOSCONN)"
tsocmd "RACDCERT ID(LIBSRV) LISTRING(*)"
```

```xxx:実行例
[CICS004@EPLEX1:/u/cics004/RACF/APIC] ./01_createKeyRing.sh
RACDCERT ID(LIBSRV) ADDRING(Keyring.ZOSCONN)
RACDCERT ID(LIBSRV) LISTRING(*)

Digital ring information for user LIBSRV:
...

  Ring:
       >Keyring.ZOSCONN<
  *** No certificates connected ***
```

### CA証明書(自己署名証明書)作成 & キーリングに紐づけ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/c988f8a5-dcfd-4c75-a906-27a3afdaa878.png)


```sh:02_createCAcert.sh
#!/bin/sh

tsocmd "RACDCERT GENCERT CERTAUTH SUBJECTSDN(CN('CA for zosConnect') O('IBM') OU('zosConnect') C('US')) SIZE(2048) WITHLABEL('zosConnectCA') NOTAFTER(DATE(2120-12-31))"
tsocmd "RACDCERT ID(LIBSRV) CONNECT(RING(Keyring.ZOSCONN) LABEL('zosConnectCA') CERTAUTH) "

tsocmd "RACDCERT ID(LIBSRV) LISTRING(Keyring.ZOSCONN)"
```

```xxx:実行例
[CICS004@EPLEX1:/u/cics004/RACF/APIC] ./02_createCAcert.sh
RACDCERT GENCERT CERTAUTH SUBJECTSDN(CN('CA for zosConnect') O('IBM') OU('zosConnect') C('US')) SIZE(2048) WITHLABEL('zosConnectCA') NOTAFTER(DATE(2120-12-31))
IRRD175I The new profile for DIGTCERT will not be in effect until a SETROPTS REFRESH has been issued.
RACDCERT ID(LIBSRV) CONNECT(RING(Keyring.ZOSCONN) LABEL('zosConnectCA') CERTAUTH)
RACDCERT ID(LIBSRV) LISTRING(Keyring.ZOSCONN)

Digital ring information for user LIBSRV:

  Ring:
       >Keyring.ZOSCONN<
  Certificate Label Name             Cert Owner     USAGE      DEFAULT
  --------------------------------   ------------   --------   -------
  zosConnectCA                       CERTAUTH       CERTAUTH     NO
```

### CA証明書で署名されたサーバー証明書を作成 & キーリングに紐づけ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/cfb7a45e-483f-9417-aa4b-1dc0f3058065.png)

サーバー証明書作成のオプションで、ALTNAMEで、z/OS Connectが稼働するIPアドレスやDNS名を指定しています。
※IPアドレス部分は`xx.xx.xx.xx`というようにマスキングしています。
<font color="red">
**サーバー証明書のDOMAIN指定について**
TLSのクライアント(ChromeやAPI Connect)側では、アクセスしたURLのドメイン名と、そこから送られてくるサーバー証明書に含まれるドメイン名をチェックしているようです。従ってそこがマッチしていないとTLSの通信がうまくできません。
このドメイン名は、RACFで証明書を作成する際はRACDCERT GENCERTの ALTNAME(DOMAIN(xxx)...) で指定します。
ここで注意が必要なのは、ローカルでブラウザからテストする場合と、API ConnectがSecure Gateway経由でアクセスする場合で、URLのドメイン名が異なることになります。
TLSの証明書では、マルチドメインという指定の仕方があるようで、複数のドメイン名を証明書の中に持たせることができるようです。ただし、RACFのRACDCERT GENCERTコマンドで直接複数のDOMAIN名を指定することはできないようです(ここでは試していませんが、request-data-setを作って生成する、別のユーティリティを使うといった代替策はあるようです)。ここではワイルドカードの指定をしています(ワイルドカードは万能ではなくドット(.)区切りの階層にまたがることはできないので注意が必要です)。
</font>
参考: 
[1枚で複数サイトを常時SSL化！ワイルドカード証明書やマルチドメイン証明書とは？](https://ssl.sakura.ad.jp/column/wc-md/)
[Multi-Domain Certificate](https://marc.info/?l=racf-l&m=150300322512086&w=2)

```sh:03_createServerCert2.sh
#!/bin/sh

tsocmd "RACDCERT ID(LIBSRV) GENCERT SUBJECTSDN(CN('myServer2.host.com') O('IBM') OU('zosConnect') C('US')) SIZE(2048) SIGNWITH(CERTAUTH LABEL('zosConnectCA')) WITHLABEL('zosConnectServerCert2') NOTAFTER(DATE(2120-12-31)) ALTNAME(IP(xx.xx.xx.xx) DOMAIN('*.securegateway.appdomain.cloud'))"
tsocmd "RACDCERT ID(LIBSRV) CONNECT(RING(Keyring.ZOSCONN) LABEL('zosConnectServerCert2'))"

tsocmd "RACDCERT ID(LIBSRV) LISTRING(Keyring.ZOSCONN)"
```

```xxx:実行例
[CICS004@EPLEX1:/u/cics004/RACF/APIC] ./03_createServerCert2.sh
RACDCERT ID(LIBSRV) GENCERT SUBJECTSDN(CN('myServer2.host.com') O('IBM') OU('zosConnect') C('US')) SIZE(2048) SIGNWITH(CERTAUTH LABEL('zosConnectCA')) WITHLABEL('zosConnectServerCert2') NOTAFTER(DATE(2120-12-31)) ALTNAME(IP(xx.xx.xx.xx) DOMAIN('*.securegateway.appdomain.cloud'))
IRRD175I The new profile for DIGTCERT will not be in effect until a SETROPTS REFRESH has been issued.
RACDCERT ID(LIBSRV) CONNECT(RING(Keyring.ZOSCONN) LABEL('zosConnectServerCert2'))
RACDCERT ID(LIBSRV) LISTRING(Keyring.ZOSCONN)

Digital ring information for user LIBSRV:

  Ring:
       >Keyring.ZOSCONN<
  Certificate Label Name             Cert Owner     USAGE      DEFAULT
  --------------------------------   ------------   --------   -------
  zosConnectCA                       CERTAUTH       CERTAUTH     NO

  zosConnectServerCert2              ID(LIBSRV)     PERSONAL     NO
```

生成された証明書の中身確認

```sh:04_listCert.sh
#!/bin/sh

tsocmd "RACDCERT CERTAUTH LIST(LABEL('zosConnectCA'))"
tsocmd "RACDCERT ID(LIBSRV) LIST(LABEL('zosConnectServerCert2'))"
```

```xxx:実行例
[CICS004@EPLEX1:/u/cics004/RACF/APIC] ./04_listCert.sh
RACDCERT CERTAUTH LIST(LABEL('zosConnectCA'))

Digital certificate information for CERTAUTH:

  Label: zosConnectCA
  Certificate ID: 2QiJmZmDhZmjgamWosOWlZWFg6PDwUBA
  Status: TRUST
  Start Date: 2020/06/30 00:00:00
  End Date:   2120/12/31 23:59:59
  Serial Number:
       >00<
  Issuer's Name:
       >CN=CA for zosConnect.OU=zosConnect.O=IBM.C=US<
  Subject's Name:
       >CN=CA for zosConnect.OU=zosConnect.O=IBM.C=US<
  Signing Algorithm: sha256RSA
  Key Usage: CERTSIGN
  Key Type: RSA
  Key Size: 2048
  Private Key: YES
  Ring Associations:
    Ring Owner: LIBSRV
    Ring:
       >Keyring.ZOSCONN<

RACDCERT ID(LIBSRV) LIST(LABEL('zosConnectServerCert2'))

Digital certificate information for user LIBSRV:

  Label: zosConnectServerCert2
  Certificate ID: 2QbTycLi2eWplqLDlpWVhYOj4oWZpYWZw4WZo/JA
  Status: TRUST
  Start Date: 2020/07/09 00:00:00
  End Date:   2120/12/31 23:59:59
  Serial Number:
       >07<
  Issuer's Name:
       >CN=CA for zosConnect.OU=zosConnect.O=IBM.C=US<
  Subject's Name:
       >CN=myServer2.host.com.OU=zosConnect.O=IBM.C=US<
  Subject's AltNames:
    IP: xx.xx.xx.xx
    Domain: *.securegateway.appdomain.cloud
  Signing Algorithm: sha256RSA
  Key Type: RSA
  Key Size: 2048
  Private Key: YES
  Ring Associations:
    Ring Owner: LIBSRV
    Ring:
       >Keyring.ZOSCONN<
```

ここでは、DOMAIN名として`*.securegateway.appdomain.cloud`というようにSecure Gatewayのドメイン名に合わせてワイルドカード指定しました。
Secure Gateway経由のアクセスの場合はそのままでよいですし、ローカルのブラウザから確認する時はターゲットのIPアドレスに対して 'eplex1.securegateway.appdomain.cloud'というようなホスト名をhostsファイルに割り当ててそれでアクセスすることを想定しています。

### CA証明書のExport

クライアント側に転送するために、SAMとしてExportしておきます(PKCS#12フォーマット)。
※API Connectがサポートしている形式がPKCS#12なので、それに合わせたフォーマットでExportします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/1d896edf-a642-efff-deab-1ac31aa82b2b.png)

```sh:05_exportCAcert.sh
#!/bin/sh

tsocmd "RACDCERT CERTAUTH EXPORT(LABEL('zosConnectCA')) DSN('CICSSHR.CICS004.CERTS.ZCCA.P12') FORMAT(PKCS12DER) PASSWORD('zcon00')"
```

```xxx:実行例
[CICS004@EPLEX1:/u/cics004/RACF/APIC] ./05_exportCAcert.sh
RACDCERT CERTAUTH EXPORT(LABEL('zosConnectCA')) DSN('CICSSHR.CICS004.CERTS.ZCCA.P12') FORMAT(PKCS12DER) PASSWORD('zcon00')
```

### z/OS Connect(server.xml)の設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/c7321bfe-865b-2c28-a48d-ba25939bada5.png)


対象スコープのエレメントで、`requireSecure="true"`を指定します(ここでは全体に有効にするためにzosconnect_zosConnectManagerで指定)。
keyStoreにて type="JCERACFKS"を指定することで、RACF上のKeyRingを指定することができます。この時passwordは使用されないので任意の文字列を指定しておけばよいです。

```xml:server.xml
...
    <httpEndpoint id="defaultHttpEndpoint"
                  host="*"
                  httpPort="30682"
                  httpsPort="30642" />

    <zosconnect_zosConnectManager 
        setUTF8ResponseEncoding="true" 
        requireSecure="true" requireAuth="false"/>

    <ssl id="defaultSSLConfig" 
         keyStoreRef="defaultKeyStore" 
         clientAuthentication="false"/>
    <keyStore id="defaultKeyStore"
      fileBased="false"
      location="safkeyring:///Keyring.ZOSCONN"
      password="password"
      readOnly="true"
      type="JCERACFKS" />
...
```

<font color="red">
※server.xmlを変更したらz/OS Connectを再起動してください。
</font>

### ブラウザでの簡易確認1(CA証明書なし)
API Connectから接続確認をする前に、ブラウザで簡易的にアクセスして動作確認をしてみます。
hostsにて、eplex1.securegateway.appdomain.cloudを指定して、ターゲットのバックエンドサーバーのIPアドレスにこの名前でアクセスできるようにしておきます。

まず、CA証明書が登録されていない状態で、ブラウザからhttpsでアクセスしてみます。
(画面キャプチャのeplexaはeplex1.securegateway.appdomain.cloudに読み替えてください)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/476f17a4-ae74-0297-2282-0792cb715414.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/ac0e4d9c-6653-3bc1-c71b-6b3e77a3d553.png)

送られてきたサーバー証明書の署名が信頼できるものかどうか判断できないので、上のような警告が出ています。想定通りの挙動です。

### ブラウザでの簡易確認2(CA証明書あり)
PCにCA証明書(zosConnectCA.p12)をダウンロードして、それを信頼された証明書として登録します。
MVS Dataset上にExportされたCA証明書(CICSSHR.CICS04.CERTS.ZCCA.P12)をバイナリでFTP転送し、PC上にzosConnectorCA.p12というファイル名で保存します。

Chrome - 設定 - セキュリティから証明書の管理を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/e79af08c-ac88-1efc-42bf-140899d68bea.png)

信頼されたルート証明機関タブでインポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/21ff3aa4-0db9-ba9e-2fd8-e077898c5f44.png)

次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/f31d2bab-ea9d-ced7-e585-553ff8603817.png)

ダウンロードしたCA証明書のファイル(zosConnectCA.p12)を指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/2a5f1887-ebfb-c930-7ef5-2da019a49103.png)

CA証明書をExportする時に指定したパスワードを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/bbe5f206-63c4-36f4-d7f7-d53d4abbb8f1.png)

次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/0c9ee133-ffd3-81c8-fd85-026bade2f192.png)

完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/635bd402-dc7e-558f-a911-677c8cc471a5.png)

はい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/ce13291d-25f8-8f62-25ed-28f50bf2cd76.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/b8fd92fa-8d28-2f59-6c7f-67a7c383ffbc.png)


<font color="red">
※CA証明書を登録したらブラウザを再起動してください(キャッシュクリアだけではなく)。
</font>


この後ブラウザからhttpsでアクセスすると、セキュリティの警告や保護されていない通信のアラートが消えました！
(画面キャプチャのeplex1はeplex1.securegateway.appdomain.cloudに読み替えてください)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/7e2a6908-dcb5-9f3b-63fb-ecac22642708.png)

※参考
アクセスしているホスト名と、サーバー証明書に含まれているドメイン名の指定が合っていないとChromeの場合以下のようなエラーになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d59c9aa2-1ed8-38d7-12ff-dab77a540994.png)

## Secure Gateway 設定

### ACL設定追加

HTTPS用のアドレス+ポート追加

```txt:ACLFile.txt
acl allow eplex1:30681
acl allow eplex1:30682
acl allow eplex1:30642
```

### Secure Gateway

Secure Gatewayの設定も、API Connect - z/OS Connect間接続構成に合わせて設定する必要があるようです。

宛先とプロトコル、TLS option辺りを以下のように変更。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/3e53cdec-ab94-81d1-b22a-6f1afbd52c78.png)


### ブラウザからの簡易確認(Secure Gateway経由)

Chromeのプラグイン"Talend API Tester"から確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d0494268-1f11-2e7e-5251-d7d52ca8652a.png)

これで、Secure Gateway経由でのアクセスも確認できました。

## クライアント側(API Connect側)設定

### TLSプロファイル作成
API Connect側には、CA証明書をトラストストアに保持させる必要があります。
TLSの証明書周りの管理には、まずTLSプロファイルというものを作る必要があるようです。
また、API Connectでサポートされるファイル形式としては、トラストストアはPKCS#12 or PEM, キーストアはPKDS#12のみのようです。

トップの「>>」のメニューから、管理を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/8c826f96-9344-ddf8-1454-983846627449.png)

セキュリティー - TLSプロファイル - 追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d6798f04-adf5-914f-59b9-4cdb45446dc0.png)

適当な名前をつけて作成したら、それを編集画面を開きます。
「トラストストア内の指定CAに対して証明書を要求して検証」を有効化して、トラストストア以下の証明書のアップロードをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d889b38e-e4a3-8e07-43e1-1b2adff2d093.png)

ダウンロードしたCA証明書(zosConnectCA.p12)を選択し、Export時に指定したパスワードを指定し、アップロード。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/bcb009ed-9e6c-3088-5f4f-03a16418097b.png)

保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/703555e9-709f-e811-0786-1e3bcaf6394f.png)


### アセンブル
呼び出し(Invoke)のURLで`https://`を指定し、TLSプロファイルに上で作成したプロファイルを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/765a3597-061d-491d-0b0c-9dbc9359efdd.png)

## テスト

アセンブルの画面からテストして、リクエストがきちんと通ることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/7aa60f5b-b9c6-cc27-286d-05e185a6d7b0.png)



# (2) TLS/サーバー認証&クライアント認証

サーバー認証&クライアント認証の構成の場合に必要な証明書を整理するとこんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d3aaebfe-3f32-6946-fa8f-b8488ed58142.png)

【サーバー側(z/OS Connect側)】
CA証明書1を使って署名されたサーバー証明書をキーストアに保持している必要があります。
クライアントから送られてきたサーバー証明書が信頼されたものかを検証するために、CA証明書2をトラストストアに保持している必要があります。

【クライアント側(API Connect側】
CA証明書2を使って署名されたクライアント証明書をキーストアに保持している必要があります。
サーバーから送られてきたサーバー証明書が信頼されたものかを検証するために、CA証明書をトラストストアに保持している必要があります。

サーバー証明書のみの構成の際に必要なセットを両側でそれぞれ持つイメージです。
ここで、サーバー証明書とクライアント証明書を発行するCAが別の可能性もあるので区別してCA証明書1,2と記載していますが、ここでの手順ではどちらもRACFをCAとして使用することにします(CA証明書1=CA証明書2)。
ここでは、上のサーバー認証の構成は済んでいる前提で、それにクライアント認証の構成を追加していくことにします。

## サーバー側(z/OS Connect側)設定
クライアント証明書を検証するために、クライアント証明書に署名しているCA証明書を取り込む必要がありますが、今回はどちらもRACFをCAとして使用する想定なので、その操作は不要です(既にKeyRingにCA証明書が存在)。
あとはこのCA証明書をトラストストアとしても認識させればよいことになります。

### z/OS Connect(server.xml)の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/11ef729b-907d-37ba-7a02-b07ac90ef090.png)

clientAuthentication="true"に設定し、trustStoreの定義を追加します。


### CA証明書で署名されたクライアント証明書を作成 & Export

クライアント証明書もRACFで作成しますので、これはz/OS側で準備してクライアント側に転送することになります。

まず、先に作成したCA証明書で署名したクライアント証明書を作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/4cc81627-5baf-259f-64a1-852dbb22804f.png)

```sh:06_createClientCert.sh
#!/bin/sh

tsocmd "RACDCERT ID(LIBSRV) GENCERT SUBJECTSDN(CN('myClient.host.com') O('IBM') OU('zosConnect') C('US')) SIZE(2048) SIGNWITH(CERTAUTH LABEL('zosConnectCA')) WITHLABEL('zosConnectClientCert') NOTAFTER(DATE(2120-12-31))"

tsocmd "RACDCERT ID(LIBSRV) LIST(LABEL('zosConnectClientCert'))"
```

```xxx:実行例
[CICS004@EPLEX1:/u/cics004/RACF/APIC] ./06_createClientCert.sh
RACDCERT ID(LIBSRV) GENCERT SUBJECTSDN(CN('myClient.host.com') O('IBM') OU('zosConnect') C('US')) SIZE(2048) SIGNWITH(CERTAUTH LABEL('zosConnectCA')) WITHLABEL('zosConnectClientCert') NOTAFTER(DATE(2120-12-31))
IRRD175I The new profile for DIGTCERT will not be in effect until a SETROPTS REFRESH has been issued.
RACDCERT ID(LIBSRV) LIST(LABEL('zosConnectClientCert'))

Digital certificate information for user LIBSRV:

  Label: zosConnectClientCert
  Certificate ID: 2QbTycLi2eWplqLDlpWVhYOjw5OJhZWjw4WZo0BA
  Status: TRUST
  Start Date: 2020/07/09 00:00:00
  End Date:   2120/12/31 23:59:59
  Serial Number:
       >03<
  Issuer's Name:
       >CN=CA for zosConnect.OU=zosConnect.O=IBM.C=US<
  Subject's Name:
       >CN=myClient.host.com.OU=zosConnect.O=IBM.C=US<
  Signing Algorithm: sha256RSA
  Key Type: RSA
  Key Size: 2048
  Private Key: YES
  Ring Associations:
  *** No rings associated ***
```

これをPKCS#12フォーマットでExportします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/286c907f-8307-1d59-3967-3bdb55b7a531.png)


```sh:07_exportClientcert.sh
#!/bin/sh

tsocmd "RACDCERT ID(LIBSRV) EXPORT(LABEL('zosConnectClientCert')) DSN('CICSSHR.CICS004.CERTS.ZCCLI.P12') FORMAT(PKCS12DER) PASSWORD('zcon00')"
```

```xxx:実行例
[CICS004@EPLEX1:/u/cics004/RACF/APIC] ./07_exportClientcert.sh
RACDCERT ID(LIBSRV) EXPORT(LABEL('zosConnectClientCert')) DSN('CICSSHR.CICS004.CERTS.ZCCLI.P12') FORMAT(PKCS12DER) PASSWORD('zcon00')
```

`CICSSHR.CICS004.CERTS.ZCCLI.P12`にExportされるので、これをPCに`zosConnectClientCert.p12`というファイル名でバイナリで転送しておきます。

### ブラウザでの簡易確認

クライアント証明書を設定していない状態でChromeからz/OS Connectにアクセスしてみると、以下のようにエラーではじかれるようになりました。
(画面キャプチャのeplex1はeplex1.securegateway.appdomain.cloudに読み替えてください)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/1398d9b2-d2ec-c607-5d36-6a0c463780ea.png)

Chrome - 設定 - セキュリティから証明書の管理を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/e79af08c-ac88-1efc-42bf-140899d68bea.png)

インポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/1a83ef08-ddd5-5ca9-95ba-c957e1a25dd1.png)

次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/bee3b38c-5f4b-5004-e822-aca017cfaa49.png)

入手したクライアント証明書を指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/f8e5821f-f632-dfba-27a4-8de12ce8d273.png)

Export時に指定したパスワードを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5beb2ce8-268e-d806-ab09-31d57a811b89.png)

次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/b5da7192-9ff2-c522-79e7-1174e50a1e4c.png)

完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/3bfd9b5e-5318-f13d-c5ce-64e2a457d811.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/a38a6bfd-e485-606f-12fe-daedaffb19b1.png)

これで、Chromeを立ち上げなおして、再度z/OS Connectにアクセスしてみます。
すると、以下のように証明書選択の画面が表示されるので、取り込んだクライアント証明書を選択してOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/211f5b93-420f-73b9-94ed-745e0d343908.png)

うまくリクエストが流れるのが確認できました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/29fe2a0e-1ca6-15a2-707f-f809659fb408.png)

## Secure Gateway設定
Secure Gatewayは、サーバー認証のみのケースと特に変更はありません。

## クライアント側(API Connect側)設定
トップの「>>」のメニューから、管理を選択し、セキュリティー - TLSプロファイルから、先に作成していたプロファイルを編集します。
証明書のアップロードを選択して、先にダウンロードしていたクライアント証明書(zosConnectClientCert.p12)をアップロードします(Export時に指定したパスワードが必要)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d4ee7b51-8d11-9b23-81e3-82735a51519d.png)

## テスト

探索の画面からテストして、リクエストがきちんと通ることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/c3a8a014-5866-1ce1-2a68-b011df63e15b.png)