The TLS certificates are now relative to the config file used.

Previously, if a relative path was provided, it was relative to the
current working directory to wherever the binaries were run.  Now
it is relative to whatever config file was used.

Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
Ying Li 2015-11-20 01:17:45 -08:00
parent c43776d36f
commit f1bd28caf4
8 changed files with 63 additions and 23 deletions

View File

@ -20,4 +20,4 @@ RUN go install \
${NOTARYPKG}/cmd/notary-server ${NOTARYPKG}/cmd/notary-server
ENTRYPOINT [ "notary-server" ] ENTRYPOINT [ "notary-server" ]
CMD [ "-config", "cmd/notary-server/config.json" ] CMD [ "-config", "fixtures/server-config.json" ]

View File

@ -38,4 +38,4 @@ RUN go install \
ENTRYPOINT [ "notary-signer" ] ENTRYPOINT [ "notary-signer" ]
CMD [ "-config=cmd/notary-signer/config.json" ] CMD [ "-config=fixtures/signer-config.json" ]

View File

@ -73,10 +73,10 @@ func getAddrAndTLSConfig(configuration *viper.Viper) (string, *tls.Config, error
// sets up TLS for the GRPC connection to notary-signer // sets up TLS for the GRPC connection to notary-signer
func grpcTLS(configuration *viper.Viper) (*tls.Config, error) { func grpcTLS(configuration *viper.Viper) (*tls.Config, error) {
rootCA := configuration.GetString("trust_service.tls_ca_file") rootCA := utils.GetPathRelativeToConfig(configuration, "trust_service.tls_ca_file")
serverName := configuration.GetString("trust_service.hostname") serverName := configuration.GetString("trust_service.hostname")
clientCert := configuration.GetString("trust_service.tls_client_cert") clientCert := utils.GetPathRelativeToConfig(configuration, "trust_service.tls_client_cert")
clientKey := configuration.GetString("trust_service.tls_client_key") clientKey := utils.GetPathRelativeToConfig(configuration, "trust_service.tls_client_key")
if (clientCert == "" && clientKey != "") || (clientCert != "" && clientKey == "") { if (clientCert == "" && clientKey != "") || (clientCert != "" && clientKey == "") {
return nil, fmt.Errorf("Partial TLS configuration found. Either include both a client cert and client key file in the configuration, or include neither.") return nil, fmt.Errorf("Partial TLS configuration found. Either include both a client cert and client key file in the configuration, or include neither.")

View File

@ -121,18 +121,22 @@ func TestGrpcTLSNoConfig(t *testing.T) {
// The rest of the functionality of grpcTLS depends upon // The rest of the functionality of grpcTLS depends upon
// utils.ConfigureClientTLS, so this test just asserts that if successful, // utils.ConfigureClientTLS, so this test just asserts that if successful,
// the correct tls.Config is returned based on all the configuration parameters // the correct tls.Config is returned based on all the configuration parameters,
// and that it gets the path relative to the config file
func TestGrpcTLSSuccess(t *testing.T) { func TestGrpcTLSSuccess(t *testing.T) {
keypair, err := tls.LoadX509KeyPair(Cert, Key) keypair, err := tls.LoadX509KeyPair(Cert, Key)
assert.NoError(t, err, "Unable to load cert and key for testing") assert.NoError(t, err, "Unable to load cert and key for testing")
config := fmt.Sprintf( configJSON := `{
`{"trust_service": { "trust_service": {
"hostname": "notary-server", "hostname": "notary-server",
"tls_client_cert": "%s", "tls_client_cert": "notary-server.crt",
"tls_client_key": "%s"}}`, "tls_client_key": "notary-server.key"
Cert, Key) }
tlsConfig, err := grpcTLS(configure(config)) }`
config := configure(configJSON)
config.SetConfigFile("../../fixtures/config.json")
tlsConfig, err := grpcTLS(config)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates) assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
} }

View File

@ -1,17 +1,17 @@
{ {
"server": { "server": {
"http_addr": ":4443", "http_addr": ":4443",
"tls_key_file": "./fixtures/notary-server.key", "tls_key_file": "./notary-server.key",
"tls_cert_file": "./fixtures/notary-server.crt" "tls_cert_file": "./notary-server.crt"
}, },
"trust_service": { "trust_service": {
"type": "remote", "type": "remote",
"hostname": "notarysigner", "hostname": "notarysigner",
"port": "7899", "port": "7899",
"tls_ca_file": "./fixtures/root-ca.crt", "tls_ca_file": "./root-ca.crt",
"key_algorithm": "ecdsa", "key_algorithm": "ecdsa",
"tls_client_cert": "./fixtures/notary-server.crt", "tls_client_cert": "./notary-server.crt",
"tls_client_key": "./fixtures/notary-server.key" "tls_client_key": "./notary-server.key"
}, },
"logging": { "logging": {
"level": "debug" "level": "debug"

View File

@ -2,9 +2,9 @@
"server": { "server": {
"http_addr": ":4444", "http_addr": ":4444",
"grpc_addr": ":7899", "grpc_addr": ":7899",
"tls_cert_file": "./fixtures/notary-signer.crt", "tls_cert_file": "./notary-signer.crt",
"tls_key_file": "./fixtures/notary-signer.key", "tls_key_file": "./notary-signer.key",
"client_ca_file": "./fixtures/notary-server.crt" "client_ca_file": "./notary-server.crt"
}, },
"logging": { "logging": {
"level": "debug" "level": "debug"

View File

@ -4,6 +4,7 @@ package utils
import ( import (
"fmt" "fmt"
"path/filepath"
"strings" "strings"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
@ -18,16 +19,30 @@ type Storage struct {
Source string Source string
} }
// GetPathRelativeToConfig gets a configuration key which is a path, and if
// it is not empty or an absolute path, returns the absolute path relative
// to the configuration file
func GetPathRelativeToConfig(configuration *viper.Viper, key string) string {
configFile := configuration.ConfigFileUsed()
p := configuration.GetString(key)
if p == "" || filepath.IsAbs(p) {
return p
}
return filepath.Join(filepath.Dir(configFile), p)
}
// ParseServerTLS tries to parse out a valid ServerTLSOpts from a Viper: // ParseServerTLS tries to parse out a valid ServerTLSOpts from a Viper:
// - If TLS is required, both the cert and key must be provided // - If TLS is required, both the cert and key must be provided
// - If TLS is not requried, either both the cert and key must be provided or // - If TLS is not requried, either both the cert and key must be provided or
// neither must be provided // neither must be provided
// The files are relative to the config file used to populate the instance
// of viper.
func ParseServerTLS(configuration *viper.Viper, tlsRequired bool) (*ServerTLSOpts, error) { func ParseServerTLS(configuration *viper.Viper, tlsRequired bool) (*ServerTLSOpts, error) {
// unmarshalling into objects does not seem to pick up env vars // unmarshalling into objects does not seem to pick up env vars
tlsOpts := ServerTLSOpts{ tlsOpts := ServerTLSOpts{
ServerCertFile: configuration.GetString("server.tls_cert_file"), ServerCertFile: GetPathRelativeToConfig(configuration, "server.tls_cert_file"),
ServerKeyFile: configuration.GetString("server.tls_key_file"), ServerKeyFile: GetPathRelativeToConfig(configuration, "server.tls_key_file"),
ClientCAFile: configuration.GetString("server.client_ca_file"), ClientCAFile: GetPathRelativeToConfig(configuration, "server.client_ca_file"),
} }
cert, key := tlsOpts.ServerCertFile, tlsOpts.ServerKeyFile cert, key := tlsOpts.ServerCertFile, tlsOpts.ServerKeyFile

View File

@ -274,6 +274,27 @@ func TestParseTLSWithTLS(t *testing.T) {
assert.Equal(t, expected, *tlsOpts) assert.Equal(t, expected, *tlsOpts)
} }
func TestParseTLSWithTLSRelativeToConfigFile(t *testing.T) {
config := configure(`{
"server": {
"tls_cert_file": "path/to/cert",
"tls_key_file": "/abspath/to/key",
"client_ca_file": ""
}
}`)
config.SetConfigFile("/opt/me.json")
expected := ServerTLSOpts{
ServerCertFile: "/opt/path/to/cert",
ServerKeyFile: "/abspath/to/key",
ClientCAFile: "",
}
tlsOpts, err := ParseServerTLS(config, false)
assert.NoError(t, err)
assert.Equal(t, expected, *tlsOpts)
}
func TestParseTLSWithEnvironmentVariables(t *testing.T) { func TestParseTLSWithEnvironmentVariables(t *testing.T) {
config := configure(`{ config := configure(`{
"server": { "server": {