package plugin import ( "context" "crypto/x509" "encoding/json" "time" "github.com/gogo/protobuf/types" "google.golang.org/grpc" "github.com/hashicorp/consul/agent/connect/ca" ) // providerPluginGRPCServer implements the CAServer interface for gRPC. type providerPluginGRPCServer struct { impl ca.Provider } func (p *providerPluginGRPCServer) Configure(_ context.Context, req *ConfigureRequest) (*Empty, error) { var rawConfig map[string]interface{} if err := json.Unmarshal(req.Config, &rawConfig); err != nil { return nil, err } return &Empty{}, p.impl.Configure(req.ClusterId, req.IsRoot, rawConfig) } func (p *providerPluginGRPCServer) GenerateRoot(context.Context, *Empty) (*Empty, error) { return &Empty{}, p.impl.GenerateRoot() } func (p *providerPluginGRPCServer) ActiveRoot(context.Context, *Empty) (*ActiveRootResponse, error) { pem, err := p.impl.ActiveRoot() return &ActiveRootResponse{CrtPem: pem}, err } func (p *providerPluginGRPCServer) GenerateIntermediateCSR(context.Context, *Empty) (*GenerateIntermediateCSRResponse, error) { pem, err := p.impl.GenerateIntermediateCSR() return &GenerateIntermediateCSRResponse{CsrPem: pem}, err } func (p *providerPluginGRPCServer) SetIntermediate(_ context.Context, req *SetIntermediateRequest) (*Empty, error) { return &Empty{}, p.impl.SetIntermediate(req.IntermediatePem, req.RootPem) } func (p *providerPluginGRPCServer) ActiveIntermediate(context.Context, *Empty) (*ActiveIntermediateResponse, error) { pem, err := p.impl.ActiveIntermediate() return &ActiveIntermediateResponse{CrtPem: pem}, err } func (p *providerPluginGRPCServer) GenerateIntermediate(context.Context, *Empty) (*GenerateIntermediateResponse, error) { pem, err := p.impl.GenerateIntermediate() return &GenerateIntermediateResponse{CrtPem: pem}, err } func (p *providerPluginGRPCServer) Sign(_ context.Context, req *SignRequest) (*SignResponse, error) { csr, err := x509.ParseCertificateRequest(req.Csr) if err != nil { return nil, err } crtPEM, err := p.impl.Sign(csr) return &SignResponse{CrtPem: crtPEM}, err } func (p *providerPluginGRPCServer) SignIntermediate(_ context.Context, req *SignIntermediateRequest) (*SignIntermediateResponse, error) { csr, err := x509.ParseCertificateRequest(req.Csr) if err != nil { return nil, err } crtPEM, err := p.impl.SignIntermediate(csr) return &SignIntermediateResponse{CrtPem: crtPEM}, err } func (p *providerPluginGRPCServer) CrossSignCA(_ context.Context, req *CrossSignCARequest) (*CrossSignCAResponse, error) { crt, err := x509.ParseCertificate(req.Crt) if err != nil { return nil, err } crtPEM, err := p.impl.CrossSignCA(crt) return &CrossSignCAResponse{CrtPem: crtPEM}, err } func (p *providerPluginGRPCServer) SupportsCrossSigning(context.Context, *Empty) (*SupportsCrossSigningResponse, error) { s := p.impl.SupportsCrossSigning() return &SupportsCrossSigningResponse{SupportsCrossSigning: s}, nil } func (p *providerPluginGRPCServer) MinLifetime(context.Context, *Empty) (*MinLifetimeResponse, error) { return &MinLifetimeResponse{MinLifetime: types.DurationProto(p.impl.MinLifetime())}, nil } func (p *providerPluginGRPCServer) Cleanup(context.Context, *Empty) (*Empty, error) { return &Empty{}, p.impl.Cleanup() } // providerPluginGRPCClient implements ca.Provider for acting as a client // to a remote CA provider plugin over gRPC. type providerPluginGRPCClient struct { client CAClient clientConn *grpc.ClientConn doneCtx context.Context } func (p *providerPluginGRPCClient) Configure( clusterId string, isRoot bool, rawConfig map[string]interface{}) error { config, err := json.Marshal(rawConfig) if err != nil { return err } _, err = p.client.Configure(p.doneCtx, &ConfigureRequest{ ClusterId: clusterId, IsRoot: isRoot, Config: config, }) return p.err(err) } func (p *providerPluginGRPCClient) GenerateRoot() error { _, err := p.client.GenerateRoot(p.doneCtx, &Empty{}) return p.err(err) } func (p *providerPluginGRPCClient) ActiveRoot() (string, error) { resp, err := p.client.ActiveRoot(p.doneCtx, &Empty{}) if err != nil { return "", p.err(err) } return resp.CrtPem, nil } func (p *providerPluginGRPCClient) GenerateIntermediateCSR() (string, error) { resp, err := p.client.GenerateIntermediateCSR(p.doneCtx, &Empty{}) if err != nil { return "", p.err(err) } return resp.CsrPem, nil } func (p *providerPluginGRPCClient) SetIntermediate(intermediatePEM, rootPEM string) error { _, err := p.client.SetIntermediate(p.doneCtx, &SetIntermediateRequest{ IntermediatePem: intermediatePEM, RootPem: rootPEM, }) return p.err(err) } func (p *providerPluginGRPCClient) ActiveIntermediate() (string, error) { resp, err := p.client.ActiveIntermediate(p.doneCtx, &Empty{}) if err != nil { return "", p.err(err) } return resp.CrtPem, nil } func (p *providerPluginGRPCClient) GenerateIntermediate() (string, error) { resp, err := p.client.GenerateIntermediate(p.doneCtx, &Empty{}) if err != nil { return "", p.err(err) } return resp.CrtPem, nil } func (p *providerPluginGRPCClient) Sign(csr *x509.CertificateRequest) (string, error) { resp, err := p.client.Sign(p.doneCtx, &SignRequest{ Csr: csr.Raw, }) if err != nil { return "", p.err(err) } return resp.CrtPem, nil } func (p *providerPluginGRPCClient) SignIntermediate(csr *x509.CertificateRequest) (string, error) { resp, err := p.client.SignIntermediate(p.doneCtx, &SignIntermediateRequest{ Csr: csr.Raw, }) if err != nil { return "", p.err(err) } return resp.CrtPem, nil } func (p *providerPluginGRPCClient) CrossSignCA(crt *x509.Certificate) (string, error) { resp, err := p.client.CrossSignCA(p.doneCtx, &CrossSignCARequest{ Crt: crt.Raw, }) if err != nil { return "", p.err(err) } return resp.CrtPem, nil } func (p *providerPluginGRPCClient) SupportsCrossSigning() bool { resp, _ := p.client.SupportsCrossSigning(p.doneCtx, &Empty{}) return resp.SupportsCrossSigning } func (p *providerPluginGRPCClient) MinLifetime() time.Duration { resp, _ := p.client.MinLifetime(p.doneCtx, &Empty{}) min, _ := types.DurationFromProto(resp.MinLifetime) return min } func (p *providerPluginGRPCClient) Cleanup() error { _, err := p.client.Cleanup(p.doneCtx, &Empty{}) return p.err(err) } func (p *providerPluginGRPCClient) err(err error) error { if err := p.doneCtx.Err(); err != nil { return err } return err } // Verification var _ CAServer = &providerPluginGRPCServer{} var _ ca.Provider = &providerPluginGRPCClient{}