This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git
The following commit(s) were added to refs/heads/main by this push:
new 90356d4 Show user SSH keys and advice next to each rsync command
90356d4 is described below
commit 90356d4eee023a78ef52632949184e965edf140a
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu May 1 17:13:26 2025 +0100
Show user SSH keys and advice next to each rsync command
---
atr/routes/compose.py | 7 +++++++
atr/routes/finish.py | 9 ++++++++-
atr/routes/upload.py | 9 ++++++++-
atr/templates/check-selected.html | 3 ++-
atr/templates/finish-selected.html | 4 +++-
atr/templates/keys-review.html | 2 +-
atr/templates/upload-selected.html | 4 +++-
atr/templates/user-ssh-keys.html | 31 +++++++++++++++++++++++++++++++
8 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/atr/routes/compose.py b/atr/routes/compose.py
index 114e395..26a7a2e 100644
--- a/atr/routes/compose.py
+++ b/atr/routes/compose.py
@@ -16,6 +16,7 @@
# under the License.
import re
+from typing import TYPE_CHECKING
import quart
import werkzeug.wrappers.response as response
@@ -29,6 +30,9 @@ import atr.routes as routes
import atr.routes.draft as draft
import atr.util as util
+if TYPE_CHECKING:
+ from collections.abc import Sequence
+
async def check(
session: routes.CommitterSession,
@@ -45,6 +49,7 @@ async def check(
path_successes = {}
path_warnings = {}
path_errors = {}
+ user_ssh_keys: Sequence[models.SSHKey] = []
for path in paths:
# Get template and substitutions
@@ -78,6 +83,7 @@ async def check(
path_errors[path] = await data.check_result(
release_name=release.name, primary_rel_path=str(path),
status=models.CheckResultStatus.FAILURE
).all()
+ user_ssh_keys = await data.ssh_key(asf_uid=session.uid).all()
revision_name_from_link, revision_editor, revision_time = await
revision.latest_info(
release.project.name, release.version
@@ -112,6 +118,7 @@ async def check(
delete_file_form=delete_file_form,
asf_id=session.uid,
server_domain=session.host,
+ user_ssh_keys=user_ssh_keys,
format_datetime=routes.format_datetime,
models=models,
task_mid=task_mid,
diff --git a/atr/routes/finish.py b/atr/routes/finish.py
index 29e6fd4..b6ad452 100644
--- a/atr/routes/finish.py
+++ b/atr/routes/finish.py
@@ -29,6 +29,7 @@ import atr.revision as revision
import atr.routes as routes
import atr.routes.root as root
import atr.util as util
+from atr import db
_LOGGER: Final = logging.getLogger(__name__)
@@ -56,7 +57,12 @@ async def selected(session: routes.CommitterSession,
project_name: str, version_
"""Finish a release preview."""
await session.check_access(project_name)
- release = await session.release(project_name, version_name,
phase=models.ReleasePhase.RELEASE_PREVIEW)
+ async with db.session() as data:
+ release = await session.release(
+ project_name, version_name,
phase=models.ReleasePhase.RELEASE_PREVIEW, data=data
+ )
+ user_ssh_keys = await data.ssh_key(asf_uid=session.uid).all()
+
current_revision_dir = util.release_directory(release)
file_paths_rel: list[pathlib.Path] = []
unique_dirs: set[pathlib.Path] = {pathlib.Path(".")}
@@ -91,6 +97,7 @@ async def selected(session: routes.CommitterSession,
project_name: str, version_
file_paths=sorted(file_paths_rel),
form=form,
can_move=can_move,
+ user_ssh_keys=user_ssh_keys,
)
diff --git a/atr/routes/upload.py b/atr/routes/upload.py
index 0733619..d74da4e 100644
--- a/atr/routes/upload.py
+++ b/atr/routes/upload.py
@@ -26,6 +26,7 @@ import werkzeug.datastructures as datastructures
import werkzeug.wrappers.response as response
import wtforms
+import atr.db as db
import atr.revision as revision
import atr.routes as routes
import atr.routes.compose as compose
@@ -96,15 +97,21 @@ async def selected(session: routes.CommitterSession,
project_name: str, version_
await quart.flash(f"Error adding file: {e!s}", "error")
svn_form = await SvnImportForm.create_form()
- release = await session.release(project_name, version_name)
+
+ async with db.session() as data:
+ release = await session.release(project_name, version_name, data=data)
+ user_ssh_keys = await data.ssh_key(asf_uid=session.uid).all()
return await quart.render_template(
"upload-selected.html",
asf_id=session.uid,
server_domain=session.host,
release=release,
+ project_name=project_name,
+ version_name=version_name,
form=form,
svn_form=svn_form,
+ user_ssh_keys=user_ssh_keys,
)
diff --git a/atr/templates/check-selected.html
b/atr/templates/check-selected.html
index a9bb04c..230eace 100644
--- a/atr/templates/check-selected.html
+++ b/atr/templates/check-selected.html
@@ -329,9 +329,10 @@
<h2 id="rsync-download">Rsync download</h2>
<p>You can download the files in this release using rsync with the following
command:</p>
<!-- TODO: Add a button to copy the command to the clipboard -->
- <pre class="bg-light p-3 mb-0">
+ <pre class="bg-light p-3 mb-3">
rsync -av -e 'ssh -p 2222' {{ asf_id }}@{{ server_domain }}:/{{
release.project.name }}/{{ release.version }}/ ${DOWNLOAD_PATH}/
</pre>
+ {% include "user-ssh-keys.html" %}
{% endblock content %}
diff --git a/atr/templates/finish-selected.html
b/atr/templates/finish-selected.html
index 99a0d36..6fe03c7 100644
--- a/atr/templates/finish-selected.html
+++ b/atr/templates/finish-selected.html
@@ -103,9 +103,11 @@
<h2 id="rsync-download">Rsync download</h2>
<p>You can download the files in this release using rsync with the following
command:</p>
<!-- TODO: Add a button to copy the command to the clipboard -->
- <pre class="bg-light p-3 mb-0">
+ <pre class="bg-light p-3 mb-3">
rsync -av -e 'ssh -p 2222' {{ asf_id }}@{{ server_domain }}:/{{
release.project.name }}/{{ release.version }}/ ${DOWNLOAD_PATH}/
</pre>
+ {% include "user-ssh-keys.html" %}
+
{% endblock content %}
{% block javascripts %}
diff --git a/atr/templates/keys-review.html b/atr/templates/keys-review.html
index ec7cde3..e3bc453 100644
--- a/atr/templates/keys-review.html
+++ b/atr/templates/keys-review.html
@@ -120,7 +120,7 @@
<div class="mb-5 p-4 bg-light rounded">
<div class="d-grid gap-4">
{% for key in user_ssh_keys %}
- <div class="card p-3 border">
+ <div id="ssh-key-{{ key.fingerprint }}" class="card p-3 border">
<table class="mb-0">
<tbody>
<tr>
diff --git a/atr/templates/upload-selected.html
b/atr/templates/upload-selected.html
index dcf144b..24766fd 100644
--- a/atr/templates/upload-selected.html
+++ b/atr/templates/upload-selected.html
@@ -135,7 +135,9 @@
<h2 id="rsync-upload">Rsync upload</h2>
<p>Import files from a remote server using rsync with the following
command:</p>
<!-- TODO: Add a button to copy the command to the clipboard -->
- <pre class="bg-light p-3 mb-0">
+ <pre class="bg-light p-3 mb-3">
rsync -av -e 'ssh -p 2222' ${YOUR_FILES}/ {{ asf_id }}@{{ server_domain }}:/{{
release.project.name }}/{{ release.version }}/
</pre>
+ {% include "user-ssh-keys.html" %}
+
{% endblock content %}
diff --git a/atr/templates/user-ssh-keys.html b/atr/templates/user-ssh-keys.html
new file mode 100644
index 0000000..756cf44
--- /dev/null
+++ b/atr/templates/user-ssh-keys.html
@@ -0,0 +1,31 @@
+{% set key_count = user_ssh_keys|length %}
+{# TODO: Abstract this and the section in finish-selected.html to a common
include or macro #}
+<div class="card bg-warning-subtle mb-3">
+ <div class="card-body p-3">
+ <p>
+ {% if key_count == 0 %}
+ We have no SSH keys on file for you, so you cannot yet use this
command. Please <a href="{{ as_url(routes.keys.ssh_add) }}">add an SSH key</a>.
+ {% elif key_count == 1 %}
+ {% set key = user_ssh_keys[0] %}
+ {% set key_parts = key.key.split(' ', 2) %}
+ {% set key_comment = key_parts[2] if key_parts|length > 2 else 'key' %}
+ We have the SSH key <a href="{{ as_url(routes.keys.keys,
_anchor='ssh-key-' + key.fingerprint) }}"
+ title="{{ key.fingerprint }}"><code>{{- key_comment | trim -}}</code></a>
on file for you. You can also <a href="{{ as_url(routes.keys.ssh_add) }}">add
another SSH key</a>.
+ {% else %}
+ We have the SSH keys
+ {% for key in user_ssh_keys %}
+ {% if loop.last and key_count > 1 %}and{% endif %}
+ {% set key_parts = key.key.split(' ', 2) %}
+ {% set key_comment = key_parts[2] if key_parts|length > 2 else 'key'
%}
+ <a href="{{ as_url(routes.keys.keys, _anchor='ssh-key-' +
key.fingerprint) }}"
+ title="{{ key.fingerprint }}"><code>{{- key_comment | trim
-}}</code></a>
+ {% if not loop.last %},{% endif %}
+ {% endfor %}
+ on file for you. You can also <a href="{{ as_url(routes.keys.ssh_add)
}}">add another SSH key</a>.
+ {% endif %}
+ </p>
+ <p class="mb-0">
+ The ATR server should be compatible with long obsolete versions of
rsync, as long as you use the command as shown, but as of May 2025 the only
rsync version line without <a
href="https://github.com/google/security-research/security/advisories/GHSA-p5pg-x43v-mvqj">known
CVEs</a> is 3.4.*. Your package manager may have backports.
+ </p>
+ </div>
+</div>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]