Merge pull request #1422 from ywk253100/170221_secretkey

Encrypt the passwords in configuration file
This commit is contained in:
Daniel Jiang 2017-02-23 10:25:39 +08:00 committed by GitHub
commit ef34b96256
20 changed files with 412 additions and 98 deletions

View File

@ -25,9 +25,9 @@ env:
HARBOR_ADMIN_PASSWD: Harbor12345 HARBOR_ADMIN_PASSWD: Harbor12345
UI_SECRET: tempString UI_SECRET: tempString
MAX_JOB_WORKERS: 3 MAX_JOB_WORKERS: 3
SECRET_KEY: 1234567890123456
AUTH_MODE: db_auth AUTH_MODE: db_auth
SELF_REGISTRATION: on SELF_REGISTRATION: on
KEY_PATH: /data/secretkey
before_install: before_install:
- sudo ./tests/hostcfg.sh - sudo ./tests/hostcfg.sh

View File

@ -48,7 +48,8 @@ services:
- ../common/config/adminserver/env - ../common/config/adminserver/env
restart: always restart: always
volumes: volumes:
- /data/config/:/etc/harbor/ - /data/config/:/etc/adminserver/
- /data/secretkey:/etc/adminserver/key
depends_on: depends_on:
- log - log
logging: logging:
@ -66,6 +67,7 @@ services:
volumes: volumes:
- ../common/config/ui/app.conf:/etc/ui/app.conf - ../common/config/ui/app.conf:/etc/ui/app.conf
- ../common/config/ui/private_key.pem:/etc/ui/private_key.pem - ../common/config/ui/private_key.pem:/etc/ui/private_key.pem
- /data/secretkey:/etc/ui/key
depends_on: depends_on:
- log - log
- adminserver - adminserver
@ -85,6 +87,7 @@ services:
volumes: volumes:
- /data/job_logs:/var/log/jobs - /data/job_logs:/var/log/jobs
- ../common/config/jobservice/app.conf:/etc/jobservice/app.conf - ../common/config/jobservice/app.conf:/etc/jobservice/app.conf
- /data/secretkey:/etc/jobservice/key
depends_on: depends_on:
- ui - ui
- adminserver - adminserver

View File

@ -48,7 +48,8 @@ services:
- ./common/config/adminserver/env - ./common/config/adminserver/env
restart: always restart: always
volumes: volumes:
- /data/config/:/etc/harbor/ - /data/config/:/etc/adminserver/
- /data/secretkey:/etc/adminserver/key
depends_on: depends_on:
- log - log
logging: logging:
@ -66,6 +67,7 @@ services:
- ./common/config/ui/app.conf:/etc/ui/app.conf - ./common/config/ui/app.conf:/etc/ui/app.conf
- ./common/config/ui/private_key.pem:/etc/ui/private_key.pem - ./common/config/ui/private_key.pem:/etc/ui/private_key.pem
- /data:/harbor_storage - /data:/harbor_storage
- /data/secretkey:/etc/ui/key
depends_on: depends_on:
- log - log
- adminserver - adminserver
@ -84,6 +86,7 @@ services:
volumes: volumes:
- /data/job_logs:/var/log/jobs - /data/job_logs:/var/log/jobs
- ./common/config/jobservice/app.conf:/etc/jobservice/app.conf - ./common/config/jobservice/app.conf:/etc/jobservice/app.conf
- /data/secretkey:/etc/jobservice/key
depends_on: depends_on:
- ui - ui
- adminserver - adminserver

View File

@ -26,15 +26,26 @@ import (
"testing" "testing"
"github.com/vmware/harbor/src/adminserver/systemcfg" "github.com/vmware/harbor/src/adminserver/systemcfg"
"github.com/vmware/harbor/src/common/config" comcfg "github.com/vmware/harbor/src/common/config"
"github.com/vmware/harbor/src/common/utils/test"
) )
func TestConfigAPI(t *testing.T) { func TestConfigAPI(t *testing.T) {
path := "/tmp/config.json" configPath := "/tmp/config.json"
secret := "secret" secretKeyPath := "/tmp/secretkey"
_, err := test.GenerateKey(secretKeyPath)
if err != nil {
t.Errorf("failed to generate secret key: %v", err)
return
}
defer os.Remove(secretKeyPath)
secret := "secret"
envs := map[string]string{ envs := map[string]string{
"JSON_STORE_PATH": path,
"JSON_CFG_STORE_PATH": configPath,
"KEY_PATH": secretKeyPath,
"UI_SECRET": secret, "UI_SECRET": secret,
"MYSQL_PORT": "3306", "MYSQL_PORT": "3306",
"TOKEN_EXPIRATION": "30", "TOKEN_EXPIRATION": "30",
@ -43,14 +54,19 @@ func TestConfigAPI(t *testing.T) {
"LDAP_SCOPE": "3", "LDAP_SCOPE": "3",
"LDAP_TIMEOUT": "30", "LDAP_TIMEOUT": "30",
"EMAIL_PORT": "25", "EMAIL_PORT": "25",
"MYSQL_PWD": "",
"LDAP_SEARCH_PWD": "",
"EMAIL_PWD": "",
"HARBOR_ADMIN_PASSWORD": "",
} }
for k, v := range envs { for k, v := range envs {
if err := os.Setenv(k, v); err != nil { if err := os.Setenv(k, v); err != nil {
t.Fatalf("failed to set env %s: %v", k, err) t.Errorf("failed to set env %s: %v", k, err)
return
} }
} }
defer os.Remove(path) defer os.Remove(configPath)
if err := systemcfg.Init(); err != nil { if err := systemcfg.Init(); err != nil {
t.Errorf("failed to initialize system configurations: %v", err) t.Errorf("failed to initialize system configurations: %v", err)
@ -88,7 +104,7 @@ func TestConfigAPI(t *testing.T) {
return return
} }
scope := int(m[config.LDAPScope].(float64)) scope := int(m[comcfg.LDAPScope].(float64))
if scope != 3 { if scope != 3 {
t.Errorf("unexpected ldap scope: %d != %d", scope, 3) t.Errorf("unexpected ldap scope: %d != %d", scope, 3)
return return
@ -96,7 +112,7 @@ func TestConfigAPI(t *testing.T) {
// modify configurations // modify configurations
c := map[string]interface{}{ c := map[string]interface{}{
config.AUTHMode: config.LDAPAuth, comcfg.AUTHMode: comcfg.LDAPAuth,
} }
b, err := json.Marshal(c) b, err := json.Marshal(c)
@ -146,9 +162,9 @@ func TestConfigAPI(t *testing.T) {
return return
} }
mode := m[config.AUTHMode].(string) mode := m[comcfg.AUTHMode].(string)
if mode != config.LDAPAuth { if mode != comcfg.LDAPAuth {
t.Errorf("unexpected ldap scope: %s != %s", mode, config.LDAPAuth) t.Errorf("unexpected ldap scope: %s != %s", mode, comcfg.LDAPAuth)
return return
} }
} }

View File

@ -19,7 +19,7 @@ import (
"net/http" "net/http"
"os" "os"
cfg "github.com/vmware/harbor/src/adminserver/systemcfg" syscfg "github.com/vmware/harbor/src/adminserver/systemcfg"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
) )
@ -41,7 +41,7 @@ func (s *Server) Serve() error {
func main() { func main() {
log.Info("initializing system configurations...") log.Info("initializing system configurations...")
if err := cfg.Init(); err != nil { if err := syscfg.Init(); err != nil {
log.Fatalf("failed to initialize the system: %v", err) log.Fatalf("failed to initialize the system: %v", err)
} }
log.Info("system initialization completed") log.Info("system initialization completed")

View File

@ -23,27 +23,39 @@ import (
"github.com/vmware/harbor/src/adminserver/systemcfg/store" "github.com/vmware/harbor/src/adminserver/systemcfg/store"
"github.com/vmware/harbor/src/adminserver/systemcfg/store/json" "github.com/vmware/harbor/src/adminserver/systemcfg/store/json"
comcfg "github.com/vmware/harbor/src/common/config" comcfg "github.com/vmware/harbor/src/common/config"
"github.com/vmware/harbor/src/common/utils"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
) )
var cfgStore store.Driver const (
defaultCfgStoreDriver string = "json"
defaultJSONCfgStorePath string = "/etc/adminserver/config.json"
defaultKeyPath string = "/etc/adminserver/key"
)
var (
// attrs need to be encrypted or decrypted
attrs = []string{
comcfg.EmailPassword,
comcfg.LDAPSearchPwd,
comcfg.MySQLPassword,
comcfg.AdminInitialPassword,
}
cfgStore store.Driver
keyProvider comcfg.KeyProvider
)
// Init system configurations. Read from config store first, if null read from env // Init system configurations. Read from config store first, if null read from env
func Init() (err error) { func Init() (err error) {
s := getCfgStore() //init configuation store
switch s { if err = initCfgStore(); err != nil {
case "json": return err
path := os.Getenv("JSON_STORE_PATH")
cfgStore, err = json.NewCfgStore(path)
if err != nil {
return
}
default:
return fmt.Errorf("unsupported configuration store driver %s", s)
} }
log.Infof("configuration store driver: %s", cfgStore.Name()) //init key provider
cfg, err := cfgStore.Read() initKeyProvider()
cfg, err := GetSystemCfg()
if err != nil { if err != nil {
return err return err
} }
@ -61,19 +73,44 @@ func Init() (err error) {
} }
//sync configurations into cfg store //sync configurations into cfg store
if err = cfgStore.Write(cfg); err != nil { if err = UpdateSystemCfg(cfg); err != nil {
return err return err
} }
return nil return nil
} }
func getCfgStore() string { func initCfgStore() (err error) {
t := os.Getenv("CFG_STORE_TYPE") t := os.Getenv("CFG_STORE_DRIVER")
if len(t) == 0 { if len(t) == 0 {
t = "json" t = defaultCfgStoreDriver
} }
return t log.Infof("configuration store driver: %s", t)
switch t {
case "json":
path := os.Getenv("JSON_CFG_STORE_PATH")
if len(path) == 0 {
path = defaultJSONCfgStorePath
}
log.Infof("json configuration store path: %s", path)
cfgStore, err = json.NewCfgStore(path)
default:
err = fmt.Errorf("unsupported configuration store driver %s", t)
}
return err
}
func initKeyProvider() {
path := os.Getenv("KEY_PATH")
if len(path) == 0 {
path = defaultKeyPath
}
log.Infof("key path: %s", path)
keyProvider = comcfg.NewFileKeyProvider(path)
} }
//read the following attrs from env every time boots up //read the following attrs from env every time boots up
@ -102,7 +139,6 @@ func readFromEnv(cfg map[string]interface{}) error {
cfg[comcfg.JobLogDir] = os.Getenv("LOG_DIR") cfg[comcfg.JobLogDir] = os.Getenv("LOG_DIR")
//TODO remove //TODO remove
cfg[comcfg.UseCompressedJS] = os.Getenv("USE_COMPRESSED_JS") == "on" cfg[comcfg.UseCompressedJS] = os.Getenv("USE_COMPRESSED_JS") == "on"
cfg[comcfg.SecretKey] = os.Getenv("SECRET_KEY")
cfgExpi, err := strconv.Atoi(os.Getenv("CFG_EXPIRATION")) cfgExpi, err := strconv.Atoi(os.Getenv("CFG_EXPIRATION"))
if err != nil { if err != nil {
return err return err
@ -162,10 +198,74 @@ func initFromEnv() (map[string]interface{}, error) {
// GetSystemCfg returns the system configurations // GetSystemCfg returns the system configurations
func GetSystemCfg() (map[string]interface{}, error) { func GetSystemCfg() (map[string]interface{}, error) {
return cfgStore.Read() m, err := cfgStore.Read()
if err != nil {
return nil, err
}
key, err := keyProvider.Get(nil)
if err != nil {
return nil, fmt.Errorf("failed to get key: %v", err)
}
if err = decrypt(m, attrs, key); err != nil {
return nil, err
}
return m, nil
} }
// UpdateSystemCfg updates the system configurations // UpdateSystemCfg updates the system configurations
func UpdateSystemCfg(cfg map[string]interface{}) error { func UpdateSystemCfg(cfg map[string]interface{}) error {
key, err := keyProvider.Get(nil)
if err != nil {
return fmt.Errorf("failed to get key: %v", err)
}
if err := encrypt(cfg, attrs, key); err != nil {
return err
}
return cfgStore.Write(cfg) return cfgStore.Write(cfg)
} }
func encrypt(m map[string]interface{}, keys []string, secretKey string) error {
for _, key := range keys {
v, ok := m[key]
if !ok {
continue
}
if len(v.(string)) == 0 {
continue
}
cipherText, err := utils.ReversibleEncrypt(v.(string), secretKey)
if err != nil {
return err
}
m[key] = cipherText
}
return nil
}
func decrypt(m map[string]interface{}, keys []string, secretKey string) error {
for _, key := range keys {
v, ok := m[key]
if !ok {
continue
}
if len(v.(string)) == 0 {
continue
}
text, err := utils.ReversibleDecrypt(v.(string), secretKey)
if err != nil {
return err
}
m[key] = text
}
return nil
}

View File

@ -20,22 +20,37 @@ import (
"testing" "testing"
comcfg "github.com/vmware/harbor/src/common/config" comcfg "github.com/vmware/harbor/src/common/config"
"github.com/vmware/harbor/src/common/utils/test"
) )
// test functions under adminserver/systemcfg // test functions in adminserver/systemcfg/systemcfg.go
func TestSystemcfg(t *testing.T) { func TestSystemcfg(t *testing.T) {
key := "JSON_STORE_PATH" configPath := "/tmp/config.json"
path := "/tmp/config.json" if _, err := os.Stat(configPath); err == nil {
if _, err := os.Stat(path); err == nil { if err := os.Remove(configPath); err != nil {
if err := os.Remove(path); err != nil { t.Errorf("failed to remove %s: %v", configPath, err)
t.Fatalf("failed to remove %s: %v", path, err) return
} }
} else if !os.IsNotExist(err) { } else if !os.IsNotExist(err) {
t.Fatalf("failed to check the existence of %s: %v", path, err) t.Errorf("failed to check the existence of %s: %v", configPath, err)
return
} }
if err := os.Setenv(key, path); err != nil { if err := os.Setenv("JSON_CFG_STORE_PATH", configPath); err != nil {
t.Fatalf("failed to set env %s: %v", key, err) t.Errorf("failed to set env: %v", err)
return
}
keyPath := "/tmp/secretkey"
if _, err := test.GenerateKey(keyPath); err != nil {
t.Errorf("failed to generate key: %v", err)
return
}
defer os.Remove(keyPath)
if err := os.Setenv("KEY_PATH", keyPath); err != nil {
t.Errorf("failed to set env: %v", err)
return
} }
m := map[string]string{ m := map[string]string{
@ -47,6 +62,10 @@ func TestSystemcfg(t *testing.T) {
"TOKEN_EXPIRATION": "30", "TOKEN_EXPIRATION": "30",
"CFG_EXPIRATION": "5", "CFG_EXPIRATION": "5",
"EMAIL_PORT": "25", "EMAIL_PORT": "25",
"MYSQL_PWD": "",
"LDAP_SEARCH_PWD": "",
"EMAIL_PWD": "",
"HARBOR_ADMIN_PASSWORD": "",
} }
for k, v := range m { for k, v := range m {
@ -59,11 +78,7 @@ func TestSystemcfg(t *testing.T) {
t.Errorf("failed to initialize system configurations: %v", err) t.Errorf("failed to initialize system configurations: %v", err)
return return
} }
defer func() { defer os.Remove(configPath)
if err := os.Remove(path); err != nil {
t.Fatalf("failed to remove %s: %v", path, err)
}
}()
// run Init again to make sure it works well when the configuration file // run Init again to make sure it works well when the configuration file
// already exists // already exists

View File

@ -74,7 +74,6 @@ const (
CfgExpiration = "cfg_expiration" CfgExpiration = "cfg_expiration"
JobLogDir = "job_log_dir" JobLogDir = "job_log_dir"
UseCompressedJS = "use_compressed_js" UseCompressedJS = "use_compressed_js"
SecretKey = "secret_key"
AdminInitialPassword = "admin_initial_password" AdminInitialPassword = "admin_initial_password"
) )

View File

@ -0,0 +1,47 @@
/*
Copyright (c) 2016 VMware, Inc. 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 config
import (
"io/ioutil"
)
// KeyProvider provides the key used to encrypt and decrypt attrs
type KeyProvider interface {
// Get returns the key
// params can be used to pass parameters in different implements
Get(params map[string]interface{}) (string, error)
}
// FileKeyProvider reads key from file
type FileKeyProvider struct {
path string
}
// NewFileKeyProvider returns an instance of FileKeyProvider
// path: where the key should be read from
func NewFileKeyProvider(path string) KeyProvider {
return &FileKeyProvider{
path: path,
}
}
// Get returns the key read from file
func (f *FileKeyProvider) Get(params map[string]interface{}) (string, error) {
b, err := ioutil.ReadFile(f.path)
if err != nil {
return "", err
}
return string(b), nil
}

View File

@ -0,0 +1,43 @@
/*
Copyright (c) 2016 VMware, Inc. 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 config
import (
"io/ioutil"
"os"
"testing"
)
func TestGetOfFileKeyProvider(t *testing.T) {
path := "/tmp/key"
key := "key_content"
if err := ioutil.WriteFile(path, []byte(key), 0777); err != nil {
t.Errorf("failed to write to file %s: %v", path, err)
return
}
defer os.Remove(path)
provider := NewFileKeyProvider(path)
k, err := provider.Get(nil)
if err != nil {
t.Errorf("failed to get key from the file provider: %v", err)
return
}
if k != key {
t.Errorf("unexpected key: %s != %s", k, key)
return
}
}

View File

@ -58,7 +58,6 @@ var adminServerDefaultConfig = map[string]interface{}{
config.CfgExpiration: 5, config.CfgExpiration: 5,
config.JobLogDir: "/var/log/jobs", config.JobLogDir: "/var/log/jobs",
config.UseCompressedJS: true, config.UseCompressedJS: true,
config.SecretKey: "secret",
config.AdminInitialPassword: "password", config.AdminInitialPassword: "password",
} }

View File

@ -0,0 +1,41 @@
/*
Copyright (c) 2016 VMware, Inc. 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 test
import (
"crypto/aes"
"crypto/rand"
"fmt"
"io/ioutil"
)
// GenerateKey generates aes key
func GenerateKey(path string) (string, error) {
data := make([]byte, aes.BlockSize)
n, err := rand.Read(data)
if err != nil {
return "", fmt.Errorf("failed to generate random bytes: %v", err)
}
if n != aes.BlockSize {
return "", fmt.Errorf("the length of random bytes %d != %d", n, aes.BlockSize)
}
if err = ioutil.WriteFile(path, data, 0777); err != nil {
return "", fmt.Errorf("failed write secret key to file %s: %v", path, err)
}
return string(data), nil
}

View File

@ -20,12 +20,23 @@ import (
comcfg "github.com/vmware/harbor/src/common/config" comcfg "github.com/vmware/harbor/src/common/config"
"github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/models"
"github.com/vmware/harbor/src/common/utils/log"
) )
var mg *comcfg.Manager const (
defaultKeyPath string = "/etc/jobservice/key"
)
var (
mg *comcfg.Manager
keyProvider comcfg.KeyProvider
)
// Init configurations // Init configurations
func Init() error { func Init() error {
//init key provider
initKeyProvider()
adminServerURL := os.Getenv("ADMIN_SERVER_URL") adminServerURL := os.Getenv("ADMIN_SERVER_URL")
if len(adminServerURL) == 0 { if len(adminServerURL) == 0 {
adminServerURL = "http://adminserver" adminServerURL = "http://adminserver"
@ -43,6 +54,16 @@ func Init() error {
return nil return nil
} }
func initKeyProvider() {
path := os.Getenv("KEY_PATH")
if len(path) == 0 {
path = defaultKeyPath
}
log.Infof("key path: %s", path)
keyProvider = comcfg.NewFileKeyProvider(path)
}
// VerifyRemoteCert returns bool value. // VerifyRemoteCert returns bool value.
func VerifyRemoteCert() (bool, error) { func VerifyRemoteCert() (bool, error) {
cfg, err := mg.Get() cfg, err := mg.Get()
@ -108,15 +129,11 @@ func LogDir() (string, error) {
// SecretKey will return the secret key for encryption/decryption password in target. // SecretKey will return the secret key for encryption/decryption password in target.
func SecretKey() (string, error) { func SecretKey() (string, error) {
cfg, err := mg.Get() return keyProvider.Get(nil)
if err != nil {
return "", err
}
return cfg[comcfg.SecretKey].(string), nil
} }
// UISecret returns the value of UI secret cookie, used for communication between UI and JobService // UISecret returns a secret used for communication of UI, JobService
// TODO // and Adminserver
func UISecret() string { func UISecret() string {
return os.Getenv("UI_SECRET") return os.Getenv("UI_SECRET")
} }

View File

@ -30,13 +30,22 @@ func TestConfig(t *testing.T) {
} }
defer server.Close() defer server.Close()
url := os.Getenv("ADMIN_SERVER_URL")
defer os.Setenv("ADMIN_SERVER_URL", url)
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil { if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err) t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err)
} }
secretKeyPath := "/tmp/secretkey"
_, err = test.GenerateKey(secretKeyPath)
if err != nil {
t.Errorf("failed to generate secret key: %v", err)
return
}
defer os.Remove(secretKeyPath)
if err := os.Setenv("KEY_PATH", secretKeyPath); err != nil {
t.Fatalf("failed to set env %s: %v", "KEY_PATH", err)
}
if err := Init(); err != nil { if err := Init(); err != nil {
t.Fatalf("failed to initialize configurations: %v", err) t.Fatalf("failed to initialize configurations: %v", err)
} }

View File

@ -461,7 +461,6 @@ func (m *ManifestPusher) enter() (string, error) {
func newRepositoryClient(endpoint string, insecure bool, credential auth.Credential, func newRepositoryClient(endpoint string, insecure bool, credential auth.Credential,
tokenServiceEndpoint, repository, scopeType, scopeName string, tokenServiceEndpoint, repository, scopeType, scopeName string,
scopeActions ...string) (*registry.Repository, error) { scopeActions ...string) (*registry.Repository, error) {
authorizer := auth.NewStandardTokenAuthorizer(credential, insecure, authorizer := auth.NewStandardTokenAuthorizer(credential, insecure,
tokenServiceEndpoint, scopeType, scopeName, scopeActions...) tokenServiceEndpoint, scopeType, scopeName, scopeActions...)

View File

@ -215,8 +215,6 @@ func validateCfg(c map[string]string) (bool, error) {
} }
} }
log.Infof("===========%v", c)
if ldapURL, ok := c[comcfg.LDAPURL]; ok && len(ldapURL) == 0 { if ldapURL, ok := c[comcfg.LDAPURL]; ok && len(ldapURL) == 0 {
return isSysErr, fmt.Errorf("%s is empty", comcfg.LDAPURL) return isSysErr, fmt.Errorf("%s is empty", comcfg.LDAPURL)
} }
@ -325,8 +323,7 @@ func convertForGet(cfg map[string]interface{}) (map[string]*value, error) {
comcfg.AdminInitialPassword, comcfg.AdminInitialPassword,
comcfg.EmailPassword, comcfg.EmailPassword,
comcfg.LDAPSearchPwd, comcfg.LDAPSearchPwd,
comcfg.MySQLPassword, comcfg.MySQLPassword}
comcfg.SecretKey}
for _, del := range dels { for _, del := range dels {
if _, ok := cfg[del]; ok { if _, ok := cfg[del]; ok {
delete(cfg, del) delete(cfg, del)

View File

@ -24,10 +24,18 @@ import (
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
) )
var mg *comcfg.Manager const defaultKeyPath string = "/etc/ui/key"
var (
mg *comcfg.Manager
keyProvider comcfg.KeyProvider
)
// Init configurations // Init configurations
func Init() error { func Init() error {
//init key provider
initKeyProvider()
adminServerURL := os.Getenv("ADMIN_SERVER_URL") adminServerURL := os.Getenv("ADMIN_SERVER_URL")
if len(adminServerURL) == 0 { if len(adminServerURL) == 0 {
adminServerURL = "http://adminserver" adminServerURL = "http://adminserver"
@ -46,6 +54,16 @@ func Init() error {
return nil return nil
} }
func initKeyProvider() {
path := os.Getenv("KEY_PATH")
if len(path) == 0 {
path = defaultKeyPath
}
log.Infof("key path: %s", path)
keyProvider = comcfg.NewFileKeyProvider(path)
}
// Load configurations // Load configurations
func Load() error { func Load() error {
_, err := mg.Load() _, err := mg.Load()
@ -125,11 +143,7 @@ func ExtEndpoint() (string, error) {
// SecretKey returns the secret key to encrypt the password of target // SecretKey returns the secret key to encrypt the password of target
func SecretKey() (string, error) { func SecretKey() (string, error) {
cfg, err := mg.Get() return keyProvider.Get(nil)
if err != nil {
return "", err
}
return cfg[comcfg.SecretKey].(string), nil
} }
// SelfRegistration returns the enablement of self registration // SelfRegistration returns the enablement of self registration
@ -228,8 +242,8 @@ func Database() (*models.Database, error) {
return database, nil return database, nil
} }
// UISecret returns the value of UI secret cookie, used for communication between UI and JobService // UISecret returns a secret used for communication of UI, JobService
// TODO // and Adminserver
func UISecret() string { func UISecret() string {
return os.Getenv("UI_SECRET") return os.Getenv("UI_SECRET")
} }

View File

@ -29,13 +29,22 @@ func TestConfig(t *testing.T) {
} }
defer server.Close() defer server.Close()
url := os.Getenv("ADMIN_SERVER_URL")
defer os.Setenv("ADMIN_SERVER_URL", url)
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil { if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err) t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err)
} }
secretKeyPath := "/tmp/secretkey"
_, err = test.GenerateKey(secretKeyPath)
if err != nil {
t.Errorf("failed to generate secret key: %v", err)
return
}
defer os.Remove(secretKeyPath)
if err := os.Setenv("KEY_PATH", secretKeyPath); err != nil {
t.Fatalf("failed to set env %s: %v", "KEY_PATH", err)
}
if err := Init(); err != nil { if err := Init(); err != nil {
t.Fatalf("failed to initialize configurations: %v", err) t.Fatalf("failed to initialize configurations: %v", err)
} }

View File

@ -29,7 +29,8 @@ services:
- ./common/config/adminserver/env - ./common/config/adminserver/env
restart: always restart: always
volumes: volumes:
- /data/config/:/etc/harbor/ - /data/config/:/etc/adminserver/
- /data/secretkey:/etc/adminserver/key
ports: ports:
- 8888:80 - 8888:80
ldap: ldap:

View File

@ -11,3 +11,5 @@ cp make/common/config/ui/app.conf conf/.
sed -i -r "s/MYSQL_HOST=mysql/MYSQL_HOST=127.0.0.1/" make/common/config/adminserver/env sed -i -r "s/MYSQL_HOST=mysql/MYSQL_HOST=127.0.0.1/" make/common/config/adminserver/env
sed -i -r "s|REGISTRY_URL=http://registry:5000|REGISTRY_URL=http://127.0.0.1:5000|" make/common/config/adminserver/env sed -i -r "s|REGISTRY_URL=http://registry:5000|REGISTRY_URL=http://127.0.0.1:5000|" make/common/config/adminserver/env
sed -i -r "s/UI_SECRET=.*/UI_SECRET=$UI_SECRET/" make/common/config/adminserver/env sed -i -r "s/UI_SECRET=.*/UI_SECRET=$UI_SECRET/" make/common/config/adminserver/env
chmod 777 /data/