package adapter import ( "crypto/tls" "crypto/x509" "errors" "os" "github.com/apache/pulsar-client-go/pulsar" "github.com/apache/pulsar-client-go/pulsar/auth" "go.yandata.net/iod/iod/trustlog-sdk/api/logger" ) // tlsConfigProvider defines the interface for TLS configuration. type tlsConfigProvider interface { GetTLSTrustCertsFilePath() string GetTLSCertificateFilePath() string GetTLSKeyFilePath() string GetTLSAllowInsecureConnection() bool } // configureTLSForClient configures TLS/mTLS settings for the Pulsar client. func configureTLSForClient(opts *pulsar.ClientOptions, config tlsConfigProvider, logger logger.Logger) error { // If no TLS configuration is provided, skip TLS setup if config.GetTLSTrustCertsFilePath() == "" && config.GetTLSCertificateFilePath() == "" && config.GetTLSKeyFilePath() == "" { return nil } // Configure TLS trust certificates if config.GetTLSTrustCertsFilePath() != "" { if _, err := os.ReadFile(config.GetTLSTrustCertsFilePath()); err != nil { return errors.Join(err, errors.New("failed to read TLS trust certificates file")) } opts.TLSTrustCertsFilePath = config.GetTLSTrustCertsFilePath() logger.Debug( "TLS trust certificates configured", "path", config.GetTLSTrustCertsFilePath(), ) } // Configure TLS allow insecure connection opts.TLSAllowInsecureConnection = config.GetTLSAllowInsecureConnection() // Configure mTLS authentication if both certificate and key are provided if config.GetTLSCertificateFilePath() != "" && config.GetTLSKeyFilePath() != "" { // Load client certificate and key cert, err := tls.LoadX509KeyPair( config.GetTLSCertificateFilePath(), config.GetTLSKeyFilePath(), ) if err != nil { return errors.Join(err, errors.New("failed to load client certificate and key")) } // Create TLS authentication provider // Pulsar Go client uses auth.NewAuthenticationTLS with certificate and key file paths tlsAuth := auth.NewAuthenticationTLS( config.GetTLSCertificateFilePath(), config.GetTLSKeyFilePath(), ) opts.Authentication = tlsAuth logger.Debug( "mTLS authentication configured", "cert", config.GetTLSCertificateFilePath(), "key", config.GetTLSKeyFilePath(), ) // Verify the certificate is valid if _, parseErr := x509.ParseCertificate(cert.Certificate[0]); parseErr != nil { return errors.Join(parseErr, errors.New("invalid client certificate")) } } else if config.GetTLSCertificateFilePath() != "" || config.GetTLSKeyFilePath() != "" { return errors.New( "both TLS certificate and key file paths must be provided for mTLS authentication", ) } return nil } // GetTLSTrustCertsFilePath returns the TLS trust certificates file path for PublisherConfig. func (c PublisherConfig) GetTLSTrustCertsFilePath() string { return c.TLSTrustCertsFilePath } // GetTLSCertificateFilePath returns the TLS certificate file path for PublisherConfig. func (c PublisherConfig) GetTLSCertificateFilePath() string { return c.TLSCertificateFilePath } // GetTLSKeyFilePath returns the TLS key file path for PublisherConfig. func (c PublisherConfig) GetTLSKeyFilePath() string { return c.TLSKeyFilePath } // GetTLSAllowInsecureConnection returns whether to allow insecure TLS connections for PublisherConfig. func (c PublisherConfig) GetTLSAllowInsecureConnection() bool { return c.TLSAllowInsecureConnection } // GetTLSTrustCertsFilePath returns the TLS trust certificates file path for SubscriberConfig. func (c SubscriberConfig) GetTLSTrustCertsFilePath() string { return c.TLSTrustCertsFilePath } // GetTLSCertificateFilePath returns the TLS certificate file path for SubscriberConfig. func (c SubscriberConfig) GetTLSCertificateFilePath() string { return c.TLSCertificateFilePath } // GetTLSKeyFilePath returns the TLS key file path for SubscriberConfig. func (c SubscriberConfig) GetTLSKeyFilePath() string { return c.TLSKeyFilePath } // GetTLSAllowInsecureConnection returns whether to allow insecure TLS connections for SubscriberConfig. func (c SubscriberConfig) GetTLSAllowInsecureConnection() bool { return c.TLSAllowInsecureConnection }