Skip to content

Commit cca9cfe

Browse files
committed
added support for password protected TLS key file
1 parent 099d7b6 commit cca9cfe

3 files changed

Lines changed: 102 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
### Added
1010
- Upcoming changes...
1111

12+
## [1.2.0] - 2023-05-18
13+
### Added
14+
- Added support for password protected TLS Key Files (`Password`)
15+
1216
## [1.1.0] - 2023-05-08
1317
### Added
1418
- Added log output configuration options (`OutputPaths`)
@@ -50,3 +54,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5054
[0.5.0]: https://github.com/scanoss/api.go/compare/v0.4.1...v0.5.0
5155
[0.7.0]: https://github.com/scanoss/api.go/compare/v0.5.0...v0.7.0
5256
[1.0.0]: https://github.com/scanoss/api.go/compare/v0.7.0...v1.0.0
57+
[1.1.0]: https://github.com/scanoss/api.go/compare/v1.0.0...v1.1.0
58+
[1.2.0]: https://github.com/scanoss/api.go/compare/v1.1.0...v1.2.0

pkg/config/server_config.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ type ServerConfig struct {
6060
ScanningURL string `env:"SCANOSS_API_URL"` // URL to present back in API responses - default https://osskb.org/api
6161
}
6262
TLS struct {
63-
CertFile string `env:"SCAN_TLS_CERT"` // TLS Certificate
64-
KeyFile string `env:"SCAN_TLS_KEY"` // Private TLS Key
63+
CertFile string `env:"SCAN_TLS_CERT"` // TLS Certificate
64+
KeyFile string `env:"SCAN_TLS_KEY"` // Private TLS Key
65+
Password string `env:"SCAN_TLS_PASSWD"` // TLS Decryption Password
6566
}
6667
Filtering struct {
6768
AllowListFile string `env:"SCAN_ALLOW_LIST"` // Allow list file for incoming connections

pkg/protocol/rest/server.go

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ package rest
2020

2121
import (
2222
"context"
23+
"crypto/tls"
24+
"crypto/x509"
25+
"encoding/pem"
2326
"errors"
2427
"fmt"
2528
"net/http"
@@ -79,7 +82,8 @@ func RunServer(config *myconfig.ServerConfig) error {
7982
var httpErr error
8083
if startTLS {
8184
zlog.S.Infof("starting REST server with TLS on %v ...", srv.Addr)
82-
httpErr = srv.ListenAndServeTLS(config.TLS.CertFile, config.TLS.KeyFile)
85+
loadTLSConfig(config, srv)
86+
httpErr = srv.ListenAndServeTLS("", "")
8387
} else {
8488
zlog.S.Infof("starting REST server on %v ...", srv.Addr)
8589
httpErr = srv.ListenAndServe()
@@ -104,6 +108,94 @@ func RunServer(config *myconfig.ServerConfig) error {
104108
return nil
105109
}
106110

111+
// loadTLSConfig loads the TLS config into memory (decrypting if required) and updates the Server config.
112+
func loadTLSConfig(config *myconfig.ServerConfig, srv *http.Server) {
113+
pemBlocks := loadCertFile(config)
114+
pkey := loadPrivateKey(config)
115+
c, err := tls.X509KeyPair(pem.EncodeToMemory(pemBlocks[0]), pkey)
116+
if err != nil {
117+
zlog.S.Panicf("Failed to load TLS key pair (%v - %v): %v", config.TLS.KeyFile, config.TLS.CertFile, err)
118+
}
119+
cfg := &tls.Config{
120+
MinVersion: tls.VersionTLS12,
121+
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
122+
CipherSuites: []uint16{
123+
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
124+
},
125+
Certificates: []tls.Certificate{c},
126+
}
127+
// tls.TLS_RSA_WITH_AES_256_CBC_SHA,
128+
// tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
129+
// tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
130+
// tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
131+
// tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
132+
srv.TLSConfig = cfg
133+
srv.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0)
134+
}
135+
136+
// loadCertFile load the certificate file into memory to use for hosting a TLS endpoint.
137+
func loadCertFile(config *myconfig.ServerConfig) []*pem.Block {
138+
b, err := os.ReadFile(config.TLS.CertFile)
139+
if err != nil {
140+
zlog.S.Panicf("Failed to load Cert file - %v: %v", config.TLS.CertFile, err)
141+
}
142+
var pemBlocks []*pem.Block
143+
var v *pem.Block
144+
for {
145+
v, b = pem.Decode(b)
146+
if v == nil {
147+
break
148+
}
149+
if v.Type != "RSA PRIVATE KEY" && v.Type != "PRIVATE KEY" {
150+
pemBlocks = append(pemBlocks, v)
151+
} else {
152+
zlog.S.Warnf("Unknown certificate type (%v): %v", config.TLS.CertFile, v.Type)
153+
}
154+
}
155+
return pemBlocks
156+
}
157+
158+
// loadPrivateKey loads the private key from file and attempt to decrypt it (if it's encrypted).
159+
func loadPrivateKey(config *myconfig.ServerConfig) []byte {
160+
var v *pem.Block
161+
var pkey []byte
162+
b, err := os.ReadFile(config.TLS.KeyFile)
163+
if err != nil {
164+
zlog.S.Panicf("Failed to load Key file - %v: %v", config.TLS.KeyFile, err)
165+
}
166+
for {
167+
v, b = pem.Decode(b)
168+
if v == nil {
169+
break
170+
}
171+
if v.Type == "RSA PRIVATE KEY" || v.Type == "PRIVATE KEY" {
172+
zlog.S.Debugf("Private Key: %v - %v", v.Type, v.Headers)
173+
// pvt, err := openssl.LoadPrivateKeyFromPEMWithPassword(encryptedPEM, passPhrase)
174+
//nolint:staticcheck
175+
if x509.IsEncryptedPEMBlock(v) {
176+
if len(config.TLS.Password) == 0 {
177+
zlog.S.Panicf("Need to configure TLS Password to decrypt encrypted Key file: %v", config.TLS.KeyFile)
178+
}
179+
zlog.S.Infof("Decrypting key...")
180+
//nolint:staticcheck
181+
pkey, err = x509.DecryptPEMBlock(v, []byte(config.TLS.Password))
182+
if err != nil {
183+
zlog.S.Panicf("Failed to decrypt Key File (%v): %v", config.TLS.KeyFile, err)
184+
}
185+
pkey = pem.EncodeToMemory(&pem.Block{
186+
Type: v.Type,
187+
Bytes: pkey,
188+
})
189+
} else {
190+
pkey = pem.EncodeToMemory(v)
191+
}
192+
} else {
193+
zlog.S.Warnf("Unexpected certificate type (%v): %v", config.TLS.KeyFile, v.Type)
194+
}
195+
}
196+
return pkey
197+
}
198+
107199
// checkFile validates if the given file exists or not.
108200
func checkFile(filename string) (bool, error) {
109201
if len(filename) == 0 {

0 commit comments

Comments
 (0)