[ 
https://issues.apache.org/jira/browse/KNOX-3513?focusedWorklogId=1047297&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1047297
 ]

ASF GitHub Bot logged work on KNOX-3513:
----------------------------------------

                Author: ASF GitHub Bot
            Created on: 13/Oct/26 18:16
            Start Date: 13/Oct/26 18:16
    Worklog Time Spent: 10m 
      Work Description: smolnar82 opened a new pull request, #1453:
URL: https://github.com/apache/knox/pull/1453

   [KNOX-3513](https://issues.apache.org/jira/browse/KNOX-3513) - Add capped 
retry for resolving LDAP backend password aliases
   
   ## What changes were proposed in this pull request?
   
   LDAP backend passwords can reference a credential store alias 
(`${ALIAS=...}`). The embedded Knox LDAP service resolves these aliases once, 
when it creates its interceptors. If the alias doesn't exist yet at that 
moment, the alias string itself is used as the password and the backend bind 
fails until the gateway restarts. This happens, for example, when a Kubernetes 
Secret and the configuration that references it are created together.
   
   This PR adds an optional, capped retry:
   
   - `gateway.ldap.backend.password.alias.retry.attempts` (default `0`, no 
retry): how many more times to look up an alias that is missing.
   - `gateway.ldap.backend.password.alias.retry.interval.ms` (default `1000`): 
the delay between lookups.
   
   Details:
   - All missing aliases are retried together, so the LDAP service waits at 
most attempts × interval while starting or reloading. Each retry is logged at 
WARN. The ERROR is logged only once the retries are exhausted.
   - Only missing aliases (a `null` lookup result) are retried. An 
`AliasServiceException`, such as a broken or unreachable store, is still 
reported right away. Retrying would only delay a permanent error and break the 
attempts × interval bound for remote alias services.
   - The Knox CLI never retries. `CLIGatewayServices` also starts the LDAP 
service, so without this, every `knoxcli` command would stall for the whole 
retry window. That includes the `create-alias` that provides the missing alias. 
The CLI passes `KnoxLDAPService.DISABLE_PASSWORD_ALIAS_RETRY_OPTION` to the 
LDAP service only.
   - Docs: `knox-site/docs/service_ldap_server.md` describes the new properties 
and the behavior.
   
   ## How was this patch tested?
   
   - Unit tests in `KnoxLDAPServerManagerTest`: no retry by default; resolved 
on a later attempt, with retries stopping as soon as the alias resolves; alias 
left unresolved after the retries run out.
     - The tests count lookups explicitly, because EasyMock nice mocks don't 
fail on calls beyond `once()` or `times(n)`.
   - New unit test 
`KnoxLDAPServiceTest.testPasswordAliasRetryDisabledByOption`: with the CLI 
option set, the alias is looked up exactly once even though retries are 
configured. I confirmed it fails (4 lookups) without the option.
   - `mvn -pl gateway-server verify` passes, including checkstyle and PMD.
   - Docker Compose integration tests: all 127 tests pass locally.
   
   ## Integration Tests
   
   The CI stack already references 
`${ALIAS=gateway_ldap_demoldap_system_password}` for the demo LDAP backend. 
This PR uses it to reproduce the race:
   
   - `.github/workflows/build/gateway-site.xml`: enables the retry with 30 
attempts, 1000 ms apart.
   - `.github/workflows/build/gateway.sh`: when the retry is configured, the 
alias is no longer created before Knox starts. A background watcher waits for 
Knox's retry WARN in `gateway.log` and only then runs `knoxcli create-alias`. 
Compose variants that mount their own `gateway-site.xml` keep the old behavior 
of creating the alias upfront.
   - `.github/workflows/compose/docker-compose.yml`: mounts the Knox logs 
read-only into the `tests` container.
   - New `test_knox_ldap_backend_password_alias_retry.py`: reads the latest 
gateway run from `gateway.log` and checks that the alias lookup was retried and 
that it never logged the final "not found" ERROR.
   - `test_knox_ldap_proxy_search.py`: its searches bind with the password from 
the late-created alias, so they now prove end to end that the retry picked it 
up. Its docstring notes this.
   




Issue Time Tracking
-------------------

            Worklog Id:     (was: 1047297)
    Remaining Estimate: 0h
            Time Spent: 10m

> Retry unresolved credential-store aliases for LDAP proxy backend passwords
> --------------------------------------------------------------------------
>
>                 Key: KNOX-3513
>                 URL: https://issues.apache.org/jira/browse/KNOX-3513
>             Project: Apache Knox
>          Issue Type: Improvement
>          Components: Server
>    Affects Versions: 3.1.0
>            Reporter: Sandor Molnar
>            Assignee: Sandor Molnar
>            Priority: Major
>             Fix For: 3.1.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> Since KNOX-3497, {{KnoxLDAPServerManager#resolveBackendPasswordAliases}} 
> resolves {{S\{ALIAS=…} / ${ALIAS=…}}} in {{{}bindPassword{}}}, 
> {{systemPassword}} and {{trustStorePassword}} exactly once, when the 
> interceptors are built. If the alias isn't in the gateway credential store 
> yet, Knox logs "{{{}No value found in the gateway credential store for alias 
> …",{}}} keeps the raw reference, and backend binds fail with 
> {{INVALID_CREDENTIALS}} until something triggers a reload.
> This happens in Kubernetes when the Secret and the CR are created together 
> and Knox is already running. Knox reloads the CR 1–10s after it's synced, but 
> the operator persists the alias about 4–5s after the Secret is created. So 
> Knox often looks up the alias before it exists, and nothing makes it look 
> again.
> *Proposal*
> When an alias lookup returns null, retry it with a cap instead of giving up 
> after the first attempt:
>  * Configurable in {{gateway-site.xml.}} Suggested defaults: 5 attempts, 2s 
> delay.
>  * Each retry must read the current credential store, not a cached negative 
> result.
>  * Log each retry at {{{}WARN{}}}. Log {{ERROR}} only after the last attempt 
> fails, then fall back to today's behaviour.
>  * Retries *must not block* gateway startup or reloads of other interceptors.
>  * Literal (non-alias) values are unchanged.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to