encrypt passwords and secret

This commit is contained in:
Wenkai Yin 2017-02-15 15:25:59 +08:00
parent 06519bb3f2
commit 390f89ee0a
21 changed files with 441 additions and 66 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

@ -49,6 +49,7 @@ services:
restart: always restart: always
volumes: volumes:
- /data/config/:/etc/harbor/ - /data/config/:/etc/harbor/
- /data/secretkey:/harbor/secretkey
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:/harbor/secretkey
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:/harbor/secretkey
depends_on: depends_on:
- ui - ui
- adminserver - adminserver

View File

@ -49,6 +49,7 @@ services:
restart: always restart: always
volumes: volumes:
- /data/config/:/etc/harbor/ - /data/config/:/etc/harbor/
- /data/secretkey:/harbor/secretkey
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:/harbor/secretkey
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:/harbor/secretkey
depends_on: depends_on:
- ui - ui
- adminserver - adminserver

View File

@ -10,6 +10,9 @@ import argparse
import subprocess import subprocess
import shutil import shutil
from io import open from io import open
import base64
from Crypto import Random
from Crypto.Cipher import AES
if sys.version_info[:3][0] == 2: if sys.version_info[:3][0] == 2:
import ConfigParser as ConfigParser import ConfigParser as ConfigParser
@ -54,6 +57,11 @@ def get_secret_key(path):
print("generated and saved secret key") print("generated and saved secret key")
return key return key
def aesEncrypt(key, raw):
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CFB, iv)
return base64.b64encode(iv + cipher.encrypt(raw))
base_dir = os.path.dirname(__file__) base_dir = os.path.dirname(__file__)
config_dir = os.path.join(base_dir, "common/config") config_dir = os.path.join(base_dir, "common/config")
templates_dir = os.path.join(base_dir, "common/templates") templates_dir = os.path.join(base_dir, "common/templates")
@ -125,6 +133,7 @@ secret_key = get_secret_key(secretkey_path)
######## ########
ui_secret = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(16)) ui_secret = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(16))
#ui_secret = aesEncrypt(secret_key, ui_secret_raw)
adminserver_config_dir = os.path.join(config_dir,"adminserver") adminserver_config_dir = os.path.join(config_dir,"adminserver")
if not os.path.exists(adminserver_config_dir): if not os.path.exists(adminserver_config_dir):

View File

@ -19,14 +19,13 @@ import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"github.com/vmware/harbor/src/adminserver/config"
cfg "github.com/vmware/harbor/src/adminserver/systemcfg" cfg "github.com/vmware/harbor/src/adminserver/systemcfg"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
) )
func isAuthenticated(r *http.Request) (bool, error) { func isAuthenticated(r *http.Request) (bool, error) {
secret := os.Getenv("UI_SECRET")
c, err := r.Cookie("secret") c, err := r.Cookie("secret")
if err != nil { if err != nil {
if err == http.ErrNoCookie { if err == http.ErrNoCookie {
@ -34,7 +33,7 @@ func isAuthenticated(r *http.Request) (bool, error) {
} }
return false, err return false, err
} }
return c != nil && c.Value == secret, nil return c != nil && c.Value == config.Secret(), nil
} }
// ListCfgs lists configurations // ListCfgs lists configurations

View File

@ -25,16 +25,36 @@ import (
"os" "os"
"testing" "testing"
"github.com/vmware/harbor/src/adminserver/config"
"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"
/*
secretPlaintext := "secret"
secretCiphertext, err := utils.ReversibleEncrypt(secretPlaintext, string(data))
if err != nil {
t.Errorf("failed to encrypt secret: %v", err)
return
}
*/
envs := map[string]string{ envs := map[string]string{
"JSON_STORE_PATH": path,
"JSON_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,6 +63,10 @@ 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 {
@ -50,7 +74,12 @@ func TestConfigAPI(t *testing.T) {
t.Fatalf("failed to set env %s: %v", k, err) t.Fatalf("failed to set env %s: %v", k, err)
} }
} }
defer os.Remove(path) defer os.Remove(configPath)
if err := config.Init(); err != nil {
t.Errorf("failed to load configurations of adminserver: %v", err)
return
}
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 +117,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 +125,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 +175,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

@ -0,0 +1,66 @@
/*
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"
//"github.com/vmware/harbor/src/common/utils"
)
const defaultKeyPath string = "/harbor/secretkey"
var (
secret string
secretKey string
)
// Init configurations used by adminserver
func Init() error {
path := os.Getenv("KEY_PATH")
if len(path) == 0 {
path = defaultKeyPath
}
b, err := ioutil.ReadFile(path)
if err != nil {
return err
}
secretKey = string(b)
secret = os.Getenv("UI_SECRET")
/*
secretCipherText := os.Getenv("UI_SECRET")
secret, err = utils.ReversibleDecrypt(secretCipherText, secretKey)
if err != nil {
return err
}
*/
return nil
}
// Secret is used by API to authenticate requests
func Secret() string {
return secret
}
// SecretKey is used to encrypt or decrypt
func SecretKey() string {
return secretKey
}

View File

@ -0,0 +1,67 @@
/*
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 (
"os"
"testing"
"github.com/vmware/harbor/src/common/utils/test"
)
func TestConfig(t *testing.T) {
secretKeyPath := "/tmp/secretkey"
secretKey, err := test.GenerateKey(secretKeyPath)
if err != nil {
t.Errorf("failed to generate secret key: %v", err)
return
}
defer os.Remove(secretKeyPath)
secret := "secret"
/*
secretPlaintext := "secret"
secretCiphertext, err := utils.ReversibleEncrypt(secretPlaintext, string(data))
if err != nil {
t.Errorf("failed to encrypt secret: %v", err)
return
}
*/
envs := map[string]string{
"KEY_PATH": secretKeyPath,
"UI_SECRET": secret,
}
for k, v := range envs {
if err := os.Setenv(k, v); err != nil {
t.Fatalf("failed to set env %s: %v", k, err)
}
}
if err := Init(); err != nil {
t.Errorf("failed to load configurations of adminserver: %v", err)
return
}
if SecretKey() != secretKey {
t.Errorf("unexpected secret key: %s != %s", SecretKey(), secretKey)
}
if Secret() != secret {
t.Errorf("unexpected secret: %s != %s", Secret(), secret)
}
}

View File

@ -19,7 +19,8 @@ import (
"net/http" "net/http"
"os" "os"
cfg "github.com/vmware/harbor/src/adminserver/systemcfg" "github.com/vmware/harbor/src/adminserver/config"
syscfg "github.com/vmware/harbor/src/adminserver/systemcfg"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
) )
@ -40,8 +41,15 @@ func (s *Server) Serve() error {
} }
func main() { func main() {
log.Info("loading configurations of adminserver...")
if err := config.Init(); err != nil {
log.Fatalf("failed to load configurations of adminserver: %v", err)
}
log.Info("load completed")
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

@ -20,12 +20,22 @@ import (
"os" "os"
"strconv" "strconv"
"github.com/vmware/harbor/src/adminserver/config"
"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"
) )
// Keys need to be encrypted or decrypted
var Keys = []string{
comcfg.EmailPassword,
comcfg.LDAPSearchPwd,
comcfg.MySQLPassword,
comcfg.AdminInitialPassword,
}
var cfgStore store.Driver var cfgStore store.Driver
// 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
@ -43,7 +53,7 @@ func Init() (err error) {
} }
log.Infof("configuration store driver: %s", cfgStore.Name()) log.Infof("configuration store driver: %s", cfgStore.Name())
cfg, err := cfgStore.Read() cfg, err := GetSystemCfg()
if err != nil { if err != nil {
return err return err
} }
@ -61,7 +71,7 @@ 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
} }
@ -102,7 +112,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 +171,64 @@ 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
}
if err = decrypt(m, Keys, config.SecretKey()); 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 {
if err := encrypt(cfg, Keys, config.SecretKey()); 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

@ -47,6 +47,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 {

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

@ -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

@ -16,16 +16,55 @@
package config package config
import ( import (
"io/ioutil"
"os" "os"
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"
//"github.com/vmware/harbor/src/common/utils/log"
) )
const defaultKeyPath string = "/harbor/secretkey"
var mg *comcfg.Manager var mg *comcfg.Manager
var (
secret string
secretKey string
)
func initSecretAndKey() error {
path := os.Getenv("KEY_PATH")
if len(path) == 0 {
path = defaultKeyPath
}
b, err := ioutil.ReadFile(path)
if err != nil {
return err
}
secretKey = string(b)
secret = os.Getenv("UI_SECRET")
/*
secretCipherText := os.Getenv("UI_SECRET")
secret, err = utils.ReversibleDecrypt(secretCipherText, secretKey)
if err != nil {
log.Errorf("failed to decrypt secret: %v", err)
}
*/
return nil
}
// Init configurations // Init configurations
func Init() error { func Init() error {
if err := initSecretAndKey(); err != nil {
return err
}
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"
@ -108,17 +147,13 @@ 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 secretKey, 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 secret
} }
// ExtEndpoint ... // ExtEndpoint ...

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

@ -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

@ -17,17 +17,53 @@ package config
import ( import (
"encoding/json" "encoding/json"
"io/ioutil"
"os" "os"
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"
"github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/log"
) )
const defaultKeyPath string = "/harbor/secretkey"
var mg *comcfg.Manager var mg *comcfg.Manager
var (
secret string
secretKey string
)
func initSecretAndKey() error {
path := os.Getenv("KEY_PATH")
if len(path) == 0 {
path = defaultKeyPath
}
b, err := ioutil.ReadFile(path)
if err != nil {
return err
}
secretKey = string(b)
secret = os.Getenv("UI_SECRET")
/*
secretCipherText := os.Getenv("UI_SECRET")
secret, err = utils.ReversibleDecrypt(secretCipherText, secretKey)
if err != nil {
return err
}
*/
return nil
}
// Init configurations // Init configurations
func Init() error { func Init() error {
if err := initSecretAndKey(); err != nil {
return err
}
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"
@ -125,11 +161,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 secretKey, 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 +260,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 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

@ -30,6 +30,7 @@ services:
restart: always restart: always
volumes: volumes:
- /data/config/:/etc/harbor/ - /data/config/:/etc/harbor/
- /data/secretkey:/harbor/secretkey
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/