Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/minio/sidekick

go 1.23

toolchain go1.23.5
toolchain go1.23.7

require (
github.com/dustin/go-humanize v1.0.1
Expand Down
8 changes: 7 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ var (
log2 *logrus.Logger
globalHostBalance string
globalTLSCert atomic.Pointer[[]byte]
globalKeyPassword string
)

const (
Expand Down Expand Up @@ -1073,6 +1074,7 @@ func sidekickMain(ctx *cli.Context) {
if globalHostBalance == "" {
globalHostBalance = "least"
}
globalKeyPassword = ctx.GlobalString("key-password")

tlsMaxVersion := uint16(tls.VersionTLS13)
switch tlsMax := ctx.GlobalString("tls-max"); tlsMax {
Expand Down Expand Up @@ -1149,7 +1151,7 @@ func sidekickMain(ctx *cli.Context) {
ErrorLog: log.New(io.Discard, "", 0), // Turn-off random logging by Go stdlib. From MinIO server implementation.
}
if ctx.String("cert") != "" && ctx.String("key") != "" {
manager, err := certs.NewManager(context.Background(), ctx.String("cert"), ctx.String("key"), tls.LoadX509KeyPair)
manager, err := certs.NewManager(context.Background(), ctx.String("cert"), ctx.String("key"), LoadX509KeyPair)
if err != nil {
console.Fatalln(err)
}
Expand Down Expand Up @@ -1347,6 +1349,10 @@ func main() {
Name: "key",
Usage: "server private key file",
},
cli.StringFlag{
Name: "key-password",
Usage: "server private key password",
},
cli.StringFlag{
Name: "pprof",
Usage: "start and listen for profiling on the specified address (e.g. `:1337`)",
Expand Down
41 changes: 41 additions & 0 deletions tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import (
"crypto/elliptic"
crand "crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"errors"
"fmt"
"math/big"
"net"
Expand Down Expand Up @@ -122,3 +124,42 @@ func generateTLSCertKey(host string) ([]byte, []byte, error) {

return certOut.Bytes(), keyOut.Bytes(), nil
}

// LoadX509KeyPair - load an X509 key pair (private key , certificate)
// from the provided paths. The private key may be encrypted and is
// decrypted using the flags: --key-password.
//
//nolint:staticcheck
func LoadX509KeyPair(certFile, keyFile string) (tls.Certificate, error) {
certPEMBlock, err := os.ReadFile(certFile)
if err != nil {
return tls.Certificate{}, fmt.Errorf("unable to read the public key: %w", err)
}
keyPEMBlock, err := os.ReadFile(keyFile)
if err != nil {
return tls.Certificate{}, fmt.Errorf("unable to read the private key: %w", err)
}
key, rest := pem.Decode(keyPEMBlock)
if len(rest) > 0 {
return tls.Certificate{}, errors.New("the private key contains additional data")
}
if key == nil {
return tls.Certificate{}, errors.New("the private key is not readable")
}
if x509.IsEncryptedPEMBlock(key) {
password := globalKeyPassword
if len(password) == 0 {
return tls.Certificate{}, errors.New("the private key is encrypted, please set the flag --key-password")
}
decryptedKey, decErr := x509.DecryptPEMBlock(key, []byte(password))
if decErr != nil {
return tls.Certificate{}, fmt.Errorf("unable to decrypt private key: %w", decErr)
}
keyPEMBlock = pem.EncodeToMemory(&pem.Block{Type: key.Type, Bytes: decryptedKey})
}
cert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock)
if err != nil {
return tls.Certificate{}, fmt.Errorf("unable to load certs: %w", err)
}
return cert, nil
}
Loading