encrypt passwords enhancement

This commit is contained in:
Wenkai Yin 2017-02-22 13:22:52 +08:00
parent 385d76e6f2
commit 40eb6bb7d3
15 changed files with 231 additions and 291 deletions

View File

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

View File

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

View File

@ -10,9 +10,6 @@ import argparse
import subprocess
import shutil
from io import open
import base64
from Crypto import Random
from Crypto.Cipher import AES
if sys.version_info[:3][0] == 2:
import ConfigParser as ConfigParser
@ -57,11 +54,6 @@ def get_secret_key(path):
print("generated and saved secret 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__)
config_dir = os.path.join(base_dir, "common/config")
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 = aesEncrypt(secret_key, ui_secret_raw)
adminserver_config_dir = os.path.join(config_dir,"adminserver")
if not os.path.exists(adminserver_config_dir):

View File

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

View File

@ -25,7 +25,6 @@ import (
"os"
"testing"
"github.com/vmware/harbor/src/adminserver/config"
"github.com/vmware/harbor/src/adminserver/systemcfg"
comcfg "github.com/vmware/harbor/src/common/config"
"github.com/vmware/harbor/src/common/utils/test"
@ -43,17 +42,9 @@ func TestConfigAPI(t *testing.T) {
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{
"JSON_STORE_PATH": configPath,
"JSON_CFG_STORE_PATH": configPath,
"KEY_PATH": secretKeyPath,
"UI_SECRET": secret,
"MYSQL_PORT": "3306",
@ -71,16 +62,12 @@ func TestConfigAPI(t *testing.T) {
for k, v := range envs {
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)
if err := config.Init(); err != nil {
t.Errorf("failed to load configurations of adminserver: %v", err)
return
}
if err := systemcfg.Init(); err != nil {
t.Errorf("failed to initialize system configurations: %v", err)
return

View File

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

View File

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

View File

@ -19,7 +19,6 @@ import (
"net/http"
"os"
"github.com/vmware/harbor/src/adminserver/config"
syscfg "github.com/vmware/harbor/src/adminserver/systemcfg"
"github.com/vmware/harbor/src/common/utils/log"
)
@ -41,13 +40,6 @@ func (s *Server) Serve() error {
}
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...")
if err := syscfg.Init(); err != nil {
log.Fatalf("failed to initialize the system: %v", err)

View File

@ -20,7 +20,6 @@ import (
"os"
"strconv"
"github.com/vmware/harbor/src/adminserver/config"
"github.com/vmware/harbor/src/adminserver/systemcfg/store"
"github.com/vmware/harbor/src/adminserver/systemcfg/store/json"
comcfg "github.com/vmware/harbor/src/common/config"
@ -28,31 +27,34 @@ import (
"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,
}
const (
defaultCfgStoreDriver string = "json"
defaultJSONCfgStorePath string = "/etc/adminserver/config.json"
defaultKeyPath string = "/etc/adminserver/key"
)
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
func Init() (err error) {
s := getCfgStore()
switch s {
case "json":
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)
//init configuation store
if err = initCfgStore(); err != nil {
return err
}
log.Infof("configuration store driver: %s", cfgStore.Name())
//init key provider
initKeyProvider()
cfg, err := GetSystemCfg()
if err != nil {
return err
@ -78,12 +80,37 @@ func Init() (err error) {
return nil
}
func getCfgStore() string {
t := os.Getenv("CFG_STORE_TYPE")
func initCfgStore() (err error) {
t := os.Getenv("CFG_STORE_DRIVER")
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
@ -176,7 +203,12 @@ func GetSystemCfg() (map[string]interface{}, error) {
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
}
@ -186,7 +218,12 @@ func GetSystemCfg() (map[string]interface{}, error) {
// UpdateSystemCfg updates the system configurations
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
}

View File

@ -20,22 +20,37 @@ import (
"testing"
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) {
key := "JSON_STORE_PATH"
path := "/tmp/config.json"
if _, err := os.Stat(path); err == nil {
if err := os.Remove(path); err != nil {
t.Fatalf("failed to remove %s: %v", path, err)
configPath := "/tmp/config.json"
if _, err := os.Stat(configPath); err == nil {
if err := os.Remove(configPath); err != nil {
t.Errorf("failed to remove %s: %v", configPath, err)
return
}
} 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 {
t.Fatalf("failed to set env %s: %v", key, err)
if err := os.Setenv("JSON_CFG_STORE_PATH", configPath); err != nil {
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{
@ -63,11 +78,7 @@ func TestSystemcfg(t *testing.T) {
t.Errorf("failed to initialize system configurations: %v", err)
return
}
defer func() {
if err := os.Remove(path); err != nil {
t.Fatalf("failed to remove %s: %v", path, err)
}
}()
defer os.Remove(configPath)
// run Init again to make sure it works well when the configuration file
// already exists

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

@ -16,54 +16,26 @@
package config
import (
"io/ioutil"
"os"
comcfg "github.com/vmware/harbor/src/common/config"
"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
const (
defaultKeyPath string = "/etc/jobservice/key"
)
var (
secret string
secretKey string
mg *comcfg.Manager
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
func Init() error {
if err := initSecretAndKey(); err != nil {
return err
}
//init key provider
initKeyProvider()
adminServerURL := os.Getenv("ADMIN_SERVER_URL")
if len(adminServerURL) == 0 {
@ -82,6 +54,16 @@ func Init() error {
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.
func VerifyRemoteCert() (bool, error) {
cfg, err := mg.Get()
@ -147,13 +129,13 @@ func LogDir() (string, error) {
// SecretKey will return the secret key for encryption/decryption password in target.
func SecretKey() (string, error) {
return secretKey, nil
return keyProvider.Get(nil)
}
// UISecret returns a secret used for communication of UI, JobService
// and Adminserver
func UISecret() string {
return secret
return os.Getenv("UI_SECRET")
}
// ExtEndpoint ...

View File

@ -17,52 +17,24 @@ package config
import (
"encoding/json"
"io/ioutil"
"os"
comcfg "github.com/vmware/harbor/src/common/config"
"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
const defaultKeyPath string = "/etc/ui/key"
var (
secret string
secretKey string
mg *comcfg.Manager
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
func Init() error {
if err := initSecretAndKey(); err != nil {
return err
}
//init key provider
initKeyProvider()
adminServerURL := os.Getenv("ADMIN_SERVER_URL")
if len(adminServerURL) == 0 {
@ -82,6 +54,16 @@ func Init() error {
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
func Load() error {
_, err := mg.Load()
@ -161,7 +143,7 @@ func ExtEndpoint() (string, error) {
// SecretKey returns the secret key to encrypt the password of target
func SecretKey() (string, error) {
return secretKey, nil
return keyProvider.Get(nil)
}
// 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
// and Adminserver
func UISecret() string {
return secret
return os.Getenv("UI_SECRET")
}

View File

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