envoy 中的證書驗證
- combined_validation_context
組合的證書驗證上下文包含預設的CertificateValidationContext和SDS配置。 當SDS伺服器傳回動态CertificateValidationContext時,動态和預設的CertificateValidationContext都将合并到新的CertificateValidationContext中以進行驗證。 此合并是通過Message::MergeFrom()完成的,是以動态的CertificateValidationContext會覆寫預設CertificateValidationContext中的單個字段,并将重複的字段連接配接到預設CertificateValidationContext中,并且邏輯OR應用于布爾字段。
- validation_context_sds_secret_config
通過SDS API擷取驗證上下文的配置。
- tls_certificate_sds_secret_configs
通過SDS API擷取TLS證書的配置
- default_validation_context
如何驗證對等證書。
- match_subject_alt_names
Subject Alternative Name比對器的可選清單.envoy将驗證所提供證書的
Subject Alternative Name
是否與指定的比對項之一比對。 當證書具有通配符DNS SAN條目時,為了比對特定的用戶端,應在字元串比對器中将其配置為完全比對類型。 例如,如果證書的DNS SAN條目具有
*.example.com
,則僅允許
api.example.com
,則應按如下所示進行配置。
match_subject_alt_names:
exact: "api.example.com"
驗證下遊證書配置
{
"@type": "type.googleapis.com/envoy.api.v2.auth.DownstreamTlsContext", //驗證下遊,接收請求
"common_tls_context": {
"alpn_protocols": [
"istio-peer-exchange",
"h2",
"http/1.1"
],
"tls_certificate_sds_secret_configs": [ //獲驗證書
{
"name": "default",
"sds_config": {
"api_config_source": {
"api_type": "GRPC",
"grpc_services": [
{
"envoy_grpc": {
"cluster_name": "sds-grpc"
}
}
]
}
}
}
],
"combined_validation_context": { //組合驗證規則
"default_validation_context": {
},
"validation_context_sds_secret_config": { //驗證CA
"name": "ROOTCA",
"sds_config": {
"api_config_source": {
"api_type": "GRPC",
"grpc_services": [
{
"envoy_grpc": {
"cluster_name": "sds-grpc"
}
}
]
}
}
}
}
},
"require_client_certificate": true // Envoy将拒絕沒有有效用戶端證書的連接配接。
}
驗證上遊證書配置
{
"name": "envoy.transport_sockets.tls",
"typed_config": {
"@type": "type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext", //驗證上遊,送出請求
"common_tls_context": {
"alpn_protocols": [
"istio-peer-exchange",
"istio",
"h2"
],
"tls_certificate_sds_secret_configs": [
{
"name": "default",
"sds_config": {
"api_config_source": {
"api_type": "GRPC",
"grpc_services": [
{
"envoy_grpc": {
"cluster_name": "sds-grpc"
}
}
]
}
}
}
],
"combined_validation_context": { //組合驗證規則
"default_validation_context": {
"match_subject_alt_names": [ SAN比對器
{
"exact": "spiffe://cluster.local/ns/istio-system/sa/default"
}
]
},
"validation_context_sds_secret_config": {
"name": "ROOTCA",
"sds_config": {
"api_config_source": {
"api_type": "GRPC",
"grpc_services": [
{
"envoy_grpc": {
"cluster_name": "sds-grpc"
}
}
]
}
}
}
}
},
"sni": "outbound_.14250_._.jaeger-collector-headless.istio-system.svc.cluster.local"
}
}
對于特殊情況,istio中請求某些基礎服務是直接透傳的,不會根據spiffeid驗證
{
"name": "envoy.transport_sockets.tls",
"typed_config": {
"@type": "type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext",
"common_tls_context": {
"validation_context": {
"trusted_ca": {
"filename": "./var/run/secrets/istio/root-cert.pem"
},
"match_subject_alt_names": [ //未經過envoy,域名如下
{
"exact": "istiod.istio-system.svc"
}
]
},
"alpn_protocols": [
"h2"
],
"tls_certificate_sds_secret_configs": [
{
"name": "default",
"sds_config": {
"api_config_source": {
"api_type": "GRPC",
"grpc_services": [
{
"envoy_grpc": {
"cluster_name": "sds-grpc"
}
}
]
}
}
}
]
}
}
}
pilot agent處理SDS流程
constructProxyConfig 構造proxy config
getDNSDomain 根據registry生成域名
istio_agent.NewAgent 初始化agent
sa.Start(role.Type == model.SidecarProxy, podNamespaceVar.Get())
開始啟動SDS agent,預設為sidecar模式,網關需要啟動為route模式
NewServer
建立SDSserver
對于sidecar模式,将執行initWorkloadSdsService進行grpc server初始化,
initWorkloadSdsService 初始化SDS service
通過s.workloadSds.register(s.grpcWorkloadServer),進行服務注冊,需要實作以下接口
type SecretDiscoveryServiceServer interface {
DeltaSecrets(SecretDiscoveryService_DeltaSecretsServer) error
// SDS API
StreamSecrets(SecretDiscoveryService_StreamSecretsServer) error
// 擷取secret
FetchSecrets(context.Context, *envoy_api_v2.DiscoveryRequest) (*envoy_api_v2.DiscoveryResponse, error)
}
FetchSecrets
FetchSecrets處理單次證書請求
通過s.st.GenerateSecret生成secret并傳回,然後調用GenerateSecret,判斷請求證書是否為rootca,若不是将調用generateSecret
如果開啟了第三方的exchanger,則進行exchanger進行驗證,現在支援Google auth
生成csr後通過sendRetriableRequest送出給pilot-discovery,
sendRetriableRequest調用CSRSign方法進行證書簽發,這裡實際上會請求istiod(pilot-discovery)
發送請求到認證中心簽發證書
func (c *citadelClient) CSRSign
func (c *istioCertificateServiceClient) CreateCertificate(ctx context.Context, in *IstioCertificateRequest, opts ...grpc.CallOption)
請求下面的接口進行證書簽發
/istio.v1.auth.IstioCertificateService/CreateCertificate"
StreamSecrets
FetchSecrets處理雙向通信,具體操作和FetchSecrets類似
##startXDS
建立xdsclient和xdsserver,用于處理envoy請求和請求pilot-discovery
ca server簽發證書流程
s.maybeCreateCA
檢視目錄是否有對應的檔案,否則生成自簽名證書,作為根證書,後續将使用該證書簽發證書
s.startCA
caOpts := &CAOptions{
TrustDomain: s.environment.Mesh().TrustDomain,
Namespace: args.Namespace,
}
實際上調用的 s.RunCA
s.RrunCA 調用detectAuthEnv,擷取k8s token pay load,内容如下示例
{"iss":"kubernetes/serviceaccount","kubernetes.io/serviceaccount/namespace":"istio-system","kubernetes.io/serviceaccount/secret.name":"istiod-service-account-token-h2mxh","kubernetes.io/serviceaccount/service-account.name":"istiod-service-account","kubernetes.io/serviceaccount/service-account.uid":"2f08fe65-6a69-4c2a-881b-8823b90dea60","sub":"system:serviceaccount:istio-system:istiod-service-account"}
caserver.NewWithGRPC
注冊以下 Authenticator
- ClientCertAuthenticator
對于VM,允許使用以前頒發的證書進行授權。對于VM,将傳回具有從SAN提取的身份的調用方,應為SPIFFE身份。
1.判斷auth type
2.判斷證書鍊的合法性
- KubeJWTAuthenticator
1.解析bear token
2. 根據叢集名稱擷取kubeclient
3. 調用tokenreview.ValidateK8sJwt函數對token進行驗證
4. 調用k8s api server token review接口對token進行驗證
然後對server進行初始化
caServer.Run()
注冊下列 grpc api 用于處理證書請求
pb.RegisterIstioCertificateServiceServer(grpcServer, s)
_IstioCertificateService_CreateCertificate_Handler
srv.(IstioCertificateServiceServer).CreateCertificate(ctx, req.(*IstioCertificateRequest))
實際調用以下方法建立證書
func (s *Server) CreateCertificate
首先調用s.authenticate(ctx)用于認證用戶端身份,該方法調用authn.Authenticate(ctx),也就是上面所注冊的驗證器進行用戶端身份驗證,傳回caller
&Caller{
AuthSource: AuthSourceIDToken,
Identities: []string{fmt.Sprintf(identityTemplate, a.trustDomain, callerNamespace, callerServiceAccount)},
}
傳回的caller主要包含證書的身份用于後續簽發時的Subject Alternative Name,格式如下
spiffe://cluster.local/ns/foo/sa/httpbin
該字段也會用于服務授權
驗證成功後
調用s.ca.GetCAKeyCertBundle().GetAll()獲驗證書鍊以及跟證書
s.ca.Sign根據csr,subjectIDs,requestedLifetime,對csr進行簽發,requestedLifetime預設為24小時
最終調用util.GenCertFromCSR簽發證書

掃描關注我: