From 7787c329c0845e01864201aa3129f228a36ca4ba Mon Sep 17 00:00:00 2001 From: Kevin Chung Date: Thu, 23 Jul 2020 16:38:21 -0400 Subject: [PATCH] Extra config ini fields (#1566) * Move server setting documentation from `config.py` to `config.ini` * Add support for adding additional config values to `config.ini` * Rename `CTFd.config.ServerConfig` to `CTFd.config.Config` so that we can instantiate an actual `Config` class and add attributes to it. * Closes #565 --- CTFd/config.ini | 134 ++++++++++++++++++++++++++++++++- CTFd/config.py | 192 ++++++++---------------------------------------- README.md | 2 +- 3 files changed, 164 insertions(+), 164 deletions(-) diff --git a/CTFd/config.ini b/CTFd/config.ini index f9e2ba4fe..849b48ab6 100644 --- a/CTFd/config.ini +++ b/CTFd/config.ini @@ -1,49 +1,181 @@ [server] +# SECRET_KEY: +# The secret value used to creation sessions and sign strings. This should be set to a random string. In the +# interest of ease, CTFd will automatically create a secret key file for you. If you wish to add this secret key +# to your instance you should hard code this value to a random static value. +# +# You can also remove .ctfd_secret_key from the .gitignore file and commit this file into whatever repository +# you are using. +# +# http://flask.pocoo.org/docs/latest/quickstart/#sessions SECRET_KEY = + +# DATABASE_URL +# The URI that specifies the username, password, hostname, port, and database of the server +# used to hold the CTFd database. +# +# If a database URL is not specified, CTFd will automatically create a SQLite database for you to use +# e.g. mysql+pymysql://root:@localhost/ctfd DATABASE_URL = + +# REDIS_URL +# The URL to connect to a Redis server. If not specified, CTFd will use the .data folder as a filesystem cache +# +# e.g. redis://user:password@localhost:6379 +# http://pythonhosted.org/Flask-Caching/#configuring-flask-caching REDIS_URL = [security] +# SESSION_COOKIE_HTTPONLY +# Controls if cookies should be set with the HttpOnly flag. Defaults to True. SESSION_COOKIE_HTTPONLY = true + +# SESSION_COOKIE_SAMESITE +# Controls the SameSite attribute on session cookies. Can be Lax or Strict. +# Should be left as Lax unless the implications are well understood SESSION_COOKIE_SAMESITE = Lax + +# PERMANENT_SESSION_LIFETIME +# The lifetime of a session. The default is 604800 seconds (7 days). PERMANENT_SESSION_LIFETIME = 604800 -TRUSTED_PROXIES = [email] +# MAILFROM_ADDR +# The email address that emails are sent from if not overridden in the configuration panel. MAILFROM_ADDR = + +# MAIL_SERVER +# The mail server that emails are sent from if not overriden in the configuration panel. MAIL_SERVER = + +# MAIL_PORT +# The mail port that emails are sent from if not overriden in the configuration panel. MAIL_PORT = + +# MAIL_USEAUTH +# Whether or not to use username and password to authenticate to the SMTP server MAIL_USEAUTH = + +# MAIL_USERNAME +# The username used to authenticate to the SMTP server if MAIL_USEAUTH is defined MAIL_USERNAME = + +# MAIL_PASSWORD +# The password used to authenticate to the SMTP server if MAIL_USEAUTH is defined MAIL_PASSWORD = + +# MAIL_TLS +# Whether to connect to the SMTP server over TLS MAIL_TLS = + +# MAIL_SSL +# Whether to connect to the SMTP server over SSL MAIL_SSL = + +# MAILGUN_API_KEY +# Mailgun API key to send email over Mailgun. As of CTFd v3, Mailgun integration is deprecated. +# Installations using the Mailgun API should migrate over to SMTP settings. MAILGUN_API_KEY = + +# MAILGUN_BASE_URL +# Mailgun base url to send email over Mailgun. As of CTFd v3, Mailgun integration is deprecated. +# Installations using the Mailgun API should migrate over to SMTP settings. MAILGUN_BASE_URL = [uploads] +# UPLOAD_PROVIDER +# Specifies the service that CTFd should use to store files. +# Can be set to filesystem or s3 UPLOAD_PROVIDER = filesystem + +# UPLOAD_FOLDER +# The location where files are uploaded under the filesystem uploader. +# The default destination is the CTFd/uploads folder. UPLOAD_FOLDER = + +# AWS_ACCESS_KEY_ID +# AWS access token used to authenticate to the S3 bucket. Only used under the s3 uploader. AWS_ACCESS_KEY_ID = + +# AWS_SECRET_ACCESS_KEY +# AWS secret token used to authenticate to the S3 bucket. Only used under the s3 uploader. AWS_SECRET_ACCESS_KEY = + +# AWS_S3_BUCKET +# The unique identifier for your S3 bucket. Only used under the s3 uploader. AWS_S3_BUCKET = + +# AWS_S3_ENDPOINT_URL +# A URL pointing to a custom S3 implementation. Only used under the s3 uploader. AWS_S3_ENDPOINT_URL = [logs] +# LOG_FOLDER +# The location where logs are written. These are the logs for CTFd key submissions, registrations, and logins. The default location is the CTFd/logs folder. LOG_FOLDER = [optional] +# REVERSE_PROXY +# Specifies whether CTFd is behind a reverse proxy or not. Set to true if using a reverse proxy like nginx. +# You can also specify a comma seperated set of numbers specifying the reverse proxy configuration settings. +# See https://werkzeug.palletsprojects.com/en/0.15.x/middleware/proxy_fix/#werkzeug.middleware.proxy_fix.ProxyFix. +# For example to configure `x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1` specify `1,1,1,1,1`. +# If you specify `true` CTFd will default to the above behavior with all proxy settings set to 1. REVERSE_PROXY = + +# TEMPLATES_AUTO_RELOAD +# Specifies whether Flask should check for modifications to templates and reload them automatically. Defaults to true. TEMPLATES_AUTO_RELOAD = + +# SQLALCHEMY_TRACK_MODIFICATIONS +# Automatically disabled to suppress warnings and save memory. +# You should only enable this if you need it. +# Defaults to false. SQLALCHEMY_TRACK_MODIFICATIONS = + +# SWAGGER_UI +# Enable the Swagger UI endpoint at /api/v1/ SWAGGER_UI = + +# UPDATE_CHECK +# Specifies whether or not CTFd will check whether or not there is a new version of CTFd. Defaults True. UPDATE_CHECK = + +# APPLICATION_ROOT +# Specifies what path CTFd is mounted under. It can be used to run CTFd in a subdirectory. +# Example: /ctfd APPLICATION_ROOT = + +# SERVER_SENT_EVENTS +# Specifies whether or not to enable the Server-Sent Events based Notifications system. +# Defaults to true SERVER_SENT_EVENTS = + +# HTML_SANITIZATION +# Specifies whether CTFd should sanitize HTML content +# Defaults to false HTML_SANITIZATION = + +# SQLALCHEMY_MAX_OVERFLOW +# Specifies the max_overflow setting for SQLAlchemy's Engine +# https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine +# https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/#configuration-keys SQLALCHEMY_MAX_OVERFLOW = + +# SQLALCHEMY_POOL_PRE_PING +# Specifies the pool_pre_ping setting for SQLAlchemy's Engine +# https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine +# https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/#configuration-keys SQLALCHEMY_POOL_PRE_PING = [oauth] +# OAUTH_CLIENT_ID +# Register an event at https://majorleaguecyber.org/ and use the Client ID here OAUTH_CLIENT_ID = + +# OAUTH_CLIENT_ID +# Register an event at https://majorleaguecyber.org/ and use the Client Secret here OAUTH_CLIENT_SECRET = + +[extra] +# The extra section can be used to specify additional values to be loaded into CTFd's configuration \ No newline at end of file diff --git a/CTFd/config.py b/CTFd/config.py index 3cfd58b7c..975b7d793 100644 --- a/CTFd/config.py +++ b/CTFd/config.py @@ -45,47 +45,13 @@ def gen_secret_key(): config_ini = configparser.ConfigParser() +config_ini.optionxform = str # Makes the key value case-insensitive path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.ini") config_ini.read(path) # fmt: off -class Config(object): - """ - CTFd Configuration Object - """ - - """ - === REQUIRED SETTINGS === - - SECRET_KEY: - The secret value used to creation sessions and sign strings. This should be set to a random string. In the - interest of ease, CTFd will automatically create a secret key file for you. If you wish to add this secret key - to your instance you should hard code this value to a random static value. - - You can also remove .ctfd_secret_key from the .gitignore file and commit this file into whatever repository - you are using. - - http://flask.pocoo.org/docs/latest/quickstart/#sessions - - DATABASE_URL: - The URI that specifies the username, password, hostname, port, and database of the server - used to hold the CTFd database. - - e.g. mysql+pymysql://root:@localhost/ctfd - - CACHE_TYPE: - Specifies how CTFd should cache configuration values. If CACHE_TYPE is set to 'redis', CTFd will make use - of the REDIS_URL specified in environment variables. You can also choose to hardcode the REDIS_URL here. - - It is important that you specify some sort of cache as CTFd uses it to store values received from the database. If - no cache is specified, CTFd will default to a simple per-worker cache. The simple cache cannot be effectively used - with multiple workers. - - REDIS_URL is the URL to connect to a Redis server. - e.g. redis://user:password@localhost:6379 - http://pythonhosted.org/Flask-Caching/#configuring-flask-caching - """ +class ServerConfig(object): SECRET_KEY: str = os.getenv("SECRET_KEY") \ or empty_str_cast(config_ini["server"]["SECRET_KEY"]) \ or gen_secret_key() @@ -109,23 +75,7 @@ class Config(object): # Override the threshold of cached values on the filesystem. The default is 500. Don't change unless you know what you're doing. CACHE_THRESHOLD: int = 0 - """ - === SECURITY === - - SESSION_COOKIE_HTTPONLY: - Controls if cookies should be set with the HttpOnly flag. Defaults to True - - PERMANENT_SESSION_LIFETIME: - The lifetime of a session. The default is 604800 seconds (7 days). - - TRUSTED_PROXIES: - Defines a set of regular expressions used for finding a user's IP address if the CTFd instance - is behind a proxy. If you are running a CTF and users are on the same network as you, you may choose to remove - some proxies from the list. - - CTFd only uses IP addresses for cursory tracking purposes. It is ill-advised to do anything complicated based - solely on IP addresses unless you know what you are doing. - """ + # === SECURITY === SESSION_COOKIE_HTTPONLY: bool = process_boolean_str(os.getenv("SESSION_COOKIE_HTTPONLY")) \ or config_ini["security"].getboolean("SESSION_COOKIE_HTTPONLY") \ or True @@ -138,6 +88,15 @@ class Config(object): or config_ini["security"].getint("PERMANENT_SESSION_LIFETIME") \ or 604800 + """ + TRUSTED_PROXIES: + Defines a set of regular expressions used for finding a user's IP address if the CTFd instance + is behind a proxy. If you are running a CTF and users are on the same network as you, you may choose to remove + some proxies from the list. + + CTFd only uses IP addresses for cursory tracking purposes. It is ill-advised to do anything complicated based + solely on IP addresses unless you know what you are doing. + """ TRUSTED_PROXIES = [ r"^127\.0\.0\.1$", # Remove the following proxies if you do not trust the local network @@ -150,41 +109,7 @@ class Config(object): r"^192\.168\.", ] - """ - === EMAIL === - - MAILFROM_ADDR: - The email address that emails are sent from if not overridden in the configuration panel. - - MAIL_SERVER: - The mail server that emails are sent from if not overriden in the configuration panel. - - MAIL_PORT: - The mail port that emails are sent from if not overriden in the configuration panel. - - MAIL_USEAUTH - Whether or not to use username and password to authenticate to the SMTP server - - MAIL_USERNAME - The username used to authenticate to the SMTP server if MAIL_USEAUTH is defined - - MAIL_PASSWORD - The password used to authenticate to the SMTP server if MAIL_USEAUTH is defined - - MAIL_TLS - Whether to connect to the SMTP server over TLS - - MAIL_SSL - Whether to connect to the SMTP server over SSL - - MAILGUN_API_KEY - Mailgun API key to send email over Mailgun. As of CTFd v3, Mailgun integration is deprecated. - Installations using the Mailgun API should migrate over to SMTP settings. - - MAILGUN_BASE_URL - Mailgun base url to send email over Mailgun. As of CTFd v3, Mailgun integration is deprecated. - Installations using the Mailgun API should migrate over to SMTP settings. - """ + # === EMAIL === MAILFROM_ADDR: str = os.getenv("MAILFROM_ADDR") \ or config_ini["email"]["MAILFROM_ADDR"] \ or "noreply@ctfd.io" @@ -216,38 +141,12 @@ class Config(object): MAILGUN_BASE_URL: str = os.getenv("MAILGUN_BASE_URL") \ or empty_str_cast(config_ini["email"]["MAILGUN_API_KEY"]) - """ - === LOGS === - LOG_FOLDER: - The location where logs are written. These are the logs for CTFd key submissions, registrations, and logins. - The default location is the CTFd/logs folder. - """ + # === LOGS === LOG_FOLDER: str = os.getenv("LOG_FOLDER") \ or empty_str_cast(config_ini["logs"]["LOG_FOLDER"]) \ or os.path.join(os.path.dirname(os.path.abspath(__file__)), "logs") - """ - === UPLOADS === - - UPLOAD_PROVIDER: - Specifies the service that CTFd should use to store files. - - UPLOAD_FOLDER: - The location where files are uploaded. The default destination is the CTFd/uploads folder. - - AWS_ACCESS_KEY_ID: - AWS access token used to authenticate to the S3 bucket. - - AWS_SECRET_ACCESS_KEY: - AWS secret token used to authenticate to the S3 bucket. - - AWS_S3_BUCKET: - The unique identifier for your S3 bucket. - - AWS_S3_ENDPOINT_URL: - A URL pointing to a custom S3 implementation. - - """ + # === UPLOADS === UPLOAD_PROVIDER: str = os.getenv("UPLOAD_PROVIDER") \ or empty_str_cast(config_ini["uploads"]["UPLOAD_PROVIDER"]) \ or "filesystem" @@ -269,45 +168,7 @@ class Config(object): AWS_S3_ENDPOINT_URL: str = os.getenv("AWS_S3_ENDPOINT_URL") \ or empty_str_cast(config_ini["uploads"]["AWS_S3_ENDPOINT_URL"]) - """ - === OPTIONAL === - - REVERSE_PROXY: - Specifies whether CTFd is behind a reverse proxy or not. Set to True if using a reverse proxy like nginx. - You can also specify a comma seperated set of numbers specifying the reverse proxy configuration settings. - - See https://werkzeug.palletsprojects.com/en/0.15.x/middleware/proxy_fix/#werkzeug.middleware.proxy_fix.ProxyFix. - For example to configure `x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1` specify `1,1,1,1,1`. - - Alternatively if you specify `true` CTFd will default to the above behavior with all proxy settings set to 1. - - TEMPLATES_AUTO_RELOAD: - Specifies whether Flask should check for modifications to templates and reload them automatically. Defaults True. - - SQLALCHEMY_TRACK_MODIFICATIONS: - Automatically disabled to suppress warnings and save memory. You should only enable this if you need it. Defaults False. - - SWAGGER_UI: - Enable the Swagger UI endpoint at /api/v1/ - - UPDATE_CHECK: - Specifies whether or not CTFd will check whether or not there is a new version of CTFd. Defaults True. - - APPLICATION_ROOT: - Specifies what path CTFd is mounted under. It can be used to run CTFd in a subdirectory. - Example: /ctfd - - HTML_SANITIZATION: - Specifies whether CTFd should sanitize HTML content from pages and descriptions - - SERVER_SENT_EVENTS: - Specifies whether or not to enable to server-sent events based Notifications system. - - SQLALCHEMY_ENGINE_OPTIONS: - A dictionary of keyword args to send to the underlying SQLAlchemy create_engine() call. - https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine - https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/#configuration-keys - """ + # === OPTIONAL === REVERSE_PROXY: bool = process_boolean_str(os.getenv("REVERSE_PROXY")) \ or empty_str_cast(config_ini["optional"]["REVERSE_PROXY"]) \ or False @@ -352,12 +213,7 @@ class Config(object): or True, # noqa: E131 } - """ - === OAUTH === - - MajorLeagueCyber Integration - Register an event at https://majorleaguecyber.org/ and use the Client ID and Client Secret here - """ + # === OAUTH === OAUTH_CLIENT_ID: str = os.getenv("OAUTH_CLIENT_ID") \ or empty_str_cast(config_ini["oauth"]["OAUTH_CLIENT_ID"]) OAUTH_CLIENT_SECRET: str = os.getenv("OAUTH_CLIENT_SECRET") \ @@ -365,7 +221,7 @@ class Config(object): # fmt: on -class TestingConfig(Config): +class TestingConfig(ServerConfig): SECRET_KEY = "AAAAAAAAAAAAAAAAAAAA" PRESERVE_CONTEXT_ON_EXCEPTION = False TESTING = True @@ -377,3 +233,15 @@ class TestingConfig(Config): CACHE_TYPE = "simple" CACHE_THRESHOLD = 500 SAFE_MODE = True + + +# Actually initialize ServerConfig to allow us to add more attributes on +Config = ServerConfig() +for k, v in config_ini.items("extra"): + # Cast numeric values to their appropriate type + if v.isdigit(): + setattr(Config, k, int(v)) + elif v.replace(".", "", 1).isdigit(): + setattr(Config, k, float(v)) + else: + setattr(Config, k, v) diff --git a/README.md b/README.md index bf29329fa..edc2f4232 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Currently CTFd master contains an alpha version of the next major CTFd release. 1. Install dependencies: `pip install -r requirements.txt` 1. You can also use the `prepare.sh` script to install system dependencies using apt. -2. Modify [CTFd/config.py](https://github.com/CTFd/CTFd/blob/master/CTFd/config.py) to your liking. +2. Modify [CTFd/config.ini](https://github.com/CTFd/CTFd/blob/master/CTFd/config.ini) to your liking. 3. Use `flask run` in a terminal to drop into debug mode. You can use the auto-generated Docker images with the following command: