from uuid import uuid4 import os.path import requests from _init import ROOT_DIR, CONF_DIR def build_requests_session(): sess = requests.Session() adapter = requests.adapters.HTTPAdapter(pool_connections=100, pool_maxsize=100) sess.mount('http://', adapter) sess.mount('https://', adapter) return sess # The set of configuration key names that will be accessible in the client. Since these # values are sent to the frontend, DO NOT PLACE ANY SECRETS OR KEYS in this list. CLIENT_WHITELIST = ['SERVER_HOSTNAME', 'PREFERRED_URL_SCHEME', 'MIXPANEL_KEY', 'STRIPE_PUBLISHABLE_KEY', 'ENTERPRISE_LOGO_URL', 'SENTRY_PUBLIC_DSN', 'AUTHENTICATION_TYPE', 'REGISTRY_TITLE', 'REGISTRY_TITLE_SHORT', 'CONTACT_INFO', 'AVATAR_KIND', 'LOCAL_OAUTH_HANDLER', 'SETUP_COMPLETE', 'DEBUG', 'MARKETO_MUNCHKIN_ID', 'STATIC_SITE_BUCKET', 'RECAPTCHA_SITE_KEY', 'CHANNEL_COLORS', 'TAG_EXPIRATION_OPTIONS', 'INTERNAL_OIDC_SERVICE_ID', 'SEARCH_RESULTS_PER_PAGE', 'SEARCH_MAX_RESULT_PAGE_COUNT', 'BRANDING'] def frontend_visible_config(config_dict): visible_dict = {} for name in CLIENT_WHITELIST: if name.lower().find('secret') >= 0: raise Exception('Cannot whitelist secrets: %s' % name) if name in config_dict: visible_dict[name] = config_dict.get(name, None) if 'ENTERPRISE_LOGO_URL' in config_dict: visible_dict['BRANDING'] = visible_dict.get('BRANDING', {}) visible_dict['BRANDING']['logo'] = config_dict['ENTERPRISE_LOGO_URL'] return visible_dict # Configuration that should not be changed by end users class ImmutableConfig(object): # Requests based HTTP client with a large request pool HTTPCLIENT = build_requests_session() # Status tag config STATUS_TAGS = {} for tag_name in ['building', 'failed', 'none', 'ready', 'cancelled']: tag_path = os.path.join(ROOT_DIR, 'buildstatus', tag_name + '.svg') with open(tag_path) as tag_svg: STATUS_TAGS[tag_name] = tag_svg.read() # Reverse DNS prefixes that are reserved for internal use on labels and should not be allowable # to be set via the API. DEFAULT_LABEL_KEY_RESERVED_PREFIXES = ['com.docker.', 'io.docker.', 'org.dockerproject.', 'org.opencontainers.', 'io.cncf.', 'io.kubernetes.', 'io.k8s.', 'io.quay', 'com.coreos', 'com.tectonic', 'internal', 'quay'] # Colors for local avatars. AVATAR_COLORS = ['#969696', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c', '#98df8a', '#d62728', '#ff9896', '#9467bd', '#c5b0d5', '#8c564b', '#c49c94', '#e377c2', '#f7b6d2', '#7f7f7f', '#c7c7c7', '#bcbd22', '#1f77b4', '#17becf', '#9edae5', '#393b79', '#5254a3', '#6b6ecf', '#9c9ede', '#9ecae1', '#31a354', '#b5cf6b', '#a1d99b', '#8c6d31', '#ad494a', '#e7ba52', '#a55194'] # Colors for channels. CHANNEL_COLORS = ['#969696', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c', '#98df8a', '#d62728', '#ff9896', '#9467bd', '#c5b0d5', '#8c564b', '#c49c94', '#e377c2', '#f7b6d2', '#7f7f7f', '#c7c7c7', '#bcbd22', '#1f77b4', '#17becf', '#9edae5', '#393b79', '#5254a3', '#6b6ecf', '#9c9ede', '#9ecae1', '#31a354', '#b5cf6b', '#a1d99b', '#8c6d31', '#ad494a', '#e7ba52', '#a55194'] PROPAGATE_EXCEPTIONS = True class DefaultConfig(ImmutableConfig): # Flask config JSONIFY_PRETTYPRINT_REGULAR = False SESSION_COOKIE_SECURE = False SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = 'Lax' LOGGING_LEVEL = 'DEBUG' SEND_FILE_MAX_AGE_DEFAULT = 0 PREFERRED_URL_SCHEME = 'http' SERVER_HOSTNAME = 'localhost:5000' REGISTRY_TITLE = 'Project Quay' REGISTRY_TITLE_SHORT = 'Project Quay' CONTACT_INFO = [] # Mail config MAIL_SERVER = '' MAIL_USE_TLS = True MAIL_PORT = 587 MAIL_USERNAME = None MAIL_PASSWORD = None MAIL_DEFAULT_SENDER = 'example@projectquay.io' MAIL_FAIL_SILENTLY = False TESTING = True # DB config DB_URI = 'sqlite:///test/data/test.db' DB_CONNECTION_ARGS = { 'threadlocals': True, 'autorollback': True, } @staticmethod def create_transaction(db): return db.transaction() DB_TRANSACTION_FACTORY = create_transaction # If set to 'readonly', the entire registry is placed into read only mode and no write operations # may be performed against it. REGISTRY_STATE = 'normal' # If set to true, TLS is used, but is terminated by an external service (such as a load balancer). # Note that PREFERRED_URL_SCHEME must be `https` when this flag is set or it can lead to undefined # behavior. EXTERNAL_TLS_TERMINATION = False # If true, CDN URLs will be used for our external dependencies, rather than the local # copies. USE_CDN = False # Authentication AUTHENTICATION_TYPE = 'Database' # Build logs BUILDLOGS_REDIS = {'host': 'localhost'} BUILDLOGS_OPTIONS = [] # Real-time user events USER_EVENTS_REDIS = {'host': 'localhost'} # Stripe config BILLING_TYPE = 'FakeStripe' # Analytics ANALYTICS_TYPE = 'FakeAnalytics' # Build Queue Metrics QUEUE_METRICS_TYPE = 'Null' QUEUE_WORKER_METRICS_REFRESH_SECONDS = 300 # Exception logging EXCEPTION_LOG_TYPE = 'FakeSentry' SENTRY_DSN = None SENTRY_PUBLIC_DSN = None # Github Config GITHUB_LOGIN_CONFIG = None GITHUB_TRIGGER_CONFIG = None # Google Config. GOOGLE_LOGIN_CONFIG = None # Bitbucket Config. BITBUCKET_TRIGGER_CONFIG = None # Gitlab Config. GITLAB_TRIGGER_CONFIG = None NOTIFICATION_QUEUE_NAME = 'notification' DOCKERFILE_BUILD_QUEUE_NAME = 'dockerfilebuild' REPLICATION_QUEUE_NAME = 'imagestoragereplication' SECSCAN_NOTIFICATION_QUEUE_NAME = 'security_notification' CHUNK_CLEANUP_QUEUE_NAME = 'chunk_cleanup' NAMESPACE_GC_QUEUE_NAME = 'namespacegc' EXPORT_ACTION_LOGS_QUEUE_NAME = 'exportactionlogs' # Super user config. Note: This MUST BE an empty list for the default config. SUPER_USERS = [] # Feature Flag: Whether sessions are permanent. FEATURE_PERMANENT_SESSIONS = True # Feature Flag: Whether super users are supported. FEATURE_SUPER_USERS = True # Feature Flag: Whether to allow anonymous users to browse and pull public repositories. FEATURE_ANONYMOUS_ACCESS = True # Feature Flag: Whether billing is required. FEATURE_BILLING = False # Feature Flag: Whether user accounts automatically have usage log access. FEATURE_USER_LOG_ACCESS = False # Feature Flag: Whether GitHub login is supported. FEATURE_GITHUB_LOGIN = False # Feature Flag: Whether Google login is supported. FEATURE_GOOGLE_LOGIN = False # Feature Flag: Whether to support GitHub build triggers. FEATURE_GITHUB_BUILD = False # Feature Flag: Whether to support Bitbucket build triggers. FEATURE_BITBUCKET_BUILD = False # Feature Flag: Whether to support GitLab build triggers. FEATURE_GITLAB_BUILD = False # Feature Flag: Dockerfile build support. FEATURE_BUILD_SUPPORT = True # Feature Flag: Whether emails are enabled. FEATURE_MAILING = True # Feature Flag: Whether users can be created (by non-super users). FEATURE_USER_CREATION = True # Feature Flag: Whether users being created must be invited by another user. # If FEATURE_USER_CREATION is off, this flag has no effect. FEATURE_INVITE_ONLY_USER_CREATION = False # Feature Flag: Whether users can be renamed FEATURE_USER_RENAME = False # Feature Flag: Whether non-encrypted passwords (as opposed to encrypted tokens) can be used for # basic auth. FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH = False # Feature Flag: Whether to automatically replicate between storage engines. FEATURE_STORAGE_REPLICATION = False # Feature Flag: Whether users can directly login to the UI. FEATURE_DIRECT_LOGIN = True # Feature Flag: Whether the v2/ endpoint is visible FEATURE_ADVERTISE_V2 = True # Semver spec for which Docker versions we will blacklist # Documentation: http://pythonhosted.org/semantic_version/reference.html#semantic_version.Spec BLACKLIST_V2_SPEC = '<1.6.0' # Feature Flag: Whether to restrict V1 pushes to the whitelist. FEATURE_RESTRICTED_V1_PUSH = False V1_PUSH_WHITELIST = [] # Feature Flag: Whether or not to rotate old action logs to storage. FEATURE_ACTION_LOG_ROTATION = False # Feature Flag: Whether to enable conversion to ACIs. FEATURE_ACI_CONVERSION = False # Feature Flag: Whether to allow for "namespace-less" repositories when pulling and pushing from # Docker. FEATURE_LIBRARY_SUPPORT = True # Feature Flag: Whether to require invitations when adding a user to a team. FEATURE_REQUIRE_TEAM_INVITE = True # Feature Flag: Whether to proxy all direct download URLs in storage via the registry's nginx. FEATURE_PROXY_STORAGE = False # Feature Flag: Whether to collect and support user metadata. FEATURE_USER_METADATA = False # Feature Flag: Whether to support signing FEATURE_SIGNING = False # Feature Flag: Whether to enable support for App repositories. FEATURE_APP_REGISTRY = False # Feature Flag: Whether app registry is in a read-only mode. FEATURE_READONLY_APP_REGISTRY = False # Feature Flag: If set to true, the _catalog endpoint returns public repositories. Otherwise, # only private repositories can be returned. FEATURE_PUBLIC_CATALOG = False # Feature Flag: If set to true, build logs may be read by those with read access to the repo, # rather than only write access or admin access. FEATURE_READER_BUILD_LOGS = False # Feature Flag: If set to true, autocompletion will apply to partial usernames. FEATURE_PARTIAL_USER_AUTOCOMPLETE = True # Feature Flag: If set to true, users can confirm (and modify) their initial usernames when # logging in via OIDC or a non-database internal auth provider. FEATURE_USERNAME_CONFIRMATION = True # If a namespace is defined in the public namespace list, then it will appear on *all* # user's repository list pages, regardless of whether that user is a member of the namespace. # Typically, this is used by an enterprise customer in configuring a set of "well-known" # namespaces. PUBLIC_NAMESPACES = [] # The namespace to use for library repositories. # Note: This must remain 'library' until Docker removes their hard-coded namespace for libraries. # See: https://github.com/docker/docker/blob/master/registry/session.go#L320 LIBRARY_NAMESPACE = 'library' BUILD_MANAGER = ('enterprise', {}) DISTRIBUTED_STORAGE_CONFIG = { 'local_eu': ['LocalStorage', {'storage_path': 'test/data/registry/eu'}], 'local_us': ['LocalStorage', {'storage_path': 'test/data/registry/us'}], } DISTRIBUTED_STORAGE_PREFERENCE = ['local_us'] DISTRIBUTED_STORAGE_DEFAULT_LOCATIONS = ['local_us'] # Health checker. HEALTH_CHECKER = ('LocalHealthCheck', {}) # Userfiles USERFILES_LOCATION = 'local_us' USERFILES_PATH = 'userfiles/' # Build logs archive LOG_ARCHIVE_LOCATION = 'local_us' LOG_ARCHIVE_PATH = 'logarchive/' # Action logs archive ACTION_LOG_ARCHIVE_LOCATION = 'local_us' ACTION_LOG_ARCHIVE_PATH = 'actionlogarchive/' ACTION_LOG_ROTATION_THRESHOLD = '30d' # Allow registry pulls when unable to write to the audit log ALLOW_PULLS_WITHOUT_STRICT_LOGGING = False # Temporary tag expiration in seconds, this may actually be longer based on GC policy PUSH_TEMP_TAG_EXPIRATION_SEC = 60 * 60 # One hour per layer # Signed registry grant token expiration in seconds SIGNED_GRANT_EXPIRATION_SEC = 60 * 60 * 24 # One day to complete a push/pull # Registry v2 JWT Auth config REGISTRY_JWT_AUTH_MAX_FRESH_S = 60 * 60 + 60 # At most signed one hour, accounting for clock skew # The URL endpoint to which we redirect OAuth when generating a token locally. LOCAL_OAUTH_HANDLER = '/oauth/localapp' # The various avatar background colors. AVATAR_KIND = 'local' # Custom branding BRANDING = { 'logo': '/static/img/quay-horizontal-color.svg', 'footer_img': None, 'footer_url': None, } # How often the Garbage Collection worker runs. GARBAGE_COLLECTION_FREQUENCY = 30 # seconds # How long notifications will try to send before timing out. NOTIFICATION_SEND_TIMEOUT = 10 # Security scanner FEATURE_SECURITY_SCANNER = False FEATURE_SECURITY_NOTIFICATIONS = False # The endpoint for the security scanner. SECURITY_SCANNER_ENDPOINT = 'http://192.168.99.101:6060' # The number of seconds between indexing intervals in the security scanner SECURITY_SCANNER_INDEXING_INTERVAL = 30 # If specified, the security scanner will only index images newer than the provided ID. SECURITY_SCANNER_INDEXING_MIN_ID = None # If specified, the endpoint to be used for all POST calls to the security scanner. SECURITY_SCANNER_ENDPOINT_BATCH = None # If specified, GET requests that return non-200 will be retried at the following instances. SECURITY_SCANNER_READONLY_FAILOVER_ENDPOINTS = [] # The indexing engine version running inside the security scanner. SECURITY_SCANNER_ENGINE_VERSION_TARGET = 3 # The version of the API to use for the security scanner. SECURITY_SCANNER_API_VERSION = 'v1' # API call timeout for the security scanner. SECURITY_SCANNER_API_TIMEOUT_SECONDS = 10 # POST call timeout for the security scanner. SECURITY_SCANNER_API_TIMEOUT_POST_SECONDS = 480 # The issuer name for the security scanner. SECURITY_SCANNER_ISSUER_NAME = 'security_scanner' # Repository mirror FEATURE_REPO_MIRROR = False # The number of seconds between indexing intervals in the repository mirror REPO_MIRROR_INTERVAL = 30 # Require HTTPS and verify certificates of Quay registry during mirror. REPO_MIRROR_TLS_VERIFY = True # Replaces the SERVER_HOSTNAME as the destination for mirroring. REPO_MIRROR_SERVER_HOSTNAME = None # JWTProxy Settings # The address (sans schema) to proxy outgoing requests through the jwtproxy # to be signed JWTPROXY_SIGNER = 'localhost:8081' # The audience that jwtproxy should verify on incoming requests # If None, will be calculated off of the SERVER_HOSTNAME (default) JWTPROXY_AUDIENCE = None # Torrent management flags FEATURE_BITTORRENT = False BITTORRENT_PIECE_SIZE = 512 * 1024 BITTORRENT_ANNOUNCE_URL = 'https://localhost:6881/announce' BITTORRENT_FILENAME_PEPPER = str(uuid4()) BITTORRENT_WEBSEED_LIFETIME = 3600 # "Secret" key for generating encrypted paging tokens. Only needed to be secret to # hide the ID range for production (in which this value is overridden). Should *not* # be relied upon for secure encryption otherwise. # This value is a Fernet key and should be 32bytes URL-safe base64 encoded. PAGE_TOKEN_KEY = '0OYrc16oBuksR8T3JGB-xxYSlZ2-7I_zzqrLzggBJ58=' # The timeout for service key approval. UNAPPROVED_SERVICE_KEY_TTL_SEC = 60 * 60 * 24 # One day # How long to wait before GCing an expired service key. EXPIRED_SERVICE_KEY_TTL_SEC = 60 * 60 * 24 * 7 # One week # The ID of the user account in the database to be used for service audit logs. If none, the # lowest user in the database will be used. SERVICE_LOG_ACCOUNT_ID = None # The service key ID for the instance service. # NOTE: If changed, jwtproxy_conf.yaml.jnj must also be updated. INSTANCE_SERVICE_KEY_SERVICE = 'quay' # The location of the key ID file generated for this instance. INSTANCE_SERVICE_KEY_KID_LOCATION = os.path.join(CONF_DIR, 'quay.kid') # The location of the private key generated for this instance. # NOTE: If changed, jwtproxy_conf.yaml.jnj must also be updated. INSTANCE_SERVICE_KEY_LOCATION = os.path.join(CONF_DIR, 'quay.pem') # This instance's service key expiration in minutes. INSTANCE_SERVICE_KEY_EXPIRATION = 120 # Number of minutes between expiration refresh in minutes. Should be the expiration / 2 minus # some additional window time. INSTANCE_SERVICE_KEY_REFRESH = 55 # The whitelist of client IDs for OAuth applications that allow for direct login. DIRECT_OAUTH_CLIENTID_WHITELIST = [] # URL that specifies the location of the prometheus stats aggregator. PROMETHEUS_AGGREGATOR_URL = 'http://localhost:9092' # Namespace prefix for all prometheus metrics. PROMETHEUS_NAMESPACE = 'quay' # Overridable list of reverse DNS prefixes that are reserved for internal use on labels. LABEL_KEY_RESERVED_PREFIXES = [] # Delays workers from starting until a random point in time between 0 and their regular interval. STAGGER_WORKERS = True # Location of the static marketing site. STATIC_SITE_BUCKET = None # Site key and secret key for using recaptcha. FEATURE_RECAPTCHA = False RECAPTCHA_SITE_KEY = None RECAPTCHA_SECRET_KEY = None # Server where TUF metadata can be found TUF_SERVER = None # Prefix to add to metadata e.g. // TUF_GUN_PREFIX = None # Maximum size allowed for layers in the registry. MAXIMUM_LAYER_SIZE = '20G' # Feature Flag: Whether team syncing from the backing auth is enabled. FEATURE_TEAM_SYNCING = False TEAM_RESYNC_STALE_TIME = '30m' TEAM_SYNC_WORKER_FREQUENCY = 60 # seconds # Feature Flag: If enabled, non-superusers can setup team syncing. FEATURE_NONSUPERUSER_TEAM_SYNCING_SETUP = False # The default configurable tag expiration time for time machine. DEFAULT_TAG_EXPIRATION = '2w' # The options to present in namespace settings for the tag expiration. If empty, no option # will be given and the default will be displayed read-only. TAG_EXPIRATION_OPTIONS = ['0s', '1d', '1w', '2w', '4w'] # Feature Flag: Whether users can view and change their tag expiration. FEATURE_CHANGE_TAG_EXPIRATION = True # Defines a secret for enabling the health-check endpoint's debug information. ENABLE_HEALTH_DEBUG_SECRET = None # The lifetime for a user recovery token before it becomes invalid. USER_RECOVERY_TOKEN_LIFETIME = '30m' # If specified, when app specific passwords expire by default. APP_SPECIFIC_TOKEN_EXPIRATION = None # Feature Flag: If enabled, users can create and use app specific tokens to login via the CLI. FEATURE_APP_SPECIFIC_TOKENS = True # How long expired app specific tokens should remain visible to users before being automatically # deleted. Set to None to turn off garbage collection. EXPIRED_APP_SPECIFIC_TOKEN_GC = '1d' # The size of pages returned by the Docker V2 API. V2_PAGINATION_SIZE = 50 # If enabled, ensures that API calls are made with the X-Requested-With header # when called from a browser. BROWSER_API_CALLS_XHR_ONLY = True # If set to a non-None integer value, the default number of maximum builds for a namespace. DEFAULT_NAMESPACE_MAXIMUM_BUILD_COUNT = None # If set to a non-None integer value, the default number of maximum builds for a namespace whose # creator IP is deemed a threat. THREAT_NAMESPACE_MAXIMUM_BUILD_COUNT = None # The API Key to use when requesting IP information. IP_DATA_API_KEY = None # For Billing Support Only: The number of allowed builds on a namespace that has been billed # successfully. BILLED_NAMESPACE_MAXIMUM_BUILD_COUNT = None # Configuration for the data model cache. DATA_MODEL_CACHE_CONFIG = { 'engine': 'memcached', 'endpoint': ('127.0.0.1', 18080), } # Defines the number of successive failures of a build trigger's build before the trigger is # automatically disabled. SUCCESSIVE_TRIGGER_FAILURE_DISABLE_THRESHOLD = 100 # Defines the number of successive internal errors of a build trigger's build before the # trigger is automatically disabled. SUCCESSIVE_TRIGGER_INTERNAL_ERROR_DISABLE_THRESHOLD = 5 # Defines the delay required (in seconds) before the last_accessed field of a user/robot or access # token will be updated after the previous update. LAST_ACCESSED_UPDATE_THRESHOLD_S = 60 # Defines the number of results per page used to show search results SEARCH_RESULTS_PER_PAGE = 10 # Defines the maximum number of pages the user can paginate before they are limited SEARCH_MAX_RESULT_PAGE_COUNT = 10 # Feature Flag: Whether to record when users were last accessed. FEATURE_USER_LAST_ACCESSED = True # Feature Flag: Whether to allow users to retrieve aggregated log counts. FEATURE_AGGREGATED_LOG_COUNT_RETRIEVAL = True # Feature Flag: Whether rate limiting is enabled. FEATURE_RATE_LIMITS = False # Feature Flag: Whether to support log exporting. FEATURE_LOG_EXPORT = True # Maximum number of action logs pages that can be returned via the API. ACTION_LOG_MAX_PAGE = None # Log model LOGS_MODEL = 'database' LOGS_MODEL_CONFIG = {} # Namespace in which all audit logging is disabled. DISABLED_FOR_AUDIT_LOGS = [] # Namespace in which pull audit logging is disabled. DISABLED_FOR_PULL_LOGS = [] # Feature Flag: Whether pull logs are disabled for free namespace. FEATURE_DISABLE_PULL_LOGS_FOR_FREE_NAMESPACES = False # Feature Flag: If set to true, no account using blacklisted email addresses will be allowed # to be created. FEATURE_BLACKLISTED_EMAILS = False # The list of domains, including subdomains, for which any *new* User with a matching # email address will be denied creation. This option is only used if # FEATURE_BLACKLISTED_EMAILS is enabled. BLACKLISTED_EMAIL_DOMAINS = [] # Feature Flag: Whether garbage collection is enabled. FEATURE_GARBAGE_COLLECTION = True