github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/envoyauthorizer/envoyproxy/sds_server.go (about)

     1  package envoyproxy
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"crypto/x509"
     7  	"encoding/pem"
     8  	"fmt"
     9  	"net"
    10  	"sync"
    11  	"time"
    12  
    13  	"context"
    14  
    15  	"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/secrets"
    16  	"go.aporeto.io/enforcerd/trireme-lib/policy"
    17  	"go.aporeto.io/enforcerd/trireme-lib/utils/cache"
    18  	"go.uber.org/zap"
    19  	"google.golang.org/grpc"
    20  
    21  	v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
    22  	envoy_api_v2_auth "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth"
    23  	envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
    24  	sds "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2"
    25  
    26  	"github.com/golang/protobuf/ptypes"
    27  	//"github.com/gogo/protobuf/types"
    28  	"google.golang.org/grpc/metadata"
    29  )
    30  
    31  const (
    32  	// SdsSocketpath is the socket path on which the envoy will talk to the remoteEnforcer.
    33  	//SdsSocketpath = "@aporeto_envoy_sds"
    34  	SdsSocketpath = "127.0.0.1:2999"
    35  	//SdsSocketpath = "/var/run/sds/uds_path"
    36  	typeCertificate = "CERTIFICATE"
    37  )
    38  
    39  // Options to create a SDS server to task to envoy
    40  type Options struct {
    41  	SocketPath string
    42  }
    43  
    44  // sdsCerts is the structure will pass the upstream certs downwards.
    45  type sdsCerts struct {
    46  	key    string
    47  	cert   string
    48  	caPool *x509.CertPool
    49  }
    50  
    51  // SdsDiscoveryStream is the same as the sds.SecretDiscoveryService_StreamSecretsServer
    52  type SdsDiscoveryStream interface {
    53  	Send(*v2.DiscoveryResponse) error
    54  	Recv() (*v2.DiscoveryRequest, error)
    55  	grpc.ServerStream
    56  }
    57  
    58  var _ sds.SecretDiscoveryServiceServer = &SdsServer{}
    59  
    60  // SdsServer to talk with envoy for sds.
    61  type SdsServer struct {
    62  	sdsGrpcServer   *grpc.Server
    63  	sdsGrpcListener net.Listener
    64  
    65  	errCh   chan error
    66  	puInfo  *policy.PUInfo
    67  	cert    *tls.Certificate
    68  	ca      *x509.CertPool
    69  	keyPEM  string
    70  	certPEM string
    71  	secrets secrets.Secrets
    72  	sync.RWMutex
    73  	// conncache is a cache of the sdsConnection, here the key is the connectionID and val is the secret.
    74  	conncache cache.DataStore
    75  	// updCertsChannel is used whenever there is a cert-update/Enfore
    76  	updCertsChannel chan sdsCerts
    77  	connMap         map[string]bool
    78  }
    79  
    80  type secretItem struct {
    81  	CertificateChain []byte
    82  	PrivateKey       []byte
    83  
    84  	RootCert []byte
    85  
    86  	// RootCertOwnedByCompoundSecret is true if this SecretItem was created by a
    87  	// K8S secret having both server cert/key and client ca and should be deleted
    88  	// with the secret.
    89  	RootCertOwnedByCompoundSecret bool
    90  
    91  	// ResourceName passed from envoy SDS discovery request.
    92  	// "ROOTCA" for root cert request, "default" for key/cert request.
    93  	ResourceName string
    94  
    95  	// Credential token passed from envoy, caClient uses this token to send
    96  	// CSR to CA to sign certificate.
    97  	Token string
    98  
    99  	// Version is used(together with token and ResourceName) to identify discovery request from
   100  	// envoy which is used only for confirm purpose.
   101  	Version string
   102  
   103  	CreatedTime time.Time
   104  
   105  	ExpireTime time.Time
   106  }
   107  
   108  // clientConn is ID for the connection between client and SDS server.
   109  type clientConn struct {
   110  	clientID string
   111  	// the TLS cert information cached for this particular connection
   112  	secret *secretItem
   113  
   114  	// connectionID is the ID for each new request, make it a combo of nodeID+counter.
   115  	connectionID string
   116  	stream       SdsDiscoveryStream
   117  }
   118  
   119  // NewSdsServer creates a instance of a server.
   120  func NewSdsServer(contextID string, puInfo *policy.PUInfo, caPool *x509.CertPool, secrets secrets.Secrets) (*SdsServer, error) {
   121  	if puInfo == nil {
   122  		zap.L().Error("SDS Server: puInfo NIL ")
   123  		return nil, fmt.Errorf("the puinfo cannot be nil")
   124  	}
   125  
   126  	sdsOptions := &Options{SocketPath: SdsSocketpath}
   127  	sdsServer := &SdsServer{
   128  		puInfo:          puInfo,
   129  		ca:              caPool,
   130  		errCh:           make(chan error),
   131  		secrets:         secrets,
   132  		conncache:       cache.NewCache("servers"),
   133  		updCertsChannel: make(chan sdsCerts),
   134  		connMap:         make(map[string]bool),
   135  	}
   136  	if err := sdsServer.CreateSdsService(sdsOptions); err != nil {
   137  		zap.L().Error("SDS Server:Error while starting the envoy sds server.")
   138  		return nil, err
   139  	}
   140  	zap.L().Debug("SDS Server: SDS start success", zap.String("pu", puInfo.ContextID))
   141  	return sdsServer, nil
   142  }
   143  
   144  // CreateSdsService does the following
   145  // 1. create grpc server.
   146  // 2. create a listener on the Unix Domain Socket.
   147  // 3.
   148  func (s *SdsServer) CreateSdsService(options *Options) error { // nolint: unparam
   149  	s.sdsGrpcServer = grpc.NewServer()
   150  	s.register(s.sdsGrpcServer)
   151  
   152  	addr, err := net.ResolveTCPAddr("tcp", options.SocketPath)
   153  	if err != nil {
   154  		return err
   155  	}
   156  	nl, err := net.ListenTCP("tcp", addr)
   157  	if err != nil {
   158  		return err
   159  	}
   160  	// if err := os.Remove(options.SocketPath); err != nil && !os.IsNotExist(err) {
   161  	// 	zap.L().Error("SDS Server: envoy-reireme, failed to remove the udspath", zap.Error(err))
   162  	// 	return err
   163  	// }
   164  	// zap.L().Debug("SDS Server: Start listening on UDS path", zap.Any("socketPath", options.SocketPath))
   165  	// addr, _ := net.ResolveUnixAddr("unix", options.SocketPath)
   166  
   167  	// sdsGrpcListener, err := net.ListenUnix("unix", addr)
   168  	// if err != nil {
   169  	// 	zap.L().Error("SDS Server:cannot listen on the socketpath", zap.Error(err))
   170  	// 	return err
   171  	// }
   172  	// //make sure the socket path can be accessed.
   173  	// if _, err := os.Stat(options.SocketPath); err != nil {
   174  	// 	zap.L().Error("SDS Server: SDS uds file doesn't exist", zap.String("socketPath:", options.SocketPath))
   175  	// 	return fmt.Errorf("sds uds file %q doesn't exist", options.SocketPath)
   176  	// }
   177  	// if err := os.Chmod(options.SocketPath, 0666); err != nil {
   178  	// 	zap.L().Error("SDS Server: Failed to update permission", zap.String("socketPath:", options.SocketPath))
   179  	// 	return fmt.Errorf("failed to update %q permission", options.SocketPath)
   180  	// }
   181  	s.sdsGrpcListener = nl
   182  
   183  	zap.L().Debug("SDS Server: run the grpc server at", zap.Any("addr", s.sdsGrpcListener.Addr()))
   184  	s.Run()
   185  	return nil
   186  }
   187  
   188  // Run starts the sdsGrpcServer to serve
   189  func (s *SdsServer) Run() {
   190  	go func() {
   191  		if s.sdsGrpcListener != nil {
   192  			if err := s.sdsGrpcServer.Serve(s.sdsGrpcListener); err != nil {
   193  				zap.L().Error("SDS Server: Error while serve", zap.Error(err))
   194  				s.errCh <- err
   195  			}
   196  		}
   197  		zap.L().Error("SDS Server: the listener is nil, cannot start the SDS server for", zap.String("puID", s.puInfo.ContextID))
   198  	}()
   199  }
   200  
   201  // Stop stops all the listeners and the grpc servers.
   202  func (s *SdsServer) Stop() {
   203  	if s.sdsGrpcListener != nil {
   204  		s.sdsGrpcListener.Close() // nolint
   205  	}
   206  	if s.sdsGrpcServer != nil {
   207  		s.sdsGrpcServer.Stop()
   208  	}
   209  }
   210  
   211  // GracefulStop calls the function with the same name on the backing gRPC server
   212  func (s *SdsServer) GracefulStop() {
   213  	s.sdsGrpcServer.GracefulStop()
   214  }
   215  
   216  // register adds the SDS handle to the grpc server
   217  func (s *SdsServer) register(sdsGrpcServer *grpc.Server) {
   218  	zap.L().Debug("SDS Server:  envoy-trireme registering the secret discovery")
   219  	sds.RegisterSecretDiscoveryServiceServer(sdsGrpcServer, s)
   220  }
   221  
   222  // UpdateSecrets updates the secrets
   223  // Whenever the Envoy makes a request for certificate, the certs and keys are fetched from
   224  // the Proxy.
   225  func (s *SdsServer) UpdateSecrets(cert *tls.Certificate, caPool *x509.CertPool, secrets secrets.Secrets, certPEM, keyPEM string) {
   226  	s.Lock()
   227  	defer s.Unlock()
   228  
   229  	s.cert = cert
   230  	s.ca = caPool
   231  	//s.secrets = secrets
   232  	s.certPEM = certPEM
   233  	s.keyPEM = keyPEM
   234  	s.updCertsChannel <- sdsCerts{key: keyPEM, cert: certPEM, caPool: caPool}
   235  }
   236  
   237  // now implement the interfaces of the SDS grpc server.
   238  // type SecretDiscoveryServiceServer interface {
   239  // 	DeltaSecrets(SecretDiscoveryService_DeltaSecretsServer) error
   240  // 	StreamSecrets(SecretDiscoveryService_StreamSecretsServer) error
   241  // 	FetchSecrets(context.Context, *v2.DiscoveryRequest) (*v2.DiscoveryResponse, error)
   242  // }
   243  
   244  // DeltaSecrets checks for the delta and sends the changes.
   245  func (s *SdsServer) DeltaSecrets(stream sds.SecretDiscoveryService_DeltaSecretsServer) error {
   246  	return nil
   247  }
   248  
   249  func startStreaming(stream SdsDiscoveryStream, discoveryReqCh chan *v2.DiscoveryRequest) {
   250  	defer close(discoveryReqCh)
   251  	for {
   252  		req, err := stream.Recv()
   253  		if err != nil {
   254  			zap.L().Error("SDS Server: Connection terminated with err", zap.Error(err))
   255  			return
   256  		}
   257  		discoveryReqCh <- req
   258  	}
   259  }
   260  
   261  // StreamSecrets is the function invoked by the envoy in-order to pull the certs, this also sends the response back to the envoy.
   262  // It does the following:
   263  // 1. create a receiver thread to stream the requests.
   264  // 2. parse the discovery request.
   265  // 3. track the request.
   266  // 4. call the Aporeto api to generate the secret
   267  func (s *SdsServer) StreamSecrets(stream sds.SecretDiscoveryService_StreamSecretsServer) error {
   268  	ctx := stream.Context()
   269  	token := ""
   270  	metadata, ok := metadata.FromIncomingContext(ctx)
   271  	if !ok {
   272  		return fmt.Errorf("unable to get metadata from incoming context")
   273  	}
   274  	if h, ok := metadata["authorization"]; ok {
   275  		if len(h) != 1 {
   276  			return fmt.Errorf("credential token from %q must have 1 value in gRPC metadata but got %d", "authorization", len(h))
   277  		}
   278  		token = h[0]
   279  	}
   280  	zap.L().Debug("SDS Server: IN stream secrets, token", zap.String("token", token))
   281  
   282  	// create new connection
   283  	conn := &clientConn{}
   284  	conn.stream = stream
   285  	discoveryReqCh := make(chan *v2.DiscoveryRequest, 1)
   286  	go startStreaming(stream, discoveryReqCh)
   287  
   288  	for {
   289  		// wait for the receiver thread to stream the request and send it to us over here.
   290  		select {
   291  		case req, ok := <-discoveryReqCh:
   292  			// if req == nil {
   293  			// 	zap.L().Warn("SDS Server: The request is nil")
   294  			// 	continue
   295  			// }
   296  			// Now check the following:
   297  			// 1. Return if stream is closed.
   298  			// 2. Return if its invalid request.
   299  			if !ok {
   300  				zap.L().Error("SDS Server: Receiver channel closed, which means the Receiver stream is closed")
   301  				return fmt.Errorf("Receiver closed the channel")
   302  			}
   303  			// then check for the req.Node
   304  			if req.Node == nil {
   305  				zap.L().Error("Invalid discovery request with no node")
   306  				return fmt.Errorf("invalid discovery request with no node")
   307  			}
   308  			if req.ErrorDetail != nil {
   309  				zap.L().Error("SDS Server: ERROR from envoy for processing the resource", zap.String("error", req.GetErrorDetail().String()))
   310  				continue
   311  			}
   312  
   313  			// now according to the Istio pilot SDS secret config we have 2 configs, this configs are pushed to envoy through Istio.
   314  			// 1. SDSDefaultResourceName is the default name in sdsconfig, used for fetching normal key/cert.
   315  			// 2. SDSRootResourceName is the sdsconfig name for root CA, used for fetching root cert.
   316  			// therefore from the above we receive 2 requests, 1 for default and 2 for the ROOTCA
   317  
   318  			// now check for the resourcename, it should atleast have one, else continue and stream the next request.
   319  			// according to the definition this could be empty.
   320  			if len(req.ResourceNames) == 0 {
   321  				continue
   322  			}
   323  			if len(req.ResourceNames) > 1 {
   324  				return fmt.Errorf("SDS Server: invalid resourceNames, greater than one")
   325  			}
   326  			resourceName := req.ResourceNames[0]
   327  			conn.clientID = req.Node.GetId()
   328  			//if len(conn.connectionID) == 0 {
   329  			conn.connectionID = createConnID(conn.clientID, resourceName)
   330  
   331  			// if this is not the 1st request and if the secret is already present then dont proceed as this is a ACK according to the XDS protocol.
   332  			if req.VersionInfo != "" && s.checkSecretPresent(conn.connectionID, req, token) {
   333  				zap.L().Warn("SDS Server: got a ACK from envoy", zap.String("connectionID", conn.connectionID), zap.String("resourceName", resourceName), zap.String("version", req.VersionInfo))
   334  				continue
   335  			}
   336  			secret := s.generateSecret(req, token)
   337  			if secret == nil {
   338  				zap.L().Error("SDS Server: the Certs cannot be served so return nil")
   339  				return fmt.Errorf("the aporeto SDS server cannot generate server, the certs are nil")
   340  			}
   341  			conn.secret = secret
   342  			s.conncache.AddOrUpdate(conn.connectionID, conn)
   343  
   344  			resp := &v2.DiscoveryResponse{
   345  				TypeUrl:     "type.googleapis.com/envoy.api.v2.auth.Secret",
   346  				VersionInfo: secret.Version,
   347  				Nonce:       secret.Version,
   348  			}
   349  			retSecret := &envoy_api_v2_auth.Secret{
   350  				Name: secret.ResourceName,
   351  			}
   352  			if secret.RootCert != nil {
   353  				retSecret.Type = getRootCert(secret)
   354  			} else {
   355  				retSecret.Type = getTLScerts(secret)
   356  			}
   357  			endSecret, err := ptypes.MarshalAny(retSecret)
   358  			if err != nil {
   359  				zap.L().Error("SDS Server: Cannot marshall the secret", zap.Error(err))
   360  				continue
   361  			}
   362  			resp.Resources = append(resp.Resources, endSecret)
   363  			if err = stream.Send(resp); err != nil {
   364  				zap.L().Error("SDS Server: Failed to send the resp cert", zap.Error(err))
   365  				return err
   366  			}
   367  			if secret.RootCert != nil {
   368  				zap.L().Debug("SDS Server: Successfully sent root cert", zap.String("rootCA", string(secret.RootCert)))
   369  			} else {
   370  				zap.L().Debug("SDS Server: Successfully sent default cert", zap.String("default cert", string(secret.CertificateChain)))
   371  			}
   372  		case updateCerts := <-s.updCertsChannel:
   373  			// 1st check if the connection is present
   374  
   375  			if _, err := s.conncache.Get(conn.connectionID); err != nil {
   376  				zap.L().Warn("SDS server: updCertsChannel, no connID found in cache,", zap.String("connID", conn.connectionID))
   377  				continue
   378  			}
   379  			fmt.Println("connID found now send certs")
   380  			if updateCerts.key != "" && updateCerts.cert != "" {
   381  				if err := s.sendUpdatedCerts(updateCerts, conn); err != nil {
   382  					zap.L().Error("SDS Server: send updated certs failed", zap.Error(err))
   383  				}
   384  			}
   385  		}
   386  	}
   387  
   388  }
   389  
   390  func (s *SdsServer) sendUpdatedCerts(apoSecret sdsCerts, conn *clientConn) error {
   391  	var err error
   392  	pemCert := []byte{} // nolint
   393  	t := time.Now()
   394  
   395  	if apoSecret.key != "" && apoSecret.cert != "" {
   396  		caPEM := s.secrets.CertAuthority()
   397  
   398  		pemCert, err = buildCertChain([]byte(apoSecret.cert), caPEM)
   399  		if err != nil {
   400  			zap.L().Error("SDS Server: Cannot build the cert chain")
   401  			return fmt.Errorf("SDS Server: Cannot build the cert chain")
   402  		}
   403  
   404  		resp := &v2.DiscoveryResponse{
   405  			TypeUrl:     "type.googleapis.com/envoy.api.v2.auth.Secret",
   406  			VersionInfo: t.String(),
   407  			Nonce:       t.String(),
   408  		}
   409  		retSecret := &envoy_api_v2_auth.Secret{
   410  			Name: "default",
   411  		}
   412  
   413  		retSecret.Type = &envoy_api_v2_auth.Secret_TlsCertificate{
   414  			TlsCertificate: &envoy_api_v2_auth.TlsCertificate{
   415  				CertificateChain: &envoy_api_v2_core.DataSource{
   416  					Specifier: &envoy_api_v2_core.DataSource_InlineBytes{
   417  						InlineBytes: pemCert,
   418  					},
   419  				},
   420  				PrivateKey: &envoy_api_v2_core.DataSource{
   421  					Specifier: &envoy_api_v2_core.DataSource_InlineBytes{
   422  						InlineBytes: []byte(apoSecret.key),
   423  					},
   424  				},
   425  			},
   426  		}
   427  
   428  		endSecret, err := ptypes.MarshalAny(retSecret)
   429  		if err != nil {
   430  			zap.L().Error("SDS Server: Cannot marshall the secret")
   431  			return fmt.Errorf("SDS Server: Cannot marshall the secret")
   432  		}
   433  
   434  		resp.Resources = append(resp.Resources, endSecret)
   435  		if err = conn.stream.Send(resp); err != nil {
   436  			zap.L().Error("SDS Server: Failed to send the resp cert")
   437  			return err
   438  		}
   439  
   440  	}
   441  	return nil
   442  }
   443  
   444  func (s *SdsServer) checkSecretPresent(connID string, req *v2.DiscoveryRequest, token string) bool {
   445  	val, err := s.conncache.Get(connID)
   446  	if err != nil {
   447  		return false
   448  	}
   449  	e := val.(*clientConn)
   450  	return e.secret.ResourceName == req.ResourceNames[0] && e.secret.Token == token && e.secret.Version == req.VersionInfo
   451  }
   452  
   453  func createConnID(clientID, resourceName string) string {
   454  	temp := clientID + resourceName
   455  	zap.L().Debug("SDS Server: generated a unique ID", zap.String("connID", temp), zap.String("resource", resourceName))
   456  	return temp
   457  }
   458  
   459  // FetchSecrets gets the discovery request and call the Aporeto backend to fetch the certs.
   460  // 1. parse the discovery request.
   461  // 2. track the request.
   462  // 3. call the Aporeto api to generate the secret
   463  func (s *SdsServer) FetchSecrets(ctx context.Context, req *v2.DiscoveryRequest) (*v2.DiscoveryResponse, error) {
   464  	token := ""
   465  	metadata, ok := metadata.FromIncomingContext(ctx)
   466  	if !ok {
   467  		return nil, fmt.Errorf("unable to get metadata from incoming context")
   468  	}
   469  	if h, ok := metadata["authorization"]; ok {
   470  		if len(h) != 1 {
   471  			return nil, fmt.Errorf("credential token from %q must have 1 value in gRPC metadata but got %d", "authorization", len(h))
   472  		}
   473  		token = h[0]
   474  	}
   475  	zap.L().Info("SDS Server: IN stream secrets, token", zap.String("token", token))
   476  	secret := s.generateSecret(req, token)
   477  
   478  	resp := &v2.DiscoveryResponse{
   479  		TypeUrl: "type.googleapis.com/envoy.api.v2.auth.Secret",
   480  	}
   481  	retSecret := &envoy_api_v2_auth.Secret{
   482  		Name: secret.ResourceName,
   483  	}
   484  	if secret.RootCert != nil {
   485  		retSecret.Type = getRootCert(secret)
   486  	} else {
   487  		retSecret.Type = getTLScerts(secret)
   488  	}
   489  	endSecret, err := ptypes.MarshalAny(retSecret)
   490  	if err != nil {
   491  		zap.L().Error("SDS Server: Cannot marshall the secret")
   492  		return nil, err
   493  	}
   494  	resp.Resources = append(resp.Resources, endSecret)
   495  
   496  	if secret.RootCert != nil {
   497  		zap.L().Debug("SDS Server: Successfully sent root cert", zap.Any("rootCA", string(secret.RootCert)))
   498  	} else {
   499  		zap.L().Debug("SDS Server: Successfully sent default cert", zap.Any("default cert", string(secret.CertificateChain)))
   500  	}
   501  	return resp, nil
   502  }
   503  
   504  // generateSecret is the call which talks to the metadata API to fetch the certs.
   505  func (s *SdsServer) generateSecret(req *v2.DiscoveryRequest, token string) *secretItem {
   506  
   507  	var err error
   508  	var pemCert []byte
   509  	t := time.Now()
   510  	var expTime time.Time
   511  
   512  	if s.puInfo.Policy == nil {
   513  		zap.L().Error("SDS Server:  The policy is nil, Policy cannot be nil.")
   514  	}
   515  	// now fetch the certificates for the PU/Service.
   516  	certPEM, keyPEM, _ := s.puInfo.Policy.ServiceCertificates()
   517  	if certPEM == "" || keyPEM == "" {
   518  		zap.L().Error("SDS Server:  the certs are empty")
   519  		return nil
   520  	}
   521  
   522  	caPEM := s.secrets.CertAuthority()
   523  	if req.ResourceNames[0] == "default" {
   524  
   525  		expTime, _ = getExpTimeFromCert([]byte(certPEM))
   526  		pemCert, _ = buildCertChain([]byte(certPEM), caPEM)
   527  		if err != nil {
   528  			zap.L().Error("SDS Server: Cannot build the cert chain")
   529  			return nil
   530  		}
   531  
   532  	} else {
   533  
   534  		expTime, _ = getExpTimeFromCert(caPEM)
   535  		pemCert, err = getTopRootCa(caPEM)
   536  		if err != nil {
   537  			zap.L().Error("SDS Server:  Cannot build the Root cert chain")
   538  		}
   539  	}
   540  	if err != nil {
   541  		zap.L().Error("SDS Server: cannot get exp time", zap.Error(err))
   542  		return nil
   543  	}
   544  	if req.ResourceNames[0] == "default" {
   545  		return &secretItem{
   546  			CertificateChain: pemCert,
   547  			PrivateKey:       []byte(keyPEM),
   548  			//PrivateKey:   []byte(keyPEMdebug),
   549  			ResourceName: req.ResourceNames[0],
   550  			Token:        token,
   551  			CreatedTime:  t,
   552  			ExpireTime:   expTime,
   553  			Version:      t.String(),
   554  		}
   555  	}
   556  
   557  	return &secretItem{
   558  		RootCert:     pemCert,
   559  		ResourceName: req.ResourceNames[0],
   560  		Token:        token,
   561  		CreatedTime:  t,
   562  		ExpireTime:   expTime,
   563  		Version:      t.String(),
   564  	}
   565  
   566  }
   567  
   568  func buildCertChain(certPEM, caPEM []byte) ([]byte, error) {
   569  	zap.L().Debug("SDS Server: BEFORE in buildCertChain certPEM", zap.String("certPEM", string(certPEM)), zap.String("caPEM", string(caPEM)))
   570  	certChain := []*x509.Certificate{}
   571  	//certPEMBlock := caPEM
   572  	clientPEMBlock := certPEM
   573  	derBlock, _ := pem.Decode(clientPEMBlock)
   574  	if derBlock != nil {
   575  		if derBlock.Type == typeCertificate {
   576  			cert, err := x509.ParseCertificate(derBlock.Bytes)
   577  			if err != nil {
   578  				return nil, err
   579  			}
   580  			certChain = append(certChain, cert)
   581  		} else {
   582  			return nil, fmt.Errorf("invalid pem block type: %s", derBlock.Type)
   583  		}
   584  	}
   585  	var certDERBlock *pem.Block
   586  	for {
   587  		certDERBlock, caPEM = pem.Decode(caPEM)
   588  		if certDERBlock == nil {
   589  			break
   590  		}
   591  		if certDERBlock.Type == typeCertificate {
   592  			cert, err := x509.ParseCertificate(certDERBlock.Bytes)
   593  			if err != nil {
   594  				return nil, err
   595  			}
   596  			certChain = append(certChain, cert)
   597  		} else {
   598  			return nil, fmt.Errorf("invalid pem block type: %s", certDERBlock.Type)
   599  		}
   600  	}
   601  	by, _ := x509CertChainToPem(certChain)
   602  	zap.L().Debug("SDS Server: After building the cert chain", zap.String("certChain", string(by)))
   603  	return x509CertChainToPem(certChain)
   604  }
   605  
   606  // x509CertToPem converts x509 to byte.
   607  func x509CertToPem(cert *x509.Certificate) ([]byte, error) {
   608  	var pemBytes bytes.Buffer
   609  	if err := pem.Encode(&pemBytes, &pem.Block{Type: typeCertificate, Bytes: cert.Raw}); err != nil {
   610  		return nil, err
   611  	}
   612  	return pemBytes.Bytes(), nil
   613  }
   614  
   615  // x509CertChainToPem converts chain of x509 certs to byte.
   616  func x509CertChainToPem(certChain []*x509.Certificate) ([]byte, error) {
   617  	var pemBytes bytes.Buffer
   618  	for _, cert := range certChain {
   619  		if err := pem.Encode(&pemBytes, &pem.Block{Type: typeCertificate, Bytes: cert.Raw}); err != nil {
   620  			return nil, err
   621  		}
   622  	}
   623  	return pemBytes.Bytes(), nil
   624  }
   625  
   626  // getTopRootCa get the top root CA
   627  func getTopRootCa(certPEMBlock []byte) ([]byte, error) {
   628  	zap.L().Debug("SDS Server: BEFORE root cert", zap.String("root_cert", string(certPEMBlock)))
   629  	//rootCert := []*x509.Certificate{}
   630  	var certChain tls.Certificate
   631  	//certPEMBlock := []byte(rootcaBundle)
   632  	var certDERBlock *pem.Block
   633  	for {
   634  		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
   635  		if certDERBlock == nil {
   636  			break
   637  		}
   638  		if certDERBlock.Type == typeCertificate {
   639  			certChain.Certificate = append(certChain.Certificate, certDERBlock.Bytes)
   640  		}
   641  	}
   642  	zap.L().Debug("SDS Server: the root ca", zap.String("cert", string(certChain.Certificate[len(certChain.Certificate)-1])))
   643  	x509Cert, err := x509.ParseCertificate(certChain.Certificate[len(certChain.Certificate)-1])
   644  	if err != nil {
   645  		panic(err)
   646  	}
   647  	by, _ := x509CertToPem(x509Cert)
   648  	zap.L().Debug("SDS Server: After building the cert chain", zap.String("rootCert", string(by)))
   649  	return x509CertToPem(x509Cert)
   650  }
   651  
   652  // getExpTimeFromCert gets the exp time from the cert, assumning the cert is in pem encoded.
   653  func getExpTimeFromCert(cert []byte) (time.Time, error) {
   654  	block, _ := pem.Decode(cert)
   655  	if block == nil {
   656  		zap.L().Error("getExpTimeFromCert: error while pem decode")
   657  		return time.Time{}, fmt.Errorf("Cannot decode the pem certs")
   658  	}
   659  	x509Cert, err := x509.ParseCertificate(block.Bytes)
   660  	if err != nil {
   661  		zap.L().Error("failed to parse the certs", zap.Error(err))
   662  		return time.Time{}, err
   663  	}
   664  	return x509Cert.NotAfter, nil
   665  }
   666  
   667  func getRootCert(secret *secretItem) *envoy_api_v2_auth.Secret_ValidationContext {
   668  	return &envoy_api_v2_auth.Secret_ValidationContext{
   669  		ValidationContext: &envoy_api_v2_auth.CertificateValidationContext{
   670  			TrustedCa: &envoy_api_v2_core.DataSource{
   671  				Specifier: &envoy_api_v2_core.DataSource_InlineBytes{
   672  					InlineBytes: secret.RootCert,
   673  				},
   674  			},
   675  		},
   676  	}
   677  }
   678  
   679  func getTLScerts(secret *secretItem) *envoy_api_v2_auth.Secret_TlsCertificate {
   680  	return &envoy_api_v2_auth.Secret_TlsCertificate{
   681  		TlsCertificate: &envoy_api_v2_auth.TlsCertificate{
   682  			CertificateChain: &envoy_api_v2_core.DataSource{
   683  				Specifier: &envoy_api_v2_core.DataSource_InlineBytes{
   684  					InlineBytes: secret.CertificateChain,
   685  				},
   686  			},
   687  			PrivateKey: &envoy_api_v2_core.DataSource{
   688  				Specifier: &envoy_api_v2_core.DataSource_InlineBytes{
   689  					InlineBytes: secret.PrivateKey,
   690  				},
   691  			},
   692  		},
   693  	}
   694  }