From a5666ffc1c69ba8b9073dc8959392da24054c95b Mon Sep 17 00:00:00 2001 From: Keith Smith Date: Sun, 8 Jan 2017 12:37:55 -0500 Subject: [PATCH] Process file names in config file correctly If a file name in the config file is not absolute, it must be processed relative to the location of the config file. See cli/server/config.go for calls to the abs function for making them absolute. https://jira.hyperledger.org/browse/FAB-1549 Change-Id: If12f12e291cb105efca9e9cb6004b9315eb9e141 Signed-off-by: Keith Smith --- cli/client/client_test.go | 2 +- cli/server/bootstrap_test.go | 90 ---------------------------- cli/server/config.go | 113 ++++++++++++++++++++++++----------- cli/server/register_test.go | 4 +- cli/server/server.go | 20 ++----- cli/server/server_test.go | 5 +- testdata/testconfig.json | 14 ++--- testdata/testconfig2.json | 80 ------------------------- util/util.go | 18 ++++++ 9 files changed, 115 insertions(+), 231 deletions(-) delete mode 100644 cli/server/bootstrap_test.go delete mode 100644 testdata/testconfig2.json diff --git a/cli/client/client_test.go b/cli/client/client_test.go index 104a4fa15..d027ea9d3 100644 --- a/cli/client/client_test.go +++ b/cli/client/client_test.go @@ -214,7 +214,7 @@ func TestLast(t *testing.T) { func runServer() { os.Setenv("COP_DEBUG", "true") - server.Start("../../testdata", "testconfig2.json") + server.Start("../../testdata", "testconfig.json") } func startServer() { diff --git a/cli/server/bootstrap_test.go b/cli/server/bootstrap_test.go deleted file mode 100644 index f8b706427..000000000 --- a/cli/server/bootstrap_test.go +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright IBM Corp. 2016 All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package server - -import ( - "os" - "path/filepath" - "testing" - - "github.com/cloudflare/cfssl/cli" -) - -// var testDB *sqlx.DB -var bootCFG *Config - -const ( - bootPath = "/tmp/bootstraptest" -) - -func prepBootstrap() error { - if _, err := os.Stat(bootPath); err != nil { - if os.IsNotExist(err) { - os.MkdirAll(bootPath, 0755) - } - } else { - os.RemoveAll(bootPath) - os.MkdirAll(bootPath, 0755) - } - var err error - - cfg := new(cli.Config) - cfg.ConfigFile = "../../testdata/testconfig.json" - configInit(cfg) - - bootCFG = CFG - home = bootPath - bootCFG.DBdriver = "sqlite3" - datasource := filepath.Join(home, "cop.db") - bootCFG.DataSource = datasource - - err = InitUserRegistry(bootCFG) - - if err != nil { - return err - } - - return nil -} - -func TestAllBootstrap(t *testing.T) { - err := prepBootstrap() - if err != nil { - t.Fatal("Failed to open connection to database") - } - - testBootstrapGroup(t) - testBootstrapUsers(t) - - os.RemoveAll(bootPath) -} - -func testBootstrapGroup(t *testing.T) { - _, err := userRegistry.GetGroup("bank_b") - - if err != nil { - t.Error("Failed bootstrapping groups table") - } -} - -func testBootstrapUsers(t *testing.T) { - _, err := userRegistry.GetUser("admin", nil) - - if err != nil { - t.Error("Failed bootstrapping users table") - } -} diff --git a/cli/server/config.go b/cli/server/config.go index 77e6b8fae..880c3b6e7 100644 --- a/cli/server/config.go +++ b/cli/server/config.go @@ -21,12 +21,14 @@ import ( "fmt" "io/ioutil" "os" + "path/filepath" "github.com/cloudflare/cfssl/cli" "github.com/cloudflare/cfssl/log" "github.com/hyperledger/fabric-cop/cli/server/ldap" "github.com/hyperledger/fabric-cop/idp" "github.com/hyperledger/fabric-cop/lib/tls" + "github.com/hyperledger/fabric-cop/util" _ "github.com/mattn/go-sqlite3" // Needed to support sqlite ) @@ -79,42 +81,63 @@ var CFG *Config // Init initializes the COP config given the CFSSL config func configInit(cfg *cli.Config) { - log.Debugf("config.Init file=%s", cfg.ConfigFile) - CFG = newConfig() - - if cfg.ConfigFile != "" { - body, err := ioutil.ReadFile(cfg.ConfigFile) - if err != nil { - panic(err.Error()) - } - log.Debugf("config.Init contents=%+v", body) - err = json.Unmarshal(body, CFG) - if err != nil { - panic(fmt.Sprintf("error parsing %s: %s", cfg.ConfigFile, err.Error())) - } - - configFile = cfg.ConfigFile - cfg.DBConfigFile = configFile - - cfg.CAFile = CFG.CAFile - cfg.CAKeyFile = CFG.KeyFile - - if CFG.TLSConf.TLSCertFile != "" { - cfg.TLSCertFile = CFG.TLSConf.TLSCertFile - } else { - cfg.TLSCertFile = CFG.CAFile - } - - if CFG.TLSConf.TLSKeyFile != "" { - cfg.TLSKeyFile = CFG.TLSConf.TLSKeyFile - } else { - cfg.TLSKeyFile = CFG.KeyFile - } - - if CFG.TLSConf.MutualTLSCAFile != "" { - cfg.MutualTLSCAFile = CFG.TLSConf.MutualTLSCAFile - } + var err error + configFile, err = filepath.Abs(cfg.ConfigFile) + if err != nil { + panic(err.Error()) + } + configDir = filepath.Dir(configFile) + log.Debugf("Initializing config file at %s", configFile) + log.Debugf("Inbound CFSSL server config is: %+v", cfg) + + CFG = new(Config) + CFG.Authentication = true + + body, err := ioutil.ReadFile(configFile) + if err != nil { + panic(err.Error()) + } + err = json.Unmarshal(body, CFG) + if err != nil { + panic(fmt.Sprintf("error parsing %s: %s", configFile, err.Error())) + } + + CFG.CAFile = abs(CFG.CAFile) + CFG.KeyFile = abs(CFG.KeyFile) + CFG.TLSConf.TLSCertFile = abs(CFG.TLSConf.TLSCertFile) + CFG.TLSConf.TLSKeyFile = abs(CFG.TLSConf.TLSKeyFile) + CFG.TLSConf.MutualTLSCAFile = abs(CFG.TLSConf.MutualTLSCAFile) + absTLSClient(&CFG.TLSConf.DBClient) + + if cfg.DBConfigFile == "" { + cfg.DBConfigFile = cfg.ConfigFile + } + + if CFG.TLSConf.TLSCertFile != "" { + cfg.TLSCertFile = CFG.TLSConf.TLSCertFile + } else { + cfg.TLSCertFile = CFG.CAFile + } + + if CFG.TLSConf.TLSKeyFile != "" { + cfg.TLSKeyFile = CFG.TLSConf.TLSKeyFile + } else { + cfg.TLSKeyFile = CFG.KeyFile + } + + if CFG.TLSConf.MutualTLSCAFile != "" { + cfg.MutualTLSCAFile = CFG.TLSConf.MutualTLSCAFile + } + if CFG.DBdriver == "" { + msg := "No database specified, a database is needed to run COP server. Using default - Type: SQLite, Name: cop.db" + log.Info(msg) + CFG.DBdriver = sqlite + CFG.DataSource = "cop.db" + } + + if CFG.DBdriver == sqlite { + CFG.DataSource = abs(CFG.DataSource) } dbg := os.Getenv("COP_DEBUG") @@ -125,4 +148,24 @@ func configInit(cfg *cli.Config) { log.Level = log.LevelDebug } + log.Debugf("CFSSL server config is: %+v", cfg) + log.Debugf("COP server config is: %+v", CFG) +} + +// Make TLS client files absolute +func absTLSClient(cfg *tls.ClientTLSConfig) { + for i := 0; i < len(cfg.CACertFiles); i++ { + cfg.CACertFiles[i] = abs(cfg.CACertFiles[i]) + } + cfg.Client.CertFile = abs(cfg.Client.CertFile) + cfg.Client.KeyFile = abs(cfg.Client.KeyFile) +} + +// Make 'file' absolute relative to the configuration directory +func abs(file string) string { + path, err := util.MakeFileAbs(file, configDir) + if err != nil { + panic(err) + } + return path } diff --git a/cli/server/register_test.go b/cli/server/register_test.go index 14b40fb32..15eb5035d 100644 --- a/cli/server/register_test.go +++ b/cli/server/register_test.go @@ -65,8 +65,8 @@ func prepRegister() error { configInit(cfg) regCFG := CFG - home = regPath - datasource := filepath.Join(home, "cop.db") + homeDir = regPath + datasource := filepath.Join(homeDir, "cop.db") regCFG.DataSource = datasource err = InitUserRegistry(regCFG) diff --git a/cli/server/server.go b/cli/server/server.go index 3f2713de5..59c78eb32 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -82,7 +82,8 @@ var ( enrollSigner signer.Signer ocspSigner ocsp.Signer db *sqlx.DB - home string + homeDir string + configDir string configFile string userRegistry spi.UserRegistry certDBAccessor *CertDBAccessor @@ -151,28 +152,17 @@ func bootstrapDB() error { // It sets up a new HTTP server to handle COP requests. func startMain(args []string, c cli.Config) error { log.Debug("server.startMain") + var err error s := new(Server) - home, err := s.CreateHome() + homeDir, err = s.CreateHome() if err != nil { return err } configInit(&c) - cfg := CFG - - if cfg.DataSource == "" { - msg := "No database specified, a database is needed to run COP server. Using default - Type: SQLite, Name: cop.db" - log.Info(msg) - cfg.DBdriver = sqlite - cfg.DataSource = "cop.db" - } - - if cfg.DBdriver == sqlite { - cfg.DataSource = filepath.Join(home, cfg.DataSource) - } // Initialize the user registry - err = InitUserRegistry(cfg) + err = InitUserRegistry(CFG) if err != nil { log.Errorf("Failed to initialize user registry [error: %s]", err) return err diff --git a/cli/server/server_test.go b/cli/server/server_test.go index 9206f0b39..eb309bd70 100644 --- a/cli/server/server_test.go +++ b/cli/server/server_test.go @@ -34,8 +34,9 @@ import ( ) const ( - CFGFile = "testconfig2.json" + CFGFile = "testconfig.json" ClientTLSConfig = "cop_client.json" + COPDB = "../../testdata/cop.db" ) var serverStarted bool @@ -57,6 +58,7 @@ func startServer() { } if !serverStarted { + os.Remove(COPDB) os.RemoveAll(dir) serverStarted = true fmt.Println("starting COP server ...") @@ -461,6 +463,7 @@ func TestCreateHome(t *testing.T) { func TestLast(t *testing.T) { // Cleanup + os.Remove(COPDB) os.RemoveAll(dir) } diff --git a/testdata/testconfig.json b/testdata/testconfig.json index 1e996a9e0..63f5b8a44 100644 --- a/testdata/testconfig.json +++ b/testdata/testconfig.json @@ -5,15 +5,15 @@ "user_registry": { "max_enrollments": 1 }, - "ca_cert":"../testdata/ec.pem", - "ca_key":"../testdata/ec-key.pem", + "ca_cert":"ec.pem", + "ca_key":"ec-key.pem", "tls":{ - "tls_cert":"../testdata/tls_server-cert.pem", - "tls_key":"../testdata/tls_server-key.pem", - "mutual_tls_ca":"../testdata/root.pem", + "tls_cert":"tls_server-cert.pem", + "tls_key":"tls_server-key.pem", + "mutual_tls_ca":"root.pem", "db_client":{ - "ca_certfiles":["../testdata/root.pem"], - "client":{"keyfile":"../testdata/tls_server-key.pem","certfile":"../testdata/tls_server-cert.pem"} + "ca_certfiles":["root.pem"], + "client":{"keyfile":"tls_server-key.pem","certfile":"tls_server-cert.pem"} } }, "users": { diff --git a/testdata/testconfig2.json b/testdata/testconfig2.json deleted file mode 100644 index fdd243a2a..000000000 --- a/testdata/testconfig2.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "user_registry": { - "max_enrollments": 1 - }, - "ca_cert":"../../testdata/tls_server-cert.pem", - "ca_key":"../../testdata/tls_server-key.pem", - "tls":{ - "mutual_tls_ca":"../../testdata/root.pem", - "db_client":{ - "ca_certfiles":["../../testdata/root.pem"], - "client":{"keyfile":"../../testdata/tls_server-key.pem","certfile":"../../testdata/tls_server-cert.pem"} - } - }, - "users": { - "admin": { - "pass": "adminpw", - "type": "client", - "group": "bank_a", - "attrs": [{"name":"hf.Registrar.Roles","value":"client,user,peer,validator,auditor"}, - {"name":"hf.Registrar.DelegateRoles", "value": "client,user,validator,auditor"}, - {"name":"hf.Revoker", "value": "true"}] - }, - "admin2": { - "pass": "adminpw2", - "type": "client", - "group": "bank_a", - "attrs": [{"name":"hf.Registrar.Roles","value":"client,user,peer,validator,auditor"}, - {"name":"hf.Registrar.DelegateRoles", "value": "client,user,validator,auditor"}, - {"name":"hf.Revoker", "value": "true"}] - }, - "revoker": { - "pass": "revokerpw", - "type": "client", - "group": "bank_a", - "attrs": [{"name":"hf.Revoker", "value": "true"}] - }, - "notadmin": { - "pass": "pass", - "type": "client", - "group": "bank_a", - "attrs": [{"name":"hf.Registrar.Roles","value":"client,peer,validator,auditor"}, - {"name":"hf.Registrar.DelegateRoles", "value": "client"}] - }, - "expiryUser": { - "pass": "expirypw", - "type": "client", - "group": "bank_a" - }, - "testUser": { - "pass": "user1", - "type": "client", - "group": "bank_b", - "attrs": [] - }, - "testUser2": { - "pass": "user2", - "type": "client", - "group": "bank_c", - "attrs": [] - }, - "testUser3": { - "pass": "user3", - "type": "client", - "group": "bank_a", - "attrs": [] - } - }, - "groups": { - "banks_and_institutions": { - "banks": ["bank_a", "bank_b", "bank_c"], - "institutions": ["institution_a"] - } - }, - "signing": { - "default": { - "usages": ["cert sign"], - "expiry": "8000h" - } - } -} diff --git a/util/util.go b/util/util.go index c24915a0d..915c3e655 100644 --- a/util/util.go +++ b/util/util.go @@ -35,6 +35,7 @@ import ( mrand "math/rand" "net/http" "os" + "path/filepath" "strings" "time" @@ -408,3 +409,20 @@ func GetEnrollmentIDFromPEM(cert []byte) (string, error) { func GetEnrollmentIDFromX509Certificate(cert *x509.Certificate) string { return cert.Subject.CommonName } + +// MakeFileAbs makes 'file' absolute relative to 'dir' if not already absolute +func MakeFileAbs(file, dir string) (string, error) { + if file == "" { + return "", nil + } + if filepath.IsAbs(file) { + log.Debugf("%s is already an absolute file", file) + return file, nil + } + path, err := filepath.Abs(filepath.Join(dir, file)) + if err != nil { + return "", fmt.Errorf("Failed making '%s' absolute based on '%s'", file, dir) + } + log.Debugf("absolute file path for %s is %s", file, path) + return path, nil +}