mirror of
https://github.com/goharbor/harbor.git
synced 2025-03-11 22:20:00 +01:00
encrypt passwords enhancement
This commit is contained in:
parent
385d76e6f2
commit
40eb6bb7d3
@ -48,8 +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:/harbor/secretkey
|
- /data/secretkey:/etc/adminserver/key
|
||||||
depends_on:
|
depends_on:
|
||||||
- log
|
- log
|
||||||
logging:
|
logging:
|
||||||
@ -67,7 +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
|
- /data/secretkey:/etc/ui/key
|
||||||
depends_on:
|
depends_on:
|
||||||
- log
|
- log
|
||||||
- adminserver
|
- adminserver
|
||||||
@ -87,7 +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
|
- /data/secretkey:/etc/jobservice/key
|
||||||
depends_on:
|
depends_on:
|
||||||
- ui
|
- ui
|
||||||
- adminserver
|
- adminserver
|
||||||
|
@ -48,8 +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:/harbor/secretkey
|
- /data/secretkey:/etc/adminserver/key
|
||||||
depends_on:
|
depends_on:
|
||||||
- log
|
- log
|
||||||
logging:
|
logging:
|
||||||
@ -67,7 +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
|
- /data/secretkey:/etc/ui/key
|
||||||
depends_on:
|
depends_on:
|
||||||
- log
|
- log
|
||||||
- adminserver
|
- adminserver
|
||||||
@ -86,7 +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
|
- /data/secretkey:/etc/jobservice/key
|
||||||
depends_on:
|
depends_on:
|
||||||
- ui
|
- ui
|
||||||
- adminserver
|
- adminserver
|
||||||
|
@ -10,9 +10,6 @@ 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
|
||||||
@ -57,11 +54,6 @@ 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")
|
||||||
@ -133,7 +125,6 @@ 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):
|
||||||
|
@ -19,13 +19,14 @@ 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 {
|
||||||
@ -33,7 +34,7 @@ func isAuthenticated(r *http.Request) (bool, error) {
|
|||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return c != nil && c.Value == config.Secret(), nil
|
return c != nil && c.Value == secret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListCfgs lists configurations
|
// ListCfgs lists configurations
|
||||||
|
@ -25,7 +25,6 @@ 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"
|
||||||
comcfg "github.com/vmware/harbor/src/common/config"
|
comcfg "github.com/vmware/harbor/src/common/config"
|
||||||
"github.com/vmware/harbor/src/common/utils/test"
|
"github.com/vmware/harbor/src/common/utils/test"
|
||||||
@ -43,17 +42,9 @@ func TestConfigAPI(t *testing.T) {
|
|||||||
defer os.Remove(secretKeyPath)
|
defer os.Remove(secretKeyPath)
|
||||||
|
|
||||||
secret := "secret"
|
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": configPath,
|
"JSON_CFG_STORE_PATH": configPath,
|
||||||
"KEY_PATH": secretKeyPath,
|
"KEY_PATH": secretKeyPath,
|
||||||
"UI_SECRET": secret,
|
"UI_SECRET": secret,
|
||||||
"MYSQL_PORT": "3306",
|
"MYSQL_PORT": "3306",
|
||||||
@ -71,16 +62,12 @@ func TestConfigAPI(t *testing.T) {
|
|||||||
|
|
||||||
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(configPath)
|
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)
|
||||||
return
|
return
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,7 +19,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/vmware/harbor/src/adminserver/config"
|
|
||||||
syscfg "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,13 +40,6 @@ 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 := syscfg.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)
|
||||||
|
@ -20,7 +20,6 @@ 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"
|
||||||
@ -28,31 +27,34 @@ import (
|
|||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Keys need to be encrypted or decrypted
|
const (
|
||||||
var Keys = []string{
|
defaultCfgStoreDriver string = "json"
|
||||||
comcfg.EmailPassword,
|
defaultJSONCfgStorePath string = "/etc/adminserver/config.json"
|
||||||
comcfg.LDAPSearchPwd,
|
defaultKeyPath string = "/etc/adminserver/key"
|
||||||
comcfg.MySQLPassword,
|
)
|
||||||
comcfg.AdminInitialPassword,
|
|
||||||
}
|
|
||||||
|
|
||||||
var cfgStore store.Driver
|
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
|
||||||
|
initKeyProvider()
|
||||||
|
|
||||||
cfg, err := GetSystemCfg()
|
cfg, err := GetSystemCfg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -78,12 +80,37 @@ func Init() (err error) {
|
|||||||
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
|
||||||
@ -176,7 +203,12 @@ func GetSystemCfg() (map[string]interface{}, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = decrypt(m, Keys, config.SecretKey()); err != nil {
|
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 nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +218,12 @@ func GetSystemCfg() (map[string]interface{}, error) {
|
|||||||
// 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 {
|
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 err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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{
|
||||||
@ -63,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
|
||||||
|
47
src/common/config/keyprovider.go
Normal file
47
src/common/config/keyprovider.go
Normal 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
|
||||||
|
}
|
43
src/common/config/keyprovider_test.go
Normal file
43
src/common/config/keyprovider_test.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -16,54 +16,26 @@
|
|||||||
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"
|
||||||
//"github.com/vmware/harbor/src/common/utils/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultKeyPath string = "/harbor/secretkey"
|
const (
|
||||||
|
defaultKeyPath string = "/etc/jobservice/key"
|
||||||
var mg *comcfg.Manager
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
secret string
|
mg *comcfg.Manager
|
||||||
secretKey string
|
keyProvider comcfg.KeyProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
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 {
|
//init key provider
|
||||||
return err
|
initKeyProvider()
|
||||||
}
|
|
||||||
|
|
||||||
adminServerURL := os.Getenv("ADMIN_SERVER_URL")
|
adminServerURL := os.Getenv("ADMIN_SERVER_URL")
|
||||||
if len(adminServerURL) == 0 {
|
if len(adminServerURL) == 0 {
|
||||||
@ -82,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()
|
||||||
@ -147,13 +129,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) {
|
||||||
return secretKey, nil
|
return keyProvider.Get(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UISecret returns a secret used for communication of UI, JobService
|
// UISecret returns a secret used for communication of UI, JobService
|
||||||
// and Adminserver
|
// and Adminserver
|
||||||
func UISecret() string {
|
func UISecret() string {
|
||||||
return secret
|
return os.Getenv("UI_SECRET")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtEndpoint ...
|
// ExtEndpoint ...
|
||||||
|
@ -17,52 +17,24 @@ 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"
|
const defaultKeyPath string = "/etc/ui/key"
|
||||||
|
|
||||||
var mg *comcfg.Manager
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
secret string
|
mg *comcfg.Manager
|
||||||
secretKey string
|
keyProvider comcfg.KeyProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
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 {
|
//init key provider
|
||||||
return err
|
initKeyProvider()
|
||||||
}
|
|
||||||
|
|
||||||
adminServerURL := os.Getenv("ADMIN_SERVER_URL")
|
adminServerURL := os.Getenv("ADMIN_SERVER_URL")
|
||||||
if len(adminServerURL) == 0 {
|
if len(adminServerURL) == 0 {
|
||||||
@ -82,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()
|
||||||
@ -161,7 +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) {
|
||||||
return secretKey, nil
|
return keyProvider.Get(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelfRegistration returns the enablement of self registration
|
// SelfRegistration returns the enablement of self registration
|
||||||
@ -263,5 +245,5 @@ func Database() (*models.Database, error) {
|
|||||||
// UISecret returns a secret used for communication of UI, JobService
|
// UISecret returns a secret used for communication of UI, JobService
|
||||||
// and Adminserver
|
// and Adminserver
|
||||||
func UISecret() string {
|
func UISecret() string {
|
||||||
return secret
|
return os.Getenv("UI_SECRET")
|
||||||
}
|
}
|
||||||
|
@ -29,8 +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:/harbor/secretkey
|
- /data/secretkey:/etc/adminserver/key
|
||||||
ports:
|
ports:
|
||||||
- 8888:80
|
- 8888:80
|
||||||
ldap:
|
ldap:
|
||||||
|
Loading…
Reference in New Issue
Block a user