Envoy SDS Example with SPIRE
环境说明
Envoy Mesh使用的网络: 172.31.92.0/24
3个Service:
- web-server:ip地址172.31.92.5
- echo-server:ip地址172.31.92.6
- spire-server:ip地址172.31.92.7
生成ca证书
openssl.conf
# environment variable values
CERT_DIR=certs
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = ${ENV::CERT_DIR}
certs = $dir
crl_dir = $dir/crl
new_certs_dir = $dir
database = $dir/index.txt
serial = $dir/serial
# certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate-ca.crl
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose
[ policy_loose ]
# Allow the CA to sign a range of certificates.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# `man req`
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
# Certificate extensions (`man x509v3_config`)
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ client_cert ]
basicConstraints = CA:FALSE
nsCertType = client
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
[ server_cert ]
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
创建证书
创建目录
# mkdir certs/{ca,echo,web}
# touch certs/index.txt
# touch certs/serial
# echo "1000" > certs/serial
# echo "unique_subject = no" > certs/index.txt.attr # Sign multiple certs for the same CN
生成ca证书
# openssl genrsa -out certs/ca/agent-cacert.key.pem 4096
# openssl req -config openssl.conf -new -x509 -days 3650 -sha256 -key certs/ca/agent-cacert.key.pem -extensions v3_ca -out certs/ca/agent-cacert.crt.pem -subj /CN=ca
生成web证书
# openssl genrsa -out certs/web/agent.key.pem 2048
# openssl req -config openssl.conf -new -sha256 -key certs/web/agent.key.pem -out certs/web/agent.csr -subj /CN=web
# openssl ca -batch -config openssl.conf -extensions server_cert -days 3650 -notext -md sha256 -in certs/web/agent.csr -out certs/web/agent.crt.pem -cert certs/ca/agent-cacert.crt.pem -keyfile certs/ca/agent-cacert.key.pem
生成echo证书
# openssl genrsa -out certs/echo/agent.key.pem 2048
# openssl req -config openssl.conf -new -sha256 -key certs/echo/agent.key.pem -out certs/echo/agent.csr -subj /CN=echo
# openssl ca -batch -config openssl.conf -extensions server_cert -days 3650 -notext -md sha256 -in certs/echo/agent.csr -out certs/echo/agent.crt.pem -cert certs/ca/agent-cacert.crt.pem -keyfile certs/ca/agent-cacert.key.pem
spire-server
spire-server.conf
server {
bind_address = "0.0.0.0"
bind_port = "9081"
socket_path = "/tmp/spire-server/private/api.sock"
trust_domain = "wgs.com"
data_dir = "/opt/spire/data/server"
log_level = "DEBUG"
# log_file = "/opt/spire/server.log"
log_file = "/dev/stdout"
default_svid_ttl = "1h"
ca_subject = {
country = ["US"],
organization = ["SPIFFE"],
common_name = "",
}
}
plugins {
DataStore "sql" {
plugin_data {
database_type = "sqlite3"
connection_string = "/opt/spire/data/server/datastore.sqlite3"
}
}
NodeAttestor "x509pop" {
plugin_data {
ca_bundle_path = "/opt/spire/conf/server/agent-cacert.pem"
}
}
KeyManager "disk" {
plugin_data = {
keys_path = "/opt/spire/data/server/keys.json"
}
}
}
Dockerfile
FROM uhub.service.ucloud.cn/xk-base/spire-server:1.4.0
# Override spire configurations
COPY conf/spire-server.conf /opt/spire/conf/server/server.conf
COPY conf/agent-cacert.crt.pem /opt/spire/conf/server/agent-cacert.pem
WORKDIR /opt/spire
web-server
web-server可执行程序源代码参考https://github.com/spiffe/spire-examples/tree/main/examples/envoy
spire-agent.conf
agent {
data_dir = "/opt/spire/data/agent"
log_level = "DEBUG"
# log_file = "/opt/spire/agent.log"
log_file = "/dev/stdout"
server_address = "spire-server"
server_port = "9081"
socket_path ="/tmp/agent.sock"
trust_bundle_path = "/opt/spire/conf/agent/bootstrap.crt"
trust_domain = "wgs.com"
}
plugins {
NodeAttestor "x509pop" {
plugin_data {
private_key_path = "/opt/spire/conf/agent/agent.key.pem"
certificate_path = "/opt/spire/conf/agent/agent.crt.pem"
}
}
KeyManager "disk" {
plugin_data {
directory = "/opt/spire/data/agent"
}
}
WorkloadAttestor "unix" {
plugin_data {
}
}
}
envoy.yaml
node:
id: "id_02"
cluster: "cluster_02"
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: web_to_echo_mtls_listener
address:
socket_address:
address: 127.0.0.1
port_value: 8001
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
common_http_protocol_options:
idle_timeout: 1s
codec_type: auto
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: "/dev/stdout"
stat_prefix: ingress_http
route_config:
name: service_route
virtual_hosts:
- name: web_to_echo_mtls
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: web_to_echo_mtls
http_filters:
- name: envoy.filters.http.router
- name: web_to_echo_tls_listener
address:
socket_address:
address: 127.0.0.1
port_value: 8002
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
common_http_protocol_options:
idle_timeout: 1s
codec_type: auto
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: "/dev/stdout"
stat_prefix: ingress_http
route_config:
name: service_route
virtual_hosts:
- name: web_to_echo_tls
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: web_to_echo_tls
http_filters:
- name: envoy.filters.http.router
clusters:
- name: spire_agent
connect_timeout: 0.25s
http2_protocol_options: {}
load_assignment:
cluster_name: spire_agent
endpoints:
- lb_endpoints:
- endpoint:
address:
pipe:
path: /tmp/agent.sock
- name: web_to_echo_mtls
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: web_to_echo_mtls
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: echo
port_value: 8001
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
tls_certificate_sds_secret_configs:
- name: "spiffe://wgs.com/web-server"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: spire_agent
transport_api_version: V3
resource_api_version: V3
combined_validation_context:
# validate the SPIFFE ID of the server (recommended)
default_validation_context:
match_subject_alt_names:
exact: "spiffe://wgs.com/echo-server"
validation_context_sds_secret_config:
name: "spiffe://wgs.com"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: spire_agent
transport_api_version: V3
resource_api_version: V3
tls_params:
ecdh_curves:
- X25519:P-256:P-521:P-384
- name: web_to_echo_tls
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: web_to_echo_tls
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: echo
port_value: 8002
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
combined_validation_context:
# validate the SPIFFE ID of the server (recommended)
default_validation_context:
match_subject_alt_names:
exact: "spiffe://wgs.com/echo-server"
validation_context_sds_secret_config:
name: "spiffe://wgs.com"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: spire_agent
transport_api_version: V3
resource_api_version: V3
tls_params:
ecdh_curves:
- X25519:P-256:P-521:P-384
Dockerfile
FROM uhub.service.ucloud.cn/xk-base/spire-agent:1.4.0 as spire
FROM envoyproxy/envoy-alpine:v1.20.0
RUN mkdir -p /opt/spire/conf/agent
RUN mkdir -p /opt/spire/data/agent
COPY --from=spire /opt/spire/bin/spire-agent /opt/spire/bin/spire-agent
COPY conf/envoy.yaml /etc/envoy/envoy.yaml
COPY conf/spire-agent.conf /opt/spire/conf/agent/agent.conf
COPY conf/agent.key.pem /opt/spire/conf/agent/agent.key.pem
COPY conf/agent.crt.pem /opt/spire/conf/agent/agent.crt.pem
COPY web-server /usr/local/bin/web-server
WORKDIR /opt/spire
CMD /usr/local/bin/envoy -l debug -c /etc/envoy/envoy.yaml --log-path /tmp/envoy.log
echo-server
echo-server可执行程序源代码参考https://github.com/spiffe/spire-examples/tree/main/examples/envoy
spire-agent.conf
agent {
data_dir = "/opt/spire/data/agent"
log_level = "DEBUG"
# log_file = "/opt/spire/agent.log"
log_file = "/dev/stdout"
server_address = "spire-server"
server_port = "9081"
socket_path ="/tmp/agent.sock"
trust_bundle_path = "/opt/spire/conf/agent/bootstrap.crt"
trust_domain = "wgs.com"
}
plugins {
NodeAttestor "x509pop" {
plugin_data {
private_key_path = "/opt/spire/conf/agent/agent.key.pem"
certificate_path = "/opt/spire/conf/agent/agent.crt.pem"
}
}
KeyManager "disk" {
plugin_data {
directory = "/opt/spire/data/agent"
}
}
WorkloadAttestor "unix" {
plugin_data {
}
}
}
envoy.yaml
node:
id: "id_01"
cluster: "cluster_01"
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: listener-sds-mtls
address:
socket_address:
address: 0.0.0.0
port_value: 8001
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
common_http_protocol_options:
idle_timeout: 1s
forward_client_cert_details: sanitize_set
set_current_client_cert_details:
uri: true
codec_type: auto
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: "/dev/stdout"
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: echo_server
http_filters:
- name: envoy.filters.http.router
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificate_sds_secret_configs:
- name: "spiffe://wgs.com/echo-server"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: spire_agent
transport_api_version: V3
resource_api_version: V3
combined_validation_context:
# validate the SPIFFE ID of incoming clients (optionally)
default_validation_context:
match_subject_alt_names:
exact: "spiffe://wgs.com/web-server"
# obtain the trust bundle from SDS
validation_context_sds_secret_config:
name: "spiffe://wgs.com"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: spire_agent
transport_api_version: V3
resource_api_version: V3
tls_params:
ecdh_curves:
- X25519:P-256:P-521:P-384
- name: listener-sds-tls
address:
socket_address:
address: 0.0.0.0
port_value: 8002
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
common_http_protocol_options:
idle_timeout: 1s
forward_client_cert_details: sanitize_set
set_current_client_cert_details:
uri: true
codec_type: auto
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: "/dev/stdout"
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: echo_server
http_filters:
- name: envoy.filters.http.router
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificate_sds_secret_configs:
- name: "spiffe://wgs.com/echo-server"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
envoy_grpc:
cluster_name: spire_agent
transport_api_version: V3
resource_api_version: V3
tls_params:
ecdh_curves:
- X25519:P-256:P-521:P-384
clusters:
- name: spire_agent
connect_timeout: 0.25s
http2_protocol_options: {}
load_assignment:
cluster_name: spire_agent
endpoints:
- lb_endpoints:
- endpoint:
address:
pipe:
path: /tmp/agent.sock
- name: echo_server
connect_timeout: 0.25s
type: strict_dns
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: echo_server
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8081
Dockerfile
FROM uhub.service.ucloud.cn/xk-base/spire-agent:1.4.0 as spire
FROM envoyproxy/envoy-alpine:v1.20.0
RUN mkdir -p /opt/spire/conf/agent
RUN mkdir -p /opt/spire/data/agent
COPY --from=spire /opt/spire/bin/spire-agent /opt/spire/bin/spire-agent
COPY conf/envoy.yaml /etc/envoy/envoy.yaml
COPY conf/spire-agent.conf /opt/spire/conf/agent/agent.conf
COPY conf/agent.key.pem /opt/spire/conf/agent/agent.key.pem
COPY conf/agent.crt.pem /opt/spire/conf/agent/agent.crt.pem
COPY echo-server /usr/local/bin/echo-server
WORKDIR /opt/spire
CMD /usr/local/bin/envoy -l debug -c /etc/envoy/envoy.yaml --log-path /tmp/envoy.log
docker-compose.yml
version: '3.3'
services:
spire-server:
build: ./docker/spire-server
hostname: spire-server
tty: true
privileged: true
networks:
envoymesh:
ipv4_address: 172.31.92.7
echo:
build: ./docker/echo
hostname: echo
tty: true
privileged: true
networks:
envoymesh:
ipv4_address: 172.31.92.6
links:
- spire-server
web:
build: ./docker/web
hostname: web
tty: true
privileged: true
networks:
envoymesh:
ipv4_address: 172.31.92.5
links:
- spire-server
- echo
ports:
- 8080:8080
networks:
envoymesh:
driver: bridge
ipam:
config:
- subnet: 172.31.92.0/24
运行服务
# docker-compose build
# docker-compose up -d
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8284c012f9d6 spire-example_web "/docker-entrypoint.…" 28 seconds ago Up 23 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 10000/tcp spire-example-web-1
36827064a257 spire-example_echo "/docker-entrypoint.…" 28 seconds ago Up 25 seconds 10000/tcp spire-example-echo-1
7bc97ab24d09 spire-example_spire-server "/usr/bin/dumb-init …" 28 seconds ago Up 26 seconds spire-example-spire-server-1
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=warning msg="Current umask 0022 is too permissive; setting umask 0027"
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg=Configured admin_ids="[]" data_dir=/opt/spire/data/server
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Opening SQL database" db_type=sqlite3 subsystem_name=sql
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Initializing new database" subsystem_name=sql
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Connected to SQL database" read_only=false subsystem_name=sql type=sqlite3 version=3.38.5
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Plugin loaded" external=false plugin_name=x509pop plugin_type=NodeAttestor subsystem_name=catalog
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Plugin loaded" external=false plugin_name=disk plugin_type=KeyManager subsystem_name=catalog
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Loading journal" path=/opt/spire/data/server/journal.pem subsystem_name=ca_manager
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Journal loaded" jwt_keys=0 subsystem_name=ca_manager x509_cas=0
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Preparing X509 CA" slot=A subsystem_name=ca_manager
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="X509 CA prepared" expiration="2022-09-28T10:06:26Z" issued_at="2022-09-27T10:06:26Z" self_signed=true slot=A subsystem_name=ca_manager
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="X509 CA activated" expiration="2022-09-28T10:06:26Z" issued_at="2022-09-27T10:06:26Z" slot=A subsystem_name=ca_manager
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Successfully rotated X.509 CA" subsystem_name=ca_manager trust_domain_id="spiffe://wgs.com" ttl=86399.708778217
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Preparing JWT key" slot=A subsystem_name=ca_manager
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="JWT key prepared" expiration="2022-09-28T10:06:26Z" issued_at="2022-09-27T10:06:26Z" slot=A subsystem_name=ca_manager
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="JWT key activated" expiration="2022-09-28T10:06:26Z" issued_at="2022-09-27T10:06:26Z" slot=A subsystem_name=ca_manager
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Rotating server SVID" subsystem_name=svid_rotator
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Signed X509 SVID" expiration="2022-09-27T11:06:26Z" spiffe_id="spiffe://wgs.com/spire/server" subsystem_name=svid_rotator
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Building in-memory entry cache" subsystem_name=endpoints
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Completed building in-memory entry cache" subsystem_name=endpoints
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Initializing API endpoints" subsystem_name=endpoints
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Starting Server APIs" address="[::]:9081" network=tcp subsystem_name=endpoints
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=info msg="Starting Server APIs" address=/tmp/spire-server/private/api.sock network=unix subsystem_name=endpoints
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Starting checker" name=catalog.datastore subsystem_name=health
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Starting checker" name=server.ca subsystem_name=health
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Starting checker" name=server.ca.manager subsystem_name=health
spire-example-spire-server-1 | time="2022-09-27T10:06:26Z" level=debug msg="Starting checker" name=server subsystem_name=health
Start Web and Echo Servers
# cat 1-start-services.sh
#!/bin/bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
bb=$(tput bold)
nn=$(tput sgr0)
# Start up the web server
echo "${bb}Starting web server...${nn}"
docker-compose -f "${DIR}"/docker-compose.yml exec -d web web-server -log /tmp/web-server.log
# Start up the echo server
echo "${bb}Starting echo server...${nn}"
docker-compose -f "${DIR}"/docker-compose.yml exec -d echo echo-server -log /tmp/echo-server.log
# ./1-start-services.sh
Starting web server...
Starting echo server...
Start SPIRE Agents
# cat 2-start-spire-agents.sh
#!/bin/bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
bb=$(tput bold)
nn=$(tput sgr0)
# Bootstrap trust to the SPIRE server for each agent by copying over the
# trust bundle into each agent container. Alternatively, an upstream CA could
# be configured on the SPIRE server and each agent provided with the upstream
# trust bundle (see UpstreamAuthority under
# https://github.com/spiffe/spire/blob/master/doc/spire_server.md#plugin-types)
echo "${bb}Bootstrapping trust between SPIRE agents and SPIRE server...${nn}"
docker-compose -f "${DIR}"/docker-compose.yml exec -T spire-server bin/spire-server bundle show |
docker-compose -f "${DIR}"/docker-compose.yml exec -T web tee conf/agent/bootstrap.crt > /dev/null
docker-compose -f "${DIR}"/docker-compose.yml exec -T spire-server bin/spire-server bundle show |
docker-compose -f "${DIR}"/docker-compose.yml exec -T echo tee conf/agent/bootstrap.crt > /dev/null
# Start up the web server SPIRE agent.
echo "${bb}Starting web server SPIRE agent...${nn}"
docker-compose -f "${DIR}"/docker-compose.yml exec -d web bin/spire-agent run
# Start up the echo server SPIRE agent.
echo "${bb}Starting echo server SPIRE agent...${nn}"
docker-compose -f "${DIR}"/docker-compose.yml exec -d echo bin/spire-agent run
# ./2-start-spire-agents.sh
Bootstrapping trust between SPIRE agents and SPIRE server...
Starting web server SPIRE agent...
Starting echo server SPIRE agent...
spire-example-spire-server-1 | time="2022-09-27T10:12:14Z" level=info msg="Agent attestation request completed" address="172.31.92.5:43168" agent_id="spiffe://wgs.com/spire/agent/x509pop/11809aeca9d7f13fe01ea5ce1fa41fd2d4566580" authorized_as=nobody authorized_via= caller_addr="172.31.92.5:43168" method=AttestAgent node_attestor_type=x509pop request_id=8a8270fe-3dec-4868-a41d-b407700465be service=agent.v1.Agent subsystem_name=api
spire-example-spire-server-1 | time="2022-09-27T10:12:14Z" level=info msg="Agent attestation request completed" address="172.31.92.6:36692" agent_id="spiffe://wgs.com/spire/agent/x509pop/2feca4602e5e37f683ef9205a3818d79b3bf7444" authorized_as=nobody authorized_via= caller_addr="172.31.92.6:36692" method=AttestAgent node_attestor_type=x509pop request_id=96483c8a-b615-49fc-912a-d3257fde6154 service=agent.v1.Agent subsystem_name=api
Create Workload Registration Entries
# cat 3-create-registration-entries.sh
#/bin/bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
bb=$(tput bold)
nn=$(tput sgr0)
fingerprint() {
# calculate the SHA1 digest of the DER bytes of the certificate using the
# "coreutils" output format (`-r`) to provide uniform output from
# `openssl sha1` on macOS and linux.
cat $1 | openssl x509 -outform DER | openssl sha1 -r | awk '{print $1}'
}
WEB_AGENT_FINGERPRINT=$(fingerprint "${DIR}"/docker/web/conf/agent.crt.pem)
ECHO_AGENT_FINGERPRINT=$(fingerprint "${DIR}"/docker/echo/conf/agent.crt.pem)
echo "${bb}Creating registration entry for the web server...${nn}"
docker-compose -f "${DIR}"/docker-compose.yml exec spire-server bin/spire-server entry create \
-parentID spiffe://wgs.com/spire/agent/x509pop/${WEB_AGENT_FINGERPRINT} \
-spiffeID spiffe://wgs.com/web-server \
-selector unix:user:envoy
echo "${bb}Creating registration entry for the echo server...${nn}"
docker-compose -f "${DIR}"/docker-compose.yml exec spire-server bin/spire-server entry create \
-parentID spiffe://wgs.com/spire/agent/x509pop/${ECHO_AGENT_FINGERPRINT} \
-spiffeID spiffe://wgs.com/echo-server \
-selector unix:user:envoy
# ./3-create-registration-entries.sh
Creating registration entry for the web server...
Entry ID : 3c1e4953-83af-45e1-8bcc-2e2c2649fe2f
SPIFFE ID : spiffe://wgs.com/web-server
Parent ID : spiffe://wgs.com/spire/agent/x509pop/11809aeca9d7f13fe01ea5ce1fa41fd2d4566580
Revision : 0
TTL : default
Selector : unix:user:envoy
Creating registration entry for the echo server...
Entry ID : b097d6da-3122-4141-bedb-83a5020c5f44
SPIFFE ID : spiffe://wgs.com/echo-server
Parent ID : spiffe://wgs.com/spire/agent/x509pop/2feca4602e5e37f683ef9205a3818d79b3bf7444
Revision : 0
TTL : default
Selector : unix:user:envoy
spire-example-spire-server-1 | time="2022-09-27T10:14:45Z" level=debug msg="Signed X509 SVID" authorized_as=agent authorized_via=datastore caller_addr="172.31.92.5:43172" caller_id="spiffe://wgs.com/spire/agent/x509pop/11809aeca9d7f13fe01ea5ce1fa41fd2d4566580" entry_id=3c1e4953-83af-45e1-8bcc-2e2c2649fe2f expiration="2022-09-27T11:14:45Z" method=BatchNewX509SVID request_id=607fe5e0-19ff-4734-b8d3-c196f6a2d2cb service=svid.v1.SVID spiffe_id="spiffe://wgs.com/web-server" subsystem_name=api
spire-example-spire-server-1 | time="2022-09-27T10:14:46Z" level=debug msg="Signed X509 SVID" authorized_as=agent authorized_via=datastore caller_addr="172.31.92.6:36698" caller_id="spiffe://wgs.com/spire/agent/x509pop/2feca4602e5e37f683ef9205a3818d79b3bf7444" entry_id=b097d6da-3122-4141-bedb-83a5020c5f44 expiration="2022-09-27T11:14:46Z" method=BatchNewX509SVID request_id=86655152-2eca-43be-a29d-0955c4dea57c service=svid.v1.SVID spiffe_id="spiffe://wgs.com/echo-server" subsystem_name=api
通过访问Web Server进行测试
访问宿主机的8080/tcp端口,即可访问到Web Server的UI,它提供了三个不同的测试链接:
Web Server和Echo Server间的直接通信
Web Server和Echo Server基于Envoy进行的mTLS通信
Web和Echo Server之间基于Envoy进行的tls通信
查看Web和Echo Server的证书
web server证书
# curl 172.31.92.5:9901/certs
{
"certificates": [
{
"ca_cert": [
{
"path": "wgs.com: \u003cinline\u003e",
"serial_number": "7311ad031b24289c8aae09b34882a656",
"subject_alt_names": [
{
"uri": "spiffe://wgs.com"
}
],
"days_until_expiration": "0",
"valid_from": "2022-09-27T10:06:16Z",
"expiration_time": "2022-09-28T10:06:26Z"
}
],
"cert_chain": []
},
{
"ca_cert": [
{
"path": "wgs.com: \u003cinline\u003e",
"serial_number": "7311ad031b24289c8aae09b34882a656",
"subject_alt_names": [
{
"uri": "spiffe://wgs.com"
}
],
"days_until_expiration": "0",
"valid_from": "2022-09-27T10:06:16Z",
"expiration_time": "2022-09-28T10:06:26Z"
}
],
"cert_chain": [
{
"path": "\u003cinline\u003e",
"serial_number": "9f980202c9de88c22f85531e3b3eba6e",
"subject_alt_names": [
{
"uri": "spiffe://wgs.com/web-server"
}
],
"days_until_expiration": "0",
"valid_from": "2022-09-27T10:14:35Z",
"expiration_time": "2022-09-27T11:14:45Z"
}
]
}
]
}
echo server的证书
# curl 172.31.92.6:9901/certs
{
"certificates": [
{
"ca_cert": [
{
"path": "wgs.com: \u003cinline\u003e",
"serial_number": "7311ad031b24289c8aae09b34882a656",
"subject_alt_names": [
{
"uri": "spiffe://wgs.com"
}
],
"days_until_expiration": "0",
"valid_from": "2022-09-27T10:06:16Z",
"expiration_time": "2022-09-28T10:06:26Z"
}
],
"cert_chain": [
{
"path": "\u003cinline\u003e",
"serial_number": "85046824c9c138a5f2a40404f66cbc6d",
"subject_alt_names": [
{
"uri": "spiffe://wgs.com/echo-server"
}
],
"days_until_expiration": "0",
"valid_from": "2022-09-27T10:14:36Z",
"expiration_time": "2022-09-27T11:14:46Z"
}
]
},
{
"ca_cert": [],
"cert_chain": [
{
"path": "\u003cinline\u003e",
"serial_number": "85046824c9c138a5f2a40404f66cbc6d",
"subject_alt_names": [
{
"uri": "spiffe://wgs.com/echo-server"
}
],
"days_until_expiration": "0",
"valid_from": "2022-09-27T10:14:36Z",
"expiration_time": "2022-09-27T11:14:46Z"
}
]
}
]
}
参考文档
https://github.com/spiffe/spire-examples
https://github.com/spiffe/spire-tutorials/tree/main/docker-compose
https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/tls_spiffe_validator_config.proto#extension-envoy-tls-cert-validator-spiffe