|
13 | 13 | from django.db import IntegrityError, models
|
14 | 14 | from django.utils.timezone import now
|
15 | 15 | from django.utils.translation import gettext_lazy as _
|
| 16 | +from flags.state import flag_enabled |
16 | 17 | from rest_framework.serializers import DateTimeField
|
17 | 18 |
|
18 | 19 | from ansible_base.authentication.models import Authenticator, AuthenticatorMap, AuthenticatorUser
|
@@ -178,10 +179,28 @@ def _add_rbac_role_mapping(has_permission, role_mapping, role, organization=None
|
178 | 179 | logger.warning(f"Role mapping is not possible, organization for team '{team}' is missing")
|
179 | 180 |
|
180 | 181 |
|
| 182 | +def _is_case_insensitivity_enabled() -> bool: |
| 183 | + return flag_enabled("FEATURE_CASE_INSENSITIVE_AUTH_MAPS") |
| 184 | + |
| 185 | + |
| 186 | +def _lowercase_group_triggers(trigger_condition: dict) -> dict: |
| 187 | + """ |
| 188 | + Lowercase all group names provided to trigger |
| 189 | + """ |
| 190 | + ci_trigger_condition = {} |
| 191 | + for operator, grouplist in trigger_condition.items(): |
| 192 | + ci_trigger_condition[operator] = [f"{group}".casefold() for group in grouplist] |
| 193 | + return ci_trigger_condition |
| 194 | + |
| 195 | + |
181 | 196 | def process_groups(trigger_condition: dict, groups: list, authenticator_id: int) -> TriggerResult:
|
182 | 197 | """
|
183 | 198 | Looks at a maps trigger for a group and users groups and determines if the trigger is defined for this user.
|
| 199 | + Group DNs are compared case-insensitively when FEATURE_CASE_INSENSITIVE_AUTH_MAPS enabled. |
184 | 200 | """
|
| 201 | + if _is_case_insensitivity_enabled(): |
| 202 | + groups = [f"{group}".casefold() for group in groups] |
| 203 | + trigger_condition = _lowercase_group_triggers(trigger_condition) |
185 | 204 |
|
186 | 205 | invalid_conditions = set(trigger_condition.keys()) - set(TRIGGER_DEFINITION['groups']['keys'].keys())
|
187 | 206 | if invalid_conditions:
|
@@ -218,10 +237,35 @@ def has_access_with_join(current_access: Optional[bool], new_access: bool, condi
|
218 | 237 | return current_access and new_access
|
219 | 238 |
|
220 | 239 |
|
| 240 | +def _lowercase_attr_triggers(trigger_condition: dict) -> dict: |
| 241 | + """ |
| 242 | + Lower case all keys (attribute names) and contained attribute values |
| 243 | + """ |
| 244 | + ci_trigger_condition = {} |
| 245 | + for attr, condition in trigger_condition.items(): |
| 246 | + if isinstance(condition, str): |
| 247 | + updated_condition = condition.casefold() |
| 248 | + elif isinstance(condition, dict): |
| 249 | + if not condition: # empty dict |
| 250 | + updated_condition = {} |
| 251 | + for operator, value in condition.items(): |
| 252 | + updated_condition = {operator: value.casefold()} |
| 253 | + else: |
| 254 | + updated_condition = condition |
| 255 | + |
| 256 | + ci_trigger_condition[attr.casefold()] = updated_condition # join_condition |
| 257 | + return ci_trigger_condition |
| 258 | + |
| 259 | + |
221 | 260 | def process_user_attributes(trigger_condition: dict, attributes: dict, authenticator_id: int) -> TriggerResult:
|
222 | 261 | """
|
223 | 262 | Looks at a maps trigger for an attribute and the users attributes and determines if the trigger is defined for this user.
|
| 263 | + Attribute names are compared case-insensitively. |
224 | 264 | """
|
| 265 | + if _is_case_insensitivity_enabled(): |
| 266 | + attributes = {f"{k}".casefold(): v for k, v in attributes.items()} |
| 267 | + trigger_condition = _lowercase_attr_triggers(trigger_condition) |
| 268 | + |
225 | 269 | has_access = None
|
226 | 270 | join_condition = trigger_condition.get('join_condition', 'or')
|
227 | 271 | if join_condition not in TRIGGER_DEFINITION['attributes']['keys']['join_condition']['choices']:
|
@@ -265,7 +309,7 @@ def process_user_attributes(trigger_condition: dict, attributes: dict, authentic
|
265 | 309 | for a_user_value in user_value:
|
266 | 310 | # We are going to do mostly string comparisons, so convert the attribute to a
|
267 | 311 | # string just in case it came back as an int or something funky
|
268 |
| - a_user_value = f"{a_user_value}" |
| 312 | + a_user_value = f"{a_user_value}".casefold() if _is_case_insensitivity_enabled() else f"{a_user_value}" |
269 | 313 |
|
270 | 314 | # Check for any of the valid conditions
|
271 | 315 | if "equals" in trigger_condition[attribute]:
|
|
0 commit comments