mmdebstrap: support for user credentials for apt sources

Message ID 20251121042931.3520717-1-cedric.hombourger@siemens.com
State Under Review
Headers show
Series mmdebstrap: support for user credentials for apt sources | expand

Commit Message

Cedric Hombourger Nov. 21, 2025, 4:29 a.m. UTC
Some organization may restrict access to their package feeds and require
users to supply a user and password/token. With Isar having adopted
mmdebstrap, we may now supply an apt auth configuration file in
/etc/apt/auth.conf.d/. Credentials may be specified in local.conf (a kas
configuration fragment with environment variables may be used). Multiple
remotes and their respective credentials may be listed:

    ISAR_APT_CREDS += "apt.server1.com"
    ISAR_APT_CREDS_apt.server1.com = "my-user-for-server1 pass-for-server1"

    ISAR_APT_CREDS += "apt.server2.com"
    ISAR_APT_CREDS_apt.server2.com = "another-user-for-server2 different-pass"

Signed-off-by: Cedric Hombourger <cedric.hombourger@siemens.com>
---
 RECIPE-API-CHANGELOG.md                       | 18 ++++++++++
 doc/user_manual.md                            | 10 ++++++
 .../isar-mmdebstrap/isar-mmdebstrap.inc       | 34 +++++++++++++++++++
 3 files changed, 62 insertions(+)

Patch

diff --git a/RECIPE-API-CHANGELOG.md b/RECIPE-API-CHANGELOG.md
index 20183a8d..ede375fa 100644
--- a/RECIPE-API-CHANGELOG.md
+++ b/RECIPE-API-CHANGELOG.md
@@ -866,3 +866,21 @@  INITRD_IMAGE is "only" deprecated; meaning that it may still be used (but
 build-time warnings will be raised). If both IMAGE_INITRD and INITRD_IMAGE
 are set then the latter will be ignored (a warning noting that both were
 set will be emitted).
+
+### User-authentification for apt sources
+
+Some organization may restrict access to their package feeds and require
+users to supply a user and password/token. With Isar having adopted
+mmdebstrap, we may now supply an apt auth configuration file in
+/etc/apt/auth.conf.d/. Credentials may be specified in local.conf (a kas
+configuration fragment with environment variables may be used). Multiple
+remotes and their respective credentials may be listed:
+
+    ISAR_APT_CREDS += "apt.server1.com"
+    ISAR_APT_CREDS_apt.server1.com = "my-user-for-server1 pass-for-server1"
+
+    ISAR_APT_CREDS += "apt.server2.com"
+    ISAR_APT_CREDS_apt.server2.com = "another-user-for-server2 different-pass"
+
+NOTE: this is not supported for the (soon-to-be-removed?) legacy bootstrap
+method (based on deboostrap)
diff --git a/doc/user_manual.md b/doc/user_manual.md
index efe65a51..30002bea 100644
--- a/doc/user_manual.md
+++ b/doc/user_manual.md
@@ -451,6 +451,7 @@  Some other variables include:
  - `ISAR_APT_SNAPSHOT_TIMESTAMP[security]` - Unix timestamp of the security distribution. Optional.
  - `ISAR_APT_SNAPSHOT_DATE` - Timestamp in upstream format (e.g. `20240702T082400Z`) of the apt snapshot. Overrides `ISAR_APT_SNAPSHOT_TIMESTAMP` if set. Otherwise, will be automatically derived from `ISAR_APT_SNAPSHOT_TIMESTAMP`
  - `ISAR_APT_SNAPSHOT_DATE[security]` - Timestamp in upstream format of the security distribution. Optional.
+ * `ISAR_APT_CREDS` - List of of remote apt servers requiring credentials (individually configured with `ISAR_APT_CREDS_server_fqdn = "user password")`
  - `THIRD_PARTY_APT_KEYS` - List of gpg key URIs used to verify apt repos for apt installation after bootstrapping.
  - `FILESEXTRAPATHS` - The default directories BitBake uses when it processes recipes are initially defined by the FILESPATH variable. You can extend FILESPATH variable by using FILESEXTRAPATHS.
  - `FILESOVERRIDES` - A subset of OVERRIDES used by the build system for creating FILESPATH. The FILESOVERRIDES variable uses overrides to automatically extend the FILESPATH variable.
@@ -540,6 +541,15 @@  DISTRO_CONFIG_SCRIPT?= "raspbian-configscript.sh"
 DISTRO_KERNELS ?= "rpi rpi2 rpi-rpfv rpi2-rpfv"
 ```
 
+If the distribution has apt sources requiring authentication, users may add the following to e.g. `local.conf`:
+
+    ```
+    ISAR_APT_CREDS += "apt.restricted-server.com"
+    ISAR_APT_CREDS_apt.restricted-server.com = "my-user-name my-password-or-token"
+    ```
+
+Consider passing these credentials via (CI-protected) environment variables and refrain from leaving your credentials in `local.conf`.
+
 For RaspiOS a different DISTRO_KERNELS list is used:
  - `kernel` - for Raspberry Pi 1, Pi Zero, Pi Zero W, and Compute Module
  - `kernel7` - for Raspberry Pi 2, Pi 3, Pi 3+, and Compute Module 3
diff --git a/meta/recipes-core/isar-mmdebstrap/isar-mmdebstrap.inc b/meta/recipes-core/isar-mmdebstrap/isar-mmdebstrap.inc
index b2de61ad..d88628ac 100644
--- a/meta/recipes-core/isar-mmdebstrap/isar-mmdebstrap.inc
+++ b/meta/recipes-core/isar-mmdebstrap/isar-mmdebstrap.inc
@@ -74,6 +74,39 @@  do_generate_keyrings() {
 }
 addtask generate_keyrings before do_build after do_unpack
 
+# Generate an apt configuration file holding credentials for the apt sources
+# requiring user authentication
+do_generate_auth_file[vardeps] += "ISAR_APT_CREDS"
+python do_generate_auth_file() {
+    creds = d.getVar('ISAR_APT_CREDS') or ''
+    auth_file = os.path.join(d.getVar('WORKDIR'), 'apt-auth')
+    if not creds:
+        if os.path.exists(auth_file):
+            os.unlink(auth_file)
+        return
+
+    with open(auth_file, "w") as f:
+        for machine in creds.split():
+            user_password = d.getVar(f"ISAR_APT_CREDS_{machine}")
+            try:
+                user, passwd = user_password.split()
+                f.write(f"machine {machine}\n"
+                        f"  user {user}\n"
+                        f"  password {passwd}\n")
+            except ValueError:
+                bb.fatal(f"Too few/many tokens in ISAR_APT_CREDS['{machine}']: "
+                         f"user and password expected (got '{user_password}')!")
+}
+addtask generate_auth_file before do_bootstrap after do_unpack
+
+def get_apt_auth_opts(d):
+    creds = d.getVar('ISAR_APT_CREDS') or ''
+    workdir = d.getVar('WORKDIR')
+    if creds:
+        return "--setup-hook='mkdir -p \"$1/etc/apt/auth.conf.d\"' " + \
+               f"--setup-hook='upload \"{workdir}/apt-auth\" /etc/apt/auth.conf.d/isar.conf'"
+    return ''
+
 do_bootstrap[vardeps] += " \
     DISTRO_APT_PREMIRRORS \
     ISAR_ENABLE_COMPAT_ARCH \
@@ -189,6 +222,7 @@  do_bootstrap() {
                    $arch_param \
                    --mode=unshare \
                    ${MMHOOKS} \
+                   ${@get_apt_auth_opts(d)} \
                    --setup-hook='mkdir -p "$1/var/cache/apt/archives/"' \
                    --setup-hook="$extra_setup" \
                    --setup-hook='upload "${APTPREFS}" /etc/apt/preferences.d/bootstrap' \