mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 06:50:18 +00:00
NOISSUE - Add ability to handle both tls cert file and raw cert data (#2871)
Deploy GitHub Pages / swagger-ui (push) Has been cancelled
Continuous Delivery / Build and Push (push) Has been cancelled
Check the consistency of generated files / check-generated-files (push) Has been cancelled
Check License Header / check-license (push) Has been cancelled
Deploy GitHub Pages / swagger-ui (push) Has been cancelled
Continuous Delivery / Build and Push (push) Has been cancelled
Check the consistency of generated files / check-generated-files (push) Has been cancelled
Check License Header / check-license (push) Has been cancelled
Signed-off-by: Jilks Smith <smithjilks@gmail.com>
This commit is contained in:
+2
-2
@@ -255,7 +255,7 @@ func proxyHTTP(ctx context.Context, cfg server.Config, logger *slog.Logger, sess
|
||||
TargetPath: targetHTTPPath,
|
||||
}
|
||||
if cfg.CertFile != "" || cfg.KeyFile != "" {
|
||||
tlsCert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
|
||||
tlsCert, err := server.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -275,7 +275,7 @@ func proxyHTTP(ctx context.Context, cfg server.Config, logger *slog.Logger, sess
|
||||
go func() {
|
||||
errCh <- mp.Listen(ctx)
|
||||
}()
|
||||
logger.Info(fmt.Sprintf("%s service HTTPS server listening at %s:%s with TLS cert %s and key %s", svcName, cfg.Host, cfg.Port, cfg.CertFile, cfg.KeyFile))
|
||||
logger.Info(fmt.Sprintf("%s service HTTPS server listening at %s:%s with TLS", svcName, cfg.Host, cfg.Port))
|
||||
default:
|
||||
go func() {
|
||||
errCh <- mp.Listen(ctx)
|
||||
|
||||
@@ -5,12 +5,11 @@ package grpcclient
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
"github.com/absmach/supermq/pkg/server"
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
@@ -112,22 +111,18 @@ func connect(cfg Config) (*grpc.ClientConn, security, error) {
|
||||
tlsConfig := &tls.Config{}
|
||||
|
||||
// Loading root ca certificates file
|
||||
rootCA, err := os.ReadFile(cfg.ServerCAFile)
|
||||
rootCA, err := server.LoadRootCACerts(cfg.ServerCAFile)
|
||||
if err != nil {
|
||||
return nil, secure, fmt.Errorf("failed to load root ca file: %w", err)
|
||||
return nil, secure, fmt.Errorf("failed to load root ca: %w", err)
|
||||
}
|
||||
if len(rootCA) > 0 {
|
||||
capool := x509.NewCertPool()
|
||||
if !capool.AppendCertsFromPEM(rootCA) {
|
||||
return nil, secure, fmt.Errorf("failed to append root ca to tls.Config")
|
||||
}
|
||||
tlsConfig.RootCAs = capool
|
||||
if rootCA != nil {
|
||||
tlsConfig.RootCAs = rootCA
|
||||
secure = withTLS
|
||||
}
|
||||
|
||||
// Loading mtls certificates file
|
||||
if cfg.ClientCert != "" || cfg.ClientKey != "" {
|
||||
certificate, err := tls.LoadX509KeyPair(cfg.ClientCert, cfg.ClientKey)
|
||||
certificate, err := server.LoadX509KeyPair(cfg.ClientCert, cfg.ClientKey)
|
||||
if err != nil {
|
||||
return nil, secure, fmt.Errorf("failed to client certificate and key %w", err)
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func TestHandler(t *testing.T) {
|
||||
Timeout: time.Second,
|
||||
ServerCAFile: "invalid",
|
||||
},
|
||||
err: errors.New("failed to load root ca file: open invalid: no such file or directory"),
|
||||
err: errors.New("failed to load root ca: failed to append root ca to tls.Config"),
|
||||
},
|
||||
{
|
||||
desc: "failed with invalid server CA file as cert key",
|
||||
@@ -74,7 +74,7 @@ func TestHandler(t *testing.T) {
|
||||
Timeout: time.Second,
|
||||
ServerCAFile: "../../docker/ssl/certs/supermq-server.key",
|
||||
},
|
||||
err: errors.New("failed to append root ca to tls.Config"),
|
||||
err: errors.New("failed to load root ca: failed to append root ca to tls.Config"),
|
||||
},
|
||||
{
|
||||
desc: "failed with invalid client cert",
|
||||
@@ -85,7 +85,7 @@ func TestHandler(t *testing.T) {
|
||||
ClientKey: "../../docker/ssl/certs/supermq-server.key",
|
||||
ServerCAFile: "../../docker/ssl/certs/ca.crt",
|
||||
},
|
||||
err: errors.New("failed to client certificate and key open invalid: no such file or directory"),
|
||||
err: errors.New("failed to client certificate and key tls: failed to find any PEM data in certificate input"),
|
||||
},
|
||||
{
|
||||
desc: "failed with invalid client key",
|
||||
@@ -96,7 +96,7 @@ func TestHandler(t *testing.T) {
|
||||
ClientKey: "invalid",
|
||||
ServerCAFile: "../../docker/ssl/certs/ca.crt",
|
||||
},
|
||||
err: errors.New("failed to client certificate and key open invalid: no such file or directory"),
|
||||
err: errors.New("failed to client certificate and key tls: failed to find any PEM data in key input"),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+9
-21
@@ -10,7 +10,6 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/supermq/pkg/server"
|
||||
@@ -56,7 +55,7 @@ func (s *grpcServer) Start() error {
|
||||
|
||||
switch {
|
||||
case s.Config.CertFile != "" || s.Config.KeyFile != "":
|
||||
certificate, err := tls.LoadX509KeyPair(s.Config.CertFile, s.Config.KeyFile)
|
||||
certificate, err := server.LoadX509KeyPair(s.Config.CertFile, s.Config.KeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load auth gRPC client certificates: %w", err)
|
||||
}
|
||||
@@ -67,32 +66,28 @@ func (s *grpcServer) Start() error {
|
||||
|
||||
var mtlsCA string
|
||||
// Loading Server CA file
|
||||
rootCA, err := loadCertFile(s.Config.ServerCAFile)
|
||||
rootCA, err := server.LoadRootCACerts(s.Config.ServerCAFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load root ca file: %w", err)
|
||||
}
|
||||
if len(rootCA) > 0 {
|
||||
if rootCA != nil {
|
||||
if tlsConfig.RootCAs == nil {
|
||||
tlsConfig.RootCAs = x509.NewCertPool()
|
||||
}
|
||||
if !tlsConfig.RootCAs.AppendCertsFromPEM(rootCA) {
|
||||
return fmt.Errorf("failed to append root ca to tls.Config")
|
||||
}
|
||||
tlsConfig.RootCAs = rootCA
|
||||
mtlsCA = fmt.Sprintf("root ca %s", s.Config.ServerCAFile)
|
||||
}
|
||||
|
||||
// Loading Client CA File
|
||||
clientCA, err := loadCertFile(s.Config.ClientCAFile)
|
||||
clientCA, err := server.LoadRootCACerts(s.Config.ClientCAFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load client ca file: %w", err)
|
||||
}
|
||||
if len(clientCA) > 0 {
|
||||
if clientCA != nil {
|
||||
if tlsConfig.ClientCAs == nil {
|
||||
tlsConfig.ClientCAs = x509.NewCertPool()
|
||||
}
|
||||
if !tlsConfig.ClientCAs.AppendCertsFromPEM(clientCA) {
|
||||
return fmt.Errorf("failed to append client ca to tls.Config")
|
||||
}
|
||||
tlsConfig.ClientCAs = clientCA
|
||||
mtlsCA = fmt.Sprintf("%s client ca %s", mtlsCA, s.Config.ClientCAFile)
|
||||
}
|
||||
creds = grpc.Creds(credentials.NewTLS(tlsConfig))
|
||||
@@ -100,9 +95,9 @@ func (s *grpcServer) Start() error {
|
||||
case mtlsCA != "":
|
||||
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
|
||||
creds = grpc.Creds(credentials.NewTLS(tlsConfig))
|
||||
s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s with TLS/mTLS cert %s , key %s and %s", s.Name, s.Address, s.Config.CertFile, s.Config.KeyFile, mtlsCA))
|
||||
s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s with TLS/mTLS", s.Name, s.Address))
|
||||
default:
|
||||
s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s with TLS cert %s and key %s", s.Name, s.Address, s.Config.CertFile, s.Config.KeyFile))
|
||||
s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s with TLS cert", s.Name, s.Address))
|
||||
}
|
||||
default:
|
||||
s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s without TLS", s.Name, s.Address))
|
||||
@@ -145,10 +140,3 @@ func (s *grpcServer) Stop() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadCertFile(certFile string) ([]byte, error) {
|
||||
if certFile != "" {
|
||||
return os.ReadFile(certFile)
|
||||
}
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
+17
-2
@@ -5,6 +5,7 @@ package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@@ -39,10 +40,23 @@ func (s *httpServer) Start() error {
|
||||
s.Protocol = httpProtocol
|
||||
switch {
|
||||
case s.Config.CertFile != "" || s.Config.KeyFile != "":
|
||||
certs, err := server.LoadX509KeyPair(s.Config.CertFile, s.Config.KeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s.server.TLSConfig == nil {
|
||||
s.server.TLSConfig = &tls.Config{}
|
||||
}
|
||||
|
||||
tlsConf := s.server.TLSConfig.Clone()
|
||||
tlsConf.Certificates = append(tlsConf.Certificates, certs)
|
||||
s.server.TLSConfig = tlsConf
|
||||
s.Protocol = httpsProtocol
|
||||
s.Logger.Info(fmt.Sprintf("%s service %s server listening at %s with TLS cert %s and key %s", s.Name, s.Protocol, s.Address, s.Config.CertFile, s.Config.KeyFile))
|
||||
|
||||
s.Logger.Info(fmt.Sprintf("%s service %s server listening at %s with TLS", s.Name, s.Protocol, s.Address))
|
||||
go func() {
|
||||
errCh <- s.server.ListenAndServeTLS(s.Config.CertFile, s.Config.KeyFile)
|
||||
errCh <- s.server.ListenAndServeTLS("", "")
|
||||
}()
|
||||
default:
|
||||
s.Logger.Info(fmt.Sprintf("%s service %s server listening at %s without TLS", s.Name, s.Protocol, s.Address))
|
||||
@@ -50,6 +64,7 @@ func (s *httpServer) Start() error {
|
||||
errCh <- s.server.ListenAndServe()
|
||||
}()
|
||||
}
|
||||
|
||||
select {
|
||||
case <-s.Ctx.Done():
|
||||
return s.Stop()
|
||||
|
||||
@@ -4,6 +4,8 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
@@ -88,3 +90,40 @@ func StopSignalHandler(ctx context.Context, cancel context.CancelFunc, logger *s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func ReadFileOrData(input string) ([]byte, error) {
|
||||
if _, err := os.Stat(input); err == nil {
|
||||
return os.ReadFile(input)
|
||||
}
|
||||
return []byte(input), nil
|
||||
}
|
||||
|
||||
func LoadX509KeyPair(certFile, keyFile string) (tls.Certificate, error) {
|
||||
cert, err := ReadFileOrData(certFile)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, fmt.Errorf("failed to read cert: %v", err)
|
||||
}
|
||||
|
||||
key, err := ReadFileOrData(keyFile)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, fmt.Errorf("failed to read key: %v", err)
|
||||
}
|
||||
|
||||
return tls.X509KeyPair(cert, key)
|
||||
}
|
||||
|
||||
func LoadRootCACerts(input string) (*x509.CertPool, error) {
|
||||
pemData, err := ReadFileOrData(input)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load root CA data: %w", err)
|
||||
}
|
||||
|
||||
if len(pemData) > 0 {
|
||||
capool := x509.NewCertPool()
|
||||
if !capool.AppendCertsFromPEM(pemData) {
|
||||
return nil, fmt.Errorf("failed to append root ca to tls.Config")
|
||||
}
|
||||
return capool, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user