Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ Change Log
----------


8.19.0.1b1
==========
* wrr / 2026-09-02 / branch: fm/dcicutils-okta-ini-config-7p
- Added first-class Okta values to ``deployment_utils``: ``build_ini_file_from_template`` and
``build_ini_stream_from_template`` now accept ``okta_issuer``, ``okta_client``, ``okta_scopes``,
and ``okta_require_email_verified``, bound to the ``OKTA_ISSUER``, ``OKTA_CLIENT``, ``OKTA_SCOPES``,
and ``OKTA_REQUIRE_EMAIL_VERIFIED`` template substitutions. Each takes its value from the explicit
argument, else the corresponding ``ENCODED_OKTA_*`` environment variable, else a safe default,
matching the existing Auth0 precedence. This lets a portal container render Okta settings into
``production.ini`` during its existing one-time startup configuration step, rather than having the
running application read Secrets Manager itself.
- ``OKTA_SCOPES`` defaults to empty so the consuming application picks its own scopes, and
``OKTA_REQUIRE_EMAIL_VERIFIED`` is omitted from the generated file unless a boolean is actually
supplied, so that the application's secure default (require a verified email) applies. There is
deliberately no Okta secret: this is a public SPA using Authorization Code with PKCE.
- Existing callers, Auth0 values, and generated output are unchanged.


8.19.0
======
* ajs/wrr/sn 2026-07-29 / branch: sn_refactor_custom_excel
Expand Down
59 changes: 58 additions & 1 deletion dcicutils/deployment_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def main():
is_fourfront_env, is_cgap_env, is_stg_or_prd_env, is_test_env, is_hotseat_env,
is_indexer_env, indexer_env_for_env, full_env_name,
)
from .misc_utils import PRINT, Retry, apply_dict_overrides, override_environ, file_contents
from .misc_utils import PRINT, Retry, apply_dict_overrides, override_environ, file_contents, to_boolean
from .env_base import EnvBase, s3Base


Expand Down Expand Up @@ -428,6 +428,8 @@ def build_ini_file_from_template(cls, template_file_name, init_file_name, *,
application_bucket_prefix=None, foursight_bucket_prefix=None,
auth0_domain=None, auth0_client=None, auth0_secret=None,
auth0_allowed_connections=None,
okta_issuer=None, okta_client=None, okta_scopes=None,
okta_require_email_verified=None,
re_captcha_key=None, re_captcha_secret=None,
redis_server=None,
google_api_key=None,
Expand Down Expand Up @@ -469,6 +471,13 @@ def build_ini_file_from_template(cls, template_file_name, init_file_name, *,
auth0_client (str): A string identifying the auth0 client application.
auth0_secret (str): A string secret that is passed with the auth0_client to authenticate that client.
auth0_allowed_connections (str): A comma separated string of allowed connections that can be used via auth0.
okta_issuer (str): The Okta issuer (authorization server) URL to validate tokens against.
okta_client (str): The Okta client (application) id. This is a public SPA client, so it has no secret.
okta_scopes (str): A space separated string of OIDC scopes to request. Empty means the application
chooses its own default.
okta_require_email_verified (bool): Whether an Okta identity must have a verified email. If neither this
nor ENCODED_OKTA_REQUIRE_EMAIL_VERIFIED is given, the setting is omitted from the generated .ini file
so that the application's own (secure, true) default applies.
re_captcha_key (str): key used for reCaptcha for throttling/detecting humans on login
re_captcha_secret (str): secret used for reCaptcha
redis_server (str): A server URL to a Redis cluster, for use with sessions
Expand Down Expand Up @@ -507,6 +516,10 @@ def build_ini_file_from_template(cls, template_file_name, init_file_name, *,
auth0_client=auth0_client,
auth0_secret=auth0_secret,
auth0_allowed_connections=auth0_allowed_connections,
okta_issuer=okta_issuer,
okta_client=okta_client,
okta_scopes=okta_scopes,
okta_require_email_verified=okta_require_email_verified,
re_captcha_key=re_captcha_key,
re_captcha_secret=re_captcha_secret,
redis_server=redis_server,
Expand Down Expand Up @@ -569,6 +582,29 @@ def omittable(cls, line, expanded_line):
PRD_DEFAULT_CREATE_MAPPING_ON_DEPLOY_WIPE_ES = None
PRD_DEFAULT_CREATE_MAPPING_ON_DEPLOY_STRICT = None

@classmethod
def okta_require_email_verified_setting(cls, okta_require_email_verified=None):
"""
Returns the string to bind to OKTA_REQUIRE_EMAIL_VERIFIED in an .ini template.

An explicit argument takes precedence over the ENCODED_OKTA_REQUIRE_EMAIL_VERIFIED environment variable.
The result is "true" or "false" if a boolean value was actually supplied, and otherwise the empty string.

The empty string is deliberate rather than accidental: an empty expansion makes cls.omittable drop the
assignment line from the generated .ini file entirely, so the consuming application falls back to its own
default, which is to require a verified email. An absent, empty, or unparseable value therefore cannot
turn that check off, and (unlike raising) it cannot break .ini generation at container startup either.
"""
if okta_require_email_verified is None:
okta_require_email_verified = os.environ.get("ENCODED_OKTA_REQUIRE_EMAIL_VERIFIED")
if isinstance(okta_require_email_verified, str):
# to_boolean recognizes only true/t/false/f (case-insensitively), yielding None for anything else,
# so any other spelling is treated as "not specified" and omitted.
okta_require_email_verified = to_boolean(okta_require_email_verified, None)
if okta_require_email_verified is None:
return ""
return "true" if okta_require_email_verified else "false"

@classmethod
def build_ini_stream_from_template(cls, template_file_name, init_file_stream, *,
bs_env=None, bs_mirror_env=None, s3_bucket_org=None, s3_bucket_env=None,
Expand All @@ -580,6 +616,8 @@ def build_ini_stream_from_template(cls, template_file_name, init_file_stream, *,
application_bucket_prefix=None, foursight_bucket_prefix=None,
auth0_domain=None, auth0_client=None, auth0_secret=None,
auth0_allowed_connections=None,
okta_issuer=None, okta_client=None, okta_scopes=None,
okta_require_email_verified=None,
re_captcha_key=None, re_captcha_secret=None,
redis_server=None,
google_api_key=None,
Expand Down Expand Up @@ -618,6 +656,13 @@ def build_ini_stream_from_template(cls, template_file_name, init_file_stream, *,
auth0_client (str): A string identifying the auth0 client application.
auth0_secret (str): A string secret that is passed with the auth0_client to authenticate that client.
auth0_allowed_connections (str): A comma separated string of allowed connections that can be used via auth0.
okta_issuer (str): The Okta issuer (authorization server) URL to validate tokens against.
okta_client (str): The Okta client (application) id. This is a public SPA client, so it has no secret.
okta_scopes (str): A space separated string of OIDC scopes to request. Empty means the application
chooses its own default.
okta_require_email_verified (bool): Whether an Okta identity must have a verified email. If neither this
nor ENCODED_OKTA_REQUIRE_EMAIL_VERIFIED is given, the setting is omitted from the generated .ini file
so that the application's own (secure, true) default applies.
re_captcha_key (str): key used for reCaptcha for throttling/detecting humans on login
re_captcha_secret (str): secret used for reCaptcha
redis_server (str): A server URL to a Redis cluster, for use with sessions
Expand Down Expand Up @@ -696,6 +741,14 @@ def build_ini_stream_from_template(cls, template_file_name, init_file_stream, *,
auth0_secret = auth0_secret or os.environ.get("ENCODED_AUTH0_SECRET", "")
auth0_allowed_connections = auth0_allowed_connections or os.environ.get("ENCODED_AUTH0_ALLOWED_CONNECTIONS", "")

# Okta Configuration.
# Note that there is deliberately no Okta secret. The portal's Okta integration is a public SPA using the
# Authorization Code flow with PKCE, which has no client secret to configure or to leak into an .ini file.
okta_issuer = okta_issuer or os.environ.get("ENCODED_OKTA_ISSUER", "")
okta_client = okta_client or os.environ.get("ENCODED_OKTA_CLIENT", "")
okta_scopes = okta_scopes or os.environ.get("ENCODED_OKTA_SCOPES", "")
okta_require_email_verified = cls.okta_require_email_verified_setting(okta_require_email_verified)

# reCatpcha Configuration
re_captcha_key = re_captcha_key or os.environ.get('reCaptchaKey', '')
re_captcha_secret = re_captcha_secret or os.environ.get('reCaptchaSecret', '')
Expand Down Expand Up @@ -806,6 +859,10 @@ def build_ini_stream_from_template(cls, template_file_name, init_file_stream, *,
'AUTH0_CLIENT': auth0_client,
'AUTH0_SECRET': auth0_secret,
'AUTH0_ALLOWED_CONNECTIONS': auth0_allowed_connections,
'OKTA_ISSUER': okta_issuer,
'OKTA_CLIENT': okta_client,
'OKTA_SCOPES': okta_scopes,
'OKTA_REQUIRE_EMAIL_VERIFIED': okta_require_email_verified,
'g.recaptcha.key': re_captcha_key,
'g.recaptcha.secret': re_captcha_secret,
'CREATE_MAPPING_SKIP': create_mapping_on_deploy_skip,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "dcicutils"
version = "8.19.0"
version = "8.19.0.1b1"
description = "Utility package for interacting with the 4DN Data Portal and other 4DN resources"
authors = ["4DN-DCIC Team <support@4dnucleome.org>"]
license = "MIT"
Expand Down
Loading
Loading