LoginSignup
5
3

More than 3 years have passed since last update.

SPIRE の Node/Workload Attestation を AWS 上で体感する

Last updated at Posted at 2019-04-23

はじめに

今回は、Amazon EC2 インスタンスに SPIRE Server を構築した後に、SPIRE Agent を起動した別インスタンスから Node Attestation を行い、最後にそのインスタンス上で Workload(UNIX系OSで動作するプロセスを例として使います)を起動して Workload Attesttion を行うまでの一連の流れを説明していきたいと思います。SPIRE は 2019年4月23日現在の最新バージョン である 0.7.3 を利用します。

注意事項ですが、当記事では SPIFFE/SPIRE に関する詳細な説明は割愛します。SPIFFE/SPIRE が初めての方は、当記事をご覧頂く前に以下の記事に目を通して頂くと理解が進むかと思います。

上記に加えて、2019-05-14 (火) SPIFFFE Meetup Tokyo #1 で発表された内容も SPIFFE/SPIRE の理解を深めるのに非常に有用なので参考までにどうぞ。

環境構築

まず初めに環境構築を行います。

EC2インスタンスの起動と IAM User の作成

EC2インスタンスの起動

Ubuntu 16.04 のインスタンスを2台起動します。VPC、プライベートIP、リージョン、インスタンスタイプ、セキュリティグループなど、細かな設定は自由に設定して下さい。また、インスタンスを起動した後に ping などで、各インスタンス同士で通信が行えることを確認しておいてください。

ホスト名 プライベートIP タグ 起動させるもの
spire-server 172.31.17.242 name:spire-server SPIRE Server
spire-agent 172.31.17.235 name:spire-agent SPIRE Agent

ここからの説明では、各インスタンスを指す際に「 spire-server ホストで ○○ を XX します」のようにホスト名を使います。説明しやすいようにホスト名をカスタムしておりますが、デフォルトの ip-xxx-xxx-xxx-xxx のままでも問題はありません。

IAM User の作成

SPIRE Server の Node Attester Plugin "aws_iid" と Node Resolver Plugin "aws_iid" の設定を行う際に、各 Plugin が AWS に接続してインスタンス情報を取得するために Access Keys が必要となるので、各 Plugin のドキュメントに記載されている必要なポリシーを満たす IAM User の作成を行います。

Node Attester Plugin "aws_iid" に設定する IAM User のポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "ec2:DescribeInstances",
            "Resource": "*"
        }
    ]
}

Node Resolver Plugin "aws_iid" に設定する IAM User のポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "iam:GetInstanceProfile"
            ],
            "Resource": "*"
        }
    ]
}

上記のポリシーを持つ IAM User の作成時に表示される Access Keys は、設定時に使うのでメモしておいてください。

SPIRE Server の構築

spire-server コマンドのインストール

spire-server ホストに ubuntu ユーザーで接続してください。

ssh -i /path/to/key ubuntu@spire-server

SPIRE の Release をダウンロードして、中身を /opt/spire に展開します。
2019年4月23日現在の最新バージョン である 0.7.3 を利用

wget https://github.com/spiffe/spire/releases/download/0.7.3/spire-0.7.3-linux-x86_64-glibc.tar.gz
tar xf spire-0.7.3-linux-x86_64-glibc.tar.gz
sudo cp -r spire-0.7.3/. /opt/spire

spire-server コマンドが使えるように /usr/local/bin 直下に symlink を作成します。

sudo ln -s /opt/spire/spire-server /usr/local/bin/spire-server

spire-server コマンドが使えることを確認できたら OK です。

ubuntu@spire-server:~$ spire-server --version
0.7.3

sqlite3 コマンドのインストール

SPIRE Server の起動には不要ですが、説明の中で SQLite の中身を参照するのでインストールを行います。

apt-getsqlite3 をインストールします。

sudo apt-get update
sudo apt-get install -y sqlite3

sqlite3 コマンドが使えることを確認できたら OK です。

ubuntu@spire-server:~$ sqlite3 --version
3.11.0 2016-02-15 17:29:24 3d862f207e3adc00f78066799ac5a8c282430a5f

SPIRE Server で利用する Plugins の選定

Plugin Type 利用するもの 備考
DataStore sql データベースには sqllite3 を設定
NodeAttestor aws_iid AWS Instance Identity document を使って Node の正当性を証明する
NodeResolver aws_iid AWS Instance Identity document を使って Node の正当性を証明する
KeyManager disk memory だと確認が大変なので disk に書くように設定
UpstreamCA disk SPIRE Server 自体を RootCA とする設定

設定ファイルの準備

/opt/spire/conf/server/server.conf の内容を以下に変更します。

  • trust domain はデフォルトの example.org を利用
  • access_key_idsecret_access_key を IAM User 作成時にメモしたものに変更すること
  • UpstreamCA Plugin で利用する CAキー と CA証明書 は SPIRE の Release に含まれているものを使用

※ SPIRE Server の設定の詳細は こちら を参照下さい

server {
    bind_address = "0.0.0.0"
    bind_port = "8081"
    registration_uds_path = "/var/run/spire/spire-registration.sock"
    trust_domain = "example.org"
    data_dir = "/opt/spire/data"
    log_level = "DEBUG"
    upstream_bundle = true
    svid_ttl = "1h"
    ca_subject = {
        Country = ["US"],
        Organization = ["SPIFFE"],
        CommonName = "",
    }
}

plugins {
    DataStore "sql" {
        plugin_data {
            database_type = "sqlite3"
            connection_string = "/opt/spire/data/sqlite/datastore.sqlite3"
        }
    }

    NodeAttestor "aws_iid" {
        plugin_data {
            access_key_id = "xxx"
            secret_access_key = "xxx"
        }
    }

    NodeResolver "aws_iid" {
        plugin_data {
            access_key_id = "xxx"
            secret_access_key = "xxx"
        }
    }

    KeyManager "disk" {
        plugin_data = {
            keys_path = "/opt/spire/data/keys"
        }
    }

    UpstreamCA "disk" {
        plugin_data {
            ttl = "1h"
            key_file_path = "/opt/spire/conf/server/dummy_upstream_ca.key"
            cert_file_path = "/opt/spire/conf/server/dummy_upstream_ca.crt"
        }
    }
}

SPIRE Server の起動

起動に必要なディレクトリを作成します。

sudo mkdir -p /opt/spire/data/sqlite
sudo mkdir -p /var/run/spire

ログは標準出力に吐くようにして、フォアグラウンドでプロセスを起動します。

sudo spire-server run -config /opt/spire/conf/server/server.conf

起動時のログから、各 Plugin の初期化が行われていることがわかります。

ubuntu@spire-server:~$ sudo spire-server run -config /opt/spire/conf/server/server.conf
WARN[0000] Current umask 0022 is too permissive; setting umask 0027.
INFO[0000] data directory: "/opt/spire/data"
INFO[0000] Starting plugin catalog                       subsystem_name=catalog
DEBU[0000] UpstreamCA(disk): configuring plugin          subsystem_name=catalog
DEBU[0000] DataStore(sql): configuring plugin            subsystem_name=catalog
INFO[0000] initializing database.
DEBU[0000] NodeAttestor(aws_iid): configuring plugin     subsystem_name=catalog
DEBU[0000] NodeResolver(aws_iid): configuring plugin     subsystem_name=catalog
DEBU[0000] KeyManager(disk): configuring plugin          subsystem_name=catalog
INFO[0000] plugins started
DEBU[0000] Keypair set "A" does not exist                subsystem_name=ca_manager
DEBU[0000] Keypair set "B" does not exist                subsystem_name=ca_manager
DEBU[0000] Loaded keypair sets                           subsystem_name=ca_manager
DEBU[0000] Preparing keypair set "A"                     subsystem_name=ca_manager
DEBU[0000] Keypair set "A" will expire 2019-04-22T15:06:07Z  subsystem_name=ca_manager
DEBU[0000] Activating keypair set "A"                    subsystem_name=ca_manager
DEBU[0000] Rotating server SVID                          subsystem_name=svid_rotator
DEBU[0000] Signed x509 SVID "spiffe://example.org/spire/server" (expires 2019-04-22T15:06:07Z)  subsystem_name=ca_manager
DEBU[0000] Initializing API endpoints                    subsystem_name=endpoints
INFO[0000] Starting TCP server on [::]:8081              subsystem_name=endpoints
INFO[0000] Starting UDS server /var/run/spire/spire-registration.sock  subsystem_name=endpoints

Registration API が UNIXドメインソケット で LISTEN を開始したことが確認できます。

ubuntu@spire-server:~$ ls -l /var/run/spire/spire-registration.sock
srwxrwx--- 1 root root 0 Apr 22 14:06 /var/run/spire/spire-registration.sock

データディレクトリには、以下のファイルが作成されます。

ubuntu@spire-server:~$ sudo ls -lR /opt/spire/data
/opt/spire/data:
total 12
-rw-r----- 1 root root 1557 Apr 22 14:06 certs.json
-rw-r----- 1 root root  489 Apr 22 14:06 keys
drwxr-xr-x 2 root root 4096 Apr 22 14:06 sqlite

/opt/spire/data/sqlite:
total 120
-rw-r----- 1 root root  4096 Apr 22 14:06 datastore.sqlite3
-rw-r----- 1 root root 32768 Apr 22 14:06 datastore.sqlite3-shm
-rw-r----- 1 root root 82432 Apr 22 14:06 datastore.sqlite3-wal

certs.jsonkeys の中身は以下のようになります。

ubuntu@spire-server:~$ sudo cat /opt/spire/data/certs.json
{
    "certs": null,
    "cas": {
        "x509-CA-A": "MIIB7jCCAXSgAwIBAgIBATAKBggqhkjOPQQDAzAeMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGU1BJRkZFMB4XDTE5MDQyMjE0MDU1N1oXDTE5MDQyMjE1MDYwN1owHjELMAkGA1UEBhMCVVMxDzANBgNVBAoTBlNQSUZGRTB2MBAGByqGSM49AgEGBSuBBAAiA2IABPrt35IAbZBcifsvJMBbBa+A6hh2zL8nw/J9xLHGwN1WU21S0Py40/IqCEgPo0KB6qYmpgT5aVvDUe094hb6qLn237siKt+xpJ0dClSQhEd2YbeEKmciBqmreN9Bl2JsxaOBhTCBgjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUJhfWNfaOhZEa+QgvdrMfeaLkAcQwHwYDVR0jBBgwFoAUh6XzV6LwNazA+GTEVOdu07o5yOgwHwYDVR0RBBgwFoYUc3BpZmZlOi8vZXhhbXBsZS5vcmcwCgYIKoZIzj0EAwMDaAAwZQIxAMyei6J1bkDP4b0/QDu0jmUG/CCM48lwokpx/b0C6xaHJkRHLyx9x56pD+AP0hwIPAIwJVGLn8bwGiyT5oLpRYcQbPiXnFnJ5RdLXk22UBy8CbeMt/QbPGk6OpuJOYBd4dDMMIIBzDCCAVOgAwIBAgIJAJM4DhRH0vmuMAoGCCqGSM49BAMEMB4xCzAJBgNVBAYTAlVTMQ8wDQYDVQQKDAZTUElGRkUwHhcNMTgwNTEzMTkzMzQ3WhcNMjMwNTEyMTkzMzQ3WjAeMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGU1BJRkZFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEWjB+nSGSxIYiznb84xu5WGDZj80nL7W1c3zf48Why0ma7Y7mCBKzfQkrgDguI4j0Z+0/tDH/r8gtOtLLrIpuMwWHoe4vbVBFte1vj6Xt6WeE8lXwcCvLs/mcmvPqVK9jo10wWzAdBgNVHQ4EFgQUh6XzV6LwNazA+GTEVOdu07o5yOgwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwGQYDVR0RBBIwEIYOc3BpZmZlOi8vbG9jYWwwCgYIKoZIzj0EAwQDZwAwZAIwE4Me13qMC9i6Fkx0h26y09QZIbuRqA9puLg9AeeAAyo5tBzRl1YL0KNEp02VKSYJAjBdeJvqjJ9wW55OGj1JQwDFD7kWeEB6oMlwPbI/5hEY3azJi16I0uN1JSYTSWGSqWc="
    },
    "public_keys": {
        "JWT-Signer-A": "ClswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARSUivCC3pPTrL2mRvosRyk625n7rosimxy96x/MRVtzjIN8OerLfl4cth3nE2ZzbH7KWpXTz4gaRdDePrySumOEiBiN3pwRU5wTXdKZHNVSmREZVI2c2tBckk2WUpvUDdMaBjfsPflBQ=="
    }
}

ubuntu@spire-server:~$ sudo cat /opt/spire/data/keys
{
    "keys": {
        "JWT-Signer-A": "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgrZgf1H6EZs6WxlcJ35TDENBAzYo0mOgA9mflyDbdGZOhRANCAARSUivCC3pPTrL2mRvosRyk625n7rosimxy96x/MRVtzjIN8OerLfl4cth3nE2ZzbH7KWpXTz4gaRdDePrySumO",
        "x509-CA-A": "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBeZ59Jo0Z6a9J8akxi8RswjF2YdQr2dslmhb4ceYw7pf6tJ0d65JKaEabyZmiGpwehZANiAAT67d+SAG2QXIn7LyTAWwWvgOoYdsy/J8PyfcSxxsDdVlNtUtD8uNPyKghID6NCgeqmJqYE+Wlbw1HtPeIW+qi59t+7IirfsaSdHQpUkIRHdmG3hCpnIgapq3jfQZdibMU="
    }
}

SQLite の中身を覗いてみると、以下のテーブルが作成されていることがわかります。

  • attested_node_entries
  • migrations
  • bundles
  • node_resolver_map_entries
  • federated_registration_entries
  • registered_entries
  • join_tokens
  • selectors
ubuntu@spire-server:~$ sudo sqlite3 /opt/spire/data/sqlite/datastore.sqlite3
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite> .tables
attested_node_entries           migrations
bundles                         node_resolver_map_entries
federated_registration_entries  registered_entries
join_tokens                     selectors

各テーブルのレコードを確認すると、この時点では migrationsbundles 以外はレコードなしの状態です。

ubuntu@spire-server:~$ sudo sqlite3 /opt/spire/data/sqlite/datastore.sqlite3
# カラムを表示するためのおまじない
sqlite> .headers on

# attested_node_entries
sqlite> select * from attested_node_entries;

# migrations
sqlite> select * from migrations;
id|created_at|updated_at|version
1|2019-04-22 14:06:07.30985429+00:00|2019-04-22 14:06:07.30985429+00:00|5

# bundles
sqlite> select * from bundles;
id|created_at|updated_at|trust_domain|data
1|2019-04-22 14:06:07.363437704+00:00|2019-04-22 14:06:07.363437704+00:00|spiffe://example.org|
spiffe://example.org�
�0��0�t�0
*�H�=01
U      0    UUS10

190422150607Z01
U              0    UUS10
SPIFFE0v0*�H�=+�

# node_resolver_map_entries
sqlite> select * from node_resolver_map_entries;

# federated_registration_entries
sqlite> select * from federated_registration_entries;

# registered_entries
sqlite> select * from registered_entries;

# join_tokens
sqlite> select * from join_tokens;

# selectors
sqlite> select * from selectors;

各テーブルのカラムは、以下から確認できますので興味ある方はどうぞ。
https://github.com/spiffe/spire/blob/0.7.3/pkg/server/plugin/datastore/sql/models.go

registered_entries が空なので、もちろんエントリーも空の状態となります。

ubuntu@spire-server:~$ sudo spire-server entry show -registrationUDSPath /var/run/spire/spire-registration.sock
Found 0 entries

専用のコマンドから Bundle が作成されたことも確認できます。
処理を詳しくは追えてませんが、実体は bundles の文字化けしていたレコードなのかなと思っています。

ubuntu@spire-server:~$ sudo spire-server bundle show -registrationUDSPath /var/run/spire/spire-registration.sock
-----BEGIN CERTIFICATE-----
MIIB7jCCAXSgAwIBAgIBATAKBggqhkjOPQQDAzAeMQswCQYDVQQGEwJVUzEPMA0G
A1UECgwGU1BJRkZFMB4XDTE5MDQyMjE0MDU1N1oXDTE5MDQyMjE1MDYwN1owHjEL
MAkGA1UEBhMCVVMxDzANBgNVBAoTBlNQSUZGRTB2MBAGByqGSM49AgEGBSuBBAAi
A2IABPrt35IAbZBcifsvJMBbBa+A6hh2zL8nw/J9xLHGwN1WU21S0Py40/IqCEgP
o0KB6qYmpgT5aVvDUe094hb6qLn237siKt+xpJ0dClSQhEd2YbeEKmciBqmreN9B
l2JsxaOBhTCBgjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
HQ4EFgQUJhfWNfaOhZEa+QgvdrMfeaLkAcQwHwYDVR0jBBgwFoAUh6XzV6LwNazA
+GTEVOdu07o5yOgwHwYDVR0RBBgwFoYUc3BpZmZlOi8vZXhhbXBsZS5vcmcwCgYI
KoZIzj0EAwMDaAAwZQIxAMyei6J1bkDP4b0/QDu0jmUG/CCM48lwokpx/b0C6xaH
JkRHLyx9x56pD+AP0hwIPAIwJVGLn8bwGiyT5oLpRYcQbPiXnFnJ5RdLXk22UBy8
CbeMt/QbPGk6OpuJOYBd4dDM
-----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-----

証明書の中身はこのようになっております。

# 上記の結果を cert ファイルに書き込んだあとに実行
ubuntu@spire-server:~$ openssl x509 -text -noout -in cert
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
    Signature Algorithm: ecdsa-with-SHA384
        Issuer: C=US, O=SPIFFE
        Validity
            Not Before: Apr 22 14:05:57 2019 GMT
            Not After : Apr 22 15:06:07 2019 GMT
        Subject: C=US, O=SPIFFE
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:fa:ed:df:92:00:6d:90:5c:89:fb:2f:24:c0:5b:
                    05:af:80:ea:18:76:cc:bf:27:c3:f2:7d:c4:b1:c6:
                    c0:dd:56:53:6d:52:d0:fc:b8:d3:f2:2a:08:48:0f:
                    a3:42:81:ea:a6:26:a6:04:f9:69:5b:c3:51:ed:3d:
                    e2:16:fa:a8:b9:f6:df:bb:22:2a:df:b1:a4:9d:1d:
                    0a:54:90:84:47:76:61:b7:84:2a:67:22:06:a9:ab:
                    78:df:41:97:62:6c:c5
                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:
                26:17:D6:35:F6:8E:85:91:1A:F9:08:2F:76:B3:1F:79:A2:E4:01:C4
            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:65:02:31:00:cc:9e:8b:a2:75:6e:40:cf:e1:bd:3f:40:3b:
         b4:8e:65:06:fc:20:8c:e3:c9:70:a2:4a:71:fd:bd:02:eb:16:
         87:26:44:47:2f:2c:7d:c7:9e:a9:0f:e0:0f:d2:1c:08:3c:02:
         30:25:51:8b:9f:c6:f0:1a:2c:93:e6:82:e9:45:87:10:6c:f8:
         97:9c:59:c9:e5:17:4b:5e:4d:b6:50:1c:bc:09:b7:8c:b7:f4:
         1b:3c:69:3a:3a:9b:89:39:80:5d:e1:d0:cc

以上で、SPIRE Server の構築は完了です。

SPIRE Agent を起動するための前準備

spire-agent コマンドのインストール

spire-agent ホストに ubuntu ユーザーで接続してください。

ssh -i /path/to/key ubuntu@spire-agent

SPIRE の Release をダウンロードして、中身を /opt/spire に展開します。
2019年4月23日現在の最新バージョン である 0.7.3 を利用

wget https://github.com/spiffe/spire/releases/download/0.7.3/spire-0.7.3-linux-x86_64-glibc.tar.gz
tar xf spire-0.7.3-linux-x86_64-glibc.tar.gz
sudo cp -r spire-0.7.3/. /opt/spire

spire-agent コマンドが使えるように /usr/local/bin 直下に symlink を作成します。

sudo ln -s /opt/spire/spire-agent /usr/local/bin/spire-agent

spire-agent コマンドが使えることを確認できたら OK です。

ubuntu@spire-agent:~$ spire-agent --version
0.7.3

SPIRE Agent が使う設定ファイルの準備

SPIRE Agent で利用する Plugins の選定

Plugin Type 利用するもの 備考
NodeAttestor aws_iid AWS Instance Identity document を使って Node の正当性を証明する
KeyManager disk memory だと確認が大変なので disk に書くように設定
Workload unix UNIXプロセスの情報から Selector を生成する

設定ファイルの準備

/opt/spire/conf/agent/agent.conf の内容を以下に変更します。

  • trust domain はデフォルトの example.org を利用
  • NodeAttestor Plugin "aws_iid" で使う設定値はデフォルト値を明示的に宣言
  • trust_bundle_path で利用する CA証明書 は SPIRE の Release に含まれているものを使用

※ SPIRE Agent の設定の詳細は こちら を参照下さい。

agent {
    data_dir = "/opt/spire/data"
    log_level = "DEBUG"
    server_address = "172.31.17.242"
    server_port = "8081"
    socket_path ="/var/run/spire/agent.sock"
    trust_bundle_path = "/opt/spire/conf/agent/dummy_root_ca.crt"
    trust_domain = "example.org"
}

plugins {
    NodeAttestor "aws_iid" {
        plugin_data {
            identity_document_url = "http://169.254.169.254/latest/dynamic/instance-identity/document"
            identity_signature_url = "http://169.254.169.254/latest/dynamic/instance-identity/signature"
        }
    }
    KeyManager "disk" {
        plugin_data = {
            keys_path = "/opt/spire/data/keys"
        }
    }
    WorkloadAttestor "unix" {
        plugin_data {}
    }
}

起動に必要なディレクトリを作成

sudo mkdir -p /var/run/spire

以上で、SPIRE Agent を起動するための前準備は完了です。
※ Node Attestation を体感するときに SPIRE Agent を起動するのでここまでの対応で OK

Workload Attestation の前準備

Workload Attestation に使う unix ユーザーを作成

今回は、Workload としてUNIX系OSで動作するプロセスを使うので、そのために必要な uid 10000 の valid-workload ユーザーと uid 20000 の invalid-workload ユーザーを作成します。

sudo useradd -u 10000 valid-workload
sudo useradd -u 20000 invalid-workload

各ユーザーが作成されていることが確認できたら OK です。

ubuntu@spire-agent:~$ id -u valid-workload
10000
ubuntu@spire-agent:~$ id -u invalid-workload
20000

以上で、環境構築は完了です。

Node Attestation を体感する

まずは SPIRE ドメインに参加するための Node 認証の仕組みである Node Attestation を体感していきます。

SPIRE Agent を起動して Node Attestation を行う

spire-agent ホストに ubuntu ユーザーで接続してください。

ssh -i /path/to/key ubuntu@spire-agent

ログは標準出力に吐くようにして、フォアグラウンドでプロセスを起動します。

sudo spire-agent run -config /opt/spire/conf/agent/agent.conf

ログの DEBU[0000] No pre-existing agent SVID found. Will perform node attestation subsystem_name=attestor から Node Attestation が実行されたことがわかります。そして、Node Attestation に成功したことで SPIRE Agent が起動しています。

ubuntu@spire-agent:~$ sudo spire-agent run -config /opt/spire/conf/agent/agent.conf
WARN[0000] Current umask 0022 is too permissive; setting umask 0027.
INFO[0000] data directory: "/opt/spire/data"
INFO[0000] Starting plugin catalog                       subsystem_name=catalog
DEBU[0000] NodeAttestor(aws_iid): configuring plugin     subsystem_name=catalog
DEBU[0000] KeyManager(disk): configuring plugin          subsystem_name=catalog
DEBU[0000] WorkloadAttestor(unix): configuring plugin    subsystem_name=catalog
DEBU[0000] No pre-existing agent SVID found. Will perform node attestation  subsystem_name=attestor
INFO[0000] Starting workload API                         subsystem_name=endpoints

突然 Node Attestation が成功したと言われても納得できないと思いますが、この後で SPIRE Server 側のログを確認しながら説明しますので、この時点ではなにげない理解で大丈夫です。

データディレクトリには、以下のファイルが作成されます。

ubuntu@spire-agent:~$ sudo ls -l /opt/spire/data
total 8
-rw------- 1 root root 1061 Apr 22 14:10 agent_svid.der
-rw------- 1 root root  962 Apr 22 14:10 bundle.der

spire-agent ホストに紐づく SPIFFE ID の値を確認するために、spire-agent ホストの Account ID、Region、Instance ID を確認します。

ubuntu@spire-agent:~$ curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | egrep 'accountId|instanceId|region'
  "accountId" : "XXXXXXXXXXXX",
  "instanceId" : "i-00fc2dca2309d04d7",
  "region" : "ap-northeast-1"

http://169.254.169.254/latest/dynamic/instance-identity/documentインスタンスメタデータを取得するための URL
※ Account ID は意図的に伏せています

Account ID、Region、Instance ID は以下となりました。

プロパティ
Account ID XXXXXXXXXXXX
Region ap-northeast-1
Instance ID i-00fc2dca2309d04d7

SPIRE Server の Node Attester Plugin "aws_iid" では、 spiffe://example.org/spire/agent/aws_iid/ACCOUNT_ID/REGION/INSTANCE_ID というルールで SPIFFE ID が登録される仕様のため、想定通りいけば spire-agent ホストに紐づく SPIFFE ID は spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7 となります。

SPIRE Server のログを確認してみる

SPIRE Server 側のログを確認してみます。

ubuntu@spire-server:~$ sudo spire-server run -config /opt/spire/conf/server/server.conf
...
DEBU[0252] Signing CSR for Agent SVID spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7  subsystem_name=node_api
DEBU[0252] Signed x509 SVID "spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7" (expires 2019-04-22T15:06:07Z)  subsystem_name=ca_manager
INFO[0252] Node attestation request from 172.31.17.235:33086 completed using strategy aws_iid  subsystem_name=node_api

以下のログから、想定通り spire-agent ホストに紐づく SPIFFE ID spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7 が登録されたことがわかります。

DEBU[0252] Signing CSR for Agent SVID spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7  subsystem_name=node_api
DEBU[0252] Signed x509 SVID "spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7" (expires 2019-04-22T15:06:07Z)  subsystem_name=ca_manager

また、以下のログから spire-agent ホストからの Node Attestation が完了したことがわかります。

INFO[0252] Node attestation request from 172.31.17.235:33086 completed using strategy aws_iid  subsystem_name=node_api

SQLite の中身を確認してみる

Node Attestation 前後で変化があったテーブルは attested_node_entriesnode_resolver_map_entries となります。

ubuntu@spire-server:~$ sudo sqlite3 /opt/spire/data/sqlite/datastore.sqlite3
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
# カラムを表示するためのおまじない
sqlite> .headers on

# attested_node_entries
sqlite> select * from attested_node_entries;
id|created_at|updated_at|spiffe_id|data_type|serial_number|expires_at
1|2019-04-22 14:10:19.469466093+00:00|2019-04-22 14:10:19.469466093+00:00|spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7|aws_iid|2|2019-04-22 15:06:07+00:00

# node_resolver_map_entries
sqlite> select * from node_resolver_map_entries;
id|created_at|updated_at|spiffe_id|type|value
1|2019-04-22 14:10:19.468130215+00:00|2019-04-22 14:10:19.468130215+00:00|spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7|aws_iid|sg:id:sg-012874274efb978c7
2|2019-04-22 14:10:19.46821413+00:00|2019-04-22 14:10:19.46821413+00:00|spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7|aws_iid|sg:name:Ubuntu 16-04 LTS - Xenial -HVM--Ubuntu 16-04 LTS 20190212-AutogenByAWSMP-1
3|2019-04-22 14:10:19.468289052+00:00|2019-04-22 14:10:19.468289052+00:00|spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7|aws_iid|tag:name:spire-agent

各テーブルのレコードを詳しく見ていきましょう。

attested_node_entries

SPIRE Server のログにも出力されていたとおり Node Attestation に成功したホストの情報が書き込まれています。

id spiffe_id data_type serial_number expires_at
1 spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7 aws_iid 2 2019-04-22 15:06:07+00:00

※ 表が見づらくなるので timestamp 系のカラムは除いてます

node_resolver_map_entries

SPIRE Server の Node Resolver Plugin "aws_iid" では、以下4つの Selector が生成される仕様となっております。

  • Instance Tag
  • Security Group ID
  • Security Group Name
  • IAM Role

自分の環境だと IAM Role を設定していなかったので、3つの Selector が生成されました。
上から Security Group ID、Security Group Name、Instance Tag となります。

id spiffe_id type value
1 spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7 aws_iid sg:id:sg-012874274efb978c7
2 spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7 aws_iid sg:name:Ubuntu 16-04 LTS - Xenial -HVM--Ubuntu 16-04 LTS 20190212-AutogenByAWSMP-1
3 spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7 aws_iid tag:name:spire-agent

※ 表が見づらくなるので timestamp 系のカラムは除いてます

以上が、Node Attestation となります。

Workload Attestation を体感する

次に、任意の Workload から SVID を取得するための認証の仕組みである Workload Attestation を体感していきます。

SPIRE Server に Entry を登録する

spire-server ホストに ubuntu ユーザーで接続してください。

ssh -i /path/to/key ubuntu@spire-server

spire-agent ホスト上で uid 10000 の valid-workload ユーザーから実行されるUNIXプロセスを認証を許可する Workload として Entry に登録します。ParentID には Node Attestation の際に登録された spire-agent ホストの SPIFFEE ID を設定し、SPIFFE ID には Workload に紐付ける任意の SPIFFE ID を設定し、Selector には uid 10000 から実行されるプロセスが対象となるように値(Workload Attester Plugin "unix" の詳細は こちら)を設定します。

sudo spire-server entry create \
    -registrationUDSPath /var/run/spire/spire-registration.sock \
    -parentID spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7 \
    -spiffeID spiffe://example.org/host/valid-workload \
    -selector unix:uid:10000

以下のような実行結果となります。

ubuntu@spire-server:~$ sudo spire-server entry create \
>     -registrationUDSPath /var/run/spire/spire-registration.sock \
>     -parentID spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7 \
>     -spiffeID spiffe://example.org/host/valid-workload \
>     -selector unix:uid:10000
Entry ID      : 9d0d2673-bf2b-42d3-9235-2090e9050fb4
SPIFFE ID     : spiffe://example.org/host/valid-workload
Parent ID     : spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7
TTL           : 3600
Selector      : unix:uid:10000

SPIRE Server のログにも Entry が登録され、SVID が発行されたログが出力されます。

ubuntu@spire-server:~$ sudo spire-server run -config /opt/spire/conf/server/server.conf
...
DEBU[3107] Signing SVID for spiffe://example.org/host/valid-workload on request by spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7  subsystem_name=node_api
DEBU[3107] Signed x509 SVID "spiffe://example.org/host/valid-workload" (expires 2019-04-22T15:36:07Z)  subsystem_name=ca_manager

専用のコマンドから Entry が追加されたことも確認できました。

ubuntu@spire-server:~$ sudo spire-server entry show -registrationUDSPath /var/run/spire/spire-registration.sock
Found 1 entry
Entry ID      : 9d0d2673-bf2b-42d3-9235-2090e9050fb4
SPIFFE ID     : spiffe://example.org/host/valid-workload
Parent ID     : spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7
TTL           : 3600
Selector      : unix:uid:10000

SQLite の中身を確認してみると registered_entriesselectors にレコードが追加されたことがわかります。

ubuntu@spire-server:~$ sudo sqlite3 /opt/spire/data/sqlite/datastore.sqlite3
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
# カラムを表示するためのおまじない
sqlite> .headers on

# registered_entries
sqlite> select * from registered_entries;
id|created_at|updated_at|entry_id|spiffe_id|parent_id|ttl|admin
1|2019-04-22 14:57:52.177533369+00:00|2019-04-22 14:57:52.177533369+00:00|9d0d2673-bf2b-42d3-9235-2090e9050fb4|spiffe://example.org/host/valid-workload|spiffe://example.org/spire/agent/aws_iid/XXXXXXXXXXXX/ap-northeast-1/i-00fc2dca2309d04d7|3600|0

# selectors
sqlite> select * from selectors;
id|created_at|updated_at|registered_entry_id|type|value
1|2019-04-22 14:57:52.177715825+00:00|2019-04-22 14:57:52.177715825+00:00|1|unix|uid:10000

valid-workload ユーザーでプロセスを実行して Workload Attestation を行う

spire-agent ホストに ubuntu ユーザーで接続してください。

ssh -i /path/to/key ubuntu@spire-agent

SVID を取得する際に Workload Attestation が必須となるので、SVID を取得するためのコマンドを uid 10000 の valid-workload ユーザーで実行してみます。

sudo -u valid-workload spire-agent api fetch x509 -socketPath /var/run/spire/agent.sock

認証が許可された Workload として Entry に追加してあるので、Workload Attestation が成功して SVID の情報を取得することができました。

ubuntu@spire-agent:~$ sudo -u valid-workload spire-agent api fetch x509 -socketPath /var/run/spire/agent.sock
Received 1 bundle after 2.006431ms

SPIFFE ID:      spiffe://example.org/host/valid-workload
SVID Valid After:   2019-04-22 14:57:44 +0000 UTC
SVID Valid Until:   2019-04-22 15:36:07 +0000 UTC
Intermediate #1 Valid After:    2019-04-22 14:35:57 +0000 UTC
Intermediate #1 Valid Until:    2019-04-22 15:36:07 +0000 UTC
CA #1 Valid After:  2019-04-22 14:05:57 +0000 UTC
CA #1 Valid Until:  2019-04-22 15:06:07 +0000 UTC
CA #2 Valid After:  2018-05-13 19:33:47 +0000 UTC
CA #2 Valid Until:  2023-05-12 19:33:47 +0000 UTC
CA #3 Valid After:  2019-04-22 14:35:57 +0000 UTC
CA #3 Valid Until:  2019-04-22 15:36:07 +0000 UTC
CA #4 Valid After:  2019-04-22 15:05:57 +0000 UTC
CA #4 Valid Until:  2019-04-22 16:06:07 +0000 UTC

以下のように -write オプションで、SVID と Bundle をディスクに書き込むことも可能です。

sudo -u valid-workload spire-agent api fetch x509 \
    -socketPath /var/run/spire/agent.sock -write /tmp

以下、例となります。

ubuntu@spire-agent:~$ sudo -u valid-workload spire-agent api fetch x509 \
>     -socketPath /var/run/spire/agent.sock -write /tmp
Received 1 bundle after 1.660049ms

SPIFFE ID:      spiffe://example.org/host/valid-workload
SVID Valid After:   2019-04-22 15:16:49 +0000 UTC
SVID Valid Until:   2019-04-22 15:36:07 +0000 UTC
Intermediate #1 Valid After:    2019-04-22 14:35:57 +0000 UTC
Intermediate #1 Valid Until:    2019-04-22 15:36:07 +0000 UTC
CA #1 Valid After:  2019-04-22 14:05:57 +0000 UTC
CA #1 Valid Until:  2019-04-22 15:06:07 +0000 UTC
CA #2 Valid After:  2018-05-13 19:33:47 +0000 UTC
CA #2 Valid Until:  2023-05-12 19:33:47 +0000 UTC
CA #3 Valid After:  2019-04-22 14:35:57 +0000 UTC
CA #3 Valid Until:  2019-04-22 15:36:07 +0000 UTC
CA #4 Valid After:  2019-04-22 15:05:57 +0000 UTC
CA #4 Valid Until:  2019-04-22 16:06:07 +0000 UTC

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

# SVID と Bundle がディスクに書き込まれた
ubuntu@spire-agent:~$ ll /tmp/svid.0.pem
-rw-r--r-- 1 valid-workload valid-workload 1482 Apr 22 15:17 /tmp/svid.0.pem
ubuntu@spire-agent:~$ ll /tmp/svid.0.key
-rw-r--r-- 1 valid-workload valid-workload 241 Apr 22 15:17 /tmp/svid.0.key
ubuntu@spire-agent:~$ ll /tmp/bundle.0.pem
-rw-r--r-- 1 valid-workload valid-workload 2875 Apr 22 15:17 /tmp/bundle.0.pem

SPIRE Agent のログからは Workload Attestation を行おうとした Workload の Selector 情報が確認できます。この出力された Selector 情報が Entry で追加したものと一致するため、Workload Attestation が成功となったわけです。

ubuntu@spire-agent:~$ sudo spire-agent run -config /opt/spire/conf/agent/agent.conf
...
DEBU[3606] PID 2082 attested to have selectors [type:"unix" value:"uid:10000"  type:"unix" value:"user:valid-workload"  type:"unix" value:"gid:10000"  type:"unix" value:"group:valid-workload" ]  subsystem_name=workload_api

invalid-workload ユーザーでプロセスを実行して Workload Attestation が失敗するか確認する

Workload Attestation が成功するパターンは確認できたので、次は失敗するパターンを試してみます。

Entry に登録されていない uid 20000 の invalid-workload ユーザーで SVID の取得を行おうとすると、Permission Denied なエラー終了となります。

ubuntu@spire-agent:~$ sudo -u invalid-workload spire-agent api fetch x509 -socketPath /var/run/spire/agent.sock
rpc error: code = PermissionDenied desc = no identity issued

SPIRE Agent のログからは Workload Attestation を行おうとした Workload の Selector 情報が確認できます。この出力された Selector 情報が許可された Workload として Entry に存在しないため、Workload Attestation が失敗となりました。

ubuntu@spire-agent:~$ sudo spire-agent run -config /opt/spire/conf/agent/agent.conf
...
DEBU[4228] PID 2137 attested to have selectors [type:"unix" value:"uid:20000"  type:"unix" value:"user:invalid-workload"  type:"unix" value:"gid:20000"  type:"unix" value:"group:invalid-workload" ]  subsystem_name=workload_api

以上が、Workload Attestation となります。

補足

Node Attestation について

今回は AWS 上での Node Attestation となりましたが、インスタンスの正当性を証明するための Node Attester(Server/Agent 両方)があれば、任意のプラットフォームで Node Attestation を行うことが可能です。SPIRE に Built-in されているものだと以下があります。

プラットフォーム Server plugin Agent plugin 備考
Azure azure_msi azure_msi Azure MSI token を使う
GCP gcp_iit gcp_iid GCP Instance Identity Token を使う
Kubernetes k8s_sat k8s_sat Kubernetes Service Account token を使う
どこでも使える join_token join_token SPIRE Server からワンタイムトークンを発行して SPIRE Agent 起動時に渡す
どこでも使える x509pop x509_pop X.509 証明書を使う

また、OSS としても公開されているものもあります。

プラットフォーム Server plugin Agent plugin 備考
OpenStack openstack_iid openstack_iid OpenStack InstanceID を使う

Workload Attestation について

今回は UNIXプロセスを Workload として使いましたが、Workload から任意のルールで Selector を発行できる Workload Attester があれば、任意の Workload で Workload Attestation を行うことが可能です。SPIRE に Built-in されているものだと以下があります。

Workload Plugin 備考
Kubernetes Resource k8s Namespace と Service Account を Selector として発行します
Docker Container docker Label と Image ID を Selector として発行します

さいごに

今回は、AWS を使って SPIRE の Node Attestation と Workload Attestation を体感する流れを紹介しました。各処理を実行しながら、ログを確認したり、どのようなデータが保存されるかを追いかけたりと、冗長な流れとなってしまいましたが、参考程度に活用頂けたらと思います。

Node Attestation、Workload Attestation を経て、最終的に Workload が SVID と Bundle が取得できる(Workload が Node 上にファイルとして書き込むことも可能)ことを理解頂いたと思いますが、その SVID と Bundle を用いたユースケースとして SPIRE の公式ページでは以下が紹介されております。

  • サービス間の安全な認証
  • VaultKnox からのシークレット取得
  • Envoy などのサービスメッシュ内のサイドカープロキシを識別するための基盤としてのIDプロビジョニング
  • 分散システムの認証に使用する PKI のプロビジョニングとローテーション

上記のユースケースも踏まえて、SPIFFE/SPIRE は今後より盛り上がってくる OSS だと思いますので、引き続き情報を追いかけていきたいと思います。

参考資料

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3