天天看點

istio證書簽發流程envoy 中的證書驗證驗證下遊證書配置驗證上遊證書配置pilot agent處理SDS流程ca server簽發證書流程caServer.Run()_IstioCertificateService_CreateCertificate_Handler

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簽發證書

istio證書簽發流程envoy 中的證書驗證驗證下遊證書配置驗證上遊證書配置pilot agent處理SDS流程ca server簽發證書流程caServer.Run()_IstioCertificateService_CreateCertificate_Handler

掃描關注我:

istio證書簽發流程envoy 中的證書驗證驗證下遊證書配置驗證上遊證書配置pilot agent處理SDS流程ca server簽發證書流程caServer.Run()_IstioCertificateService_CreateCertificate_Handler

繼續閱讀