mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-19 23:28:20 +01:00
Merge pull request #10369 from reasonerjt/registry-basic-auth
Populate basic auth information for registry
This commit is contained in:
commit
99e052aeb0
@ -26,6 +26,9 @@ https:
|
|||||||
# Remember Change the admin password from UI after launching Harbor.
|
# Remember Change the admin password from UI after launching Harbor.
|
||||||
harbor_admin_password: Harbor12345
|
harbor_admin_password: Harbor12345
|
||||||
|
|
||||||
|
#TODO: remove this temporary flag before ships v1.11/v2, this should always be true
|
||||||
|
registry_use_basic_auth: false
|
||||||
|
|
||||||
# Harbor DB configuration
|
# Harbor DB configuration
|
||||||
database:
|
database:
|
||||||
# The password for the root user of Harbor DB. Change this before any production use.
|
# The password for the root user of Harbor DB. Change this before any production use.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
FROM photon:2.0
|
FROM photon:2.0
|
||||||
|
|
||||||
RUN tdnf install -y python3 \
|
RUN tdnf install -y python3 python3-pip httpd
|
||||||
&& tdnf install -y python3-pip
|
|
||||||
RUN pip3 install pipenv==2018.11.26
|
RUN pip3 install pipenv==2018.11.26
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ def main(conf, with_notary, with_clair, with_chartmuseum):
|
|||||||
try:
|
try:
|
||||||
validate(config_dict, notary_mode=with_notary)
|
validate(config_dict, notary_mode=with_notary)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.info('Error happend in config validation...')
|
logging.info('Error happened in config validation...')
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ RELOAD_KEY={{reload_key}}
|
|||||||
CHART_REPOSITORY_URL={{chart_repository_url}}
|
CHART_REPOSITORY_URL={{chart_repository_url}}
|
||||||
REGISTRY_CONTROLLER_URL={{registry_controller_url}}
|
REGISTRY_CONTROLLER_URL={{registry_controller_url}}
|
||||||
WITH_CHARTMUSEUM={{with_chartmuseum}}
|
WITH_CHARTMUSEUM={{with_chartmuseum}}
|
||||||
|
REGISTRY_CREDENTIAL_USERNAME={{registry_username}}
|
||||||
|
REGISTRY_CREDENTIAL_PASSWORD={{registry_password}}
|
||||||
|
|
||||||
HTTP_PROXY={{core_http_proxy}}
|
HTTP_PROXY={{core_http_proxy}}
|
||||||
HTTPS_PROXY={{core_https_proxy}}
|
HTTPS_PROXY={{core_https_proxy}}
|
||||||
|
@ -26,11 +26,17 @@ http:
|
|||||||
debug:
|
debug:
|
||||||
addr: localhost:5001
|
addr: localhost:5001
|
||||||
auth:
|
auth:
|
||||||
|
{% if registry_use_basic_auth %}
|
||||||
|
htpasswd:
|
||||||
|
realm: harbor-registry-basic-realm
|
||||||
|
path: /etc/registry/passwd
|
||||||
|
{% else %}
|
||||||
token:
|
token:
|
||||||
issuer: harbor-token-issuer
|
issuer: harbor-token-issuer
|
||||||
realm: {{public_url}}/service/token
|
realm: {{public_url}}/service/token
|
||||||
rootcertbundle: /etc/registry/root.crt
|
rootcertbundle: /etc/registry/root.crt
|
||||||
service: harbor-registry
|
service: harbor-registry
|
||||||
|
{% endif %}
|
||||||
validation:
|
validation:
|
||||||
disabled: true
|
disabled: true
|
||||||
notifications:
|
notifications:
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
# Get or generate private key
|
# Get or generate private key
|
||||||
import os, sys, subprocess, shutil
|
import os, subprocess, shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import DEVNULL
|
from subprocess import DEVNULL
|
||||||
from functools import wraps
|
|
||||||
|
|
||||||
from g import DEFAULT_GID, DEFAULT_UID
|
from g import DEFAULT_GID, DEFAULT_UID
|
||||||
from .misc import (
|
from .misc import (
|
||||||
mark_file,
|
mark_file,
|
||||||
generate_random_string,
|
generate_random_string,
|
||||||
check_permission)
|
check_permission,
|
||||||
|
stat_decorator)
|
||||||
|
|
||||||
SSL_CERT_PATH = os.path.join("/etc/cert", "server.crt")
|
SSL_CERT_PATH = os.path.join("/etc/cert", "server.crt")
|
||||||
SSL_CERT_KEY_PATH = os.path.join("/etc/cert", "server.key")
|
SSL_CERT_KEY_PATH = os.path.join("/etc/cert", "server.key")
|
||||||
@ -44,19 +44,6 @@ def get_alias(path):
|
|||||||
alias = _get_secret(path, "defaultalias", length=8)
|
alias = _get_secret(path, "defaultalias", length=8)
|
||||||
return alias
|
return alias
|
||||||
|
|
||||||
## decorator actions
|
|
||||||
def stat_decorator(func):
|
|
||||||
@wraps(func)
|
|
||||||
def check_wrapper(*args, **kw):
|
|
||||||
stat = func(*args, **kw)
|
|
||||||
if stat == 0:
|
|
||||||
print("Generated certificate, key file: {key_path}, cert file: {cert_path}".format(**kw))
|
|
||||||
else:
|
|
||||||
print("Fail to generate key file: {key_path}, cert file: {cert_path}".format(**kw))
|
|
||||||
sys.exit(1)
|
|
||||||
return check_wrapper
|
|
||||||
|
|
||||||
|
|
||||||
@stat_decorator
|
@stat_decorator
|
||||||
def create_root_cert(subj, key_path="./k.key", cert_path="./cert.crt"):
|
def create_root_cert(subj, key_path="./k.key", cert_path="./cert.crt"):
|
||||||
rc = subprocess.call(["/usr/bin/openssl", "genrsa", "-out", key_path, "4096"], stdout=DEVNULL, stderr=subprocess.STDOUT)
|
rc = subprocess.call(["/usr/bin/openssl", "genrsa", "-out", key_path, "4096"], stdout=DEVNULL, stderr=subprocess.STDOUT)
|
||||||
|
@ -9,6 +9,8 @@ default_db_max_open_conns = 0 # NOTE: https://golang.org/pkg/database/sql/#DB.S
|
|||||||
default_https_cert_path = '/your/certificate/path'
|
default_https_cert_path = '/your/certificate/path'
|
||||||
default_https_key_path = '/your/certificate/path'
|
default_https_key_path = '/your/certificate/path'
|
||||||
|
|
||||||
|
REGISTRY_USER_NAME = 'harbor_registry_user'
|
||||||
|
|
||||||
|
|
||||||
def validate(conf: dict, **kwargs):
|
def validate(conf: dict, **kwargs):
|
||||||
# hostname validate
|
# hostname validate
|
||||||
@ -83,6 +85,7 @@ def validate(conf: dict, **kwargs):
|
|||||||
# TODO:
|
# TODO:
|
||||||
# If user enable trust cert dir, need check if the files in this dir is readable.
|
# If user enable trust cert dir, need check if the files in this dir is readable.
|
||||||
|
|
||||||
|
|
||||||
def parse_versions():
|
def parse_versions():
|
||||||
if not versions_file_path.is_file():
|
if not versions_file_path.is_file():
|
||||||
return {}
|
return {}
|
||||||
@ -90,6 +93,7 @@ def parse_versions():
|
|||||||
versions = yaml.load(f)
|
versions = yaml.load(f)
|
||||||
return versions
|
return versions
|
||||||
|
|
||||||
|
|
||||||
def parse_yaml_config(config_file_path, with_notary, with_clair, with_chartmuseum):
|
def parse_yaml_config(config_file_path, with_notary, with_clair, with_chartmuseum):
|
||||||
'''
|
'''
|
||||||
:param configs: config_parser object
|
:param configs: config_parser object
|
||||||
@ -321,6 +325,12 @@ def parse_yaml_config(config_file_path, with_notary, with_clair, with_chartmuseu
|
|||||||
# UAA configs
|
# UAA configs
|
||||||
config_dict['uaa'] = configs.get('uaa') or {}
|
config_dict['uaa'] = configs.get('uaa') or {}
|
||||||
|
|
||||||
|
config_dict['registry_username'] = REGISTRY_USER_NAME
|
||||||
|
config_dict['registry_password'] = generate_random_string(32)
|
||||||
|
|
||||||
|
# TODO: remove the flag before release
|
||||||
|
config_dict['registry_use_basic_auth'] = configs['registry_use_basic_auth']
|
||||||
|
|
||||||
return config_dict
|
return config_dict
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import os
|
import os, string, sys
|
||||||
import string
|
|
||||||
import secrets
|
import secrets
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
from g import DEFAULT_UID, DEFAULT_GID
|
from g import DEFAULT_UID, DEFAULT_GID
|
||||||
|
|
||||||
|
|
||||||
# To meet security requirement
|
# To meet security requirement
|
||||||
# By default it will change file mode to 0600, and make the owner of the file to 10000:10000
|
# 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=DEFAULT_UID, gid=DEFAULT_GID):
|
def mark_file(path, mode=0o600, uid=DEFAULT_UID, gid=DEFAULT_GID):
|
||||||
@ -154,3 +153,18 @@ def other_can_read(st_mode: int) -> bool:
|
|||||||
Check if other user have the read permission of this st_mode
|
Check if other user have the read permission of this st_mode
|
||||||
"""
|
"""
|
||||||
return True if st_mode & 0o004 else False
|
return True if st_mode & 0o004 else False
|
||||||
|
|
||||||
|
|
||||||
|
# decorator actions
|
||||||
|
def stat_decorator(func):
|
||||||
|
@wraps(func)
|
||||||
|
def check_wrapper(*args, **kw):
|
||||||
|
stat = func(*args, **kw)
|
||||||
|
if stat == 0:
|
||||||
|
print("Successfully called func: %s" % func.__name__)
|
||||||
|
else:
|
||||||
|
print("Failed to call func: %s" % func.__name__)
|
||||||
|
sys.exit(1)
|
||||||
|
return check_wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import os, copy
|
import os, copy, subprocess
|
||||||
|
|
||||||
from g import config_dir, templates_dir, DEFAULT_GID, DEFAULT_UID, data_dir
|
from g import config_dir, templates_dir, DEFAULT_GID, DEFAULT_UID, data_dir
|
||||||
from utils.misc import prepare_dir
|
from utils.misc import prepare_dir
|
||||||
@ -8,6 +8,7 @@ from utils.jinja import render_jinja
|
|||||||
registry_config_dir = os.path.join(config_dir, "registry")
|
registry_config_dir = os.path.join(config_dir, "registry")
|
||||||
registry_config_template_path = os.path.join(templates_dir, "registry", "config.yml.jinja")
|
registry_config_template_path = os.path.join(templates_dir, "registry", "config.yml.jinja")
|
||||||
registry_conf = os.path.join(config_dir, "registry", "config.yml")
|
registry_conf = os.path.join(config_dir, "registry", "config.yml")
|
||||||
|
registry_passwd_path = os.path.join(config_dir, "registry", "passwd")
|
||||||
registry_data_dir = os.path.join(data_dir, 'registry')
|
registry_data_dir = os.path.join(data_dir, 'registry')
|
||||||
|
|
||||||
levels_map = {
|
levels_map = {
|
||||||
@ -18,10 +19,13 @@ levels_map = {
|
|||||||
'fatal': 'fatal'
|
'fatal': 'fatal'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def prepare_registry(config_dict):
|
def prepare_registry(config_dict):
|
||||||
prepare_dir(registry_data_dir, uid=DEFAULT_UID, gid=DEFAULT_GID)
|
prepare_dir(registry_data_dir, uid=DEFAULT_UID, gid=DEFAULT_GID)
|
||||||
prepare_dir(registry_config_dir)
|
prepare_dir(registry_config_dir)
|
||||||
|
|
||||||
|
if config_dict['registry_use_basic_auth']:
|
||||||
|
gen_passwd_file(config_dict)
|
||||||
storage_provider_info = get_storage_provider_info(
|
storage_provider_info = get_storage_provider_info(
|
||||||
config_dict['storage_provider_name'],
|
config_dict['storage_provider_name'],
|
||||||
config_dict['storage_provider_config'])
|
config_dict['storage_provider_config'])
|
||||||
@ -55,3 +59,8 @@ def get_storage_provider_info(provider_name, provider_config):
|
|||||||
storage_provider_conf_list.append('{}: {}'.format(config[0], value))
|
storage_provider_conf_list.append('{}: {}'.format(config[0], value))
|
||||||
storage_provider_info = ('\n' + ' ' * 4).join(storage_provider_conf_list)
|
storage_provider_info = ('\n' + ' ' * 4).join(storage_provider_conf_list)
|
||||||
return storage_provider_info
|
return storage_provider_info
|
||||||
|
|
||||||
|
|
||||||
|
def gen_passwd_file(config_dict):
|
||||||
|
return subprocess.call(["/usr/bin/htpasswd", "-bcB", registry_passwd_path, config_dict['registry_username'],
|
||||||
|
config_dict['registry_password']], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
||||||
|
@ -299,6 +299,11 @@ func CoreSecret() string {
|
|||||||
return os.Getenv("CORE_SECRET")
|
return os.Getenv("CORE_SECRET")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegistryCredential returns the username and password the core uses to access registry
|
||||||
|
func RegistryCredential() (string, string) {
|
||||||
|
return os.Getenv("REGISTRY_CREDENTIAL_USERNAME"), os.Getenv("REGISTRY_CREDENTIAL_PASSWORD")
|
||||||
|
}
|
||||||
|
|
||||||
// JobserviceSecret returns a secret to mark Jobservice when communicate with
|
// JobserviceSecret returns a secret to mark Jobservice when communicate with
|
||||||
// other component
|
// other component
|
||||||
// TODO replace it with method of SecretStore
|
// TODO replace it with method of SecretStore
|
||||||
|
Loading…
Reference in New Issue
Block a user