Envoy spiffe spire
spiffe:规范,协议
SPIFFE标准定义了一种能够跨异构环境和组织边界完成bootstrap以及向服务发布身份ID的规模框架。
SPIFFE规范标准化了向工作负载( workload) 分配身份、 验证和确认工作负载身份以及工作负载API以检索身份的过程。
SPIFFE身份包含在SVID( SPIFFE Verifiable Identity Document) 中, SVID规范提供了实现SVID时必须支持的属性的要求。
spire:是spiffe的实现,是工具
SPIRE是SPIFFE规范的工具链实现, 也是一种参考实现, 它可以跨不同的部署环境在工作负载( 使用mTLS或JWT) 之间建立信任关系, 签发SPIFFE ID和工作负载API以检索工作负载SVID。
简而言之, SPIFFE是一个可信bootstrapping和identification框架, 它已作为标准提交并被CNCF( 云原生计算基金会) 接受。
到目前为止, 该标准具有两个主要实现, 分别是SPIRE和Istio Citadel。
workload:Pod中的主程序和子进程。
spiffe给每一个workload分配一个spiffe id来表示身份放在SVID文件中。
workload API:用来给workload请求SVID的接口,spire中用agent来实现的。
SPIFFE Workload API用于提供使工作负载能够使用的SPIFFE身份,以及基于的身份验证系统的信息和服务。
SPIFFE Workload API支持任意数量的本地客户端,从而使其能够引导可以访问它的任何进程的身份。
1、通常, 希望在每个进程被授予某些身份的情况下即可以每个进程为基础分配身份。
2、为此, SPIFFE Workload API实现必须能够确定调用者的身份;
X.509身份文档格式标识符:
1、即SPIFFE ID;
2、与ID关联的私钥, 由当前workload签署数据,以及一个短存活期的用于建立tls通信的X.509格式的数字证书
3、可信证书集( trust bundle),由workload用于验证其它workload的X.509-SVID;
JWT身份文档格式标识符:
1、即SPIFFE ID;
2、JWT Token;
3、可信证书集, 由workload用于验证其它workload的身份;
SPIFFE Workload API需要被实现为gRPC流式服务器,以便快速传播更新, 例如证书吊销等。
SPIRE
SPIRE是SPIFFEAPI的可用于生产的实现,它负责执行node和workload的身份证明,以便根据一组预定义的条件安全地向workload签发SVID,并验证其他workload的SVID。
SPIRE可以用于多种情况,并可以执行多种与身份相关的功能:
1、服务之间的安全身份验证。
2、安全地引入Vault和PinterestKnox等secretstores。
3、为服务网格中的sidecar代理服务提供身份认证的基础设施。
4、用于分布式系统组件的PKI的供给和轮替。
SPIRE架构和组件:
一、SPIRE Server: 签名授权机构, 它通过各SPIRE Agent接收请求。
1、负责管理和发布已配置的SPIFFE可信域中的所有身份;
2、它存储注册条目( 用于指定确定特定SPIFFE ID的发布条件的选择器) 和签名密钥
3、使用node attestation自动认证Agent的身份, 并在经过认证的agent请求时为其本地的workload创建SVID
二、SPIRE Agent: 运行于各工作节点, 用于向节点上的workload提供workload API;
1、从服务器请求SVID并缓存它们, 直到workload请求其SVID
2、将SPIFFE Workload API暴露给本地节点上的workload, 并负责证明调用它的workload的身份
3、提供已识别的workload及其SVID
SPIRE Server:
SPIRE Server高度插件化, 用户需要通过一系列插件来配置其行为
1、Node attestor插件负责结合各节点上运行的agent node attestor插件一同来验证节点身份;
2、Node resolver为SPIRE Server提供一系列selector( 选择器) 从而让Server能够基于其它属性来验证节点身份;
3、Datastore插件被SPIRE Server用于存储、 查询和更新各种信息,例如registration entries,包括哪些节点身份业已得到证明, 以及这些节点各自相关的选择器等 。
内置的数据存储插件支持使用SQLite 3或PostgresSQL作为存储后端。
默认情况下, 它使用SQLite 3。
4、Key manager插件负责控制服务器如何存储用于签署X.509-SVID和JWT-SVID的私钥。
5、默认情况下, SPIRE Server充当其自己的证书颁发机构, 必要时也可以使用Upstream certificate authority (CA) 插件来使用来自不同PKI系统的不同CA。
SPIRE Agent:
SPIREAgent需要运行于每个运行有workload的节点上,并负责以下任务:
1、从SPIREServer请求SVID并缓存它们,直到workload请求其SVID
2、将SPIFFEWorkloadAPI暴露给节点上的workload,并证明调用它的workload的身份
3、提供已识别的workload及其SVID
SPIREAgent同样基于组合配置一系列插件完成其工作:
1、Nodeattestor插件同Server端的nodeattestor插件一起完成对agent程序所在节点的身份验证。
2、Workloadattestor插件通过从节点操作系统查询相关进程的信息,并将其与使用selector注册workload属性时提供给server的信息进行比较,从而验证节点上workload进程的身份。
3、Keymanager插件,负责让agent用来为发布给workload的X.509-SVID生成私钥。
示例:
front-envoy.yaml
node: id: "front-envoy" cluster: "front-envoy" admin: access_log_path: "/dev/null" address: socket_address: address: 0.0.0.0 port_value: 9901 static_resources: secrets: - name: server_cert tls_certificate: certificate_chain: filename: "/etc/envoy/certs/server.crt" private_key: filename: "/etc/envoy/certs/server.key" listeners: - name: listener_http address: socket_address: { address: 0.0.0.0, port_value: 80 } filter_chains: - filters: - name: envoy.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager codec_type: AUTO stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: backend domains: ["*"] routes: - match: prefix: "/" redirect: https_redirect: true port_redirect: 443 http_filters: - name: envoy.router typed_config: {} - name: listener_https address: socket_address: { address: 0.0.0.0, port_value: 443 } filter_chains: - filters: - name: envoy.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager stat_prefix: ingress_https codec_type: AUTO route_config: name: https_route virtual_hosts: - name: https_route domains: ["*"] routes: - match: prefix: "/service/gray" route: cluster: service-gray - match: prefix: "/service/purple" route: cluster: service-purple - match: prefix: "/" route: cluster: mycluster http_filters: - name: envoy.router typed_config: {} tls_context: common_tls_context: tls_certificate_sds_secret_configs: - name: server_cert clusters: - name: spire_agent connect_timeout: 0.25s http2_protocol_options: {} hosts: - pipe: path: /tmp/agent.sock - name: mycluster connect_timeout: 0.25s type: STRICT_DNS lb_policy: ROUND_ROBIN http2_protocol_options: {} load_assignment: cluster_name: mycluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: myservice port_value: 80 - name: service-gray connect_timeout: 0.25s type: strict_dns lb_policy: ROUND_ROBIN hosts: - socket_address: address: service-gray port_value: 443 tls_context: common_tls_context: tls_certificate_sds_secret_configs: - name: "spiffe://ilinux.io/front-envoy" # spiffe id 要唯一 sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent combined_validation_context: # validate the SPIFFE ID of the server default_validation_context: verify_subject_alt_name: - "spiffe://ilinux.io/service-gray" validation_context_sds_secret_config: name: "spiffe://ilinux.io" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent - name: service-purple connect_timeout: 0.25s type: strict_dns lb_policy: ROUND_ROBIN hosts: - socket_address: address: service-purple port_value: 443 tls_context: common_tls_context: tls_certificate_sds_secret_configs: - name: "spiffe://ilinux.io/front-envoy" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent combined_validation_context: # validate the SPIFFE ID of the server default_validation_context: verify_subject_alt_name: - "spiffe://ilinux.io/service-purple" validation_context_sds_secret_config: name: "spiffe://ilinux.io" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent
spire-server.conf
server { bind_address = "0.0.0.0" bind_port = "9081" registration_uds_path = "/tmp/spire-registration.sock" trust_domain = "ilinux.io" data_dir = "/opt/spire/data/server" plugin_dir = "/opt/spire/conf/server/plugin" log_level = "DEBUG" log_file = "/dev/stdout" upstream_bundle = false svid_ttl = "1h" ca_subject = { Country = ["CN"], Organization = ["SPIFFE"], CommonName = "", } } 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" } } NodeResolver "noop" { plugin_data {} } KeyManager "disk" { plugin_data = { keys_path = "/opt/spire/data/server/keys.json" } } }
service-purple:
service-purple spire-agent.conf
agent { data_dir = "/opt/spire/data/agent" log_level = "DEBUG" log_file = "/dev/stdout" plugin_dir = "/opt/spire/conf/agent/plugin" server_address = "spire-server" server_port = "9081" socket_path ="/tmp/agent.sock" trust_bundle_path = "/opt/spire/conf/agent/bootstrap.crt" trust_domain = "ilinux.io" enable_sds = true } 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 { } } }
service-purple-envoy.yaml:
node: id: "service-purple" cluster: "service-purple" admin: access_log_path: "/dev/null" address: socket_address: address: 0.0.0.0 port_value: 9901 static_resources: listeners: - name: listener_http address: socket_address: address: 0.0.0.0 port_value: 80 filter_chains: - filters: - name: envoy.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager codec_type: auto stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: service domains: - "*" routes: - match: prefix: "/" route: cluster: local_service http_filters: - name: envoy.router typed_config: {} - name: listener_https address: socket_address: { address: 0.0.0.0, port_value: 443 } filter_chains: - filters: - name: envoy.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager stat_prefix: ingress_https codec_type: AUTO route_config: name: https_route virtual_hosts: - name: https_route domains: ["*"] routes: - match: prefix: "/" route: cluster: local_service http_filters: - name: envoy.router typed_config: {} tls_context: common_tls_context: tls_certificate_sds_secret_configs: - name: "spiffe://ilinux.io/service-purple" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent # obtain the trust bundle from SDS validation_context_sds_secret_config: name: "spiffe://ilinux.io" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent clusters: - name: spire_agent connect_timeout: 0.25s http2_protocol_options: {} hosts: - pipe: path: /tmp/agent.sock - name: local_service connect_timeout: 0.25s type: strict_dns lb_policy: round_robin load_assignment: cluster_name: local_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 8080