mirror of https://github.com/docker/docs.git
Allow client CAs to be provided to notary-signer.
Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
parent
daa36b43b7
commit
bbf941d198
|
@ -1,10 +1,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
_ "expvar"
|
_ "expvar"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -68,6 +70,30 @@ func passphraseRetriever(keyName, alias string, createNew bool, attempts int) (p
|
||||||
return passphrase, false, nil
|
return passphrase, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parses and sets up the TLS for the signer http + grpc server
|
||||||
|
func signerTLS(configuration *viper.Viper, printUsage bool) (*tls.Config, error) {
|
||||||
|
certFile := configuration.GetString("server.cert_file")
|
||||||
|
keyFile := configuration.GetString("server.key_file")
|
||||||
|
if certFile == "" || keyFile == "" {
|
||||||
|
if printUsage {
|
||||||
|
usage()
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Certificate and key are mandatory")
|
||||||
|
}
|
||||||
|
|
||||||
|
clientCAFile := configuration.GetString("server.client_ca_file")
|
||||||
|
tlsConfig, err := utils.ConfigureServerTLS(&utils.ServerTLSOpts{
|
||||||
|
ServerCertFile: certFile,
|
||||||
|
ServerKeyFile: keyFile,
|
||||||
|
RequireClientAuth: clientCAFile != "",
|
||||||
|
ClientCAFile: clientCAFile,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Unable to set up TLS: %s", err.Error())
|
||||||
|
}
|
||||||
|
return tlsConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = usage
|
flag.Usage = usage
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
@ -95,19 +121,9 @@ func main() {
|
||||||
|
|
||||||
logrus.SetLevel(logrus.Level(mainViper.GetInt("logging.level")))
|
logrus.SetLevel(logrus.Level(mainViper.GetInt("logging.level")))
|
||||||
|
|
||||||
certFile := mainViper.GetString("server.cert_file")
|
tlsConfig, err := signerTLS(mainViper, true)
|
||||||
keyFile := mainViper.GetString("server.key_file")
|
|
||||||
if certFile == "" || keyFile == "" {
|
|
||||||
usage()
|
|
||||||
log.Fatalf("Certificate and key are mandatory")
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConfig, err := utils.ConfigureServerTLS(&utils.ServerTLSOpts{
|
|
||||||
ServerCertFile: certFile,
|
|
||||||
ServerKeyFile: keyFile,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatalf("Unable to set up TLS: %s", err.Error())
|
logrus.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
cryptoServices := make(signer.CryptoServiceIndex)
|
cryptoServices := make(signer.CryptoServiceIndex)
|
||||||
|
@ -163,10 +179,7 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to listen %v", err)
|
log.Fatalf("failed to listen %v", err)
|
||||||
}
|
}
|
||||||
creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)
|
creds := credentials.NewTLS(tlsConfig)
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to generate credentials %v", err)
|
|
||||||
}
|
|
||||||
opts := []grpc.ServerOption{grpc.Creds(creds)}
|
opts := []grpc.ServerOption{grpc.Creds(creds)}
|
||||||
grpcServer := grpc.NewServer(opts...)
|
grpcServer := grpc.NewServer(opts...)
|
||||||
|
|
||||||
|
@ -191,7 +204,7 @@ func main() {
|
||||||
log.Println("HTTP server listening on", httpAddr)
|
log.Println("HTTP server listening on", httpAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = server.ListenAndServeTLS(certFile, keyFile)
|
err = server.ListenAndServe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("HTTP server failed to start:", err)
|
log.Fatal("HTTP server failed to start:", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,71 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Cert = "../../fixtures/notary-signer.crt"
|
||||||
|
Key = "../../fixtures/notary-signer.key"
|
||||||
|
Root = "../../fixtures/root-ca.crt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// initializes a viper object with test configuration
|
||||||
|
func configure(jsonConfig []byte) *viper.Viper {
|
||||||
|
config := viper.New()
|
||||||
|
config.SetConfigType("json")
|
||||||
|
config.ReadConfig(bytes.NewBuffer(jsonConfig))
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignerTLSMissingCertAndOrKey(t *testing.T) {
|
||||||
|
configs := []string{
|
||||||
|
"{}",
|
||||||
|
fmt.Sprintf(`{"cert_file": "%s"}`, Cert),
|
||||||
|
fmt.Sprintf(`{"key_file": "%s"}`, Key),
|
||||||
|
}
|
||||||
|
for _, serverConfig := range configs {
|
||||||
|
config := configure(
|
||||||
|
[]byte(fmt.Sprintf(`{"server": %s}`, serverConfig)))
|
||||||
|
tlsConfig, err := signerTLS(config, false)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, tlsConfig)
|
||||||
|
assert.Equal(t, "Certificate and key are mandatory", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rest of the functionality of singerTLS depends upon
|
||||||
|
// utils.ConfigureServerTLS, so this test just asserts that if successful,
|
||||||
|
// the correct tls.Config is returned based on all the configuration parameters
|
||||||
|
func TestSignerTLSSuccess(t *testing.T) {
|
||||||
|
keypair, err := tls.LoadX509KeyPair(Cert, Key)
|
||||||
|
assert.NoError(t, err, "Unable to load cert and key for testing")
|
||||||
|
|
||||||
|
config := fmt.Sprintf(
|
||||||
|
`{"server": {"cert_file": "%s", "key_file": "%s", "client_ca_file": "%s"}}`,
|
||||||
|
Cert, Key, Cert)
|
||||||
|
tlsConfig, err := signerTLS(configure([]byte(config)), false)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
|
||||||
|
assert.NotNil(t, tlsConfig.ClientCAs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rest of the functionality of singerTLS depends upon
|
||||||
|
// utils.ConfigureServerTLS, so this test just asserts that if it fails,
|
||||||
|
// the error is propogated.
|
||||||
|
func TestSignerTLSFailure(t *testing.T) {
|
||||||
|
config := fmt.Sprintf(
|
||||||
|
`{"server": {"cert_file": "%s", "key_file": "%s", "client_ca_file": "%s"}}`,
|
||||||
|
Cert, Key, "non-existant")
|
||||||
|
tlsConfig, err := signerTLS(configure([]byte(config)), false)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, tlsConfig)
|
||||||
|
assert.True(t, strings.Contains(err.Error(), "Unable to set up TLS"))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue