From eab6b43d99badf46426436b8045dd98eab35361d Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Mon, 16 Oct 2017 17:40:29 +0800 Subject: [PATCH] Make the root CA certificate of UAA should be configurable --- make/common/templates/ui/env | 1 + make/docker-compose.tpl | 1 + make/harbor.cfg | 1 + make/prepare | 8 ++++++++ src/common/models/uaa.go | 1 + src/common/utils/uaa/client.go | 17 ++++++++++++++-- src/common/utils/uaa/client_test.go | 30 ++++++++++++++++++++++++++++ src/common/utils/uaa/test/ca.pem | 18 +++++++++++++++++ src/common/utils/uaa/test/non-ca.pem | 1 + src/ui/auth/uaa/uaa.go | 3 +-- src/ui/config/config.go | 3 +++ 11 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/common/utils/uaa/test/ca.pem create mode 100644 src/common/utils/uaa/test/non-ca.pem diff --git a/make/common/templates/ui/env b/make/common/templates/ui/env index 1f457e2570..d87c931059 100644 --- a/make/common/templates/ui/env +++ b/make/common/templates/ui/env @@ -3,3 +3,4 @@ CONFIG_PATH=/etc/ui/app.conf UI_SECRET=$ui_secret JOBSERVICE_SECRET=$jobservice_secret GODEBUG=netdns=cgo +UAA_CA_ROOT=/etc/ui/certificates/uaa_ca.pem diff --git a/make/docker-compose.tpl b/make/docker-compose.tpl index ec516f0e10..154fbc0940 100644 --- a/make/docker-compose.tpl +++ b/make/docker-compose.tpl @@ -75,6 +75,7 @@ services: volumes: - ./common/config/ui/app.conf:/etc/ui/app.conf:z - ./common/config/ui/private_key.pem:/etc/ui/private_key.pem:z + - ./common/config/ui/certificates/:/etc/ui/certifates/ - /data/secretkey:/etc/ui/key:z - /data/ca_download/:/etc/ui/ca/:z - /data/psc/:/etc/ui/token/:z diff --git a/make/harbor.cfg b/make/harbor.cfg index 224b75b3d3..1214b77f91 100644 --- a/make/harbor.cfg +++ b/make/harbor.cfg @@ -117,4 +117,5 @@ db_user = root uaa_endpoint = uaa.mydomain.org uaa_clientid= id uaa_clientsecret= secret +uaa_ca_root= /path/to/uaa_ca.pem ############# diff --git a/make/prepare b/make/prepare index d429e14965..426d5b62c6 100755 --- a/make/prepare +++ b/make/prepare @@ -160,6 +160,7 @@ pg_password = rcp.get("configuration", "clair_db_password") uaa_endpoint = rcp.get("configuration", "uaa_endpoint") uaa_clientid = rcp.get("configuration", "uaa_clientid") uaa_clientsecret = rcp.get("configuration", "uaa_clientsecret") +uaa_ca_root = rcp.get("configuration", "uaa_ca_root") secret_key = get_secret_key(secretkey_path) ######## @@ -171,6 +172,7 @@ if not os.path.exists(adminserver_config_dir): os.makedirs(os.path.join(config_dir, "adminserver")) ui_config_dir = prep_conf_dir(config_dir,"ui") +ui_certificates_dir = prep_conf_dir(ui_config_dir,"certificates") db_config_dir = prep_conf_dir(config_dir, "db") job_config_dir = prep_conf_dir(config_dir, "jobservice") registry_config_dir = prep_conf_dir(config_dir, "registry") @@ -201,6 +203,12 @@ if protocol == "https": else: render(os.path.join(templates_dir, "nginx", "nginx.http.conf"), nginx_conf) + +if auth_mode == "uaa_auth": + if os.path.isfile(uaa_ca_root): + shutil.copy2(uaa_ca_root, os.path.join(ui_certificates_dir, "uaa_ca.pem")) + else: + raise Exception("Error: Invalid path for uaa ca root: %s" % uaa_ca_root) render(os.path.join(templates_dir, "adminserver", "env"), adminserver_conf_env, diff --git a/src/common/models/uaa.go b/src/common/models/uaa.go index 9869cc47fb..46469c94c0 100644 --- a/src/common/models/uaa.go +++ b/src/common/models/uaa.go @@ -19,4 +19,5 @@ type UAASettings struct { Endpoint string ClientID string ClientSecret string + CARootPath string } diff --git a/src/common/utils/uaa/client.go b/src/common/utils/uaa/client.go index c5df061e9f..d0f259bfa8 100644 --- a/src/common/utils/uaa/client.go +++ b/src/common/utils/uaa/client.go @@ -17,9 +17,12 @@ package uaa import ( "context" "crypto/tls" + "crypto/x509" + "io/ioutil" "net/http" "strings" + "github.com/vmware/harbor/src/common/utils/log" "golang.org/x/oauth2" ) @@ -61,8 +64,18 @@ func NewDefaultClient(cfg *ClientConfig) (Client, error) { tc := &tls.Config{ InsecureSkipVerify: cfg.SkipTLSVerify, } - if len(cfg.CARootPath) > 0 { - //TODO + if !cfg.SkipTLSVerify && len(cfg.CARootPath) > 0 { + content, err := ioutil.ReadFile(cfg.CARootPath) + if err != nil { + return nil, err + } + pool := x509.NewCertPool() + //Do not throw error if the certificate is malformed, so we can put a place holder. + if ok := pool.AppendCertsFromPEM(content); !ok { + log.Warningf("Failed to append certificate to cert pool, cert path: %s", cfg.CARootPath) + } else { + tc.RootCAs = pool + } } hc := &http.Client{ Transport: &http.Transport{ diff --git a/src/common/utils/uaa/client_test.go b/src/common/utils/uaa/client_test.go index 65864919f5..1a8081bb55 100644 --- a/src/common/utils/uaa/client_test.go +++ b/src/common/utils/uaa/client_test.go @@ -5,6 +5,8 @@ import ( "github.com/vmware/harbor/src/common/utils/uaa/test" "net/http/httptest" "os" + "path" + "runtime" "testing" ) @@ -40,3 +42,31 @@ func TestPasswordAuth(t *testing.T) { _, err = client.PasswordAuth("wrong", "wrong") assert.NotNil(err) } + +func currPath() string { + _, f, _, ok := runtime.Caller(0) + if !ok { + panic("Failed to get current directory") + } + return path.Dir(f) +} + +func TestNewClientWithCACert(t *testing.T) { + assert := assert.New(t) + cfg := &ClientConfig{ + ClientID: "uaa", + ClientSecret: "secret", + Endpoint: mockUAAServer.URL, + SkipTLSVerify: false, + CARootPath: "/notexist", + } + _, err := NewDefaultClient(cfg) + assert.NotNil(err) + //Skip if it's malformed. + cfg.CARootPath = path.Join(currPath(), "test", "non-ca.pem") + _, err = NewDefaultClient(cfg) + assert.Nil(err) + cfg.CARootPath = path.Join(currPath(), "test", "ca.pem") + _, err = NewDefaultClient(cfg) + assert.Nil(err) +} diff --git a/src/common/utils/uaa/test/ca.pem b/src/common/utils/uaa/test/ca.pem new file mode 100644 index 0000000000..9807f27cd0 --- /dev/null +++ b/src/common/utils/uaa/test/ca.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC7TCCAdWgAwIBAgIJAKmFRnILlp3XMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV +BAMMAmNhMB4XDTE3MDkyNDA3MDA1M1oXDTI3MDkyMjA3MDA1M1owDTELMAkGA1UE +AwwCY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCr4+HxXkY81j1p +5OD3htFkbJI+XulBgc7ja5YorU323VB7JfNBnau3rDZS8NdyvkLLEQT4rKw5Dd4p +phlmdKsmIq9ej1OlDjWnCOGr+HG2jG5POgPYRCf5WgCGoQ4eUIA+IXcVroG8f1YM +LDzZEBKlEP80W0zyh0ma/BYN8HG4Ica4q/iIjffJc7ob/tWFGt2HobI9wbTSyBgR +s7JSs6MBIISXGAuOE3cs7vJNzKtWhQSBw4j8FFUZSYCyONFYfOg2OtZG6z1XhpTC +rfVMm6cEsYla/mf9bJB2AqtRiUdUZwAOWQbalWPFKEO73Bj4/5sVNHKFCd/S6J1z +LHaWM0W7AgMBAAGjUDBOMB0GA1UdDgQWBBR0jFgTuL9K2iWE0wzU7r4RZT0k+zAf +BgNVHSMEGDAWgBR0jFgTuL9K2iWE0wzU7r4RZT0k+zAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4IBAQCemrfEKHPe5ahb2III89+iuIDmbPgVESXqnf88UUdS +Iv+htE8hu9CkSemsErXcC0kUbPSM0vWN9IbHINq78cXucVyi+YTzaKJ8zsK01/zf +x0xYeK5bffYTQzs+BopTCwVqd9zHSs9a2zPnsBVHXCn25j30anQgQH9ODsspXZ3i +WUAkEOmZDnNuX7tGDesA+7h8BPcZ8zrz94kxsrdneMXuHdT1iHxS/hTxTEUUhOMF +FntwT6zx3fGL4cNG06d+pdjjp+CuUR+8GRxeASbYBWhXeiY1ykipiptxkp1zhZ3x +SNandCCdeMRntnNs/+xvRhsEGbhyrvzg2WFL2NrqiKtg +-----END CERTIFICATE----- diff --git a/src/common/utils/uaa/test/non-ca.pem b/src/common/utils/uaa/test/non-ca.pem new file mode 100644 index 0000000000..0373d9336f --- /dev/null +++ b/src/common/utils/uaa/test/non-ca.pem @@ -0,0 +1 @@ +abcdef diff --git a/src/ui/auth/uaa/uaa.go b/src/ui/auth/uaa/uaa.go index 7e12b43fbf..4ce8f2bae5 100644 --- a/src/ui/auth/uaa/uaa.go +++ b/src/ui/auth/uaa/uaa.go @@ -42,8 +42,7 @@ func GetClient() (uaa.Client, error) { ClientID: UAASettings.ClientID, ClientSecret: UAASettings.ClientSecret, Endpoint: UAASettings.Endpoint, - //TODO: remove it - SkipTLSVerify: true, + CARootPath: UAASettings.CARootPath, } client, err = uaa.NewDefaultClient(cfg) return client, err diff --git a/src/ui/config/config.go b/src/ui/config/config.go index 3898895c41..9b0651902c 100644 --- a/src/ui/config/config.go +++ b/src/ui/config/config.go @@ -434,5 +434,8 @@ func UAASettings() (*models.UAASettings, error) { ClientID: cfg[common.UAAClientID].(string), ClientSecret: cfg[common.UAAClientSecret].(string), } + if len(os.Getenv("UAA_CA_ROOT")) != 0 { + us.CARootPath = os.Getenv("UAA_CA_ROOT") + } return us, nil }