#1. はじめに
CISではmTLSがサポートされており、クライアント証明書・サーバー証明書の両方を利用することで非常にセキュアな通信が可能である。CISのmTLS機能は内部的には、Cloudflareの「Cloudflare Access」を利用しており、**Enterprise Plan(Usage & Packageのみ。Enterprise GLBやEnterprise Securityでは不可)**が必要である。
本記事では、CISにおけるmTLSの設定、動作確認、およびmTLSに必要なクライアント証明書やCA(認証局)の作成方法について記載する。
- mTLSの挙動については、ここを参照。
- クライアント証明書の発行には公的なCAを利用しない。なぜならば、その公的なCAから正当性を保証された証明書を持っていれば誰でもアクセスできてしまうためである。むしろ特定のユーザーからしかアクセスさせたくないため、自前でroot CAを作成する。
- mTLSの有効化はドメインレベルで行うが、実際にはFQDNごとにmTLSを設定することになる。よって、mTLSを有効化したドメインにおいて、あるFQDNはmTLSを利用するが別のFQDNはmTLSを利用しないという構成が可能である。
2020/09/01追記
本記事を初めて投稿した時にはAPI/CLIしかサポートされていなかったが、現時点ではUIでの構成も可能になっている。以下はCLIで以前構成した内容をUIで確認した画面である。
#2. mTLS機能の有効化
##2-1. ibmcloudコマンドおよびCIS pluginを最新化する。
ibmcloudコマンド本体の更新
# ibmcloud update
まだCIS pluginを導入していない場合は新規導入
# ibmcloud plugin install cloud-internet-services
CIS pluginを導入済みの場合は、最新化
# ibmcloud plugin update
##2-2. mTLSを有効化する対象domain IDの取得
インスタンスを探す
# ibmcloud cis instances
Retrieving service instances for service 'internet-svcs' ...
OK
Name ID Location State Service Name
CIS-Enterprise-Usage1 crn:v1:bluemix:public:internet-svcs:global:a/039dbe6794084c7cb514a276dd2345da:cf4d8b04-b49e-4bf0-a99d-9303bba2cd90:: global active internet-svcs
コマンドごとにIDを指定しなくて済むように、default instanceを設定しておく
# ibmcloud cis instance-set CIS-Enterprise-Usage1
Setting context service instance to 'CIS-Enterprise-Usage1' ...
OK
Context service instance set succeeded.
# ibmcloud cis domains
Listing domains for service instance 'CIS-Enterprise-Usage1' ...
OK
ID Name Status Paused
3476b3464d25f1****************** certest.tk active false
##2-3. Caseを起票してmTLSを利用するための資格を割り当ててもらう
Please assign the entitlement for mTLS to my following CIS domain.
InstanceID: crn:v1:bluemix:public:internet-svcs:global:a/039dbe6794084c7cb514a276dd2345da:cf4d8b04-b49e-4bf0-a99d-9303bba2cd90::
DomainID: 3476b3464d25f1******************
##2-4. mTLS機能を有効化する
ibmcloud cis access-enableを利用。
有効化コマンド
# ibmcloud cis access-enable
Mutual TLS is not enabled. Do you want to enable Mutual TLS? [y/N]> y
OK
Status MTLS enabled
Created At 2020-04-10 06:49:01 +0000 UTC
確認(有効化コマンドと同じ)
# ibmcloud cis access-enable
OK
Status MTLS enabled
Created At 2020-04-10 06:49:01 +0000 UTC
#3. CA証明書、クライアント証明書の作成
ここが参考になるので、この通りにやってみる。
##3-1. cfsslおよびcfssljsonの導入
ここにパッケージがあるので、導入。
# curl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl
# curl https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson
# chmod +x /usr/local/bin/cfssl
# chmod +x /usr/local/bin/cfssljson
##3-2. クライアント証明書用のRoot CAの作成
{
"CN": "Access Testing CA",
"key": {
"algo": "rsa",
"size": 4096
},
"names": [
{
"C": "US",
"L": "Austin",
"O": "Access Testing",
"OU": "TX",
"ST": "Texas"
}
]
}
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"server": {
"usages": ["signing", "key encipherment", "server auth"],
"expiry": "8760h"
},
"client": {
"usages": ["signing","key encipherment","client auth"],
"expiry": "8760h"
}
}
}
}
# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2020/04/14 14:17:44 [INFO] generating a new CA key and certificate from CSR
2020/04/14 14:17:44 [INFO] generate received request
2020/04/14 14:17:44 [INFO] received CSR
2020/04/14 14:17:44 [INFO] generating key: rsa-4096
2020/04/14 14:17:50 [INFO] encoded CSR
2020/04/14 14:17:50 [INFO] signed certificate with serial number 627775792215544866389038048136817977289645998627
ca.pemがCA証明書。ca-key.pemがCA秘密鍵。
# ls -l
合計 20
-rw-r--r--. 1 root root 330 4月 14 14:04 ca-config.json
-rw-r--r--. 1 root root 219 4月 14 14:04 ca-csr.json
-rw-------. 1 root root 3243 4月 14 14:17 ca-key.pem
-rw-r--r--. 1 root root 1708 4月 14 14:17 ca.csr
-rw-r--r--. 1 root root 2082 4月 14 14:17 ca.pem
##3-3. クライアント証明書の作成
{
"CN": "James Royal",
"hosts": [""],
"key": {
"algo": "rsa",
"size": 4096
},
"names": [
{
"C": "US",
"L": "Austin",
"O": "Access",
"OU": "Access Admins",
"ST": "Texas"
}
]
}
# cfssl gencert -ca=./ca.pem -ca-key=./ca-key.pem -config=./ca-config.json -profile=client client-csr.json | cfssljson -bare client
2020/04/14 14:30:35 [INFO] generate received request
2020/04/14 14:30:35 [INFO] received CSR
2020/04/14 14:30:35 [INFO] generating key: rsa-4096
2020/04/14 14:30:37 [INFO] encoded CSR
2020/04/14 14:30:37 [INFO] signed certificate with serial number 634572527291617866038895563282136013011215666520
2020/04/14 14:30:37 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
# ls -l
合計 36
-rw-r--r--. 1 root root 330 4月 14 14:04 ca-config.json
-rw-r--r--. 1 root root 219 4月 14 14:04 ca-csr.json
-rw-------. 1 root root 3243 4月 14 14:17 ca-key.pem
-rw-r--r--. 1 root root 1708 4月 14 14:17 ca.csr
-rw-r--r--. 1 root root 2082 4月 14 14:17 ca.pem
-rw-r--r--. 1 root root 233 4月 14 14:29 client-csr.json
-rw-------. 1 root root 3243 4月 14 14:30 client-key.pem
-rw-r--r--. 1 root root 1744 4月 14 14:30 client.csr
-rw-r--r--. 1 root root 2118 4月 14 14:30 client.pem
#4. mTLSを構成してクライアント証明書なしでのアクセスを禁止する
##4-1. Cloudflare AccessにCA証明書をアップロード
ibmcloud cis access-certificate-create
なお、コマンド中で--associated-hostnames
の項は設定しないと動かないので注意(一度はまりました)。
# ibmcloud cis access-certificate-create 3476b3464d25f1****************** --name CA_YASUDA --ca-cert-file ./ca.pem --associated-hostnames www.certest.tk
Creating access certificate for domain '3476b3464d25f1******************' ...
OK
ID 837de934-5edc-438d-b7bc-b77980b55979
Name CA_YASUDA
Fingerprint MD5 Fingerprint=37:C5:53:A6:81:B5:7D:21:76:94:87:3E:63:A7:54:5F
Associated Hostnames www.certest.tk
Created At 2020-04-14 05:34:13 +0000 UTC
Updated At 2020-04-14 05:34:13 +0000 UTC
Expires On 2025-04-13 05:13:00 +0000 UTC
ここまでは、https://www.certest.tk
に普通にアクセスできる。
##4-2. Cloudflare Accessでアクセス制御されるアプリ名を定義
ibmcloud cis access-app-create
-
--domain
指定時にドメイン名だけでなくPATHも一緒に指定が可能。PATHを指定しない場合は、ドメイン全体が対象となる。参考
# ibmcloud cis access-app-create 3476b3464d25f1****************** --name sampleapp1 --domain www.certest.tk
Creating access application for domain '3476b3464d25f1******************' ...
OK
ID 9958befb-a0a7-4923-8c18-fa0783210b77
Name sampleapp1
Domain/Path www.certest.tk
Session Duration 24h
Created At 2020-04-14 19:29:37 +0000 UTC
Updated At 2020-04-14 19:29:37 +0000 UTC
Aud 79d720b7ec9fd37fc45926b59444fe62baa1033c77b4da2fdf99ffc9d356f9a8
この状態で該当ドメインにブラウザでアクセスすると、以下のように表示されるようになる。
##4-3. Cloudflare Accessでアクセス制御されるアプリでクライアント証明書が必要であるように定義
ibmcloud cis access-policy-create
# ibmcloud cis access-policy-create 3476b3464d25f1****************** 9958befb-a0a7-4923-8c18-fa0783210b77 --name sampleapp1policy --decision non_identity --include certificate
Creating access policy for access application '9958befb-a0a7-4923-8c18-fa0783210b77' of domain '3476b3464d25f1******************' ...
OK
ID be34f795-71ec-4f65-becc-bec980414f96
Name sampleapp1policy
Decision non_identity
Include {"certificate": {}}
Created At 2020-04-14 19:31:23 +0000 UTC
Updated At 2020-04-14 19:31:23 +0000 UTC
#5. テスト
##5-1. クライアント証明書なしでcurlでアクセス
# curl -svo /dev/null https://www.certest.tk
* About to connect() to www.certest.tk port 443 (#0)
* Trying 104.18.18.234...
* Connected to www.certest.tk (104.18.18.234) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS: client certificate not found (nickname not specified)
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=certest.tk,O="Cloudflare, Inc.",L=San Francisco,ST=CA,C=US
* start date: Mar 17 00:00:00 2020 GMT
* expire date: Oct 09 12:00:00 2020 GMT
* common name: certest.tk
* issuer: CN=CloudFlare Inc ECC CA-2,O="CloudFlare, Inc.",L=San Francisco,ST=CA,C=US
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.certest.tk
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Date: Tue, 14 Apr 2020 19:32:44 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=xxxxxxxx; expires=Thu, 14-May-20 19:32:44 GMT; path=/; domain=.certest.tk; HttpOnly; SameSite=Lax
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 583fdac11b7def96-NRT
<
{ [data not shown]
* Connection #0 to host www.certest.tk left intact
##5-2. クライアント証明書なしでブラウザでアクセス
こちらも当然アクセスに失敗する(Status codeは403)
##5-3. クライアント証明書ありでcurlでアクセス
こちらは期待通り成功
# curl -svo /dev/null --cert ./client.pem --key ./client-key.pem https://www.certest.tk
* About to connect() to www.certest.tk port 443 (#0)
* Trying 104.18.19.234...
* Connected to www.certest.tk (104.18.19.234) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS: client certificate from file
* subject: CN=James Royal,OU=Access Admins,O=Access,L=Austin,ST=Texas,C=US
* start date: Apr 14 05:26:00 2020 GMT
* expire date: Apr 14 05:26:00 2021 GMT
* common name: James Royal
* issuer: CN=Access Testing CA,OU=TX,O=Access Testing,L=Austin,ST=Texas,C=US
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=certest.tk,O="Cloudflare, Inc.",L=San Francisco,ST=CA,C=US
* start date: Mar 17 00:00:00 2020 GMT
* expire date: Oct 09 12:00:00 2020 GMT
* common name: certest.tk
* issuer: CN=CloudFlare Inc ECC CA-2,O="CloudFlare, Inc.",L=San Francisco,ST=CA,C=US
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.certest.tk
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 14 Apr 2020 19:33:22 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=xxxxxxxx; expires=Thu, 14-May-20 19:33:21 GMT; path=/; domain=.certest.tk; HttpOnly; SameSite=Lax
< Set-Cookie: CF_Authorization=xxxxxxxx; Expires=Wed, 15 Apr 2020 19:33:21 GMT; Path=/; Secure; HttpOnly
< Last-Modified: Fri, 11 Oct 2019 11:35:18 GMT
< Accept-Ranges: bytes
< CF-Cache-Status: DYNAMIC
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 583fdbabd8edf8f3-NRT
<
{ [data not shown]
* Connection #0 to host www.certest.tk left intact