SPIRE における SVID を利用した Workload の認証の流れを理解する

# はじめに

SPIRE では Node/Workload に対して、その Node/Workload の Identity となる SPIFFE ID が含まれた SVID を発行する機構があります。

Node Attestation を経て、Base SVID（SPIRE Agent が起動している Node に対して割り当てられる SVID）が Node に配布され、その Base SVID は SPIRE Agent が SPIRE Server に対して認証を行う際に利用され、認証に成功することで Workload Attestation の開始が可能になる流れは理解できていました。

しかし、Workload Attestation を経て、Workload に対して配布される SVID を使って行う Workload 間の認証（ないしは同じ PKIツリー 内のシステムとの認証）の流れを自分の中でイメージできていなかったので、今回はそれらの理解を深めるために SPIRE の仕様をおさらいしながら、Workload 間の認証の流れを整理していきたいと思います。

# SVID を使った認証の流れをおさらい

Node/Workload Attestation に成功した Node/Workload は、自身の Identity となる SPIFFE ID が含まれた SVID と、それを検証するための Trust Bundle（SVID に署名を行った CA証明書）を取得することが可能になっています。

「Trust Bundle が SVID の検証に利用される」とは「Trust Bundle があることで通信相手となる Node/Workload の Identity である SPIFFE ID が信頼できるものか判断できる」ということになります。

そして、通信相手の SPIFFE ID がわかったところで、意図した通信相手であれば 認証OK という流れになるわけです。

# openssl を使って手動で Workload の SVID の検証をやってみる

## 検証環境

spiffe/spire に含まれる Dockerイメージ を使って、コンテナでスタンドアローンな環境を構築して SVID の検証を行っていきます。なお、SPIRE のバージョンは 0.8.0 を利用します。
https://github.com/spiffe/spire/tree/0.8.0

## 前準備

以下に記載されている Walkthrough を最後まで実施して、ファイルとして X.509-SVID と Trust Bundle が作成できたら、前準備が完了となります。
https://github.com/spiffe/spire/blob/0.8.0/doc/SPIRE101.md

以下、例となります。

```bash
root@spire-dev:~/spire# mkdir certs

root@spire-dev:~/spire# su -c "./cmd/spire-agent/spire-agent api fetch x509 -write ./certs" workload
Received 1 bundle after 12.017658ms

SPIFFE ID:		spiffe://example.org/workload
SVID Valid After:	2019-06-02 19:32:42 +0000 UTC
SVID Valid Until:	2019-06-02 20:32:20 +0000 UTC
Intermediate #1 Valid After:	2019-06-02 19:32:10 +0000 UTC
Intermediate #1 Valid Until:	2019-06-02 20:32:20 +0000 UTC
CA #1 Valid After:	2018-05-13 19:33:47 +0000 UTC
CA #1 Valid Until:	2023-05-12 19:33:47 +0000 UTC

Writing SVID #0 to file certs/svid.0.pem.
Writing key #0 to file certs/svid.0.key.
Writing bundle #0 to file certs/bundle.0.pem.

root@spire-dev:~/spire# ll certs/
total 12
drwxr-xr-x  5 root root  170 Jun  2 19:32 ./
drwxr-xr-x 44 root root 1496 Jun  2 19:32 ../
-rw-r--r--  1 root root  684 Jun  2 19:32 bundle.0.pem
-rw-r--r--  1 root root  241 Jun  2 19:32 svid.0.key
-rw-r--r--  1 root root 1474 Jun  2 19:32 svid.0.pem
```

## Node が取得した Base SVID

### Base SVID（ `./.data/agent_svid.der` ） の証明書情報

Base SVID は X.509-SVID 形式となります。

openssl で Base SVID（ `./.data/agent_svid.der` ）の証明書情報を表示します。
Issuer, Subject, SAN(Subject Alternative Name) だけがわかれば良いので出力は一部抜粋しています。

```bash
root@spire-dev:~/spire# openssl x509 -text -noout -inform der -in ./.data/agent_svid.der
Certificate:
    ...
    Signature Algorithm: ecdsa-with-SHA384
        Issuer: C=US, O=SPIFFE
        ...
        Subject: C=US, O=SPIRE
        ...
        X509v3 extensions:
            ...
            X509v3 Subject Alternative Name:
                URI:spiffe://example.org/spire/agent/join_token/7287a190-f46f-45ed-b822-c13df57af498
    ...
```

<details>
<summary>全ての出力はこちら</summary>
<div>

```bash
root@spire-dev:~/spire# openssl x509 -text -noout -inform der -in ./.data/agent_svid.der
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
    Signature Algorithm: ecdsa-with-SHA384
        Issuer: C=US, O=SPIFFE
        Validity
            Not Before: Jun  2 19:32:27 2019 GMT
            Not After : Jun  2 20:32:20 2019 GMT
        Subject: C=US, O=SPIRE
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:4d:94:1f:29:13:36:1f:64:7f:c4:28:c5:95:ec:
                    27:db:ee:57:92:c3:44:32:59:a1:33:cc:af:ac:eb:
                    74:f1:47:ac:75:ec:a9:af:1c:48:fc:cb:f5:2e:c7:
                    49:f2:88:02:e9:11:18:19:ca:5a:60:05:af:c3:3c:
                    7f:11:53:a5:e2
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment, Key Agreement
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                BE:19:33:D4:1D:9F:DD:92:0A:9B:33:C8:2E:00:4E:3F:EE:88:84:19
            X509v3 Authority Key Identifier:
                keyid:87:3C:F9:8B:43:80:8D:06:63:16:7A:EA:B2:10:D7:2B:4D:73:F4:A6

            X509v3 Subject Alternative Name:
                URI:spiffe://example.org/spire/agent/join_token/7287a190-f46f-45ed-b822-c13df57af498
    Signature Algorithm: ecdsa-with-SHA384
         30:66:02:31:00:d4:83:a4:08:cd:7f:73:31:d9:e9:49:b4:19:
         ae:7f:d7:d3:61:56:56:90:76:17:d4:45:19:b2:74:f9:b9:51:
         5f:b1:45:f2:db:cd:88:8a:ba:4b:e7:9f:c0:b2:9e:be:5b:02:
         31:00:b9:b3:d4:97:72:f3:9b:c4:63:3b:08:ec:c6:e7:97:20:
         24:55:7e:c7:d6:73:b8:96:ad:b2:f4:76:85:25:1b:11:32:ae:
         0d:6b:0a:d6:5b:bf:5a:df:70:fe:56:0f:47:ee
```

</div>
</details>

## Workload が取得した X.509-SVID

### X.509-SVID（ `./certs/svid.0.pem` ） の実体

以下、2つのファイルで構成されていることがわかります。

- X.509-SVID（上）
- X.509-SVID を検証するための CA証明書（下）

"X.509-SVID を検証するための CA証明書" ですが、Walkthrough では PKIツリー における SPIRE Server の上段に ルートCA を配置する構成となっているので、UpstreamCA Plugin で指定した ルートCA によって署名された "中間CA証明書" となります。
https://github.com/spiffe/spire/blob/0.8.0/conf/server/server.conf#L38-L44

```bash
root@spire-dev:~/spire# cat ./certs/svid.0.pem
-----BEGIN CERTIFICATE-----
MIIB9TCCAXugAwIBAgIBBDAKBggqhkjOPQQDAzAeMQswCQYDVQQGEwJVUzEPMA0G
A1UEChMGU1BJRkZFMB4XDTE5MDYwMjE5MzI0MloXDTE5MDYwMjIwMzIyMFowHTEL
MAkGA1UEBhMCVVMxDjAMBgNVBAoTBVNQSVJFMFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEB6COJnwWjnZ25ZvLYm7m9K15F1t+6v+0Zs375BW9Ulbh3+gZ8ej5G+p+
pvHS+IsuMN/76Ukha2wfy9QBJymd8KOBqjCBpzAOBgNVHQ8BAf8EBAMCA6gwHQYD
VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0O
BBYEFJYunZ7mxmetJ34QnAEg6d49o8nsMB8GA1UdIwQYMBaAFIc8+YtDgI0GYxZ6
6rIQ1ytNc/SmMCgGA1UdEQQhMB+GHXNwaWZmZTovL2V4YW1wbGUub3JnL3dvcmts
b2FkMAoGCCqGSM49BAMDA2gAMGUCMQCFeBWZzdiwJJCTZKZigS44Ymej23d9ozFZ
P8Q6jW1htyRpkHJyTZxv41+kGjqbyY4CMAiYZLlP3vrqN2sbpKY5dHiWCluKK4sn
stwQuxE5+qI767Ig5ZEQvBiA1f3IZa3izw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB7zCCAXSgAwIBAgIBATAKBggqhkjOPQQDAzAeMQswCQYDVQQGEwJVUzEPMA0G
A1UECgwGU1BJRkZFMB4XDTE5MDYwMjE5MzIxMFoXDTE5MDYwMjIwMzIyMFowHjEL
MAkGA1UEBhMCVVMxDzANBgNVBAoTBlNQSUZGRTB2MBAGByqGSM49AgEGBSuBBAAi
A2IABGHcciQK5m85Ukz9sDRbKoOpzt/6UVmXHl/Itb4U5OdgbsMglJUAuzqKX//x
geLV9mhlgoG3ZIYLrqGEwI9vUIGyhYIU/bsVTNN/iNKrev5mVmfP00b+sEptn4ZU
6iCW6qOBhTCBgjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
HQ4EFgQUhzz5i0OAjQZjFnrqshDXK01z9KYwHwYDVR0jBBgwFoAUh6XzV6LwNazA
+GTEVOdu07o5yOgwHwYDVR0RBBgwFoYUc3BpZmZlOi8vZXhhbXBsZS5vcmcwCgYI
KoZIzj0EAwMDaQAwZgIxAMwETO7BX8ELJwWFFWctgzqqsdCnJwCB00201q+GvLPd
oYOcE6vqo7C+VNc8lhBwWAIxAPQSAoNUva4hTX31DRrtRC/3xhsXucMex91BWwzI
+ehylCfUCHN4BWNx9nliWoMCIA==
-----END CERTIFICATE-----
```

### X.509-SVID（ `./certs/svid.0.pem` ） の証明書情報

openssl で X.509-SVID（ `./certs/svid.0.pem` ）の証明書情報を表示します。
Issuer, Subject, SAN(Subject Alternative Name) だけがわかれば良いので出力は一部抜粋しています。

```bash
root@spire-dev:~/spire# openssl crl2pkcs7 -nocrl -certfile ./certs/svid.0.pem | openssl pkcs7 -print_certs -text -noout
Certificate:
    ...
    Signature Algorithm: ecdsa-with-SHA384
        Issuer: C=US, O=SPIFFE
        ...
        Subject: C=US, O=SPIRE
        ...
        X509v3 extensions:
            ...
            X509v3 Subject Alternative Name:
                URI:spiffe://example.org/workload
    ...
Certificate:
    ...
    Signature Algorithm: ecdsa-with-SHA384
        Issuer: C=US, O=SPIFFE
        ...
        Subject: C=US, O=SPIFFE
        ...
        X509v3 extensions:
            ...
            X509v3 Subject Alternative Name:
                URI:spiffe://example.org
    ...
```

X.509-SVID の Issuer と 中間CA証明書 の Subject が同じことから、X.509-SVID は 中間CA証明書 から署名されていて PKIツリー における親子関係にある（openssl を使った厳格な検証はここから先の作業で実施）ことがわかります。また、SAN には SPIRE Server と Workload それぞれの SPIFFE ID が格納（SPIRE Server の SPIFFE ID は Trust Domain です）されていることがわかります。

Issuer と Subject が同じなので、中間CA証明書ではなく ルートCA証明書 なのでは？となりますが、Walkthrough で使われるルートCA証明書 の Subject と、SPIRE Server の config の Subject と同じなので、このような状況となっています。

- ルートCA証明書の Subject: https://github.com/spiffe/spire/blob/0.8.0/script/generate_dummy_ca.sh#L9
- 中間CA証明書の Subject: https://github.com/spiffe/spire/blob/0.8.0/conf/server/server.conf#L10-L14

<details>
<summary>全ての出力はこちら</summary>
<div>

```bash
root@spire-dev:~/spire# openssl crl2pkcs7 -nocrl -certfile ./certs/svid.0.pem | openssl pkcs7 -print_certs -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 4 (0x4)
    Signature Algorithm: ecdsa-with-SHA384
        Issuer: C=US, O=SPIFFE
        Validity
            Not Before: Jun  2 19:32:42 2019 GMT
            Not After : Jun  2 20:32:20 2019 GMT
        Subject: C=US, O=SPIRE
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:07:a0:8e:26:7c:16:8e:76:76:e5:9b:cb:62:6e:
                    e6:f4:ad:79:17:5b:7e:ea:ff:b4:66:cd:fb:e4:15:
                    bd:52:56:e1:df:e8:19:f1:e8:f9:1b:ea:7e:a6:f1:
                    d2:f8:8b:2e:30:df:fb:e9:49:21:6b:6c:1f:cb:d4:
                    01:27:29:9d:f0
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment, Key Agreement
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                96:2E:9D:9E:E6:C6:67:AD:27:7E:10:9C:01:20:E9:DE:3D:A3:C9:EC
            X509v3 Authority Key Identifier:
                keyid:87:3C:F9:8B:43:80:8D:06:63:16:7A:EA:B2:10:D7:2B:4D:73:F4:A6

            X509v3 Subject Alternative Name:
                URI:spiffe://example.org/workload
    Signature Algorithm: ecdsa-with-SHA384
         30:65:02:31:00:85:78:15:99:cd:d8:b0:24:90:93:64:a6:62:
         81:2e:38:62:67:a3:db:77:7d:a3:31:59:3f:c4:3a:8d:6d:61:
         b7:24:69:90:72:72:4d:9c:6f:e3:5f:a4:1a:3a:9b:c9:8e:02:
         30:08:98:64:b9:4f:de:fa:ea:37:6b:1b:a4:a6:39:74:78:96:
         0a:5b:8a:2b:8b:27:b2:dc:10:bb:11:39:fa:a2:3b:eb:b2:20:
         e5:91:10:bc:18:80:d5:fd:c8:65:ad:e2:cf

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
    Signature Algorithm: ecdsa-with-SHA384
        Issuer: C=US, O=SPIFFE
        Validity
            Not Before: Jun  2 19:32:10 2019 GMT
            Not After : Jun  2 20:32:20 2019 GMT
        Subject: C=US, O=SPIFFE
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:61:dc:72:24:0a:e6:6f:39:52:4c:fd:b0:34:5b:
                    2a:83:a9:ce:df:fa:51:59:97:1e:5f:c8:b5:be:14:
                    e4:e7:60:6e:c3:20:94:95:00:bb:3a:8a:5f:ff:f1:
                    81:e2:d5:f6:68:65:82:81:b7:64:86:0b:ae:a1:84:
                    c0:8f:6f:50:81:b2:85:82:14:fd:bb:15:4c:d3:7f:
                    88:d2:ab:7a:fe:66:56:67:cf:d3:46:fe:b0:4a:6d:
                    9f:86:54:ea:20:96:ea
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier:
                87:3C:F9:8B:43:80:8D:06:63:16:7A:EA:B2:10:D7:2B:4D:73:F4:A6
            X509v3 Authority Key Identifier:
                keyid:87:A5:F3:57:A2:F0:35:AC:C0:F8:64:C4:54:E7:6E:D3:BA:39:C8:E8

            X509v3 Subject Alternative Name:
                URI:spiffe://example.org
    Signature Algorithm: ecdsa-with-SHA384
         30:66:02:31:00:cc:04:4c:ee:c1:5f:c1:0b:27:05:85:15:67:
         2d:83:3a:aa:b1:d0:a7:27:00:81:d3:4d:b4:d6:af:86:bc:b3:
         dd:a1:83:9c:13:ab:ea:a3:b0:be:54:d7:3c:96:10:70:58:02:
         31:00:f4:12:02:83:54:bd:ae:21:4d:7d:f5:0d:1a:ed:44:2f:
         f7:c6:1b:17:b9:c3:1e:c7:dd:41:5b:0c:c8:f9:e8:72:94:27:
         d4:08:73:78:05:63:71:f6:79:62:5a:83:02:20
```

</div>
</details>

## Workload が取得した Trust Bundle

### Trust Bundle（ `./certs/bundle.0.pem` ） の実体

Trust Bundle の実体は、ルートCA証明書 となります。

```bash
root@spire-dev:~/spire# cat ./certs/bundle.0.pem
-----BEGIN CERTIFICATE-----
MIIBzDCCAVOgAwIBAgIJAJM4DhRH0vmuMAoGCCqGSM49BAMEMB4xCzAJBgNVBAYT
AlVTMQ8wDQYDVQQKDAZTUElGRkUwHhcNMTgwNTEzMTkzMzQ3WhcNMjMwNTEyMTkz
MzQ3WjAeMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGU1BJRkZFMHYwEAYHKoZIzj0C
AQYFK4EEACIDYgAEWjB+nSGSxIYiznb84xu5WGDZj80nL7W1c3zf48Why0ma7Y7m
CBKzfQkrgDguI4j0Z+0/tDH/r8gtOtLLrIpuMwWHoe4vbVBFte1vj6Xt6WeE8lXw
cCvLs/mcmvPqVK9jo10wWzAdBgNVHQ4EFgQUh6XzV6LwNazA+GTEVOdu07o5yOgw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwGQYDVR0RBBIwEIYOc3Bp
ZmZlOi8vbG9jYWwwCgYIKoZIzj0EAwQDZwAwZAIwE4Me13qMC9i6Fkx0h26y09QZ
IbuRqA9puLg9AeeAAyo5tBzRl1YL0KNEp02VKSYJAjBdeJvqjJ9wW55OGj1JQwDF
D7kWeEB6oMlwPbI/5hEY3azJi16I0uN1JSYTSWGSqWc=
-----END CERTIFICATE-----
```

### Trust Bundle（ `./certs/bundle.0.pem` ） の証明書情報

openssl で Trust Bundle（ `./certs/bundle.0.pem` ）の証明書情報を表示します。
Issuer, Subject, SAN(Subject Alternative Name) だけがわかれば良いので出力は一部抜粋しています。

```bash
root@spire-dev:~/spire# openssl x509 -text -noout -in ./certs/bundle.0.pem
Certificate:
    ...
    Signature Algorithm: ecdsa-with-SHA512
        Issuer: C=US, O=SPIFFE
        ...
        Subject: C=US, O=SPIFFE
        ...
        X509v3 extensions:
            ...
            X509v3 Subject Alternative Name:
                URI:spiffe://local
    ...
```

Issuer と Subject が同じことから、Trust Bundle は ルートCA証明書 であることがわかります。

<details>
<summary>全ての出力はこちら</summary>
<div>

```bash
root@spire-dev:~/spire# openssl x509 -text -noout -in ./certs/bundle.0.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 10608244402538346926 (0x93380e1447d2f9ae)
    Signature Algorithm: ecdsa-with-SHA512
        Issuer: C=US, O=SPIFFE
        Validity
            Not Before: May 13 19:33:47 2018 GMT
            Not After : May 12 19:33:47 2023 GMT
        Subject: C=US, O=SPIFFE
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:5a:30:7e:9d:21:92:c4:86:22:ce:76:fc:e3:1b:
                    b9:58:60:d9:8f:cd:27:2f:b5:b5:73:7c:df:e3:c5:
                    a1:cb:49:9a:ed:8e:e6:08:12:b3:7d:09:2b:80:38:
                    2e:23:88:f4:67:ed:3f:b4:31:ff:af:c8:2d:3a:d2:
                    cb:ac:8a:6e:33:05:87:a1:ee:2f:6d:50:45:b5:ed:
                    6f:8f:a5:ed:e9:67:84:f2:55:f0:70:2b:cb:b3:f9:
                    9c:9a:f3:ea:54:af:63
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                87:A5:F3:57:A2:F0:35:AC:C0:F8:64:C4:54:E7:6E:D3:BA:39:C8:E8
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Subject Alternative Name:
                URI:spiffe://local
    Signature Algorithm: ecdsa-with-SHA512
         30:64:02:30:13:83:1e:d7:7a:8c:0b:d8:ba:16:4c:74:87:6e:
         b2:d3:d4:19:21:bb:91:a8:0f:69:b8:b8:3d:01:e7:80:03:2a:
         39:b4:1c:d1:97:56:0b:d0:a3:44:a7:4d:95:29:26:09:02:30:
         5d:78:9b:ea:8c:9f:70:5b:9e:4e:1a:3d:49:43:00:c5:0f:b9:
         16:78:40:7a:a0:c9:70:3d:b2:3f:e6:11:18:dd:ac:c9:8b:5e:
         88:d2:e3:75:25:26:13:49:61:92:a9:67
```

</div>
</details>

## openssl を使って手動で Workload の X.509-SVID の検証をやってみる

Workload が取得した X.509-SVID と Trust Bundle を使って、X.509-SVID の検証を行っていきます。

まず、検証を行う前に X.509-SVID と 中間CA証明書 が一緒になっていると困るので、以下のコマンドで分割します。

```bash
awk 'BEGIN {c=0;} /BEGIN CERT/{c++} { print > c }' < ./certs/svid.0.pem
mv 1 ./certs/svid.pem
mv 2 ./certs/intermediate_ca.pem
```

次に 中間CA証明書 と ルートCA証明書 を1つの証明書バンドルにします。

```bash
cat ./certs/intermediate_ca.pem ./certs/bundle.0.pem > ./certs/ca_bundle.pem
```

完成したファイルはこちら。

```bash
# X.509-SVID
root@spire-dev:~/spire# cat ./certs/svid.pem
-----BEGIN CERTIFICATE-----
MIIB9TCCAXugAwIBAgIBBDAKBggqhkjOPQQDAzAeMQswCQYDVQQGEwJVUzEPMA0G
A1UEChMGU1BJRkZFMB4XDTE5MDYwMjE5MzI0MloXDTE5MDYwMjIwMzIyMFowHTEL
MAkGA1UEBhMCVVMxDjAMBgNVBAoTBVNQSVJFMFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEB6COJnwWjnZ25ZvLYm7m9K15F1t+6v+0Zs375BW9Ulbh3+gZ8ej5G+p+
pvHS+IsuMN/76Ukha2wfy9QBJymd8KOBqjCBpzAOBgNVHQ8BAf8EBAMCA6gwHQYD
VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0O
BBYEFJYunZ7mxmetJ34QnAEg6d49o8nsMB8GA1UdIwQYMBaAFIc8+YtDgI0GYxZ6
6rIQ1ytNc/SmMCgGA1UdEQQhMB+GHXNwaWZmZTovL2V4YW1wbGUub3JnL3dvcmts
b2FkMAoGCCqGSM49BAMDA2gAMGUCMQCFeBWZzdiwJJCTZKZigS44Ymej23d9ozFZ
P8Q6jW1htyRpkHJyTZxv41+kGjqbyY4CMAiYZLlP3vrqN2sbpKY5dHiWCluKK4sn
stwQuxE5+qI767Ig5ZEQvBiA1f3IZa3izw==
-----END CERTIFICATE-----

# 証明書バンドル
root@spire-dev:~/spire# cat ./certs/ca_bundle.pem
-----BEGIN CERTIFICATE-----
MIIB7zCCAXSgAwIBAgIBATAKBggqhkjOPQQDAzAeMQswCQYDVQQGEwJVUzEPMA0G
A1UECgwGU1BJRkZFMB4XDTE5MDYwMjE5MzIxMFoXDTE5MDYwMjIwMzIyMFowHjEL
MAkGA1UEBhMCVVMxDzANBgNVBAoTBlNQSUZGRTB2MBAGByqGSM49AgEGBSuBBAAi
A2IABGHcciQK5m85Ukz9sDRbKoOpzt/6UVmXHl/Itb4U5OdgbsMglJUAuzqKX//x
geLV9mhlgoG3ZIYLrqGEwI9vUIGyhYIU/bsVTNN/iNKrev5mVmfP00b+sEptn4ZU
6iCW6qOBhTCBgjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
HQ4EFgQUhzz5i0OAjQZjFnrqshDXK01z9KYwHwYDVR0jBBgwFoAUh6XzV6LwNazA
+GTEVOdu07o5yOgwHwYDVR0RBBgwFoYUc3BpZmZlOi8vZXhhbXBsZS5vcmcwCgYI
KoZIzj0EAwMDaQAwZgIxAMwETO7BX8ELJwWFFWctgzqqsdCnJwCB00201q+GvLPd
oYOcE6vqo7C+VNc8lhBwWAIxAPQSAoNUva4hTX31DRrtRC/3xhsXucMex91BWwzI
+ehylCfUCHN4BWNx9nliWoMCIA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBzDCCAVOgAwIBAgIJAJM4DhRH0vmuMAoGCCqGSM49BAMEMB4xCzAJBgNVBAYT
AlVTMQ8wDQYDVQQKDAZTUElGRkUwHhcNMTgwNTEzMTkzMzQ3WhcNMjMwNTEyMTkz
MzQ3WjAeMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGU1BJRkZFMHYwEAYHKoZIzj0C
AQYFK4EEACIDYgAEWjB+nSGSxIYiznb84xu5WGDZj80nL7W1c3zf48Why0ma7Y7m
CBKzfQkrgDguI4j0Z+0/tDH/r8gtOtLLrIpuMwWHoe4vbVBFte1vj6Xt6WeE8lXw
cCvLs/mcmvPqVK9jo10wWzAdBgNVHQ4EFgQUh6XzV6LwNazA+GTEVOdu07o5yOgw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwGQYDVR0RBBIwEIYOc3Bp
ZmZlOi8vbG9jYWwwCgYIKoZIzj0EAwQDZwAwZAIwE4Me13qMC9i6Fkx0h26y09QZ
IbuRqA9puLg9AeeAAyo5tBzRl1YL0KNEp02VKSYJAjBdeJvqjJ9wW55OGj1JQwDF
D7kWeEB6oMlwPbI/5hEY3azJi16I0uN1JSYTSWGSqWc=
-----END CERTIFICATE-----
```

最後に openssl コマンドで X.509-SVID の検証を行います。

```bash
root@spire-dev:~/spire# openssl verify -CAfile ./certs/ca_bundle.pem ./certs/svid.pem
./certs/svid.pem: OK
```

X.509-SVID の検証に成功したので、この X.509-SVID に含まれる SPIFFE ID `spiffe://example.org/workload` が信頼できることがわかりました。あとはその SPIFFE ID に対応する Workload が意図した通信相手かどうかをチェックする認証処理を行えば良いというわけです。

X.509-SVID であれ、JWT-SVID であれ、別の Workload と通信を行う際にリクエストと一緒に渡してクライアント認証を行う流れですね。

```bash
root@spire-dev:~/spire# openssl x509 -text -noout -in ./certs/svid.pem
Certificate:
    ...
    Signature Algorithm: ecdsa-with-SHA384
        ...
        X509v3 extensions:
            ...
            X509v3 Subject Alternative Name:
                URI:spiffe://example.org/workload
    ...
```

ここまでやって気付いたのですが、これ普通に TLS のクライアント認証ですね...。
なんか悲しい終わり方になりました...。

## 補足

SPIRE 0.8.0 以前のバージョンでは Trust Bundle は ルートCA証明書 と 中間CA証明書 で構成されていたのですが、0.8.0 で  中間CA証明書 が取り除かれて、Trust Bundle は本来の形である ルートCA証明書 のみとなったようです。

どのような経緯があったのか知りたい方は以下を参照ください。

[0.7.1](https://github.com/spiffe/spire/releases/tag/0.7.1) で 0.6.x との互換性を保つために 中間CA証明書 が Trust Bundle に含まれるようになった。

- https://github.com/spiffe/spire/pull/633

[0.8.0](https://github.com/spiffe/spire/releases/tag/0.8.0) で Trust Bundle が ルートCA証明書 のみの本来の形に戻った。

- https://github.com/spiffe/spire/pull/858
- https://github.com/spiffe/spire/pull/859

# このままじゃ終われない...。

時間を掛けて書いた記事が悲しい終わり方になるのは辛すぎるので、ソースコードを眺めて SPIRE Server が SPIRE Agent から渡される Base SVID を使って、どのように認可を行うのかを追いかけていきたいと思います。

<details>
<summary>こちらはもう自己満足でしかないので興味あればどうぞ</summary>
<div>

## Node Attestatin が完了して Node に SVID と Key と Trust Bundle が配布されるまで

`spire-agent run` が開始される。
https://github.com/spiffe/spire/blob/0.8.0/cmd/spire-agent/main.go#L9-L11
https://github.com/spiffe/spire/blob/0.8.0/cmd/spire-agent/cli/cli.go#L32-L34

Node Attestation が開始される。
https://github.com/spiffe/spire/blob/0.8.0/cmd/spire-agent/cli/run/run.go#L113
https://github.com/spiffe/spire/blob/0.8.0/pkg/agent/agent.go#L66 （ここの直前で各 Plugins をロードする）
https://github.com/spiffe/spire/blob/0.8.0/pkg/agent/agent.go#L143-L156

ここまでは前処理でここからが Node Attestation の実処理。
ここの処理で Trust Bundle と SVID などの生成を行っている。SVID は X.509-SVID 固定の様子。
https://github.com/spiffe/spire/blob/0.8.0/pkg/agent/attestor/node/node.go#L61-L80

Node Attestation に成功したら、Cache Manager が Node のファイルシステムに SVID と Key と Trust Bundle が書き込み、SPIRE Server と通信して Registration Entry の同期を行う。
https://github.com/spiffe/spire/blob/0.8.0/pkg/agent/agent.go#L71
https://github.com/spiffe/spire/blob/0.8.0/pkg/agent/agent.go#L177
https://github.com/spiffe/spire/blob/0.8.0/pkg/agent/manager/manager.go#L81-L91
https://github.com/spiffe/spire/blob/0.8.0/pkg/agent/manager/sync.go#L26-L78

全ての処理が完了したら SPIRE Agent が起動する。
https://github.com/spiffe/spire/blob/0.8.0/pkg/agent/agent.go#L78-L82

## SPIRE Server が SPIRE Agent から渡される Base SVID を使って認可を行う処理

`spire-server run` で SPIRE Server が起動するまでの処理。
https://github.com/spiffe/spire/blob/0.8.0/cmd/spire-server/main.go#L10
https://github.com/spiffe/spire/blob/0.8.0/cmd/spire-server/cli/run/run.go#L126
https://github.com/spiffe/spire/blob/0.8.0/pkg/server/server.go#L106-L201

SPIRE Server 起動中は、内部では SPIRE Agent と通信するための gRPC サーバーが起動し続けている状態。
https://github.com/spiffe/spire/blob/0.8.0/pkg/server/server.go#L194
https://github.com/spiffe/spire/blob/0.8.0/pkg/server/endpoints/endpoints.go#L52
https://github.com/spiffe/spire/blob/0.8.0/pkg/server/endpoints/endpoints.go#L60

そして、その gRPC サーバーに対して SPIRE Agent がリクエストを行う際には認可の処理がなされる。
https://github.com/spiffe/spire/blob/0.8.0/pkg/server/endpoints/endpoints.go#L80
https://github.com/spiffe/spire/blob/0.8.0/pkg/common/auth/interceptors.go#L29-L39

どのように認可の処理が行われるかを追いかけていく。
https://github.com/spiffe/spire/blob/0.8.0/pkg/common/auth/interceptors.go#L46
https://github.com/spiffe/spire/blob/0.8.0/pkg/server/endpoints/node/handler.go#L386-L426

SPIRE Agent が Workload API を介して X.509-SVID, JWT-SVID を取得しようとすると、SPIRE Server が Base SVID のバリデーションを開始する。バリデーションは X.509-SVID 形式である Base SVID から SPIFFE ID を取得して、Attested Node の一覧に照合をかけるだけ。
https://github.com/spiffe/spire/blob/0.8.0/pkg/server/endpoints/node/handler.go#L391-L405
https://github.com/spiffe/spire/blob/0.8.0/pkg/server/endpoints/node/handler.go#L447-L480

認可の処理に成功することで、Workload は SVID を取得することが可能になる。

</div>
</details>

# まとめ

Workload が SVID を得た後は、別の Workload に対して X.509証明書 または JWT を使ってクライアント認証を行い、リクエストを受けた Workload は SPIFFE ID の照合を行うことで意図した通信相手であるか確認ができるということがわかりました。あとは SPIFFE ID の照合までは行わずとも、[SPIRE の Use cases](https://spiffe.io/spire/#use-cases) にあるように同じ PKIツリー の中に属すシステム（e.g. Vault, Pinterest Knox）に対する認証に使用したりかなと思います。

当初自分が想定していた内容に比べて薄い内容となってしまい、少し残念な感じはありましたが、SVID の良い復習になったのと、ソースコードを追って少しだけ実処理を理解できたことは良かったかなと思っています。また、この記事を書き上げる中で spiffe/spire に PR を 2つ（[#940](https://github.com/spiffe/spire/pull/940), [#941](https://github.com/spiffe/spire/pull/941)）投げることが出来たので、結果オーライだと思いたいです...!!!

今後も SPIRE を地道にやっていこうと思います、おしまい。

# 参考資料

- Trust Bundle の利用用途に関して
    - https://qiita.com/hiyosi/items/6e8d56b257c55a709b4d#svid
    - https://spiffe.io/spiffe/#trust-bundle
- openssl のチートシート
    - http://multix.jp/openssl-command/
    - https://security.stackexchange.com/questions/163507/can-openssl-verify-a-public-key-intermediate-ca-certificate-chain-with-a-root
- openssl で証明書バンドル内のすべての証明書情報を表示する方法
    - https://serverfault.com/questions/590870/how-to-view-all-ssl-certificates-in-a-bundle
- 証明書バンドルを分割する方法
    - https://stackoverflow.com/questions/23644473/how-can-i-split-a-ca-certificate-bundle-into-separate-files