diff --git a/make/common/templates/notary/server-config.json b/make/common/templates/notary/server-config.json index dc8ffba31..faf06584c 100644 --- a/make/common/templates/notary/server-config.json +++ b/make/common/templates/notary/server-config.json @@ -22,7 +22,7 @@ "realm": "$token_endpoint/service/token", "service": "harbor-notary", "issuer": "harbor-token-issuer", - "rootcertbundle": "/config/root.crt" + "rootcertbundle": "/etc/notary/root.crt" } } } diff --git a/make/docker-compose.clair.tpl b/make/docker-compose.clair.tpl index 4c652f115..b3429c042 100644 --- a/make/docker-compose.clair.tpl +++ b/make/docker-compose.clair.tpl @@ -41,7 +41,7 @@ services: depends_on: - postgres volumes: - - ./common/config/clair:/config:z + - ./common/config/clair/config.yaml:/etc/clair/config.yaml:z logging: driver: "syslog" options: diff --git a/make/docker-compose.notary.tpl b/make/docker-compose.notary.tpl index 320ba9f8b..5633b6e02 100644 --- a/make/docker-compose.notary.tpl +++ b/make/docker-compose.notary.tpl @@ -15,7 +15,7 @@ services: - notary-sig - harbor-notary volumes: - - ./common/config/notary:/config:z + - ./common/config/notary:/etc/notary:z depends_on: - notary-db - notary-signer @@ -34,7 +34,7 @@ services: aliases: - notarysigner volumes: - - ./common/config/notary:/config:z + - ./common/config/notary:/etc/notary:z env_file: - ./common/config/notary/signer_env depends_on: diff --git a/make/photon/clair/docker-entrypoint.sh b/make/photon/clair/docker-entrypoint.sh index 56f3affc1..f8e60defb 100644 --- a/make/photon/clair/docker-entrypoint.sh +++ b/make/photon/clair/docker-entrypoint.sh @@ -1,5 +1,4 @@ #!/bin/bash set -e -chown -R 10000:10000 /config -sudo -E -H -u \#10000 sh -c "/dumb-init -- /clair2.0.1/clair -config /config/config.yaml" +sudo -E -H -u \#10000 sh -c "/dumb-init -- /clair2.0.1/clair -config /etc/clair/config.yaml" set +e diff --git a/make/photon/jobservice/start.sh b/make/photon/jobservice/start.sh index 623e58b4e..607d44a4e 100644 --- a/make/photon/jobservice/start.sh +++ b/make/photon/jobservice/start.sh @@ -1,13 +1,4 @@ #!/bin/sh -if [ -d /etc/jobservice/ ]; then - chown -R 10000:10000 /etc/jobservice/ -fi -if [ -d /var/log/jobs ]; then - chown -R 10000:10000 /var/log/jobs/ -fi -if [ -d /var/log/jobs/scan_job ]; then - chmod +x /var/log/jobs/scan_job -fi sudo -E -u \#10000 "/harbor/harbor_jobservice" "-c" "/etc/jobservice/config.yml" diff --git a/make/photon/notary/server-start.sh b/make/photon/notary/server-start.sh index 62083adb4..bbb38699e 100644 --- a/make/photon/notary/server-start.sh +++ b/make/photon/notary/server-start.sh @@ -1,3 +1,2 @@ #!/bin/sh -chown 10000:10000 -R /config -sudo -E -u \#10000 sh -c "/usr/bin/env /migrations/migrate.sh && /bin/notary-server -config=/config/server-config.json -logf=logfmt" +sudo -E -u \#10000 sh -c "/usr/bin/env /migrations/migrate.sh && /bin/notary-server -config=/etc/notary/server-config.json -logf=logfmt" diff --git a/make/photon/notary/signer-start.sh b/make/photon/notary/signer-start.sh index c6107dbac..4ddc97715 100644 --- a/make/photon/notary/signer-start.sh +++ b/make/photon/notary/signer-start.sh @@ -1,3 +1,2 @@ #!/bin/sh -chown 10000:10000 -R /config -sudo -E -u \#10000 sh -c "/usr/bin/env && /migrations/migrate.sh && /bin/notary-signer -config=/config/signer-config.json -logf=logfmt" +sudo -E -u \#10000 sh -c "/usr/bin/env && /migrations/migrate.sh && /bin/notary-signer -config=/etc/notary/signer-config.json -logf=logfmt" diff --git a/make/photon/registry/entrypoint.sh b/make/photon/registry/entrypoint.sh index 690a399f0..cbeb08bb1 100644 --- a/make/photon/registry/entrypoint.sh +++ b/make/photon/registry/entrypoint.sh @@ -2,12 +2,12 @@ set -e -if [ -d /etc/registry ]; then - chown 10000:10000 -R /etc/registry -fi +# The directory /var/lib/registry is within the container, and used to store image in CI testing. +# So for now we need to chown to it to avoid failure in CI. if [ -d /var/lib/registry ]; then chown 10000:10000 -R /var/lib/registry fi + if [ -d /storage ]; then if ! stat -c '%u:%g' /storage | grep -q '10000:10000' ; then # 10000 is the id of harbor user/group. diff --git a/make/photon/ui/start.sh b/make/photon/ui/start.sh index 6acfe61ec..db1385302 100644 --- a/make/photon/ui/start.sh +++ b/make/photon/ui/start.sh @@ -1,6 +1,3 @@ #!/bin/sh -if [ -d /etc/ui/ ]; then - chown -R 10000:10000 /etc/ui/ -fi sudo -E -u \#10000 "/harbor/harbor_ui" diff --git a/make/prepare b/make/prepare index 247d04d24..761d11cb9 100755 --- a/make/prepare +++ b/make/prepare @@ -19,6 +19,9 @@ if sys.version_info[:3][0] == 3: import configparser as ConfigParser import io as StringIO +DATA_VOL = "/data" +JOB_LOG_DIR = os.path.join(DATA_VOL, "job_logs") + def validate(conf, args): if args.ha_mode: db_host = rcp.get("configuration", "db_host") @@ -68,6 +71,12 @@ def validate(conf, args): if project_creation != "everyone" and project_creation != "adminonly": raise Exception("Error invalid value for project_creation_restriction: %s" % project_creation) +#To meet security requirement +#By default it will change file mode to 0600, and make the owner of the file to 10000:10000 +def mark_file(path, mode=0o600, uid=10000, gid=10000): + os.chmod(path, mode) + os.chown(path, uid, gid) + def prepare_ha(conf, args): #files under ha folder will have high prority protocol = rcp.get("configuration", "ui_url_protocol") @@ -88,7 +97,7 @@ def prepare_ha(conf, args): if os.path.isfile(cert_path): shutil.copy2(cert_path, shared_cert_path) #check if ca exsit - cert_ca_path = "/data/ca_download/ca.crt" + cert_ca_path = os.path.join(DATA_VOL, 'ca_download', 'ca.crt') shared_ca_path = os.path.join(base_dir, "ha", os.path.basename(cert_ca_path)) if os.path.isfile(shared_ca_path): shutil.copy2(shared_ca_path, cert_ca_path) @@ -138,16 +147,16 @@ def _get_secret(folder, filename, length=16): print("loaded secret from file: %s" % key_file) return key if not os.path.isdir(folder): - os.makedirs(folder, mode=0o600) + os.makedirs(folder) key = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(length)) with open(key_file, 'w') as f: f.write(key) print("Generated and saved secret to file: %s" % key_file) - os.chmod(key_file, 0o600) + mark_file(key_file) return key -def prep_conf_dir(root, name): - absolute_path = os.path.join(root, name) +def prep_conf_dir(root, *name): + absolute_path = os.path.join(root, *name) if not os.path.exists(absolute_path): os.makedirs(absolute_path) return absolute_path @@ -173,6 +182,10 @@ def delfile(src): itemsrc=os.path.join(src,item) delfile(itemsrc) +if not os.path.exists(JOB_LOG_DIR): + os.makedirs(JOB_LOG_DIR) +mark_file(JOB_LOG_DIR, mode=0o755) + parser = argparse.ArgumentParser() parser.add_argument('--conf', dest='cfgfile', default=base_dir+'/harbor.cfg',type=str,help="the path of Harbor configuration file") parser.add_argument('--with-notary', dest='notary_mode', default=False, action='store_true', help="the Harbor instance is to be deployed with notary") @@ -431,7 +444,7 @@ shutil.copyfile(os.path.join(templates_dir, "ui", "app.conf"), ui_conf) if auth_mode == "uaa_auth": if os.path.isfile(uaa_ca_cert): if not os.path.isdir(ui_cert_dir): - os.makedirs(ui_cert_dir, mode=0o600) + os.makedirs(ui_cert_dir) ui_uaa_ca = os.path.join(ui_cert_dir, "uaa_ca.pem") print("Copying UAA CA cert to %s" % ui_uaa_ca) shutil.copyfile(uaa_ca_cert, ui_uaa_ca) @@ -491,8 +504,8 @@ if customize_crt == 'on' and openssl_installed(): private_key_pem = os.path.join(config_dir, "ui", "private_key.pem") root_crt = os.path.join(config_dir, "registry", "root.crt") create_root_cert(empty_subj, key_path=private_key_pem, cert_path=root_crt) - os.chmod(private_key_pem, 0o600) - os.chmod(root_crt, 0o600) + mark_file(private_key_pem) + mark_file(root_crt) else: print("Copied configuration file: %s" % ui_config_dir + "private_key.pem") shutil.copyfile(os.path.join(templates_dir, "ui", "private_key.pem"), os.path.join(ui_config_dir, "private_key.pem")) @@ -520,9 +533,6 @@ if args.notary_mode: create_root_cert(ca_subj, key_path=signer_ca_key, cert_path=signer_ca_cert) create_cert(cert_subj, signer_ca_key, signer_ca_cert, key_path=signer_key_path, cert_path=signer_cert_path) print("Copying certs for notary signer") - os.chmod(signer_cert_path, 0o600) - os.chmod(signer_key_path, 0o600) - os.chmod(signer_ca_cert, 0o600) shutil.copy2(signer_cert_path, notary_config_dir) shutil.copy2(signer_key_path, notary_config_dir) shutil.copy2(signer_ca_cert, notary_config_dir) @@ -538,6 +548,10 @@ if args.notary_mode: shutil.copy2(os.path.join(notary_temp_dir, "notary-signer.key"), notary_config_dir) shutil.copy2(os.path.join(notary_temp_dir, "notary-signer-ca.crt"), notary_config_dir) shutil.copy2(os.path.join(registry_config_dir, "root.crt"), notary_config_dir) + mark_file(os.path.join(notary_config_dir, "notary-signer.crt")) + mark_file(os.path.join(notary_config_dir, "notary-signer.key")) + mark_file(os.path.join(notary_config_dir, "notary-signer-ca.crt")) + mark_file(os.path.join(notary_config_dir, "root.crt")) print("Copying notary signer configuration file") shutil.copy2(os.path.join(notary_temp_dir, "signer-config.json"), notary_config_dir) render(os.path.join(notary_temp_dir, "server-config.json"), diff --git a/src/common/utils/notary/helper.go b/src/common/utils/notary/helper.go index 63f9ae1cc..af7775a6e 100644 --- a/src/common/utils/notary/helper.go +++ b/src/common/utils/notary/helper.go @@ -36,7 +36,7 @@ import ( ) var ( - notaryCachePath = "/etc/ui/notary-cache" + notaryCachePath = "/tmp/notary-cache" trustPin trustpinning.TrustPinConfig mockRetriever notary.PassRetriever ) diff --git a/src/ui/config/config.go b/src/ui/config/config.go index 1035c562b..8b69c1e0a 100644 --- a/src/ui/config/config.go +++ b/src/ui/config/config.go @@ -38,8 +38,9 @@ import ( ) const ( - defaultKeyPath string = "/etc/ui/key" - defaultTokenFilePath string = "/etc/ui/token/tokens.properties" + defaultKeyPath = "/etc/ui/key" + defaultTokenFilePath = "/etc/ui/token/tokens.properties" + defaultRegistryTokenPrivateKeyPath = "/etc/ui/private_key.pem" ) var ( @@ -56,7 +57,7 @@ var ( AdmiralClient *http.Client // TokenReader is used in integration mode to read token TokenReader admiral.TokenReader - + // defined as a var for testing. defaultCACertPath = "/etc/ui/ca/ca.crt" ) @@ -189,6 +190,15 @@ func AuthMode() (string, error) { return cfg[common.AUTHMode].(string), nil } +// TokenPrivateKeyPath returns the path to the key for signing token for registry +func TokenPrivateKeyPath() string { + path := os.Getenv("TOKEN_PRIVATE_KEY_PATH") + if len(path) == 0 { + path = defaultRegistryTokenPrivateKeyPath + } + return path +} + // LDAPConf returns the setting of ldap server func LDAPConf() (*models.LdapConf, error) { cfg, err := mg.Get() diff --git a/src/ui/config/config_test.go b/src/ui/config/config_test.go index 67e50c6cb..b66e76cf4 100644 --- a/src/ui/config/config_test.go +++ b/src/ui/config/config_test.go @@ -185,6 +185,10 @@ func TestConfig(t *testing.T) { t.Errorf("unexpected scan all policy %v", s) } + if tokenKeyPath := TokenPrivateKeyPath(); tokenKeyPath != "/etc/ui/private_key.pem" { + t.Errorf("Unexpected token private key path: %s, expected: %s", tokenKeyPath, "/etc/ui/private_key.pem") + } + us, err := UAASettings() if err != nil { t.Fatalf("failed to get UAA setting, error: %v", err) diff --git a/src/ui/service/token/authutils.go b/src/ui/service/token/authutils.go index 18d2fa31a..79b5140a9 100644 --- a/src/ui/service/token/authutils.go +++ b/src/ui/service/token/authutils.go @@ -39,7 +39,7 @@ const ( var privateKey string func init() { - privateKey = "/etc/ui/private_key.pem" + privateKey = config.TokenPrivateKeyPath() } // GetResourceActions ... diff --git a/tests/testprepare.sh b/tests/testprepare.sh index c55e852f0..f0f25d921 100755 --- a/tests/testprepare.sh +++ b/tests/testprepare.sh @@ -3,10 +3,10 @@ set -e cp tests/docker-compose.test.yml make/. mkdir -p /etc/ui -cp make/common/config/ui/private_key.pem /etc/ui/. +cp make/common/config/ui/private_key.pem /etc/ui/ mkdir src/ui/conf -cp make/common/config/ui/app.conf src/ui/conf/. +cp make/common/config/ui/app.conf src/ui/conf/ IP=`ip addr s eth0 |grep "inet "|awk '{print $2}' |awk -F "/" '{print $1}'` echo "server ip is "$IP sed -i -r "s/MYSQL_HOST=mysql/MYSQL_HOST=$IP/" make/common/config/adminserver/env