feat: Add configurable user default domain for login

Add 'user_default_domain' config option to replace the hardcoded
"Default" domain when users login without specifying a domain.

Also add '/config' API endpoint to expose public configurations
before authentication. Currently returns user_default_domain and
can be extended for other public configs.

Changes:
- Add user_default_domain in openstack config section
- Add GET /config endpoint (no auth required)
- Use generic Config schema for extensibility
- Update docs and sample files

This improves flexibility for multi-domain deployments.

Change-Id: I6fc40337c9835cf8172bcfa86cac621b7effeb0d
Signed-off-by: Reet Srivastava <reet.srivastava@rackspace.com>
Signed-off-by: Wu Wenxiang <wu.wenxiang@algoblu.com>
This commit is contained in:
Wu Wenxiang
2025-10-01 06:57:21 +08:00
parent 2b6a71ea9d
commit dde20cbb20
8 changed files with 67 additions and 2 deletions

View File

@@ -31,6 +31,7 @@ file ``skyline.yaml.sample`` in ``etc`` directory.
base_domains:
- heat_user_domain
default_region: RegionOne
user_default_domain: Default
enforce_new_defaults: true
extension_mapping:
floating-ip-port-forwarding: neutron_port_forwarding

View File

@@ -64,6 +64,7 @@ openstack:
system_user_domain: Default
system_user_name: skyline
system_user_password: ''
user_default_domain: Default
setting:
base_settings:
- flavor_families

View File

@@ -179,10 +179,11 @@ def login(
),
) -> schemas.Profile:
region = credential.region or CONF.openstack.default_region
domain = credential.domain or CONF.openstack.user_default_domain
try:
project_scope, unscope_token, default_project_id = _get_projects_and_unscope_token(
region=region,
domain=credential.domain,
domain=domain,
username=credential.username,
password=credential.password,
project_enabled=True,
@@ -213,6 +214,20 @@ def login(
return profile
@router.get(
"/config",
description="Get public configuration",
responses={
200: {"model": schemas.Config},
},
response_model=schemas.Config,
status_code=status.HTTP_200_OK,
response_description="OK",
)
def get_config(request: Request) -> schemas.Config:
return schemas.Config(default_domain=CONF.openstack.user_default_domain)
@router.get(
"/sso",
description="SSO configuration.",

View File

@@ -73,6 +73,13 @@ default_region = Opt(
default="RegionOne",
)
user_default_domain = Opt(
name="user_default_domain",
description="Default domain for user authentication when no domain is specified",
schema=StrictStr,
default="Default",
)
interface_type = Opt(
name="interface_type",
description="OpenStack endpoint interface type",
@@ -205,6 +212,7 @@ ALL_OPTS = (
system_user_name,
system_user_password,
default_region,
user_default_domain,
interface_type,
nginx_prefix,
base_domains,

View File

@@ -81,6 +81,7 @@ async def validate_token(request: Request, call_next):
f"{constants.API_PREFIX}/openapi.json",
"/favicon.ico",
f"{constants.API_PREFIX}/sso",
f"{constants.API_PREFIX}/config",
f"{constants.API_PREFIX}/contrib/keystone_endpoints",
# f"{constants.API_PREFIX}/contrib/domains",
f"{constants.API_PREFIX}/contrib/regions",

View File

@@ -42,7 +42,7 @@ from .extension import (
VolumesResponse,
VolumeStatus,
)
from .login import SSO, Credential, Payload, Profile
from .login import SSO, Config, Credential, Payload, Profile
from .policy import Policies, PoliciesRules
from .policy_manager import Operation, OperationsSchema, ScopeTypesSchema
from .prometheus import (

View File

@@ -120,3 +120,7 @@ class SSOInfo(BaseModel):
class SSO(BaseModel):
enable_sso: bool
protocols: List[SSOInfo]
class Config(BaseModel):
default_domain: str

View File

@@ -70,6 +70,28 @@
}
}
},
"/api/v1/config": {
"get": {
"tags": [
"Login"
],
"summary": "Get Config",
"description": "Get public configuration",
"operationId": "get_config_api_v1_config_get",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Config"
}
}
}
}
}
}
},
"/api/v1/sso": {
"get": {
"tags": [
@@ -2631,6 +2653,19 @@
],
"title": "ComputeServicesResponseBase"
},
"Config": {
"properties": {
"default_domain": {
"type": "string",
"title": "Default Domain"
}
},
"type": "object",
"required": [
"default_domain"
],
"title": "Config"
},
"Credential": {
"properties": {
"region": {