Skip to content

Commit

Permalink
Merge pull request #2 from ikaakkola/master
Browse files Browse the repository at this point in the history
Support multiple certificates for ssh-inscribe server
  • Loading branch information
aakso authored Jan 23, 2019
2 parents 8b0035b + 2a180ec commit d07feec
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*~
.DS_Store
build
.vscode
58 changes: 55 additions & 3 deletions pkg/server/config.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
package server

import (
"crypto/tls"
"path"

"github.com/aakso/ssh-inscribe/pkg/globals"

"github.com/pkg/errors"
)

type CertificateConfig struct {
Certificates []tls.Certificate
CertificateMap map[string]*tls.Certificate
}

type AuthBackend struct {
Type string
Config string
Expand All @@ -16,6 +24,9 @@ type Config struct {
Listen string
TLSCertFile string `yaml:"TLSCertFile"`
TLSKeyFile string `yaml:"TLSKeyFile"`
TLSCertFiles []string `yaml:"TLSCertFiles"`
TLSKeyFiles []string `yaml:"TLSKeyFiles"`
TLSCertNames []string `yaml:"TLSCertNames"`
AuthBackends []AuthBackend `yaml:"authBackends"`
DefaultAuthBackends []string `yaml:"defaultAuthBackends"`
MaxCertLifetime string `yaml:"maxCertLifetime"`
Expand All @@ -28,9 +39,11 @@ type Config struct {
}

var Defaults *Config = &Config{
Listen: ":8540",
TLSCertFile: "",
TLSKeyFile: "",
Listen: ":8540",
TLSCertFile: "",
TLSKeyFile: "",
TLSCertFiles: []string{},
TLSKeyFiles: []string{},
AuthBackends: []AuthBackend{
AuthBackend{
Type: "authfile",
Expand All @@ -47,3 +60,42 @@ var Defaults *Config = &Config{
CertSigningKeyFingerprint: "",
TokenSigningKey: "",
}

func (c Config) GetCertificateMap() (cc CertificateConfig, err error) {
cc = CertificateConfig{
Certificates: []tls.Certificate{},
CertificateMap: make(map[string]*tls.Certificate),
}

// Single certificate has no name configuration
if c.TLSCertFile != "" && c.TLSKeyFile != "" {
if len(c.TLSCertFiles) > 0 {
return cc, errors.New("Unsupported configuration, either set TLSCertFile or TLSCertFiles, not both")
}

var certificate, err = tls.LoadX509KeyPair(c.TLSCertFile, c.TLSKeyFile)
if err != nil {
return cc, err
}
cc.Certificates = append(cc.Certificates, certificate)
return cc, nil
}

if len(c.TLSCertFiles) > 0 && len(c.TLSKeyFiles) > 0 && len(c.TLSCertNames) > 0 {
if (len(c.TLSCertFiles) != len(c.TLSKeyFiles)) || (len(c.TLSCertFiles) != len(c.TLSCertNames)) {
return cc, errors.New("TLSCertFiles, TLSKeyFiles and TLSCertNames must contain same number of elements")
}

cc.Certificates = make([]tls.Certificate, len(c.TLSCertFiles))
for index, cert := range c.TLSCertFiles {
var certificate, err = tls.LoadX509KeyPair(cert, c.TLSKeyFiles[index])
if err != nil {
return cc, err
}
cc.Certificates[index] = certificate
cc.CertificateMap[c.TLSCertNames[index]] = &cc.Certificates[index]
}
return cc, nil
}
return cc, nil
}
35 changes: 31 additions & 4 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package server

import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
Expand Down Expand Up @@ -32,10 +33,36 @@ func (s *Server) Start() error {
var err error
log := Log.WithField("server_version", globals.Version())
s.web.Logger.SetOutput(ioutil.Discard)
certFile, keyFile := s.config.TLSCertFile, s.config.TLSKeyFile
if certFile != "" && keyFile != "" {
log.WithField("listen", fmt.Sprintf("https://%s", s.config.Listen)).Info("server starting")
err = s.web.StartTLS(s.config.Listen, certFile, keyFile)

cc, err := s.config.GetCertificateMap()
if err != nil {
return errors.Wrap(err, "invalid certificate configuration")
}

if len(cc.Certificates) > 0 {
// Configure TLSServer before starting
tlsServer := s.web.TLSServer
tlsServer.TLSConfig = new(tls.Config)

if len(cc.Certificates) == 1 {
tlsServer.TLSConfig.Certificates = make([]tls.Certificate, 1)
tlsServer.TLSConfig.Certificates[0] = cc.Certificates[0]
} else {
tlsServer.TLSConfig.NameToCertificate = cc.CertificateMap
tlsServer.TLSConfig.Certificates = cc.Certificates
}

tlsServer.Addr = s.config.Listen
if !s.web.DisableHTTP2 {
tlsServer.TLSConfig.NextProtos = append(tlsServer.TLSConfig.NextProtos, "h2")
}
log.WithField("listen", fmt.Sprintf("https://%s", s.config.Listen)).WithField(
"certificates", fmt.Sprintf("%d", len(cc.Certificates))).Info("server starting")

err = s.web.StartServer(tlsServer)
if err != nil {
return errors.Wrap(err, "cannot start server")
}
} else {
log.WithField("listen", fmt.Sprintf("http://%s", s.config.Listen)).Warn("server starting without TLS")
err = s.web.Start(s.config.Listen)
Expand Down

0 comments on commit d07feec

Please sign in to comment.