diff --git a/packages/opal-client/opal_client/config.py b/packages/opal-client/opal_client/config.py index 7af68da6..385d38e3 100644 --- a/packages/opal-client/opal_client/config.py +++ b/packages/opal-client/opal_client/config.py @@ -23,40 +23,39 @@ class OpalClientConfig(Confi): "POLICY_STORE_TYPE", PolicyStoreTypes, PolicyStoreTypes.OPA, - description="The type of policy store to use (e.g., OPA, Cedar)" + description="Specifies the type of policy store to use. Currently supports OPA (Open Policy Agent) and Cedar. This determines how OPAL interacts with the policy engine." ) POLICY_STORE_URL = confi.str( "POLICY_STORE_URL", "http://localhost:8181", - description="URL of the policy store" + description="The URL of the policy store (e.g., OPA server) that OPAL client will interact with. This is where OPAL will push updated policies and data. Ensure this URL is reachable from the OPAL client's network." ) POLICY_STORE_AUTH_TYPE = confi.enum( "POLICY_STORE_AUTH_TYPE", PolicyStoreAuth, PolicyStoreAuth.NONE, - description="Authentication type for the policy store" + description="Specifies the authentication method for connecting to the policy store. Possible values are 'none', 'token', 'tls' or 'oauth'. Use this to secure the connection between OPAL and the policy store." ) POLICY_STORE_AUTH_TOKEN = confi.str( "POLICY_STORE_AUTH_TOKEN", None, - description="the authentication (bearer) token OPAL client will use to " - "authenticate against the policy store (i.e: OPA agent).", + description="The authentication (bearer) token OPAL client will use to authenticate against the policy store (e.g., OPA). Required if POLICY_STORE_AUTH_TYPE is set to 'token'." ) POLICY_STORE_AUTH_OAUTH_SERVER = confi.str( "POLICY_STORE_AUTH_OAUTH_SERVER", None, - description="the authentication server OPAL client will use to authenticate against for retrieving the access_token.", + description="The OAuth server URL that OPAL client will use to authenticate and retrieve an access token for the policy store. Required if POLICY_STORE_AUTH_TYPE is set to 'oauth'." ) POLICY_STORE_AUTH_OAUTH_CLIENT_ID = confi.str( "POLICY_STORE_AUTH_OAUTH_CLIENT_ID", None, - description="the client_id OPAL will use to authenticate against the OAuth server.", + description="The client ID OPAL will use to authenticate against the OAuth server for policy store access. Required if POLICY_STORE_AUTH_TYPE is set to 'oauth'." ) POLICY_STORE_AUTH_OAUTH_CLIENT_SECRET = confi.str( "POLICY_STORE_AUTH_OAUTH_CLIENT_SECRET", None, - description="the client secret OPAL will use to authenticate against the OAuth server.", + description="The client secret OPAL will use to authenticate against the OAuth server for policy store access. Required if POLICY_STORE_AUTH_TYPE is set to 'oauth'." ) POLICY_STORE_CONN_RETRY: ConnRetryOptions = confi.model( @@ -64,7 +63,7 @@ class OpalClientConfig(Confi): ConnRetryOptions, # defaults are being set according to ConnRetryOptions pydantic definitions (see class) {}, - description="retry options when connecting to the policy store (i.e. the agent that handles the policy, e.g. OPA)", + description="Retry options when connecting to the policy store (e.g., OPA). Configures how OPAL handles connection failures, including wait times and retry attempts." ) POLICY_UPDATER_CONN_RETRY: ConnRetryOptions = confi.model( "POLICY_UPDATER_CONN_RETRY", @@ -75,14 +74,14 @@ class OpalClientConfig(Confi): "attempts": 5, "wait_time": 1, }, - description="retry options when connecting to the policy source (e.g. the policy bundle server)", + description="Retry options when connecting to the policy source (e.g., the policy bundle server). Configures how OPAL handles connection failures when fetching policy updates." ) DATA_STORE_CONN_RETRY: ConnRetryOptions = confi.model( "DATA_STORE_CONN_RETRY", ConnRetryOptions, None, - description="DEPTRECATED - The old confusing name for DATA_UPDATER_CONN_RETRY, kept for backwards compatibilit (for now)", + description="DEPRECATED - The old confusing name for DATA_UPDATER_CONN_RETRY, kept for backwards compatibility (for now). Use DATA_UPDATER_CONN_RETRY instead." ) DATA_UPDATER_CONN_RETRY: ConnRetryOptions = confi.model( @@ -94,41 +93,41 @@ class OpalClientConfig(Confi): "attempts": 5, "wait_time": 1, }, - description="retry options when connecting to the base data source (e.g. an external API server which returns data snapshot)", + description="Retry options when connecting to the base data source (e.g., an external API server which returns data snapshots). Configures how OPAL handles connection failures when fetching data updates." ) POLICY_STORE_POLICY_PATHS_TO_IGNORE = confi.list( "POLICY_STORE_POLICY_PATHS_TO_IGNORE", [], - description="When loading policies manually or otherwise externally into the policy store, use this list of glob patterns to have OPAL ignore and not delete or override them, end paths (without any wildcards in the middle) with '/**' to indicate you want all nested under the path to be ignored", + description="A list of glob-style paths or paths ending with '/**' to indicate policy paths that should be ignored by OPAL. Use this to prevent OPAL from overwriting or deleting specific policies in the policy store." ) POLICY_UPDATER_ENABLED = confi.bool( "POLICY_UPDATER_ENABLED", True, - description="If set to False, opal client will not listen to dynamic policy updates." "Policy update fetching will be completely disabled.", + description="Controls whether OPAL client listens to dynamic policy updates. If set to False, policy update fetching will be completely disabled, and OPAL will not fetch policies or listen to policy updates." ) POLICY_STORE_TLS_CLIENT_CERT = confi.str( "POLICY_STORE_TLS_CLIENT_CERT", None, - description="path to the client certificate used for tls authentication with the policy store", + description="Path to the client certificate file used for TLS authentication with the policy store. Use this for secure communication between OPAL and the policy store." ) POLICY_STORE_TLS_CLIENT_KEY = confi.str( "POLICY_STORE_TLS_CLIENT_KEY", None, - description="path to the client key used for tls authentication with the policy store", + description="Path to the client key file used for TLS authentication with the policy store. Paired with POLICY_STORE_TLS_CLIENT_CERT for secure communication." ) POLICY_STORE_TLS_CA = confi.str( "POLICY_STORE_TLS_CA", None, - description="path to the file containing the ca certificate(s) used for tls authentication with the policy store", + description="Path to the file containing the CA certificate(s) used for TLS authentication with the policy store. Use this to verify the policy store's certificate." ) EXCLUDE_POLICY_STORE_SECRETS = confi.bool( "EXCLUDE_POLICY_STORE_SECRETS", False, - description="If set, policy store secrets will be excluded from the /policy-store/config route", + description="If set to True, policy store secrets will be excluded from the /policy-store/config route. Use this to enhance security by not exposing sensitive information." ) # create an instance of a policy store upon load @@ -145,7 +144,7 @@ def load_policy_store(): INLINE_OPA_ENABLED = confi.bool( "INLINE_OPA_ENABLED", True, - description="Whether to run OPA inline within OPAL" + description="Determines whether OPAL should run OPA inline within its own container. When enabled, OPAL manages OPA directly, simplifying deployment but potentially limiting OPA configuration options." ) # if inline OPA is indeed enabled, user can pass cli options @@ -153,40 +152,37 @@ def load_policy_store(): INLINE_OPA_CONFIG = confi.model( "INLINE_OPA_CONFIG", OpaServerOptions, - {}, # defaults are being set according to OpaServerOptions pydantic definitions (see class) - description="cli options used when running `opa run --server` inline", + {}, # defaults are being set according to OpaServerOptions pydantic definitions (see class) + description="CLI options used when running `opa run --server` inline. This allows you to configure how OPA runs when managed by OPAL, including server configuration options that affect OPA's behavior." ) INLINE_OPA_LOG_FORMAT: EngineLogFormat = confi.enum( "INLINE_OPA_LOG_FORMAT", EngineLogFormat, EngineLogFormat.NONE, - description="Specifies the log format for inline OPA. Options are: none, minimal, http, or full." + description="Specifies the log format for inline OPA. Options are: none (no OPA logs), minimal (only event names), http (HTTP method, path, and status code), or full (entire data dict). Use this to control the verbosity of OPA logs when run inline." ) # Cedar runner configuration (Cedar-engine can optionally be run by OPAL) ---------------- - # whether or not OPAL should run the Cedar agent by itself in the same container INLINE_CEDAR_ENABLED = confi.bool( "INLINE_CEDAR_ENABLED", True, - description="Whether to run Cedar inline within OPAL" + description="Determines whether OPAL should run the Cedar agent inline within its own container. Similar to INLINE_OPA_ENABLED, but for Cedar policy engine." ) - # if inline Cedar is indeed enabled, user can pass cli options - # (configuration) that affects how the agent will run INLINE_CEDAR_CONFIG = confi.model( "INLINE_CEDAR_CONFIG", CedarServerOptions, - {}, # defaults are being set according to CedarServerOptions pydantic definitions (see class) - description="cli options used when running the Cedar agent inline", + {}, # defaults are being set according to CedarServerOptions pydantic definitions (see class) + description="CLI options used when running the Cedar agent inline. This allows you to configure how the Cedar agent runs when managed by OPAL." ) INLINE_CEDAR_LOG_FORMAT: EngineLogFormat = confi.enum( "INLINE_CEDAR_LOG_FORMAT", EngineLogFormat, EngineLogFormat.NONE, - description="Specifies the log format for inline Cedar. Options are: none, minimal, http, or full." + description="Specifies the log format for inline Cedar. Options are the same as INLINE_OPA_LOG_FORMAT. Use this to control the verbosity of Cedar logs when run inline." ) # configuration for fastapi routes @@ -196,7 +192,7 @@ def load_policy_store(): KEEP_ALIVE_INTERVAL = confi.int( "KEEP_ALIVE_INTERVAL", 0, - description="Interval for keep-alive messages in seconds (0 to disable)" + description="Interval in seconds for sending keep-alive messages on the WebSocket connection to the OPAL server. Set to 0 to disable. Use this to maintain long-lived connections in environments with aggressive timeouts." ) # Opal Server general configuration ------------------------------------------- @@ -205,7 +201,7 @@ def load_policy_store(): SERVER_URL = confi.str( "SERVER_URL", "http://localhost:7002", - description="URL of the OPAL server", + description="The URL of the OPAL server that this client will connect to for receiving policy and data updates. Ensure this URL is reachable from the client's network.", flags=["-s"] ) # opal server pubsub url @@ -217,19 +213,19 @@ def load_policy_store(): "http", "ws" ) ), - description="WebSocket URL of the OPAL server" + description="WebSocket URL of the OPAL server, automatically derived from SERVER_URL. This is used for real-time communication between the OPAL client and server." ) SERVER_PUBSUB_URL = confi.str( "SERVER_PUBSUB_URL", confi.delay("{SERVER_WS_URL}" + f"{OPAL_WS_ROUTE}"), - description="PubSub URL of the OPAL server" + description="PubSub URL of the OPAL server, used for subscribing to real-time updates. This is typically the WebSocket URL with the /ws route appended." ) # opal server auth token CLIENT_TOKEN = confi.str( "CLIENT_TOKEN", "THIS_IS_A_DEV_SECRET", - description="Authentication token for the OPAL server", + description="Authentication token used by the OPAL client to authenticate with the OPAL server. Ensure this matches the token configured on the server side for secure communication.", flags=["-t"] ) @@ -237,25 +233,25 @@ def load_policy_store(): CLIENT_API_SERVER_WORKER_COUNT = confi.int( "CLIENT_API_SERVER_WORKER_COUNT", 1, - description="(if run via CLI) Worker count for the opal-client's internal server", + description="Number of worker processes for the OPAL client's internal server when run via CLI. Adjust based on expected load and available resources." ) CLIENT_API_SERVER_HOST = confi.str( "CLIENT_API_SERVER_HOST", "127.0.0.1", - description="(if run via CLI) Address for the opal-client's internal server to bind", + description="Address for the OPAL client's internal server to bind to when run via CLI. Use '0.0.0.0' to allow external connections, or '127.0.0.1' for local-only access." ) CLIENT_API_SERVER_PORT = confi.int( "CLIENT_API_SERVER_PORT", 7000, - description="(if run via CLI) Port for the opal-client's internal server to bind", + description="Port for the OPAL client's internal server to bind to when run via CLI. Ensure this port is available and not blocked by firewalls." ) WAIT_ON_SERVER_LOAD = confi.bool( "WAIT_ON_SERVER_LOAD", False, - description="If set, client would wait for 200 from server's loadlimit endpoint before starting background tasks", + description="If set to True, the OPAL client will wait for a 200 response from the server's loadlimit endpoint before starting background tasks. This ensures the server is ready to handle requests." ) # Policy updater configuration ------------------------------------------------ @@ -265,40 +261,38 @@ def load_policy_store(): "POLICY_SUBSCRIPTION_DIRS", ["."], delimiter=":", - description="Directories in the policy repo to subscribe to" + description="Colon-separated list of directories in the policy repository to subscribe to for policy updates. Use '.' for the root directory. This allows fine-grained control over which policies the client receives." ) # Data updater configuration -------------------------------------------------- DATA_UPDATER_ENABLED = confi.bool( "DATA_UPDATER_ENABLED", True, - description="If set to False, opal client will not listen to dynamic data updates. " - "Dynamic data fetching will be completely disabled.", + description="Controls whether the OPAL client listens to dynamic data updates. If set to False, dynamic data fetching will be completely disabled, and OPAL will not process data updates." ) DATA_TOPICS = confi.list( "DATA_TOPICS", [DEFAULT_DATA_TOPIC], - description="Data topics to subscribe to" + description="List of data topics to subscribe to for updates. Use this to filter which data updates the client receives, allowing for more targeted data distribution." ) DEFAULT_DATA_SOURCES_CONFIG_URL = confi.str( "DEFAULT_DATA_SOURCES_CONFIG_URL", confi.delay("{SERVER_URL}/data/config"), - description="Default URL to fetch data configuration from", + description="URL to fetch the initial data sources configuration. This configuration tells the OPAL client where to fetch data from and how to structure it in the policy store." ) DEFAULT_DATA_URL = confi.str( "DEFAULT_DATA_URL", "http://localhost:8000/policy-config", - description="Default URL to fetch data from", + description="Default URL to fetch policy data from if not specified in the data sources configuration. This serves as a fallback for data fetching." ) SHOULD_REPORT_ON_DATA_UPDATES = confi.bool( "SHOULD_REPORT_ON_DATA_UPDATES", False, - description="Should the client report on updates to callbacks defined in " - "DEFAULT_UPDATE_CALLBACKS or within the given updates", + description="If set to True, the client will report on data updates to callbacks defined in DEFAULT_UPDATE_CALLBACKS or within the given updates. This can be used for monitoring or triggering actions based on data changes." ) DEFAULT_UPDATE_CALLBACK_CONFIG = confi.model( "DEFAULT_UPDATE_CALLBACK_CONFIG", @@ -308,7 +302,7 @@ def load_policy_store(): "headers": {"content-type": "application/json"}, "process_data": False, }, - description="Default configuration for update callbacks, including HTTP method, headers, and data processing options." + description="Default configuration for update callbacks, including HTTP method, headers, and data processing options. This defines how the client reports on data updates when SHOULD_REPORT_ON_DATA_UPDATES is True." ) DEFAULT_UPDATE_CALLBACKS = confi.model( @@ -317,27 +311,26 @@ def load_policy_store(): confi.delay( lambda SERVER_URL="": {"callbacks": [f"{SERVER_URL}/data/callback_report"]} ), - description="Where/How the client should report on the completion of data updates", + description="Specifies where and how the client should report on the completion of data updates. By default, it reports to the OPAL server's callback endpoint." ) # OPA transaction log / healthcheck policy ------------------------------------ OPA_HEALTH_CHECK_POLICY_ENABLED = confi.bool( "OPA_HEALTH_CHECK_POLICY_ENABLED", False, - description="Should we load a special healthcheck policy into OPA that checks " - + "that opa was synced correctly and is ready to answer to authorization queries", + description="When enabled, OPAL loads a special healthcheck policy into OPA that verifies OPA was synced correctly and is ready to answer authorization queries. This helps ensure the integrity of the policy store." ) OPA_HEALTH_CHECK_TRANSACTION_LOG_PATH = confi.str( "OPA_HEALTH_CHECK_TRANSACTION_LOG_PATH", "system/opal/transactions", - description="Path to OPA document that stores the OPA write transactions", + description="Path to the OPA document that stores the OPA write transactions for health checking. This is used in conjunction with the healthcheck policy when OPA_HEALTH_CHECK_POLICY_ENABLED is True." ) OPAL_CLIENT_STAT_ID = confi.str( "OPAL_CLIENT_STAT_ID", None, - description="Unique client statistics identifier", + description="Unique identifier for client statistics. This can be used to track and differentiate between multiple OPAL clients in a distributed setup." ) OPA_HEALTH_CHECK_POLICY_PATH = "engine/healthcheck/opal.rego" @@ -345,26 +338,28 @@ def load_policy_store(): SCOPE_ID = confi.str( "SCOPE_ID", "default", - description="OPAL Scope ID" + description="Identifier for the OPAL scope. This can be used to logically separate different OPAL deployments or environments within the same infrastructure." ) STORE_BACKUP_PATH = confi.str( "STORE_BACKUP_PATH", "/opal/backup/opa.json", - description="Path to backup policy store's data to", + description="Path to backup the policy store's data. This is used for persistence and recovery in case of restarts or failures." ) STORE_BACKUP_INTERVAL = confi.int( "STORE_BACKUP_INTERVAL", 60, - description="Interval in seconds to backup policy store's data", + description="Interval in seconds to backup the policy store's data. Regular backups ensure data persistence and allow for quicker recovery." ) OFFLINE_MODE_ENABLED = confi.bool( "OFFLINE_MODE_ENABLED", False, - description="If set, opal client will try to load policy store from backup file and operate even if server is unreachable. Ignored if INLINE_OPA_ENABLED=False", + description="When enabled, the OPAL client will attempt to load the policy store from a backup file and operate even if the OPAL server is unreachable. This is ignored if INLINE_OPA_ENABLED is False. Useful for scenarios where temporary network issues shouldn't impact policy enforcement." ) SPLIT_ROOT_DATA = confi.bool( - "SPLIT_ROOT_DATA", False, description="Split writing data updates to root path" + "SPLIT_ROOT_DATA", + False, + description="When enabled, OPAL will split writing data updates to the root path. This can be useful for managing large datasets or improving update performance in certain scenarios." ) def on_load(self): diff --git a/packages/opal-common/opal_common/config.py b/packages/opal-common/opal_common/config.py index dc3e8fda..8da514a2 100644 --- a/packages/opal-common/opal_common/config.py +++ b/packages/opal-common/opal_common/config.py @@ -10,13 +10,19 @@ class OpalCommonConfig(Confi): ALLOWED_ORIGINS = confi.list( - "ALLOWED_ORIGINS", ["*"], description="List of allowed origins for CORS" + "ALLOWED_ORIGINS", + ["*"], + description="List of allowed origins for CORS. Use ['*'] to allow all origins, or specify a list of trusted domains for enhanced security in production environments." ) # Process name to show in logs - Not confi-controlable on purpose PROCESS_NAME = "" # Logging # - Log formatting - LOG_FORMAT_INCLUDE_PID = confi.bool("LOG_FORMAT_INCLUDE_PID", False, description="Include process ID in log format") + LOG_FORMAT_INCLUDE_PID = confi.bool( + "LOG_FORMAT_INCLUDE_PID", + False, + description="Include process ID in log format. Useful for distinguishing between multiple OPAL processes in a distributed setup." + ) LOG_FORMAT = confi.str( "LOG_FORMAT", confi.delay( @@ -26,23 +32,39 @@ class OpalCommonConfig(Confi): else _LOG_FORMAT_WITHOUT_PID ) ), - description="The format of the log messages", + description="The format of the log messages. Automatically adjusts based on LOG_FORMAT_INCLUDE_PID setting.", ) LOG_TRACEBACK = confi.bool( - "LOG_TRACEBACK", True, description="Include traceback in log messages" + "LOG_TRACEBACK", + True, + description="Include traceback in log messages. Helpful for debugging but may increase log verbosity." ) LOG_DIAGNOSE = confi.bool( - "LOG_DIAGNOSE", True, description="Include diagnosis in log messages" + "LOG_DIAGNOSE", + True, + description="Include diagnosis in log messages. Provides additional context for troubleshooting." + ) + LOG_COLORIZE = confi.bool( + "LOG_COLORIZE", + True, + description="Colorize log messages for improved readability in terminal output." ) - LOG_COLORIZE = confi.bool("LOG_COLORIZE", True, description="Colorize log messages") LOG_SERIALIZE = confi.bool( - "LOG_SERIALIZE", False, description="Serialize log messages" + "LOG_SERIALIZE", + False, + description="Serialize log messages to JSON format. Useful for log aggregation and analysis tools." ) LOG_SHOW_CODE_LINE = confi.bool( - "LOG_SHOW_CODE_LINE", True, description="Show code line in log messages" + "LOG_SHOW_CODE_LINE", + True, + description="Show code line in log messages. Aids in pinpointing the exact location of logged events in the source code." ) # - log level - LOG_LEVEL = confi.str("LOG_LEVEL", "INFO", description="The log level to show") + LOG_LEVEL = confi.str( + "LOG_LEVEL", + "INFO", + description="The log level to show. Options: DEBUG, INFO, WARNING, ERROR, CRITICAL. Adjust based on desired verbosity and environment (e.g., DEBUG for development, INFO or WARNING for production)." + ) # - Which modules should be logged LOG_MODULE_EXCLUDE_LIST = confi.list( "LOG_MODULE_EXCLUDE_LIST", @@ -50,75 +72,99 @@ class OpalCommonConfig(Confi): "uvicorn", # NOTE: the env var LOG_MODULE_EXCLUDE_OPA affects this list ], - description="List of modules to exclude from logging", + description="List of modules to exclude from logging. Use this to reduce noise from well-behaved third-party libraries." ) LOG_MODULE_INCLUDE_LIST = confi.list( "LOG_MODULE_INCLUDE_LIST", ["uvicorn.protocols.http"], - description="List of modules to include in logging", + description="List of modules to include in logging. Overrides LOG_MODULE_EXCLUDE_LIST for specific modules you want to monitor closely." ) LOG_PATCH_UVICORN_LOGS = confi.bool( "LOG_PATCH_UVICORN_LOGS", True, - description="Should we takeover UVICORN's logs so they appear in the main logger", + description="Should we takeover UVICORN's logs so they appear in the main logger. Enables consistent logging format across OPAL and its web server." ) # - Log to file as well ( @see https://github.com/Delgan/loguru#easier-file-logging-with-rotation--retention--compression) LOG_TO_FILE = confi.bool( - "LOG_TO_FILE", False, description="Should we log to a file" + "LOG_TO_FILE", + False, + description="Enable logging to a file in addition to console output. Useful for persistent logs and post-mortem analysis." ) LOG_FILE_PATH = confi.str( "LOG_FILE_PATH", f"opal_{PROCESS_NAME}{{time}}.log", - description="path to save log file", + description="Path to save log file. Supports time-based formatting for log rotation." ) LOG_FILE_ROTATION = confi.str( - "LOG_FILE_ROTATION", "250 MB", description="Log file rotation size" + "LOG_FILE_ROTATION", + "250 MB", + description="Log file rotation size. Helps manage disk space by creating new log files when the current one reaches this size." ) LOG_FILE_RETENTION = confi.str( - "LOG_FILE_RETENTION", "10 days", description="Log file retention time" + "LOG_FILE_RETENTION", + "10 days", + description="Log file retention time. Automatically removes old log files to prevent disk space issues." ) LOG_FILE_COMPRESSION = confi.str( - "LOG_FILE_COMPRESSION", None, description="Log file compression format" + "LOG_FILE_COMPRESSION", + None, + description="Log file compression format. Set to 'gz' or 'zip' to compress rotated logs and save disk space." ) LOG_FILE_SERIALIZE = confi.str( - "LOG_FILE_SERIALIZE", True, description="Serialize log messages in file" + "LOG_FILE_SERIALIZE", + True, + description="Serialize log messages in file to JSON format. Facilitates parsing and analysis by log management tools." ) LOG_FILE_LEVEL = confi.str( - "LOG_FILE_LEVEL", "INFO", description="The log level to show in file" + "LOG_FILE_LEVEL", + "INFO", + description="The log level to show in file. Can be set differently from console logging for more detailed file logs." ) STATISTICS_ENABLED = confi.bool( "STATISTICS_ENABLED", False, - description="Set if OPAL server will collect statistics about OPAL clients may cause a small performance hit", + description="Enable collection of statistics about OPAL clients. Useful for monitoring and optimization but may cause a small performance hit." ) STATISTICS_ADD_CLIENT_CHANNEL = confi.str( "STATISTICS_ADD_CLIENT_CHANNEL", "__opal_stats_add", - description="The topic to update about new OPAL clients connection", + description="The topic to update about new OPAL clients connection. Used for real-time monitoring of client connections." ) STATISTICS_REMOVE_CLIENT_CHANNEL = confi.str( "STATISTICS_REMOVE_CLIENT_CHANNEL", "__opal_stats_rm", - description="The topic to update about OPAL clients disconnection", + description="The topic to update about OPAL clients disconnection. Helps track client lifecycle and potential issues." ) # Fetching Providers - # - where to load providers from FETCH_PROVIDER_MODULES = confi.list( - "FETCH_PROVIDER_MODULES", ["opal_common.fetcher.providers"], description="Modules to load fetch providers from" + "FETCH_PROVIDER_MODULES", + ["opal_common.fetcher.providers"], + description="Modules to load fetch providers from. Extend this list to add custom data fetching capabilities for policy and data updates." ) # Fetching engine - # Max number of worker tasks handling fetch events concurrently - FETCHING_WORKER_COUNT = confi.int("FETCHING_WORKER_COUNT", 6, description="Number of worker tasks for handling fetch events concurrently") - # Time in seconds to wait on the queued fetch task. - FETCHING_CALLBACK_TIMEOUT = confi.int("FETCHING_CALLBACK_TIMEOUT", 10, description="Timeout in seconds for fetch task callbacks") - # Time in seconds to wait for queuing a new task (if the queue is full) - FETCHING_ENQUEUE_TIMEOUT = confi.int("FETCHING_ENQUEUE_TIMEOUT", 10, description="Timeout in seconds for enqueueing new fetch tasks") + FETCHING_WORKER_COUNT = confi.int( + "FETCHING_WORKER_COUNT", + 6, + description="Number of worker tasks for handling fetch events concurrently. Adjust based on available resources and expected load." + ) + FETCHING_CALLBACK_TIMEOUT = confi.int( + "FETCHING_CALLBACK_TIMEOUT", + 10, + description="Timeout in seconds for fetch task callbacks. Prevents hanging on slow or unresponsive data sources." + ) + FETCHING_ENQUEUE_TIMEOUT = confi.int( + "FETCHING_ENQUEUE_TIMEOUT", + 10, + description="Timeout in seconds for enqueueing new fetch tasks. Helps manage backpressure in high-load scenarios." + ) GIT_SSH_KEY_FILE = confi.str( - "GIT_SSH_KEY_FILE", str(Path.home() / ".ssh/opal_repo_ssh_key"), description="Path to SSH key file for Git operations" + "GIT_SSH_KEY_FILE", + str(Path.home() / ".ssh/opal_repo_ssh_key"), + description="Path to SSH key file for Git operations. Used for authenticating with private policy repositories." ) # Trust self signed certificates (Advanced Usage - only affects OPAL client) ----------------------------- @@ -129,51 +175,67 @@ class OpalCommonConfig(Confi): CLIENT_SELF_SIGNED_CERTIFICATES_ALLOWED = confi.bool( "CLIENT_SELF_SIGNED_CERTIFICATES_ALLOWED", False, - description="Whether or not OPAL Client will trust HTTPs connections protected by self signed certificates. DO NOT USE THIS IN PRODUCTION!", + description="Whether OPAL Client will trust HTTPS connections protected by self-signed certificates. CAUTION: Do not enable in production environments as it reduces security." ) CLIENT_SSL_CONTEXT_TRUSTED_CA_FILE = confi.str( "CLIENT_SSL_CONTEXT_TRUSTED_CA_FILE", None, - description="A path to your own CA public certificate file (usually a .crt or a .pem file). Certificates signed by this issuer will be trusted by OPAL Client. DO NOT USE THIS IN PRODUCTION!", + description="Path to a custom CA public certificate file (.crt or .pem) for OPAL Client to trust. Use for organizational CAs in secure environments. NOT recommended for production use." ) # security AUTH_PUBLIC_KEY_FORMAT = confi.enum( - "AUTH_PUBLIC_KEY_FORMAT", EncryptionKeyFormat, EncryptionKeyFormat.ssh, description="Format of the public key used for authentication" + "AUTH_PUBLIC_KEY_FORMAT", + EncryptionKeyFormat, + EncryptionKeyFormat.ssh, + description="Format of the public key used for authentication. Supports SSH and PEM formats for flexibility in key management." ) AUTH_PUBLIC_KEY = confi.delay( lambda AUTH_PUBLIC_KEY_FORMAT=None: confi.public_key( - "AUTH_PUBLIC_KEY", default=None, key_format=AUTH_PUBLIC_KEY_FORMAT, - description="The public key used for authentication and JWT token verification" + "AUTH_PUBLIC_KEY", + default=None, + key_format=AUTH_PUBLIC_KEY_FORMAT, + description="The public key used for authentication and JWT token verification. Critical for securing communication between OPAL components." ) ) AUTH_JWT_ALGORITHM = confi.enum( "AUTH_JWT_ALGORITHM", JWTAlgorithm, getattr(JWTAlgorithm, "RS256"), - description="jwt algorithm, possible values: see: https://pyjwt.readthedocs.io/en/stable/algorithms.html", + description="JWT algorithm for token signing and verification. RS256 is recommended for production use. See: https://pyjwt.readthedocs.io/en/stable/algorithms.html" + ) + AUTH_JWT_AUDIENCE = confi.str( + "AUTH_JWT_AUDIENCE", + "https://api.opal.ac/v1/", + description="Audience claim for JWT tokens. Should match the intended recipient of the token, typically the OPAL API endpoint." + ) + AUTH_JWT_ISSUER = confi.str( + "AUTH_JWT_ISSUER", + f"https://opal.ac/", + description="Issuer claim for JWT tokens. Identifies the token issuer, usually set to your OPAL server's domain." ) - AUTH_JWT_AUDIENCE = confi.str("AUTH_JWT_AUDIENCE", "https://api.opal.ac/v1/", description="Audience claim for JWT tokens") - AUTH_JWT_ISSUER = confi.str("AUTH_JWT_ISSUER", f"https://opal.ac/", description="Issuer claim for JWT tokens") POLICY_REPO_POLICY_EXTENSIONS = confi.list( "POLICY_REPO_POLICY_EXTENSIONS", [".rego"], - description="List of extensions to serve as policy modules", + description="List of file extensions to recognize as policy modules. Extend this list if using custom policy file types beyond Rego." ) - ENABLE_METRICS = confi.bool("ENABLE_METRICS", False, description="Enable metrics collection") + ENABLE_METRICS = confi.bool( + "ENABLE_METRICS", + False, + description="Enable metrics collection for monitoring OPAL performance and behavior. Useful for operational insights and troubleshooting." + ) # optional APM tracing with datadog ENABLE_DATADOG_APM = confi.bool( "ENABLE_DATADOG_APM", False, - description="Set if OPAL server should enable tracing with datadog APM", + description="Enable tracing with Datadog APM for advanced performance monitoring and distributed tracing capabilities." ) HTTP_FETCHER_PROVIDER_CLIENT = confi.str( "HTTP_FETCHER_PROVIDER_CLIENT", "aiohttp", - description="The client to use for fetching data, can be either aiohttp or httpx." - "if provided different value, aiohttp will be used.", + description="The HTTP client library to use for fetching data. Options: 'aiohttp' or 'httpx'. Affects performance and features of HTTP-based data fetching." ) diff --git a/packages/opal-server/opal_server/config.py b/packages/opal-server/opal_server/config.py index ec1eacf2..13b8bef8 100644 --- a/packages/opal-server/opal_server/config.py +++ b/packages/opal-server/opal_server/config.py @@ -30,36 +30,37 @@ class OpalServerConfig(Confi): OPAL_WS_LOCAL_URL = confi.str( "WS_LOCAL_URL", "ws://localhost:7002/ws", - description="Local WebSocket URL for OPAL server" + description="Local WebSocket URL for OPAL server. This is the endpoint that OPAL clients will connect to for real-time updates." ) OPAL_WS_TOKEN = confi.str( "WS_TOKEN", "THIS_IS_A_DEV_SECRET", - description="Authentication token for WebSocket connections" + description="Authentication token for WebSocket connections. This token is used to secure the WebSocket connection between OPAL server and clients." ) CLIENT_LOAD_LIMIT_NOTATION = confi.str( "CLIENT_LOAD_LIMIT_NOTATION", None, - "If supplied, rate limit would be enforced on server's websocket endpoint. " - + "Format is `limits`-style notation (e.g '10 per second'), " - + "see link: https://limits.readthedocs.io/en/stable/quickstart.html#rate-limit-string-notation", + "Rate limit notation for the server's WebSocket endpoint. Format uses 'limits'-style notation (e.g., '10 per second'). " + "This helps prevent server overload from too many client connections. " + "See: https://limits.readthedocs.io/en/stable/quickstart.html#rate-limit-string-notation" ) + # The URL for the backbone pub/sub server (e.g. Postgres, Kafka, Redis) @see BROADCAST_URI = confi.str( "BROADCAST_URI", None, - description="The URL for the backbone pub/sub server (e.g. Postgres, Kafka, Redis)" + description="The URL for the backbone pub/sub server (e.g., Postgres, Kafka, Redis). " + "This is used for broadcasting updates across multiple OPAL server instances, ensuring scalability and consistency." ) - # The name to be used for segmentation in the backbone pub/sub (e.g. the Kafka topic) BROADCAST_CHANNEL_NAME = confi.str( "BROADCAST_CHANNEL_NAME", "EventNotifier", - description="Channel name for broadcast messages" + description="Channel name for broadcast messages. This is used to segment messages in the backbone pub/sub system." ) BROADCAST_CONN_LOSS_BUGFIX_EXPERIMENT_ENABLED = confi.bool( "BROADCAST_CONN_LOSS_BUGFIX_EXPERIMENT_ENABLED", True, - description="Enable experimental fix for broadcast connection loss" + description="Enable experimental fix for broadcast connection loss. This aims to improve reliability of the broadcast system." ) # server security @@ -67,39 +68,36 @@ class OpalServerConfig(Confi): "AUTH_PRIVATE_KEY_FORMAT", EncryptionKeyFormat, EncryptionKeyFormat.pem, - description="Format of the private key used for authentication" + description="Format of the private key used for authentication. This key is used for signing JWTs for client authentication." ) AUTH_PRIVATE_KEY_PASSPHRASE = confi.str( "AUTH_PRIVATE_KEY_PASSPHRASE", None, - description="Passphrase for the private key used in authentication" + description="Passphrase for the private key used in authentication. Required if the private key is encrypted." ) - AUTH_PRIVATE_KEY = confi.delay( lambda AUTH_PRIVATE_KEY_FORMAT=None, AUTH_PRIVATE_KEY_PASSPHRASE="": confi.private_key( "AUTH_PRIVATE_KEY", default=None, key_format=AUTH_PRIVATE_KEY_FORMAT, passphrase=AUTH_PRIVATE_KEY_PASSPHRASE, - description="Private key used for authentication" + description="Private key used for authentication. This is crucial for securing the OPAL server and client communication." ) ) - AUTH_JWKS_URL = confi.str( "AUTH_JWKS_URL", "/.well-known/jwks.json", - description="URL for JSON Web Key Set (JWKS)" + description="URL for JSON Web Key Set (JWKS). This is used for JWT validation in a distributed system." ) AUTH_JWKS_STATIC_DIR = confi.str( "AUTH_JWKS_STATIC_DIR", os.path.join(os.getcwd(), "jwks_dir"), - description="Directory for static JWKS files" + description="Directory for static JWKS files. Used when JWKS are stored locally rather than fetched from a URL." ) - AUTH_MASTER_TOKEN = confi.str( "AUTH_MASTER_TOKEN", None, - description="Master token for authentication" + description="Master token for authentication. This provides a high-level access token for administrative operations." ) # policy source watcher @@ -107,168 +105,169 @@ class OpalServerConfig(Confi): "POLICY_SOURCE_TYPE", PolicySourceTypes, PolicySourceTypes.Git, - description="Set your policy source can be GIT / API", + description="Set your policy source. Can be GIT for Git repositories or API for API-based policy sources.", ) POLICY_REPO_URL = confi.str( "POLICY_REPO_URL", None, - description="Set your remote repo URL e.g:https://github.com/permitio/opal-example-policy-repo.git\ - , relevant only on GIT source type", + description="URL of the Git repository hosting the policy. For example: https://github.com/permitio/opal-example-policy-repo.git. " + "This is used when POLICY_SOURCE_TYPE is set to GIT.", ) POLICY_BUNDLE_URL = confi.str( "POLICY_BUNDLE_URL", None, - description="Set your API bundle URL, relevant only on API source type", + description="URL for the API-based policy bundle. This is used when POLICY_SOURCE_TYPE is set to API.", ) POLICY_REPO_CLONE_PATH = confi.str( "POLICY_REPO_CLONE_PATH", os.path.join(os.getcwd(), "regoclone"), - description="Base path to create local git folder inside it that manage policy change", + description="Base path to create local git folder for managing policy changes. OPAL will clone the policy repo to this location.", ) POLICY_REPO_CLONE_FOLDER_PREFIX = confi.str( "POLICY_REPO_CLONE_FOLDER_PREFIX", "opal_repo_clone", - description="Prefix for the local git folder", + description="Prefix for the local git folder. This helps identify OPAL-managed clones.", ) POLICY_REPO_REUSE_CLONE_PATH = confi.bool( "POLICY_REPO_REUSE_CLONE_PATH", False, - "Set if OPAL server should use a fixed clone path (and reuse if it already exists) instead of randomizing its suffix on each run", + "Determines if OPAL server should use a fixed clone path and reuse it if it exists, instead of creating a new clone with a randomized suffix on each run.", ) POLICY_REPO_MAIN_BRANCH = confi.str( "POLICY_REPO_MAIN_BRANCH", "master", - description="The main branch of the policy repository" + description="The main branch of the policy repository to track. OPAL will watch this branch for policy updates." ) POLICY_REPO_SSH_KEY = confi.str( "POLICY_REPO_SSH_KEY", None, - description="SSH key for accessing the policy repository" + description="SSH key for accessing private policy repositories. Required if the policy repo is not public." ) POLICY_REPO_MANIFEST_PATH = confi.str( "POLICY_REPO_MANIFEST_PATH", "", - "Path of the directory holding the '.manifest' file (new fashion), or of the manifest file itself (old fashion). Repo's root is used by default", + "Path to the directory containing the '.manifest' file, or to the manifest file itself. " + "The manifest file is used to specify which files in the repo should be treated as policies.", ) POLICY_REPO_CLONE_TIMEOUT = confi.int( "POLICY_REPO_CLONE_TIMEOUT", 0, - description="Timeout for cloning the policy repository (0 means wait forever)" + description="Timeout in seconds for cloning the policy repository. 0 means wait indefinitely." ) LEADER_LOCK_FILE_PATH = confi.str( "LEADER_LOCK_FILE_PATH", "/tmp/opal_server_leader.lock", - description="Path to the leader lock file" + description="Path to the leader lock file. Used in multi-server setups to determine the primary server." ) POLICY_BUNDLE_SERVER_TYPE = confi.enum( "POLICY_BUNDLE_SERVER_TYPE", PolicyBundleServerType, PolicyBundleServerType.HTTP, - description="The type of bundle server e.g. basic HTTP , AWS S3. (affects how we authenticate with it)", + description="The type of bundle server, e.g., basic HTTP or AWS S3. This affects how OPAL authenticates with the bundle server.", ) POLICY_BUNDLE_SERVER_TOKEN = confi.str( "POLICY_BUNDLE_SERVER_TOKEN", None, - description="Secret token to be sent to API bundle server", + description="Secret token to be sent to the API bundle server for authentication.", ) POLICY_BUNDLE_SERVER_TOKEN_ID = confi.str( "POLICY_BUNDLE_SERVER_TOKEN_ID", None, - description="The id of the secret token to be sent to API bundle server", + description="The ID of the secret token to be sent to the API bundle server. Used in conjunction with POLICY_BUNDLE_SERVER_TOKEN.", ) POLICY_BUNDLE_SERVER_AWS_REGION = confi.str( "POLICY_BUNDLE_SERVER_AWS_REGION", "us-east-1", - description="The AWS region of the S3 bucket", + description="The AWS region of the S3 bucket when using S3 as a bundle server.", ) POLICY_BUNDLE_TMP_PATH = confi.str( "POLICY_BUNDLE_TMP_PATH", "/tmp/bundle.tar.gz", - description="Path for temp policy file, need to be writeable", + description="Temporary path for storing downloaded policy bundles. Ensure this path is writable.", ) POLICY_BUNDLE_GIT_ADD_PATTERN = confi.str( "POLICY_BUNDLE_GIT_ADD_PATTERN", "*", - description="File pattern to add files to git default to all the files (*)", + description="File pattern to add files to git. Default is all files (*).", ) REPO_WATCHER_ENABLED = confi.bool( "REPO_WATCHER_ENABLED", True, - description="Enable or disable the repository watcher" + description="Enable or disable the repository watcher. When enabled, OPAL will actively watch for changes in the policy repository." ) # publisher PUBLISHER_ENABLED = confi.bool( "PUBLISHER_ENABLED", True, - description="Enable or disable the publisher" + description="Enable or disable the publisher. The publisher is responsible for broadcasting policy and data updates to clients." ) # broadcaster keepalive BROADCAST_KEEPALIVE_INTERVAL = confi.int( "BROADCAST_KEEPALIVE_INTERVAL", 3600, - description="the time to wait between sending two consecutive broadcaster keepalive messages", + description="Time in seconds to wait between sending consecutive broadcaster keepalive messages. This helps maintain active connections.", ) BROADCAST_KEEPALIVE_TOPIC = confi.str( "BROADCAST_KEEPALIVE_TOPIC", "__broadcast_session_keepalive__", - description="the topic on which we should send broadcaster keepalive messages", + description="The topic on which broadcaster keepalive messages are sent. This is used to maintain the pub/sub connection.", ) # statistics MAX_CHANNELS_PER_CLIENT = confi.int( "MAX_CHANNELS_PER_CLIENT", 15, - description="max number of records per client, after this number it will not be added to statistics, relevant only if STATISTICS_ENABLED", + description="Maximum number of channels per client for statistics tracking. After this number, new channels won't be added to statistics.", ) STATISTICS_WAKEUP_CHANNEL = confi.str( "STATISTICS_WAKEUP_CHANNEL", "__opal_stats_wakeup", - description="The topic a waking-up OPAL server uses to notify others he needs their statistics data", + description="The topic a waking-up OPAL server uses to notify others it needs their statistics data.", ) STATISTICS_STATE_SYNC_CHANNEL = confi.str( "STATISTICS_STATE_SYNC_CHANNEL", "__opal_stats_state_sync", - description="The topic other servers with statistics provide their state to a waking-up server", + description="The topic other servers use to provide their statistics state to a waking-up server.", ) STATISTICS_SERVER_KEEPALIVE_CHANNEL = confi.str( "STATISTICS_SERVER_KEEPALIVE_CHANNEL", "__opal_stats_server_keepalive", - description="The topic workers use to signal they exist and are alive", + description="The topic workers use to signal they exist and are alive. Part of the server health monitoring system.", ) STATISTICS_SERVER_KEEPALIVE_TIMEOUT = confi.str( "STATISTICS_SERVER_KEEPALIVE_TIMEOUT", 20, - description="Timeout for forgetting a server from which a keep-alive haven't been seen (keep-alive frequency would be half of this value)", + description="Timeout in seconds for forgetting a server from which a keep-alive hasn't been seen. Keep-alive frequency is half of this value.", ) # Data updates ALL_DATA_TOPIC = confi.str( "ALL_DATA_TOPIC", DEFAULT_DATA_TOPIC, - description="Top level topic for data", + description="Top-level topic for all data updates. Clients subscribe to this topic to receive all data changes.", ) ALL_DATA_ROUTE = confi.str( "ALL_DATA_ROUTE", "/policy-data", - description="Route for accessing all policy data" + description="Route for accessing all policy data. This endpoint provides a complete snapshot of the current policy data." ) ALL_DATA_URL = confi.str( "ALL_DATA_URL", confi.delay("http://localhost:7002{ALL_DATA_ROUTE}"), - description="URL for all data config [If you choose to have it all at one place]", + description="URL for fetching all data config. Used when all policy data is centralized in one location.", ) DATA_CONFIG_ROUTE = confi.str( "DATA_CONFIG_ROUTE", "/data/config", - description="URL to fetch the full basic configuration of data", + description="URL to fetch the full basic configuration of data sources.", ) DATA_CALLBACK_DEFAULT_ROUTE = confi.str( "DATA_CALLBACK_DEFAULT_ROUTE", "/data/callback_report", - description="Exists as a sane default in case the user did not set OPAL_DEFAULT_UPDATE_CALLBACKS", + description="Default route for data update callbacks. Used if OPAL_DEFAULT_UPDATE_CALLBACKS is not set.", ) DATA_CONFIG_SOURCES = confi.model( @@ -281,20 +280,20 @@ class OpalServerConfig(Confi): } } ), - description="Configuration of data sources by topics", + description="Configuration of data sources by topics. This defines how OPAL fetches and distributes policy data.", ) DATA_UPDATE_TRIGGER_ROUTE = confi.str( "DATA_CONFIG_ROUTE", "/data/update", - description="URL to trigger data update events", + description="URL to trigger data update events. Used to manually initiate data updates.", ) # Git service webhook (Default is Github) POLICY_REPO_WEBHOOK_SECRET = confi.str( "POLICY_REPO_WEBHOOK_SECRET", None, - description="Secret for validating policy repo webhooks" + description="Secret for validating policy repo webhooks. This ensures that webhook calls are coming from a trusted source." ) # The topic the event of the webhook will publish POLICY_REPO_WEBHOOK_TOPIC = "webhook" @@ -302,9 +301,10 @@ class OpalServerConfig(Confi): POLICY_REPO_WEBHOOK_ENFORCE_BRANCH: bool = confi.bool( "POLICY_REPO_WEBHOOK_ENFORCE_BRANCH", False, - description="Enforce branch name check in webhook payload" + description="Enforce branch name check in webhook payload. When enabled, OPAL verifies that the webhook mentions the correct branch name." ) # Parameters controlling how the incoming webhook should be read and processed + # Parameters controlling how the incoming webhook should be read and processed POLICY_REPO_WEBHOOK_PARAMS: GitWebhookRequestParams = confi.model( "POLICY_REPO_WEBHOOK_PARAMS", GitWebhookRequestParams, @@ -316,98 +316,102 @@ class OpalServerConfig(Confi): "event_request_key": None, "push_event_value": "push", }, - description="Parameters for processing incoming webhooks from the policy repository" + description="Parameters for processing incoming webhooks from the policy repository. These settings define how OPAL interprets webhook payloads." ) POLICY_REPO_POLLING_INTERVAL = confi.int( "POLICY_REPO_POLLING_INTERVAL", 0, - description="Interval (in seconds) for polling the policy repository (0 means disabled)" + description="Interval in seconds for polling the policy repository. Set to 0 to disable polling. " + "When set, OPAL will check for policy updates at this interval, useful when webhooks are not available." ) ALLOWED_ORIGINS = confi.list( "ALLOWED_ORIGINS", ["*"], - description="List of allowed origins for CORS" + description="List of allowed origins for CORS (Cross-Origin Resource Sharing). Use '*' to allow all origins, or specify domains for more restrictive security." ) FILTER_FILE_EXTENSIONS = confi.list( "FILTER_FILE_EXTENSIONS", [".rego", ".json"], - description="File extensions to filter when processing policy files" + description="File extensions to filter when processing policy files. OPAL will only consider files with these extensions as part of the policy." ) BUNDLE_IGNORE = confi.list( "BUNDLE_IGNORE", [], - description="List of patterns to ignore when creating policy bundles" + description="List of patterns to ignore when creating policy bundles. Similar to .gitignore, this allows excluding certain files or directories from policy bundles." ) NO_RPC_LOGS = confi.bool( "NO_RPC_LOGS", True, - description="Disable RPC logs" + description="Disable RPC logs to reduce log verbosity. Set to False if you need detailed logging of RPC calls for debugging." ) # client-api server SERVER_WORKER_COUNT = confi.int( "SERVER_WORKER_COUNT", None, - description="(if run via CLI) Worker count for the server [Default calculated to CPU-cores]", + description="Number of worker processes for the server. If not set, it defaults to the number of CPU cores. More workers can handle more concurrent requests." ) SERVER_HOST = confi.str( "SERVER_HOST", "127.0.0.1", - description="(if run via CLI) Address for the server to bind", + description="Address for the server to bind to. Use '0.0.0.0' to bind to all available network interfaces." ) SERVER_PORT = confi.str( "SERVER_PORT", None, - # Users have experienced errors when kubernetes sets the env-var OPAL_SERVER_PORT="tcp://..." (which fails to parse as a port integer). - description="Deprecated, use SERVER_BIND_PORT instead", + description="Deprecated. Use SERVER_BIND_PORT instead. Kept for backward compatibility." ) SERVER_BIND_PORT = confi.int( "SERVER_BIND_PORT", 7002, - description="(if run via CLI) Port for the server to bind", + description="Port for the server to bind to. This is the port on which OPAL server will listen for incoming connections." ) # optional APM tracing with datadog ENABLE_DATADOG_APM = confi.bool( "ENABLE_DATADOG_APM", False, - description="Set if OPAL server should enable tracing with datadog APM", + description="Enable tracing with Datadog APM (Application Performance Monitoring). Useful for monitoring OPAL's performance in production environments." ) + # Scopes feature SCOPES = confi.bool( "SCOPES", default=False, - description="Enable scopes feature" + description="Enable the scopes feature. Scopes allow for more granular control over policy and data distribution." ) SCOPES_REPO_CLONES_SHARDS = confi.int( "SCOPES_REPO_CLONES_SHARDS", 1, - description="The max number of local clones to use for the same repo (reused across scopes)", + description="The maximum number of local clones to use for the same repo (reused across scopes). This helps in managing multiple scopes efficiently." ) + # Redis configuration REDIS_URL = confi.str( "REDIS_URL", default="redis://localhost", - description="URL for Redis connection" + description="URL for Redis connection. Redis is used for caching and as a potential backbone for broadcasting updates." ) + # Base directory configuration BASE_DIR = confi.str( "BASE_DIR", default=pathlib.Path.home() / ".local/state/opal", - description="Base directory for OPAL server files" + description="Base directory for OPAL server files. This is where OPAL stores its state and temporary files." ) + # Policy refresh configuration POLICY_REFRESH_INTERVAL = confi.int( "POLICY_REFRESH_INTERVAL", default=0, - description="Policy polling refresh interval", + description="Policy polling refresh interval in seconds. Set to 0 to disable periodic refreshes. This is useful for ensuring policies are up-to-date even without webhooks." ) def on_load(self):