asf-tooling commented on issue #651:
URL: 
https://github.com/apache/tooling-trusted-releases/issues/651#issuecomment-4407563756

   <!-- gofannon-issue-triage-bot v2 -->
   
   **Automated triage** — analyzed at `main@751c2146`
   
   **Type:** `bug_fix`  •  **Classification:** `actionable`  •  **Confidence:** 
`high`
   **Application domain(s):** `authentication_authorization`, 
`announcements_reporting`
   
   ### Summary
   The issue requested SVN credentials for ATR to commit to dist/release. 
Infrastructure has set up the `atr-svn-rw` service account (confirmed by @sbp 
on 2026-04-10, who tested by adding a README). The remaining work is to fix the 
existing `commit()` function in `atr/svn/__init__.py` to use the proxy commit 
pattern: authenticate as the service account (`atr-svn-rw`) and pass the actual 
committer's UID via `--with-revprop asf:uid=<UID>`. Currently, the code 
incorrectly uses the committer's username directly for `--username` 
authentication, and does not set `asf:uid` revprop.
   
   ### Where this lives in the code today
   
   #### `atr/svn/__init__.py` — `commit` (lines 94-115)
   _needs modification_
   Uses committer UID as --username for authentication, but proxy commits 
require the service account for auth and the committer UID in a revprop.
   
   ```python
   async def commit(path: pathlib.Path, url: str, username: str, revision: str, 
message: str) -> str:
       log.debug(f"running svn commit for user '{username}' to '{url}'")
       # The username here is the ASF UID of the committer
       svn_token = config.get().SVN_TOKEN
       if svn_token is None:
           raise ValueError("SVN_TOKEN must be set")
       return await _run_svnmucc_command(
           "put",
           str(path),
           url,
           "--username",
           username,
           "--password",
           svn_token,
           "--non-interactive",
           "--with-revprop",
           f"asf:tool={_ASF_TOOL}",
           "-r",
           revision,
           "-m",
           message,
       )
   ```
   
   #### `atr/svn/__init__.py` — `get_diff` (lines 118-126)
   _needs modification_
   Uses literal 'atr' as username for SVN auth; should use the service account 
username from config.
   
   ```python
   async def get_diff(path: pathlib.Path, revision: int) -> str:
       log.debug(f"running svn diff for '{path}': r{revision}")
       svn_token = config.get().SVN_TOKEN
       if svn_token is None:
           raise ValueError("SVN_TOKEN must be set")
       # TODO: Or omit username entirely?
       return await _run_svn_command(
           "diff", str(path), "-c", str(revision), "--username", _ASF_TOOL, 
"--password", svn_token
       )
   ```
   
   #### `atr/svn/__init__.py` — `get_log` (lines 129-137)
   _needs modification_
   Same issue as get_diff - uses 'atr' as username instead of the service 
account.
   
   ```python
   async def get_log(path: pathlib.Path) -> SvnLog:
       log.debug(f"running svn log for '{path}'")
       svn_token = config.get().SVN_TOKEN
       if svn_token is None:
           raise ValueError("SVN_TOKEN must be set")
       # TODO: Or omit username entirely?
       log_output = await _run_svn_command("log", str(path), "--xml", 
"--username", _ASF_TOOL, "--password", svn_token)
       root = ElementTree.fromstring(log_output)
       return SvnLog.from_xml_tree(root)
   ```
   
   #### `atr/svn/commits.py` — `handle` (lines 34-39)
   _currently does this_
   Handles PubSub notifications for SVN commits - related infrastructure for 
the dist repo integration.
   
   ```python
   async def handle(payload: dict, working_copy_root: pathlib.Path) -> None:
       pubsub_path = str(payload.get("pubsub_path", ""))
       # Ignore commits outside dist/dev or dist/release
       if pubsub_path.startswith(_WATCHED_PREFIXES):
           log.debug(f"PubSub payload: {payload}")
           await _process_payload(payload, working_copy_root)
   ```
   
   ### Where new code would go
   - `atr/config.py` — near SVN_TOKEN definition
     A new SVN_USERNAME config option is needed to store the service account 
name (atr-svn-rw), complementing the existing SVN_TOKEN.
   
   ### Proposed approach
   The fix involves two changes: (1) Add an `SVN_USERNAME` config option for 
the service account name (`atr-svn-rw`), and (2) Modify the `commit()` function 
to authenticate as the service account and pass the actual committer's UID via 
`--with-revprop asf:uid=<UID>` for proxy commit attribution. The `get_diff` and 
`get_log` functions should also be updated to use the service account username 
from config rather than the literal `_ASF_TOOL` string.
   
   This follows the proxy commit pattern discussed by @sbp (who mentioned 
needing `asf:uid=<UID>` and `asf:tool=atr` revprops, as BAT does), and 
@dave2wave (who confirmed the approach). The `roleaccount_hooks.lua` inclusion 
for `atr-svn-rw` was also requested in INFRA-27688, which has been completed.
   
   ### Suggested patches
   
   #### `atr/svn/__init__.py`
   Fix commit() to use service account auth with proxy commit revprops, and fix 
get_diff/get_log to use service account username from config.
   
   ````diff
   --- a/atr/svn/__init__.py
   +++ b/atr/svn/__init__.py
   @@ -71,17 +71,22 @@
    
    
    async def commit(path: pathlib.Path, url: str, username: str, revision: 
str, message: str) -> str:
   -    log.debug(f"running svn commit for user '{username}' to '{url}'")
   -    # The username here is the ASF UID of the committer
   +    log.debug(f"running svn commit on behalf of '{username}' to '{url}'")
   +    # The username here is the ASF UID of the committer, used for proxy 
commit attribution
        svn_token = config.get().SVN_TOKEN
        if svn_token is None:
            raise ValueError("SVN_TOKEN must be set")
   +    svn_username = config.get().SVN_USERNAME  # TODO: confirm this config 
attribute exists
   +    if svn_username is None:
   +        raise ValueError("SVN_USERNAME must be set")
        return await _run_svnmucc_command(
            "put",
            str(path),
            url,
            "--username",
   -        username,
   +        svn_username,
            "--password",
            svn_token,
            "--non-interactive",
   +        "--with-revprop",
   +        f"asf:uid={username}",
            "--with-revprop",
            f"asf:tool={_ASF_TOOL}",
            "-r",
   @@ -93,16 +98,20 @@
    
    async def get_diff(path: pathlib.Path, revision: int) -> str:
        log.debug(f"running svn diff for '{path}': r{revision}")
        svn_token = config.get().SVN_TOKEN
        if svn_token is None:
            raise ValueError("SVN_TOKEN must be set")
   -    # TODO: Or omit username entirely?
   -    return await _run_svn_command(
   -        "diff", str(path), "-c", str(revision), "--username", _ASF_TOOL, 
"--password", svn_token
   -    )
   +    svn_username = config.get().SVN_USERNAME  # TODO: confirm this config 
attribute exists
   +    if svn_username is None:
   +        raise ValueError("SVN_USERNAME must be set")
   +    return await _run_svn_command(
   +        "diff", str(path), "-c", str(revision), "--username", svn_username, 
"--password", svn_token
   +    )
    
    
    async def get_log(path: pathlib.Path) -> SvnLog:
        log.debug(f"running svn log for '{path}'")
        svn_token = config.get().SVN_TOKEN
        if svn_token is None:
            raise ValueError("SVN_TOKEN must be set")
   -    # TODO: Or omit username entirely?
   -    log_output = await _run_svn_command("log", str(path), "--xml", 
"--username", _ASF_TOOL, "--password", svn_token)
   +    svn_username = config.get().SVN_USERNAME  # TODO: confirm this config 
attribute exists
   +    if svn_username is None:
   +        raise ValueError("SVN_USERNAME must be set")
   +    log_output = await _run_svn_command("log", str(path), "--xml", 
"--username", svn_username, "--password", svn_token)
        root = ElementTree.fromstring(log_output)
        return SvnLog.from_xml_tree(root)
   ````
   
   ### Open questions
   - Does `atr/config.py` already have an `SVN_USERNAME` attribute, or does it 
need to be added? The existing code only references `SVN_TOKEN`.
   - Should the `asf:uid` revprop be omitted when the committer IS a PMC member 
with direct commit access (per @dave2wave's note that proxy is only needed for 
non-PMC members in certain groups)?
   - Has the eyaml at 
`infrastructure-p6/data/nodes/tooling-vm-ec2-de.apache.org.eyaml` been updated 
with the credentials, or is that still pending?
   - The roleaccount_hooks.lua inclusion for `atr-svn-rw` (INFRA-27688) - has 
this been confirmed as completed alongside the account setup?
   
   ### Files examined
   - `atr/svn/__init__.py`
   - `atr/principal.py`
   - `atr/tasks/svn.py`
   - `atr/ssh.py`
   - `atr/svn/commits.py`
   - `atr/storage/writers/ssh.py`
   - `atr/ldap.py`
   - `atr/sessions.py`
   
   ---
   *Draft from a triage agent. A human reviewer should validate before merging 
any change. The agent did not run tests or verify diffs apply.*


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to