Compare commits
5 Commits
| Author | SHA256 | Date | |
|---|---|---|---|
|
85ff080b40
|
|||
|
9d3f283297
|
|||
|
74897d85b1
|
|||
|
9ef535554a
|
|||
|
800cd175fc
|
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 🔐 Generating a Private Live ISO TRIXIE.
|
name: 🔐 Generating a Private Live ISO TRIXIE.
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 🔐 Generating a Private Live ISO TRIXIE.
|
name: 🔐 Generating a Private Live ISO TRIXIE.
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 💙 Generating a PUBLIC Live ISO.
|
name: 💙 Generating a PUBLIC Live ISO.
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: "Version"
|
label: "Version"
|
||||||
description: "Which version are you running? Use `./ciss_live_builder.sh -v`."
|
description: "Which version are you running? Use `./ciss_live_builder.sh -v`."
|
||||||
placeholder: "e.g., Master V9.14.020.2026.06.08"
|
placeholder: "e.g., Master V9.14.022.2026.06.10"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
FROM debian:bookworm
|
FROM debian:bookworm
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 🔁 Render README.md to README.html.
|
name: 🔁 Render README.md to README.html.
|
||||||
|
|
||||||
|
|||||||
@@ -11,5 +11,5 @@
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
counter: 1023
|
counter: 1023
|
||||||
version: V9.14.020.2026.06.08
|
version: V9.14.022.2026.06.10
|
||||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
|
||||||
|
|||||||
@@ -11,5 +11,5 @@
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
counter: 1023
|
counter: 1023
|
||||||
version: V9.14.020.2026.06.08
|
version: V9.14.022.2026.06.10
|
||||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
|
||||||
|
|||||||
@@ -11,5 +11,5 @@
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
counter: 1023
|
counter: 1023
|
||||||
version: V9.14.020.2026.06.08
|
version: V9.14.022.2026.06.10
|
||||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 🔐 Generating a Private Live ISO TRIXIE.
|
name: 🔐 Generating a Private Live ISO TRIXIE.
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 🔐 Generating a Private Live ISO TRIXIE.
|
name: 🔐 Generating a Private Live ISO TRIXIE.
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 💙 Generating a PUBLIC Live ISO.
|
name: 💙 Generating a PUBLIC Live ISO.
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
# Gitea Workflow: Shell-Script Linting
|
# Gitea Workflow: Shell-Script Linting
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 🛡️ Retrieve DNSSEC status of coresecret.dev.
|
name: 🛡️ Retrieve DNSSEC status of coresecret.dev.
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
name: 🔁 Render Graphviz Diagrams.
|
name: 🔁 Render Graphviz Diagrams.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -15,5 +15,5 @@ properties_SPDX-License-Identifier="LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1 "
|
|||||||
properties_SPDX-LicenseComment="This file is part of the CISS.debian.installer.secure framework."
|
properties_SPDX-LicenseComment="This file is part of the CISS.debian.installer.secure framework."
|
||||||
properties_SPDX-PackageName="CISS.debian.live.builder"
|
properties_SPDX-PackageName="CISS.debian.live.builder"
|
||||||
properties_SPDX-Security-Contact="security@coresecret.eu"
|
properties_SPDX-Security-Contact="security@coresecret.eu"
|
||||||
properties_version="V9.14.020.2026.06.08"
|
properties_version="V9.14.022.2026.06.10"
|
||||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=conf
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Creator: Person: Marc S. Weidner (Centurion Intelligence Consulting Agency)
|
|||||||
Created: 2025-05-07T12:00:00Z
|
Created: 2025-05-07T12:00:00Z
|
||||||
Package: CISS.debian.live.builder
|
Package: CISS.debian.live.builder
|
||||||
PackageName: CISS.debian.live.builder
|
PackageName: CISS.debian.live.builder
|
||||||
PackageVersion: Master V9.14.020.2026.06.08
|
PackageVersion: Master V9.14.022.2026.06.10
|
||||||
PackageSupplier: Organization: Centurion Intelligence Consulting Agency
|
PackageSupplier: Organization: Centurion Intelligence Consulting Agency
|
||||||
PackageDownloadLocation: https://git.coresecret.dev/msw/CISS.debian.live.builder
|
PackageDownloadLocation: https://git.coresecret.dev/msw/CISS.debian.live.builder
|
||||||
PackageHomePage: https://git.coresecret.dev/msw/CISS.debian.live.builder
|
PackageHomePage: https://git.coresecret.dev/msw/CISS.debian.live.builder
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
gitea: none
|
gitea: none
|
||||||
include_toc: true
|
include_toc: true
|
||||||
---
|
---
|
||||||
[](https://git.coresecret.dev/msw/CISS.debian.live.builder)
|
[](https://git.coresecret.dev/msw/CISS.debian.live.builder)
|
||||||
|
|
||||||
[](https://eupl.eu/1.2/en/)
|
[](https://eupl.eu/1.2/en/)
|
||||||
[](https://opensource.org/license/eupl-1-2)
|
[](https://opensource.org/license/eupl-1-2)
|
||||||
@@ -27,7 +27,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
**CISS.debian.live.builder — First of its own.**<br>
|
**CISS.debian.live.builder — First of its own.**<br>
|
||||||
**World-class CIA: Designed, handcrafted, and powered by Centurion Intelligence Consulting Agency.**
|
**World-class CIA: Designed, handcrafted, and powered by Centurion Intelligence Consulting Agency.**
|
||||||
@@ -60,12 +60,15 @@ and spoofing surfaces.
|
|||||||
|
|
||||||
Internally, the builder employs a dedicated secret-handling pipeline backed by a tmpfs-only secrets directory
|
Internally, the builder employs a dedicated secret-handling pipeline backed by a tmpfs-only secrets directory
|
||||||
(`/dev/shm/cdlb_secrets`). Sensitive material such as root passwords, SSH keys, and signing keys never appears on the command
|
(`/dev/shm/cdlb_secrets`). Sensitive material such as root passwords, SSH keys, and signing keys never appears on the command
|
||||||
line, is guarded by strict `0400 root:root` permissions, and any symlink inside the secret path is treated as a hard failure
|
line, is guarded by a `0700 root:root` secret root and single-link regular `0400` or `0600` root-owned files, and any symlink
|
||||||
that aborts the run. Critical code paths temporarily disable Bash xtrace so that credentials never leak into debug logs, and
|
inside the secret path is treated as a hard failure that aborts the run. Filename-only secret arguments reject slashes and
|
||||||
transient secret files are shredded (`shred -fzu`) as soon as they are no longer needed. GNUPG homes used for signing are
|
traversal.
|
||||||
wiped, unencrypted chroot artifacts and includes are removed after `lb build`, and the final artifact is reduced to the
|
Critical code paths temporarily disable Bash xtrace, and a final exact-value debug-log sanitisation pass provides additional
|
||||||
encrypted SquashFS inside the LUKS2 container. At runtime, LUKS passphrases in the live ISO and installer are transported via
|
defence in depth. Transient secret files are shredded (`shred -fzu`) as soon as they are no longer needed, but this is only a
|
||||||
named pipes inside the initramfs instead of process arguments, further minimizing exposure in process listings.
|
best-effort cleanup on SSD, NVMe, copy-on-write, journaled, and virtualised storage. Use tmpfs for secrets and encrypted storage
|
||||||
|
for build workspaces. Destructive build cleanup is restricted to the exact canonical directory carrying the
|
||||||
|
`.ciss-live-builder-owned` marker. This private operator workflow still requires strict local path validation; it does not
|
||||||
|
define public ISO release policy.
|
||||||
|
|
||||||
Check out more leading world-class services powered by Centurion Intelligence Consulting Agency:
|
Check out more leading world-class services powered by Centurion Intelligence Consulting Agency:
|
||||||
* [CenturionDNS Resolver](https://eddns.eu/)
|
* [CenturionDNS Resolver](https://eddns.eu/)
|
||||||
@@ -175,7 +178,7 @@ installer toolchain.
|
|||||||
|
|
||||||
This project adheres strictly to a structured versioning scheme following the pattern x.y.z-Date.
|
This project adheres strictly to a structured versioning scheme following the pattern x.y.z-Date.
|
||||||
|
|
||||||
Example: `V9.14.020.2026.06.08`
|
Example: `V9.14.022.2026.06.10`
|
||||||
|
|
||||||
`x.y.z` represents major (x), minor (y), and patch (z) version increments.
|
`x.y.z` represents major (x), minor (y), and patch (z) version increments.
|
||||||
|
|
||||||
@@ -365,6 +368,11 @@ For further details see: **[90-ciss-local.hardened.md](docs/documentation/90-cis
|
|||||||
## 2.9. UFW Hardening
|
## 2.9. UFW Hardening
|
||||||
|
|
||||||
* **Description**: Defaults to `deny incoming` and (optionally) `deny outgoing`; automatically opens only whitelisted ports.
|
* **Description**: Defaults to `deny incoming` and (optionally) `deny outgoing`; automatically opens only whitelisted ports.
|
||||||
|
* **Primordial SSH exception**: `--primordial-url <https-git-url>`, `--primordial-key <ssh-identity-filename>` and
|
||||||
|
`--primordial-ssh <port>` configure the CDI Primordial overlay clone. `--primordial-ssh` also adds an outgoing-only UFW TCP
|
||||||
|
exception for a bootstrap/recovery SSH port when the live system's UFW outgoing policy is `deny`. It adds no incoming firewall
|
||||||
|
rule and does not replace `--ssh-port`. If the requested port already matches an existing outgoing SSH exception, the current
|
||||||
|
hook still emits the requested labelled rule because this repository has no separate UFW rule deduplication layer.
|
||||||
* **Rationale**: Implements a default-deny firewall, reducing lateral movement and data exfiltration risks immediately after
|
* **Rationale**: Implements a default-deny firewall, reducing lateral movement and data exfiltration risks immediately after
|
||||||
deployment.
|
deployment.
|
||||||
|
|
||||||
@@ -488,10 +496,14 @@ To use **``CISS.debian.live.builder``** as intended, the following baseline is e
|
|||||||
|
|
||||||
2. Preparation:
|
2. Preparation:
|
||||||
1. Ensure you are root.
|
1. Ensure you are root.
|
||||||
2. Create the build directory `mkdir /opt/cdlb` and the tmpfs secrets directory `mkdir /dev/shm/cdlb_secrets`.
|
2. Create the empty build directory with `install -d -m 0700 -o root -g root /opt/cdlb`.
|
||||||
3. Place your desired SSH public key in the `authorized_keys` file, for example, in the `/dev/shm/cdlb_secrets` directory.
|
3. Create the tmpfs secret root with `install -d -m 0700 -o root -g root /dev/shm/cdlb_secrets`.
|
||||||
4. Place your desired Password in the `password.txt` file, for example, in the `/dev/shm/cdlb_secrets` directory.
|
4. Place required secret files in the secret root as single-link regular, non-symlink, root-owned files with mode `0400`
|
||||||
5. Make any other changes you need to.
|
or `0600`.
|
||||||
|
5. Place your desired SSH public key in `/dev/shm/cdlb_secrets/authorized_keys`.
|
||||||
|
6. Place your desired root password in `/dev/shm/cdlb_secrets/password.txt`.
|
||||||
|
7. Use filename-only values without slashes, `.` or `..` for `--key_age`, `--key_luks`, and signing-file arguments.
|
||||||
|
8. Make any other changes you need to.
|
||||||
|
|
||||||
3. Run the config builder script `./ciss_live_builder.sh` and the integrated `lb build` command (example):
|
3. Run the config builder script `./ciss_live_builder.sh` and the integrated `lb build` command (example):
|
||||||
|
|
||||||
@@ -520,6 +532,9 @@ To use **``CISS.debian.live.builder``** as intended, the following baseline is e
|
|||||||
--signing_key_pass=signing_key_pass.txt \
|
--signing_key_pass=signing_key_pass.txt \
|
||||||
--signing_key=signing_key.asc \
|
--signing_key=signing_key.asc \
|
||||||
--ssh-port 4242 \
|
--ssh-port 4242 \
|
||||||
|
--primordial-url https://git.coresecret.dev/ahz/PhysNet.primordial.git \
|
||||||
|
--primordial-key id--git.coresecret.dev--PhysNet.primordial_deploy--ed25519--newton--2025-10 \
|
||||||
|
--primordial-ssh 42842 \
|
||||||
--ssh-pubkey /dev/shm/cdlb_secrets \
|
--ssh-pubkey /dev/shm/cdlb_secrets \
|
||||||
--sshfp \
|
--sshfp \
|
||||||
--trixie
|
--trixie
|
||||||
@@ -530,6 +545,10 @@ To use **``CISS.debian.live.builder``** as intended, the following baseline is e
|
|||||||
both the newer Sigstore bundle asset, and the legacy-split certificate/signature assets before checking the downloaded
|
both the newer Sigstore bundle asset, and the legacy-split certificate/signature assets before checking the downloaded
|
||||||
SOPS binary with `sha256sum -c --ignore-missing`.
|
SOPS binary with `sha256sum -c --ignore-missing`.
|
||||||
|
|
||||||
|
On the first run, the builder creates `.ciss-live-builder-owned` in a new or empty build directory whose canonical parent
|
||||||
|
already exists. A populated directory without that marker is rejected and is never adopted automatically. Cleanup remains
|
||||||
|
intentionally destructive inside the exact validated marker-owned directory.
|
||||||
|
|
||||||
4. Locate your ISO in the `--build-directory`.
|
4. Locate your ISO in the `--build-directory`.
|
||||||
5. Boot from the ISO and login to the live image via the console, or the multi-layer secured **coresecret** SSH tunnel.
|
5. Boot from the ISO and login to the live image via the console, or the multi-layer secured **coresecret** SSH tunnel.
|
||||||
6. Type `sysp` for the final kernel hardening features.
|
6. Type `sysp` for the final kernel hardening features.
|
||||||
@@ -551,7 +570,8 @@ preview it or run it.
|
|||||||
|
|
||||||
2. Preparation:
|
2. Preparation:
|
||||||
1. Ensure you are root.
|
1. Ensure you are root.
|
||||||
2. Create the build directory `mkdir /opt/cdlb` and the tmpfs secrets directory `mkdir /dev/shm/cdlb_secrets`.
|
2. Create the empty build directory and tmpfs secret root with restrictive ownership and permissions:
|
||||||
|
`install -d -m 0700 -o root -g root /opt/cdlb /dev/shm/cdlb_secrets`.
|
||||||
3. Place your desired SSH public key in the `authorized_keys` file, for example, in the `/dev/shm/cdlb_secrets` directory.
|
3. Place your desired SSH public key in the `authorized_keys` file, for example, in the `/dev/shm/cdlb_secrets` directory.
|
||||||
4. Place your desired Password in the `password.txt` file, for example, in the `/dev/shm/cdlb_secrets` directory.
|
4. Place your desired Password in the `password.txt` file, for example, in the `/dev/shm/cdlb_secrets` directory.
|
||||||
5. Copy and edit the sample and set your options (no spaces around commas in lists):
|
5. Copy and edit the sample and set your options (no spaces around commas in lists):
|
||||||
@@ -569,6 +589,9 @@ preview it or run it.
|
|||||||
SSH_PUBKEY=/dev/shm/cdlb_secrets
|
SSH_PUBKEY=/dev/shm/cdlb_secrets
|
||||||
|
|
||||||
# Optional
|
# Optional
|
||||||
|
PRIMORDIAL_URL=https://git.coresecret.dev/ahz/PhysNet.primordial.git
|
||||||
|
PRIMORDIAL_KEY=id--git.coresecret.dev--PhysNet.primordial_deploy--ed25519--newton--2025-10
|
||||||
|
PRIMORDIAL_SSH_PORT=42842
|
||||||
PROVIDER_NETCUP_IPV6=2001:cdb::1
|
PROVIDER_NETCUP_IPV6=2001:cdb::1
|
||||||
# comma-separated; IPv6 in [] is fine
|
# comma-separated; IPv6 in [] is fine
|
||||||
JUMP_HOSTS=[2001:db8::1],[2001:db8::2]
|
JUMP_HOSTS=[2001:db8::1],[2001:db8::2]
|
||||||
@@ -645,10 +668,10 @@ The private directory is ignored by Git. The hooks fail if the CISS EFI image si
|
|||||||
#...
|
#...
|
||||||
- name: Preparing the build environment.
|
- name: Preparing the build environment.
|
||||||
run: |
|
run: |
|
||||||
mkdir -p /opt/config
|
install -d -m 0700 -o root -g root /opt/livebuild /dev/shm/cdlb_secrets
|
||||||
mkdir -p /opt/livebuild
|
umask 0077
|
||||||
echo "${{ secrets.CHANGE_ME }}" >| /opt/config/password.txt
|
printf '%s\n' "${{ secrets.CHANGE_ME }}" >| /dev/shm/cdlb_secrets/password.txt
|
||||||
echo "${{ secrets.CHANGE_ME }}" >| /opt/config/authorized_keys
|
printf '%s\n' "${{ secrets.CHANGE_ME }}" >| /dev/shm/cdlb_secrets/authorized_keys
|
||||||
#...
|
#...
|
||||||
- name: Starting CISS.debian.live.builder. This may take a while ...
|
- name: Starting CISS.debian.live.builder. This may take a while ...
|
||||||
run: |
|
run: |
|
||||||
@@ -661,9 +684,9 @@ The private directory is ignored by Git. The hooks fail if the CISS EFI image si
|
|||||||
--build-directory /opt/livebuild \
|
--build-directory /opt/livebuild \
|
||||||
--control "${timestamp}" \
|
--control "${timestamp}" \
|
||||||
--jump-host "${{ secrets.CHANGE_ME }}" \
|
--jump-host "${{ secrets.CHANGE_ME }}" \
|
||||||
--root-password-file /opt/config/password.txt \
|
--root-password-file /dev/shm/cdlb_secrets/password.txt \
|
||||||
--ssh-port CHANGE_ME \
|
--ssh-port CHANGE_ME \
|
||||||
--ssh-pubkey /opt/config
|
--ssh-pubkey /dev/shm/cdlb_secrets
|
||||||
#...
|
#...
|
||||||
### SKIP OR CHANGE ALL REMAINING STEPS
|
### SKIP OR CHANGE ALL REMAINING STEPS
|
||||||
```
|
```
|
||||||
|
|||||||
+2
-2
@@ -8,13 +8,13 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Repository Structure
|
# 2. Repository Structure
|
||||||
|
|
||||||
**Project:** Centurion Intelligence Consulting Agency Information Security Standard (CISS) — Debian Live Builder
|
**Project:** Centurion Intelligence Consulting Agency Information Security Standard (CISS) — Debian Live Builder
|
||||||
**Branch:** `master`
|
**Branch:** `master`
|
||||||
**Repository State:** Master Version **9.14**, Build **V9.14.020.2026.06.08** (as of 2025-10-11)
|
**Repository State:** Master Version **9.14**, Build **V9.14.022.2026.06.10** (as of 2025-10-11)
|
||||||
|
|
||||||
## 3.1. Top-Level Layout
|
## 3.1. Top-Level Layout
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
.:-=++***#####***+==-:.
|
||||||
|
.-=*#%%@@@@@@@@@@@@@@@@@@@@@%%#*=-.
|
||||||
|
.=*#@@@@@@@%%%%%%%%%%%%%%%%%%%%%@@@@@@@%*=:
|
||||||
|
:+#@@@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@%*=.
|
||||||
|
.+#@@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@#=:
|
||||||
|
:*%@@%%%%%%%%%%%%%%%%@@@@@@@@@@@@@%%%%%%%%%%%%%%%%@@@@%%%*=
|
||||||
|
:*@@%%%%%%%%%%%%%%@@@@@%%#*******#%%@@@@%%%%%%%%%@@%#+-:.
|
||||||
|
.+@@%%%%%%%%%%%%%%@@%#+-. .-+#%@@%%%%@@#=.
|
||||||
|
-%@%%%%%%%%%%%%%@@%*-. :-+**####**+-: .-*%@@@*:
|
||||||
|
+@@%%%%%%%%%%%%%@%+. :+#%@@@@@@@@@@@@@@%#+: .+#:
|
||||||
|
*@%%%%%%%%%%%%%%@*. =#@@@@%%%%%%%%%%%%%%@@@@#-
|
||||||
|
*@%%%%%%%%%%%%%%@- -%@@%%%%%%%%%%%%%%%%%%%%%%@@#-
|
||||||
|
+@%%%%%%%%%%%%%%@- +@@%%%%%%%%%%%%%%%%%%%%%%%%%%@@+-*#
|
||||||
|
-@%%%%%%%%%%%%%%@+ +@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@-
|
||||||
|
%%%%%%%%%%%%%%%%% :@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
-@%%%%%%%%%%%%%%@* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@=
|
||||||
|
#%%%%%%%%%%%%%%%@= *@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
.%%%%%%%%%%%%%%%%@+ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@%%%%%%%=
|
||||||
|
-@%%%%%%%%%%%%%%%@* :@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@.
|
||||||
|
=@%%%%%%%%%%%%%%%%%. #@%%%%%%%%%%%%%%%%%%%%%%%%%%%*..:--==+*-
|
||||||
|
=@%%%%%%%%%%%%%%%%@= :@%%%%%%%%%%%%%%%%%%%%%%%%%%%@#:
|
||||||
|
=@%%%%%%%%%%%%%%%%%%. +@%%%%%%%%%%%%%%%%%%%%%%%%%%%@@+
|
||||||
|
:@%%%%%%%%%%%%%%%%%@# #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@#::::.
|
||||||
|
%@%%%%%%%%%%%%%%%%%@= :@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@%#:
|
||||||
|
*%%%%%%%%%%%%%%%%%%- *@%%%%%%%%%%%%%%%@@@@%%%%%%%%%%%%%%%@@@.
|
||||||
|
:@%%%%%%%%%%%%%%%@- -@%%%%%%%%%%%%@@@%%%%%@@%%%%%%%%%%%%%%%.
|
||||||
|
*@%%%%%%%%%%%%%@+ .%%%%%%%%%%%@@*=:. .-*@%%%%%%%%%%%%@=
|
||||||
|
.%%%%%%%%%%%%%%%. .%%%%%%%%%@@*: :%%%%%%%%%%%@+
|
||||||
|
=@%%%%%%%%%%%@* -@%%%%%%%@#: =@%%%%%%%%@*
|
||||||
|
+@%%%%%%%%%%@. *@%%%%%@@+ .@%%%%%%%%%.
|
||||||
|
*@%%%%%%%%@+ -@%%%%%@%- .@%%%%%%%@=
|
||||||
|
+@%%%%%@@* :%%%%%@@*. -@%%%%%%%%
|
||||||
|
=@@@@@#- :%%%%@@%- #%%%%%%%@+
|
||||||
|
:#*+: :%%%@@%+ -@@@%%%%%@:
|
||||||
|
=@@@@#=. :+#@@@@%%.
|
||||||
|
.*%#*=. .=*%@%
|
||||||
|
::. .-+
|
||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. CISS Secure Boot Private Material
|
# 2. CISS Secure Boot Private Material
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. CISS Secure Boot Public Material
|
# 2. CISS Secure Boot Public Material
|
||||||
|
|
||||||
|
|||||||
+20
-17
@@ -111,6 +111,7 @@ source_guard "./var/bash.var.sh"
|
|||||||
### CHECK FOR CONTACT, HELP, VERSION STRING, AND XTRACE DEBUG.
|
### CHECK FOR CONTACT, HELP, VERSION STRING, AND XTRACE DEBUG.
|
||||||
for arg in "$@"; do case "${arg,,}" in -c|--contact) . ./lib/lib_contact.sh ; contact; exit 0;; esac; done
|
for arg in "$@"; do case "${arg,,}" in -c|--contact) . ./lib/lib_contact.sh ; contact; exit 0;; esac; done
|
||||||
for arg in "$@"; do case "${arg,,}" in -h|--help) . ./lib/lib_usage.sh ; usage ; exit 0;; esac; done
|
for arg in "$@"; do case "${arg,,}" in -h|--help) . ./lib/lib_usage.sh ; usage ; exit 0;; esac; done
|
||||||
|
for arg in "$@"; do case "${arg,,}" in -l|--logo) . ./lib/lib_logo.sh ; logo ; exit 0;; esac; done
|
||||||
for arg in "$@"; do case "${arg,,}" in -v|--version) . ./lib/lib_version.sh ; version; exit 0;; esac; done
|
for arg in "$@"; do case "${arg,,}" in -v|--version) . ./lib/lib_version.sh ; version; exit 0;; esac; done
|
||||||
for arg in "$@"; do case "${arg,,}" in -d|--debug) . ./meta_sources_debug.sh; debugger "${@}";; esac; done
|
for arg in "$@"; do case "${arg,,}" in -d|--debug) . ./meta_sources_debug.sh; debugger "${@}";; esac; done
|
||||||
|
|
||||||
@@ -123,22 +124,28 @@ sleep 4
|
|||||||
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
|
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
|
||||||
declare -grx VAR_SETUP="true"
|
declare -grx VAR_SETUP="true"
|
||||||
|
|
||||||
### SECURING SECRETS ARTIFACTS.
|
|
||||||
test ! -L "${VAR_TMP_SECRET}" || {
|
|
||||||
. ./var/global.var.sh
|
|
||||||
printf "\e[91m❌ Refusing symlink: '%s'! Bye... \e[0m\n" "${VAR_TMP_SECRET}" >&2
|
|
||||||
exit "${ERR_SECRETSSYM}"
|
|
||||||
}
|
|
||||||
find "${VAR_TMP_SECRET}" -type f -exec chmod 0400 {} +
|
|
||||||
find "${VAR_TMP_SECRET}" -type f -exec chown root:root {} +
|
|
||||||
|
|
||||||
### SOURCING VARIABLES.
|
### SOURCING VARIABLES.
|
||||||
[[ "${VAR_SETUP}" == true ]] && {
|
[[ "${VAR_SETUP}" == true ]] && {
|
||||||
source_guard "./var/color.var.sh"
|
source_guard "./var/color.var.sh"
|
||||||
source_guard "./var/global.var.sh"
|
source_guard "./var/global.var.sh"
|
||||||
}
|
}
|
||||||
|
|
||||||
### SOURCING LIBRARIES.
|
### SOURCE THE MINIMUM REQUIRED FOR EARLY EXIT CLEANUP COVERAGE.
|
||||||
|
[[ "${VAR_SETUP}" == true ]] && {
|
||||||
|
source_guard "./lib/lib_secret_validation.sh"
|
||||||
|
source_guard "./lib/lib_build_directory.sh"
|
||||||
|
source_guard "./lib/lib_debug_sanitizer.sh"
|
||||||
|
source_guard "./lib/lib_clean_up.sh"
|
||||||
|
source_guard "./lib/lib_trap_on_err.sh"
|
||||||
|
source_guard "./lib/lib_trap_on_exit.sh"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'trap_on_exit "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' EXIT
|
||||||
|
|
||||||
|
### Validate the fixed tmpfs secret staging area without modifying operator-provided files.
|
||||||
|
validate_secret_staging_area
|
||||||
|
|
||||||
|
### SOURCING REMAINING LIBRARIES.
|
||||||
[[ "${VAR_SETUP}" == true ]] && {
|
[[ "${VAR_SETUP}" == true ]] && {
|
||||||
source_guard "./lib/lib_arg_parser.sh"
|
source_guard "./lib/lib_arg_parser.sh"
|
||||||
source_guard "./lib/lib_arg_priority_check.sh"
|
source_guard "./lib/lib_arg_priority_check.sh"
|
||||||
@@ -157,7 +164,6 @@ find "${VAR_TMP_SECRET}" -type f -exec chown root:root {} +
|
|||||||
source_guard "./lib/lib_ciss_upgrades_boot.sh"
|
source_guard "./lib/lib_ciss_upgrades_boot.sh"
|
||||||
source_guard "./lib/lib_ciss_upgrades_build.sh"
|
source_guard "./lib/lib_ciss_upgrades_build.sh"
|
||||||
source_guard "./lib/lib_clean_screen.sh"
|
source_guard "./lib/lib_clean_screen.sh"
|
||||||
source_guard "./lib/lib_clean_up.sh"
|
|
||||||
source_guard "./lib/lib_copy_integrity.sh"
|
source_guard "./lib/lib_copy_integrity.sh"
|
||||||
source_guard "./lib/lib_gnupg.sh"
|
source_guard "./lib/lib_gnupg.sh"
|
||||||
source_guard "./lib/lib_hardening_root_pw.sh"
|
source_guard "./lib/lib_hardening_root_pw.sh"
|
||||||
@@ -173,12 +179,13 @@ find "${VAR_TMP_SECRET}" -type f -exec chown root:root {} +
|
|||||||
source_guard "./lib/lib_run_analysis.sh"
|
source_guard "./lib/lib_run_analysis.sh"
|
||||||
source_guard "./lib/lib_sanitizer.sh"
|
source_guard "./lib/lib_sanitizer.sh"
|
||||||
source_guard "./lib/lib_secureboot_profile.sh"
|
source_guard "./lib/lib_secureboot_profile.sh"
|
||||||
source_guard "./lib/lib_trap_on_err.sh"
|
|
||||||
source_guard "./lib/lib_trap_on_exit.sh"
|
|
||||||
source_guard "./lib/lib_update_microcode.sh"
|
source_guard "./lib/lib_update_microcode.sh"
|
||||||
source_guard "./lib/lib_usage.sh"
|
source_guard "./lib/lib_usage.sh"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### Add ERR handling after all remaining libraries are available.
|
||||||
|
trap 'trap_on_err "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' ERR
|
||||||
|
|
||||||
### PRE-SCAN SECURE BOOT PROFILE FOR BUILD-HOST PACKAGE CHECKS.
|
### PRE-SCAN SECURE BOOT PROFILE FOR BUILD-HOST PACKAGE CHECKS.
|
||||||
### Formal validation still happens in arg_parser().
|
### Formal validation still happens in arg_parser().
|
||||||
for ((idx=0; idx<${#ARY_PARAM_ARRAY[@]}; idx++)); do
|
for ((idx=0; idx<${#ARY_PARAM_ARRAY[@]}; idx++)); do
|
||||||
@@ -222,10 +229,6 @@ if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nInitialization done ... \nXXX\n
|
|||||||
### Updating Status of Dialog Gauge Bar.
|
### Updating Status of Dialog Gauge Bar.
|
||||||
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nActivate traps ... \nXXX\n50\n" >&3; fi
|
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nActivate traps ... \nXXX\n50\n" >&3; fi
|
||||||
|
|
||||||
### Following the CISS Bash naming and ordering scheme:
|
|
||||||
trap 'trap_on_exit "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' EXIT
|
|
||||||
trap 'trap_on_err "$?" "${BASH_SOURCE[0]}" "${LINENO}" "${FUNCNAME[0]:-main}" "${BASH_COMMAND}"' ERR
|
|
||||||
|
|
||||||
### Updating Status of Dialog Gauge Bar.
|
### Updating Status of Dialog Gauge Bar.
|
||||||
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nSanitizing Arguments ... \nXXX\n75\n" >&3; fi
|
if ! ${VAR_HANDLER_AUTOBUILD}; then printf "XXX\nSanitizing Arguments ... \nXXX\n75\n" >&3; fi
|
||||||
arg_check "$@"
|
arg_check "$@"
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ BUILD_DIR ?=
|
|||||||
DROPBEAR_VERSION ?=
|
DROPBEAR_VERSION ?=
|
||||||
### Optional SOPS release override; empty uses VAR_SOPS_VERSION from var/global.var.sh:
|
### Optional SOPS release override; empty uses VAR_SOPS_VERSION from var/global.var.sh:
|
||||||
SOPS_VERSION ?=
|
SOPS_VERSION ?=
|
||||||
|
### Optional Primordial CDI overlay settings; all three values are required for automatic overlay bootstrap:
|
||||||
|
PRIMORDIAL_URL ?=
|
||||||
|
PRIMORDIAL_KEY ?=
|
||||||
|
PRIMORDIAL_SSH_PORT ?=
|
||||||
PROVIDER_NETCUP_IPV6 ?=
|
PROVIDER_NETCUP_IPV6 ?=
|
||||||
ROOT_PASSWORD_FILE ?=
|
ROOT_PASSWORD_FILE ?=
|
||||||
### Secure Boot profile; debian-shim or ciss-uki:
|
### Secure Boot profile; debian-shim or ciss-uki:
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ printf "\e[95m🧪 '%s' starting ... \e[0m\n" "${0}"
|
|||||||
|
|
||||||
declare -r UFW_OUT_POLICY="deny"
|
declare -r UFW_OUT_POLICY="deny"
|
||||||
declare -r SSHPORT="SSHPORT_MUST_BE_SET"
|
declare -r SSHPORT="SSHPORT_MUST_BE_SET"
|
||||||
|
# PRIMORDIAL_SSH_PORT_DECLARATION_MUST_BE_SET
|
||||||
|
|
||||||
ufw --force reset
|
ufw --force reset
|
||||||
|
|
||||||
@@ -44,7 +45,8 @@ if [[ ${UFW_OUT_POLICY,,} == "deny" ]]; then
|
|||||||
ufw allow out 853/tcp comment 'Outgoing DoT'
|
ufw allow out 853/tcp comment 'Outgoing DoT'
|
||||||
ufw allow out 993/tcp comment 'Outgoing IMAPS'
|
ufw allow out 993/tcp comment 'Outgoing IMAPS'
|
||||||
ufw allow out 4460/tcp comment 'Outgoing NTS'
|
ufw allow out 4460/tcp comment 'Outgoing NTS'
|
||||||
ufw allow out "${SSHPORT}"/tcp comment 'Outgoing SSH (Custom-Port)'
|
ufw allow out "${SSHPORT}"/tcp comment 'Outgoing SSH Custom-Port'
|
||||||
|
# PRIMORDIAL_SSH_RULE_MUST_BE_SET
|
||||||
ufw allow out 53/udp comment 'Outgoing DNS'
|
ufw allow out 53/udp comment 'Outgoing DNS'
|
||||||
ufw allow out 123/udp comment 'Outgoing NTP'
|
ufw allow out 123/udp comment 'Outgoing NTP'
|
||||||
ufw allow out 443/udp comment 'Outgoing QUIC'
|
ufw allow out 443/udp comment 'Outgoing QUIC'
|
||||||
|
|||||||
@@ -66,6 +66,49 @@ readonly -f preallocate
|
|||||||
declare ROOTFS="${VAR_HANDLER_BUILD_DIR}/binary/live/filesystem.squashfs"
|
declare ROOTFS="${VAR_HANDLER_BUILD_DIR}/binary/live/filesystem.squashfs"
|
||||||
declare LUKSFS="${VAR_HANDLER_BUILD_DIR}/binary/live/ciss_rootfs.crypt"
|
declare LUKSFS="${VAR_HANDLER_BUILD_DIR}/binary/live/ciss_rootfs.crypt"
|
||||||
declare KEYFD=""
|
declare KEYFD=""
|
||||||
|
declare LUKS_KEY_FILE=""
|
||||||
|
declare LUKS_KEY_FILENAME="${VAR_LUKS_KEY:-luks.txt}"
|
||||||
|
declare LUKS_KEY_LINK_COUNT=""
|
||||||
|
declare LUKS_KEY_MODE=""
|
||||||
|
declare LUKS_KEY_OWNER=""
|
||||||
|
declare SECRET_ROOT_FS=""
|
||||||
|
declare SECRET_ROOT_MODE=""
|
||||||
|
declare SECRET_ROOT_OWNER=""
|
||||||
|
|
||||||
|
if [[ -L "${VAR_TMP_SECRET}" || ! -d "${VAR_TMP_SECRET}" ]]; then
|
||||||
|
printf "\e[91m❌ Unsafe secret root rejected. \e[0m\n" >&2
|
||||||
|
exit 42
|
||||||
|
fi
|
||||||
|
|
||||||
|
SECRET_ROOT_OWNER="$(stat -c '%u' "${VAR_TMP_SECRET}")"
|
||||||
|
SECRET_ROOT_MODE="$(stat -c '%a' "${VAR_TMP_SECRET}")"
|
||||||
|
SECRET_ROOT_FS="$(stat -f -c '%T' "${VAR_TMP_SECRET}")"
|
||||||
|
if [[ "${SECRET_ROOT_OWNER}" != "${EUID}" || "${SECRET_ROOT_MODE}" != "700" \
|
||||||
|
|| ( "${SECRET_ROOT_FS}" != "tmpfs" && "${SECRET_ROOT_FS}" != "ramfs" ) ]]; then
|
||||||
|
printf "\e[91m❌ Unsafe secret-root ownership, permissions, or filesystem rejected. \e[0m\n" >&2
|
||||||
|
exit 42
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${LUKS_KEY_FILENAME}" || "${LUKS_KEY_FILENAME}" == "." || "${LUKS_KEY_FILENAME}" == ".." \
|
||||||
|
|| "${LUKS_KEY_FILENAME}" == */* || ! "${LUKS_KEY_FILENAME}" =~ ^[A-Za-z0-9._@%+=:,~-]+$ ]]; then
|
||||||
|
printf "\e[91m❌ Unsafe LUKS key filename rejected. \e[0m\n" >&2
|
||||||
|
exit 42
|
||||||
|
fi
|
||||||
|
|
||||||
|
LUKS_KEY_FILE="${VAR_TMP_SECRET}/${LUKS_KEY_FILENAME}"
|
||||||
|
if [[ -L "${LUKS_KEY_FILE}" || ! -f "${LUKS_KEY_FILE}" ]]; then
|
||||||
|
printf "\e[91m❌ Unsafe LUKS key file rejected. \e[0m\n" >&2
|
||||||
|
exit 42
|
||||||
|
fi
|
||||||
|
|
||||||
|
LUKS_KEY_OWNER="$(stat -c '%u' "${LUKS_KEY_FILE}")"
|
||||||
|
LUKS_KEY_MODE="$(stat -c '%a' "${LUKS_KEY_FILE}")"
|
||||||
|
LUKS_KEY_LINK_COUNT="$(stat -c '%h' "${LUKS_KEY_FILE}")"
|
||||||
|
if [[ "${LUKS_KEY_OWNER}" != "${EUID}" || "${LUKS_KEY_LINK_COUNT}" != "1" \
|
||||||
|
|| ( "${LUKS_KEY_MODE}" != "400" && "${LUKS_KEY_MODE}" != "600" ) ]]; then
|
||||||
|
printf "\e[91m❌ Unsafe LUKS key ownership, permissions, or link count rejected. \e[0m\n" >&2
|
||||||
|
exit 42
|
||||||
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2155
|
# shellcheck disable=SC2155
|
||||||
declare -i VAR_ROOTFS_SIZE=$(stat -c%s -- "${ROOTFS}")
|
declare -i VAR_ROOTFS_SIZE=$(stat -c%s -- "${ROOTFS}")
|
||||||
@@ -82,7 +125,7 @@ declare -i VAR_LUKSFS_SIZE=$(( ( (BASE_SIZE + ALIGN_BYTES - 1) / ALIGN_BYTES ) *
|
|||||||
|
|
||||||
preallocate "${LUKSFS}" "${VAR_LUKSFS_SIZE}"
|
preallocate "${LUKSFS}" "${VAR_LUKSFS_SIZE}"
|
||||||
|
|
||||||
exec {KEYFD}<"${VAR_TMP_SECRET}/luks.txt"
|
exec {KEYFD}<"${LUKS_KEY_FILE}"
|
||||||
|
|
||||||
if [[ "${VAR_CDLB_INSIDE_RUNNER}" == "false" ]]; then
|
if [[ "${VAR_CDLB_INSIDE_RUNNER}" == "false" ]]; then
|
||||||
|
|
||||||
@@ -146,7 +189,7 @@ cryptsetup close crypt_liveiso
|
|||||||
|
|
||||||
exec {KEYFD}<&-
|
exec {KEYFD}<&-
|
||||||
|
|
||||||
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/luks.txt"
|
shred -fzu -n 5 -- "${LUKS_KEY_FILE}"
|
||||||
|
|
||||||
rm -f -- "${ROOTFS}"
|
rm -f -- "${ROOTFS}"
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
[git.coresecret.dev]:42842 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGQA107AVmg1D/jnyXiqbPf38zQRl8s3c+PM1zbfpeQl
|
[git.coresecret.dev]:42842 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGQA107AVmg1D/jnyXiqbPf38zQRl8s3c+PM1zbfpeQl
|
||||||
[git.coresecret.dev]:42842 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDYD9ysmMWZlejUnxu0qOzeWcIYezoFLbYdo6ffGUL5kqOBAYb+5CF4bJLUpA93XFYVF+TbrcMV1yJh6JaHFL0VU5CvgAzruCeedx0c4qUV6lWcJUGNk5K0yb9n2Wosdy6F/zTOxL9KXBt/TV+cscsen2Dahvx0ctMKgNbu+vvUcWxHf9lOkbYoF/uA/nW5CVXy5XUPVUDFUhEeKXL85+6gid5AEMfYT8aRl5YDGvo1iMBmBYOljN4S7MnRe14qbAZG0GDGvF22eHbSU2pILcFIjc2Lo/S5Ox/MJpbLAqpFlLPTKgr6F7yVwfNMSNwl05ysUOZfrQKSXzCU6+lfqKYCwemLALyG/n1ernpp7/8W/2RYoz3fd+TQyfhW++rx3yUHpYCkTv9A4LRYZYGSAWKMHSBEYq3EcATQUxQi0xpwmcR+u0uC9F9eta5Bim+sBZD6F2hgPJ5xgYT8LFm880g1YadAwBoD4TAkqSvl+jYW0VA2GH9CknKHJ36gc/X4eeUHDC1Hf/E8M5RBj4D6NuHfeVRik/ahHmoCqKQUW7VU/EBsWFsngDiLEHcV71iMtWiUddWOHwoAPHIzn6p9HTeLCxTwsPMG5UDGK/S9HUozqDXxexRtqbcFa7DWuzRvZ1bcZ2VQsaafuzKCkkc4NjC7h1wssel7q9aeYPFg+1vS6Q==
|
[git.coresecret.dev]:42842 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDYD9ysmMWZlejUnxu0qOzeWcIYezoFLbYdo6ffGUL5kqOBAYb+5CF4bJLUpA93XFYVF+TbrcMV1yJh6JaHFL0VU5CvgAzruCeedx0c4qUV6lWcJUGNk5K0yb9n2Wosdy6F/zTOxL9KXBt/TV+cscsen2Dahvx0ctMKgNbu+vvUcWxHf9lOkbYoF/uA/nW5CVXy5XUPVUDFUhEeKXL85+6gid5AEMfYT8aRl5YDGvo1iMBmBYOljN4S7MnRe14qbAZG0GDGvF22eHbSU2pILcFIjc2Lo/S5Ox/MJpbLAqpFlLPTKgr6F7yVwfNMSNwl05ysUOZfrQKSXzCU6+lfqKYCwemLALyG/n1ernpp7/8W/2RYoz3fd+TQyfhW++rx3yUHpYCkTv9A4LRYZYGSAWKMHSBEYq3EcATQUxQi0xpwmcR+u0uC9F9eta5Bim+sBZD6F2hgPJ5xgYT8LFm880g1YadAwBoD4TAkqSvl+jYW0VA2GH9CknKHJ36gc/X4eeUHDC1Hf/E8M5RBj4D6NuHfeVRik/ahHmoCqKQUW7VU/EBsWFsngDiLEHcV71iMtWiUddWOHwoAPHIzn6p9HTeLCxTwsPMG5UDGK/S9HUozqDXxexRtqbcFa7DWuzRvZ1bcZ2VQsaafuzKCkkc4NjC7h1wssel7q9aeYPFg+1vS6Q==
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
### https://www.ssh-audit.com/
|
### https://www.ssh-audit.com/
|
||||||
### ssh -Q cipher | cipher-auth | compression | kex | kex-gss | key | key-cert | key-plain | key-sig | mac | protocol-version | sig
|
### ssh -Q cipher | cipher-auth | compression | kex | kex-gss | key | key-cert | key-plain | key-sig | mac | protocol-version | sig
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
# Version Master V9.14.020.2026.06.08
|
# Version Master V9.14.022.2026.06.10
|
||||||
|
|
||||||
### https://docs.kernel.org/
|
### https://docs.kernel.org/
|
||||||
### https://github.com/a13xp0p0v/kernel-hardening-checker/
|
### https://github.com/a13xp0p0v/kernel-hardening-checker/
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# SPDX-PackageName: CISS.debian.live.builder
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
# SPDX-Security-Contact: security@coresecret.eu
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
declare -gr VERSION="Master V9.14.020.2026.06.08"
|
declare -gr VERSION="Master V9.14.022.2026.06.10"
|
||||||
|
|
||||||
### VERY EARLY CHECK FOR DEBUGGING
|
### VERY EARLY CHECK FOR DEBUGGING
|
||||||
if [[ $* == *" --debug "* ]]; then
|
if [[ $* == *" --debug "* ]]; then
|
||||||
|
|||||||
@@ -112,4 +112,4 @@ d-i preseed/late_command string sh /preseed/.ash/3_di_preseed_late_command.sh
|
|||||||
|
|
||||||
# Please consider donating to my work at: https://coresecret.eu/spenden/
|
# Please consider donating to my work at: https://coresecret.eu/spenden/
|
||||||
###########################################################################################
|
###########################################################################################
|
||||||
# Written by: ./preseed_hash_generator.sh Version: Master V9.14.020.2026.06.08 at: 10:18:37.9542
|
# Written by: ./preseed_hash_generator.sh Version: Master V9.14.022.2026.06.10 at: 10:18:37.9542
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. DNSSEC Status
|
# 2. DNSSEC Status
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Haveged Audit on Netcup RS 2000 G11
|
# 2. Haveged Audit on Netcup RS 2000 G11
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Lynis Audit:
|
# 2. Lynis Audit:
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. SSH Audit by ssh-audit.com
|
# 2. SSH Audit by ssh-audit.com
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. TLS Audit:
|
# 2. TLS Audit:
|
||||||
````text
|
````text
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Hardened Kernel Boot Parameters
|
# 2. Hardened Kernel Boot Parameters
|
||||||
|
|
||||||
|
|||||||
+19
-13
@@ -8,11 +8,17 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Changelog
|
# 2. Changelog
|
||||||
|
|
||||||
|
## V9.14.022.2026.06.10
|
||||||
|
* **Added**: [lib_logo.sh](../lib/lib_logo.sh)
|
||||||
|
* **Added**: [9999_cdi_starter.sh](../scripts/usr/local/sbin/9999_cdi_starter.sh) Retrieve rdns for Primordial-Workflow™
|
||||||
|
* **Added**: [0900_ufw_setup.chroot](../config/hooks/live/0900_ufw_setup.chroot) SSH ufw out exception for Primordial-Workflow™
|
||||||
|
|
||||||
## V9.14.020.2026.06.08
|
## V9.14.020.2026.06.08
|
||||||
|
* **Added**: [bootscreen.txt](../bootscreen.txt)
|
||||||
* **Changed**: ``sops 3.13.0`` to ``sops 3.13.1``
|
* **Changed**: ``sops 3.13.0`` to ``sops 3.13.1``
|
||||||
|
|
||||||
## V9.14.018.2026.06.07
|
## V9.14.018.2026.06.07
|
||||||
@@ -132,7 +138,7 @@ include_toc: true
|
|||||||
* **Changed**: [lib_check_secrets.sh](../lib/lib_check_secrets.sh) + updated shopt handling.
|
* **Changed**: [lib_check_secrets.sh](../lib/lib_check_secrets.sh) + updated shopt handling.
|
||||||
* **Changed**: [lib_ciss_upgrades_boot.sh](../lib/lib_ciss_upgrades_boot.sh) + integrates and generates sha512sum and GPG signatures on CISS specific LIVE boot artifacts.
|
* **Changed**: [lib_ciss_upgrades_boot.sh](../lib/lib_ciss_upgrades_boot.sh) + integrates and generates sha512sum and GPG signatures on CISS specific LIVE boot artifacts.
|
||||||
* **Changed**: [lib_gnupg.sh](../lib/lib_gnupg.sh) + integration of optional import of offline GPG CA public keys.
|
* **Changed**: [lib_gnupg.sh](../lib/lib_gnupg.sh) + integration of optional import of offline GPG CA public keys.
|
||||||
* **Changed**: [lib_primordial.sh](../lib/lib_primordial.sh) + Updates for CISS and PhysNet primordial-workflow™.
|
* **Changed**: [lib_primordial.sh](../lib/lib_primordial.sh) + Updates for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Changed**: [lib_usage.sh](../lib/lib_usage.sh) + ``--signing_ca=*``.
|
* **Changed**: [lib_usage.sh](../lib/lib_usage.sh) + ``--signing_ca=*``.
|
||||||
* **Changed**: [binary_checksums.sh](../scripts/usr/lib/live/build/binary_checksums.sh) + ``! -path './live/filesystem.squashfs'``
|
* **Changed**: [binary_checksums.sh](../scripts/usr/lib/live/build/binary_checksums.sh) + ``! -path './live/filesystem.squashfs'``
|
||||||
* **Changed**: [9999_cdi_starter.sh](../scripts/usr/local/sbin/9999_cdi_starter.sh) + increased verbosity.
|
* **Changed**: [9999_cdi_starter.sh](../scripts/usr/local/sbin/9999_cdi_starter.sh) + increased verbosity.
|
||||||
@@ -186,10 +192,10 @@ include_toc: true
|
|||||||
* **Added**: [marc_s_weidner_msw+deploy@coresecet.dev_0x2CCF4601_public.asc](../.pubkey/marc_s_weidner_msw%2Bdeploy%40coresecet.dev_0x2CCF4601_public.asc)
|
* **Added**: [marc_s_weidner_msw+deploy@coresecet.dev_0x2CCF4601_public.asc](../.pubkey/marc_s_weidner_msw%2Bdeploy%40coresecet.dev_0x2CCF4601_public.asc)
|
||||||
* **Added**: [0870_bashdb.chroot](../config/hooks/live/0870_bashdb.chroot) bashdb debugger https://github.com/Trepan-Debuggers/bashdb.git
|
* **Added**: [0870_bashdb.chroot](../config/hooks/live/0870_bashdb.chroot) bashdb debugger https://github.com/Trepan-Debuggers/bashdb.git
|
||||||
* **Added**: [0030-ciss-verify-checksums](../config/includes.chroot/usr/lib/live/boot/0030-ciss-verify-checksums) Unified handling via includes.chroot.
|
* **Added**: [0030-ciss-verify-checksums](../config/includes.chroot/usr/lib/live/boot/0030-ciss-verify-checksums) Unified handling via includes.chroot.
|
||||||
* **Added**: [lib_ciss_upgrades_boot.sh](../lib/lib_ciss_upgrades_boot.sh) Updates for CISS and PhysNet primordial-workflow™.
|
* **Added**: [lib_ciss_upgrades_boot.sh](../lib/lib_ciss_upgrades_boot.sh) Updates for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Added**: [lib_ciss_upgrades_build.sh](../lib/lib_ciss_upgrades_build.sh) Updates for CISS and PhysNet primordial-workflow™.
|
* **Added**: [lib_ciss_upgrades_build.sh](../lib/lib_ciss_upgrades_build.sh) Updates for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Added**: [lib_gnupg.sh](../lib/lib_gnupg.sh) Updates for CISS and PhysNet primordial-workflow™.
|
* **Added**: [lib_gnupg.sh](../lib/lib_gnupg.sh) Updates for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Added**: [lib_primordial.sh](../lib/lib_primordial.sh) Updates for CISS and PhysNet primordial-workflow™.
|
* **Added**: [lib_primordial.sh](../lib/lib_primordial.sh) Updates for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Added**: [0030-ciss-verify-checksums](../scripts/usr/lib/live/boot/0030-ciss-verify-checksums) Unified handling via includes.chroot.
|
* **Added**: [0030-ciss-verify-checksums](../scripts/usr/lib/live/boot/0030-ciss-verify-checksums) Unified handling via includes.chroot.
|
||||||
* **Bugfixes**: [linter_char_scripts.yaml](../.gitea/workflows/linter_char_scripts.yaml) - WORKFLOW_ID="${GITHUB_WORKFLOW:-linter_char_scripts.yaml}"
|
* **Bugfixes**: [linter_char_scripts.yaml](../.gitea/workflows/linter_char_scripts.yaml) - WORKFLOW_ID="${GITHUB_WORKFLOW:-linter_char_scripts.yaml}"
|
||||||
* **Bugfixes**: [render-dnssec-status.yaml](../.gitea/workflows/render-dnssec-status.yaml) - WORKFLOW_ID="${GITHUB_WORKFLOW:-render-dnssec-status.yaml}"
|
* **Bugfixes**: [render-dnssec-status.yaml](../.gitea/workflows/render-dnssec-status.yaml) - WORKFLOW_ID="${GITHUB_WORKFLOW:-render-dnssec-status.yaml}"
|
||||||
@@ -197,11 +203,11 @@ include_toc: true
|
|||||||
* **Changed**: [generate_PRIVATE_trixie_1.yaml](../.gitea/workflows/generate_PRIVATE_trixie_1.yaml) Rewritten for new secrets handling.
|
* **Changed**: [generate_PRIVATE_trixie_1.yaml](../.gitea/workflows/generate_PRIVATE_trixie_1.yaml) Rewritten for new secrets handling.
|
||||||
* **Changed**: [0000_basic_chroot_setup.chroot](../config/hooks/live/0000_basic_chroot_setup.chroot) + VAR_DATE improvements.
|
* **Changed**: [0000_basic_chroot_setup.chroot](../config/hooks/live/0000_basic_chroot_setup.chroot) + VAR_DATE improvements.
|
||||||
* **Changed**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + VAR_DATE improvements.
|
* **Changed**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + VAR_DATE improvements.
|
||||||
* **Changed**: [9930_hardening_ssh.chroot](../config/hooks/live/9930_hardening_ssh.chroot) Rewritten for CISS and PhysNet primordial-workflow™.
|
* **Changed**: [9930_hardening_ssh.chroot](../config/hooks/live/9930_hardening_ssh.chroot) Rewritten for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Changed**: [9999_zzzz.chroot](../config/hooks/live/9999_zzzz.chroot) + Final update-initramfs
|
* **Changed**: [9999_zzzz.chroot](../config/hooks/live/9999_zzzz.chroot) + Final update-initramfs
|
||||||
* **Changed**: [sshd_config](../config/includes.chroot/etc/ssh/sshd_config) + Less strict MaxStartups settings.
|
* **Changed**: [sshd_config](../config/includes.chroot/etc/ssh/sshd_config) + Less strict MaxStartups settings.
|
||||||
* **Changed**: [live.list.common.chroot](../config/package-lists/live.list.common.chroot) + tmux
|
* **Changed**: [live.list.common.chroot](../config/package-lists/live.list.common.chroot) + tmux
|
||||||
* **Changed**: [lib_arg_parser.sh](../lib/lib_arg_parser.sh) Rewritten for CISS and PhysNet primordial-workflow™.
|
* **Changed**: [lib_arg_parser.sh](../lib/lib_arg_parser.sh) Rewritten for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Changed**: [lib_arg_priority_check.sh](../lib/lib_arg_priority_check.sh) Unified UI.
|
* **Changed**: [lib_arg_priority_check.sh](../lib/lib_arg_priority_check.sh) Unified UI.
|
||||||
* **Changed**: [lib_cdi.sh](../lib/lib_cdi.sh) + Commandline parameters: verify-checksums=sha512,sha384 verify-checksums-signatures
|
* **Changed**: [lib_cdi.sh](../lib/lib_cdi.sh) + Commandline parameters: verify-checksums=sha512,sha384 verify-checksums-signatures
|
||||||
* **Changed**: [lib_change_splash.sh](../lib/lib_change_splash.sh) Unified UI.
|
* **Changed**: [lib_change_splash.sh](../lib/lib_change_splash.sh) Unified UI.
|
||||||
@@ -210,11 +216,11 @@ include_toc: true
|
|||||||
* **Changed**: [lib_check_kernel.sh](../lib/lib_check_kernel.sh) Minor declare unification.
|
* **Changed**: [lib_check_kernel.sh](../lib/lib_check_kernel.sh) Minor declare unification.
|
||||||
* **Changed**: [lib_check_pkgs.sh](../lib/lib_check_pkgs.sh) Improved command checks. Unified UI.
|
* **Changed**: [lib_check_pkgs.sh](../lib/lib_check_pkgs.sh) Improved command checks. Unified UI.
|
||||||
* **Changed**: [lib_check_provider.sh](../lib/lib_check_provider.sh) Unified variables.
|
* **Changed**: [lib_check_provider.sh](../lib/lib_check_provider.sh) Unified variables.
|
||||||
* **Changed**: [lib_clean_up.sh](../lib/lib_clean_up.sh) Secure deletion of CISS and PhysNet primordial-workflow™ artifacts.
|
* **Changed**: [lib_clean_up.sh](../lib/lib_clean_up.sh) Secure deletion of CISS and PhysNet Primordial-Workflow™ artifacts.
|
||||||
* **Changed**: [lib_debug.sh](../lib/lib_debug.sh) + Integrated EPOCH in PS4.
|
* **Changed**: [lib_debug.sh](../lib/lib_debug.sh) + Integrated EPOCH in PS4.
|
||||||
* **Changed**: [lib_debug_header.sh](../lib/lib_debug_header.sh) + Integrated SOURCE_DATE_EPOCH.
|
* **Changed**: [lib_debug_header.sh](../lib/lib_debug_header.sh) + Integrated SOURCE_DATE_EPOCH.
|
||||||
* **Changed**: [lib_hardening_root_pw.sh](../lib/lib_hardening_root_pw.sh) Unified UI.
|
* **Changed**: [lib_hardening_root_pw.sh](../lib/lib_hardening_root_pw.sh) Unified UI.
|
||||||
* **Changed**: [lib_hardening_ultra.sh](../lib/lib_hardening_ultra.sh) Rewritten for CISS and PhysNet primordial-workflow™.
|
* **Changed**: [lib_hardening_ultra.sh](../lib/lib_hardening_ultra.sh) Rewritten for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Changed**: [lib_hardening_ssh_tcp.sh](../lib/lib_hardening_ssh_tcp.sh) Unified UI.
|
* **Changed**: [lib_hardening_ssh_tcp.sh](../lib/lib_hardening_ssh_tcp.sh) Unified UI.
|
||||||
* **Changed**: [lib_lb_build_start.sh](../lib/lib_lb_build_start.sh) Deterministic return code examination.
|
* **Changed**: [lib_lb_build_start.sh](../lib/lib_lb_build_start.sh) Deterministic return code examination.
|
||||||
* **Changed**: [lib_lb_config_start.sh](../lib/lib_lb_config_start.sh) Removed potential disown race condition.
|
* **Changed**: [lib_lb_config_start.sh](../lib/lib_lb_config_start.sh) Removed potential disown race condition.
|
||||||
@@ -254,11 +260,11 @@ include_toc: true
|
|||||||
## V8.13.290.2025.10.26
|
## V8.13.290.2025.10.26
|
||||||
* **Updated**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + ESP/FAT/UEFI mods
|
* **Updated**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + ESP/FAT/UEFI mods
|
||||||
* **Updated**: [9950_hardening_fail2ban.chroot](../config/hooks/live/9950_hardening_fail2ban.chroot)
|
* **Updated**: [9950_hardening_fail2ban.chroot](../config/hooks/live/9950_hardening_fail2ban.chroot)
|
||||||
* **Updated**: [9999-cdi-starter](../scripts/usr/local/sbin/9999_cdi_starter.sh) Preparations for CISS and PhysNet primordial-workflow™.
|
* **Updated**: [9999-cdi-starter](../scripts/usr/local/sbin/9999_cdi_starter.sh) Preparations for CISS and PhysNet Primordial-Workflow™.
|
||||||
|
|
||||||
## V8.13.288.2025.10.24
|
## V8.13.288.2025.10.24
|
||||||
* **Added**: Preparations for CISS and PhysNet primordial-workflow™.
|
* **Added**: Preparations for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Added**: [0865_yq.chroot](../config/hooks/live/0865_yq.chroot)Preparations for CISS and PhysNet primordial-workflow™.
|
* **Added**: [0865_yq.chroot](../config/hooks/live/0865_yq.chroot)Preparations for CISS and PhysNet Primordial-Workflow™.
|
||||||
* **Updated**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + nftables mods
|
* **Updated**: [0001_initramfs_modules.chroot](../config/hooks/live/0001_initramfs_modules.chroot) + nftables mods
|
||||||
* **Updated**: [9950_hardening_fail2ban.chroot](../config/hooks/live/9950_hardening_fail2ban.chroot) + banaction = nftables-*
|
* **Updated**: [9950_hardening_fail2ban.chroot](../config/hooks/live/9950_hardening_fail2ban.chroot) + banaction = nftables-*
|
||||||
* **Updated**: [0900_ufw_setup.chroot](../config/hooks/live/0900_ufw_setup.chroot) changed var injection
|
* **Updated**: [0900_ufw_setup.chroot](../config/hooks/live/0900_ufw_setup.chroot) changed var injection
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Centurion Net - Developer Branch Overview
|
# 2. Centurion Net - Developer Branch Overview
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Purpose
|
# 2. Purpose
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Contributing / participating
|
# 2. Contributing / participating
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Credits
|
# 2. Credits
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Download the latest PUBLIC CISS.debian.live.ISO
|
# 2. Download the latest PUBLIC CISS.debian.live.ISO
|
||||||
|
|
||||||
|
|||||||
+34
-5
@@ -8,14 +8,14 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2.1. Usage
|
# 2.1. Usage
|
||||||
````text
|
````text
|
||||||
CDLB(1) CISS.debian.live.builder CDLB(1)
|
CDLB(1) CISS.debian.live.builder CDLB(1)
|
||||||
|
|
||||||
CISS.debian.live.builder from https://git.coresecret.dev/msw
|
CISS.debian.live.builder from https://git.coresecret.dev/msw
|
||||||
Master V9.14.020.2026.06.08
|
Master V9.14.022.2026.06.10
|
||||||
A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
||||||
|
|
||||||
(c) Marc S. Weidner, 2018 - 2026
|
(c) Marc S. Weidner, 2018 - 2026
|
||||||
@@ -37,6 +37,10 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
|||||||
|
|
||||||
--build-directory </path/to/build_directory>
|
--build-directory </path/to/build_directory>
|
||||||
Where the Debian Live Build Image should be generated. RECOMMENDED path: </opt/cdlb>
|
Where the Debian Live Build Image should be generated. RECOMMENDED path: </opt/cdlb>
|
||||||
|
The path MUST be canonical and dedicated to the builder; a new directory's canonical parent MUST already exist.
|
||||||
|
New or empty directories receive the
|
||||||
|
'.ciss-live-builder-owned' marker; populated unmarked directories are rejected. Cleanup is intentionally destructive
|
||||||
|
only inside the exact validated marker-owned directory.
|
||||||
MUST be provided.
|
MUST be provided.
|
||||||
|
|
||||||
--change-splash <STRING> one of <club | hexagon>
|
--change-splash <STRING> one of <club | hexagon>
|
||||||
@@ -57,6 +61,7 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
|||||||
--debug, -d
|
--debug, -d
|
||||||
Enables debug logging for the main program routine. Detailed logging information are written to:
|
Enables debug logging for the main program routine. Detailed logging information are written to:
|
||||||
</tmp/ciss_live_builder_1801049.log>
|
</tmp/ciss_live_builder_1801049.log>
|
||||||
|
A final exact-value sanitisation pass is defence in depth and does not replace careful tracing discipline.
|
||||||
|
|
||||||
--dhcp-centurion
|
--dhcp-centurion
|
||||||
If a DHCP lease is provided, the provider's name server will be overridden and the hardened, privacy-focused
|
If a DHCP lease is provided, the provider's name server will be overridden and the hardened, privacy-focused
|
||||||
@@ -86,11 +91,13 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
|||||||
|
|
||||||
--key_age=*
|
--key_age=*
|
||||||
The SOPS AGE private keyring for decryption operations. Change '*' to your desired SOPS AGE key file.
|
The SOPS AGE private keyring for decryption operations. Change '*' to your desired SOPS AGE key file.
|
||||||
|
'*' MUST be a filename only without slashes, '.' or '..' traversal.
|
||||||
File MUST be placed in:
|
File MUST be placed in:
|
||||||
</dev/shm/cdlb_secrets>
|
</dev/shm/cdlb_secrets>
|
||||||
|
|
||||||
--key_luks=*
|
--key_luks=*
|
||||||
The LUKS encryption / decryption passphrase for '/'-fs-encryption. Change '*' to your desired passphrase file.
|
The LUKS encryption / decryption passphrase for '/'-fs-encryption. Change '*' to your desired passphrase file.
|
||||||
|
'*' MUST be a filename only without slashes, '.' or '..' traversal.
|
||||||
File MUST be placed in:
|
File MUST be placed in:
|
||||||
</dev/shm/cdlb_secrets>
|
</dev/shm/cdlb_secrets>
|
||||||
|
|
||||||
@@ -98,6 +105,24 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
|||||||
Provides statistic only after successful building a CISS.debian.live-ISO. While enabling '--log-statistics-only'
|
Provides statistic only after successful building a CISS.debian.live-ISO. While enabling '--log-statistics-only'
|
||||||
the argument '--build-directory' MUST be provided.
|
the argument '--build-directory' MUST be provided.
|
||||||
|
|
||||||
|
--primordial-key <ssh-identity-filename>
|
||||||
|
SSH identity filename for the Primordial overlay clone. This MUST be a filename only; the runtime path is derived as
|
||||||
|
'/root/.ssh/<ssh-identity-filename>'.
|
||||||
|
Example fragment:
|
||||||
|
./ciss_live_builder.sh --primordial-url https://git.coresecret.dev/ahz/PhysNet.primordial.git \
|
||||||
|
--primordial-key id--git.coresecret.dev--PhysNet.primordial_deploy--ed25519--newton--2025-10 \
|
||||||
|
--primordial-ssh 42842
|
||||||
|
|
||||||
|
--primordial-ssh <INTEGER>
|
||||||
|
Adds one outgoing UFW TCP exception for a bootstrap/recovery SSH port.
|
||||||
|
Outgoing only: no incoming firewall rule is added, and this option does not replace '--ssh-port'.
|
||||||
|
Effective only when the Live System's UFW outgoing policy is 'deny'.
|
||||||
|
Port MUST be a decimal integer between '1' and '65535'.
|
||||||
|
|
||||||
|
--primordial-url <https-git-url>
|
||||||
|
HTTPS Git repository URL for the Primordial CDI overlay. MUST start with 'https://', include a host and path, and end in
|
||||||
|
'.git'. The CDI starter converts this URL to an SSH clone URL at runtime.
|
||||||
|
|
||||||
--provider-netcup-ipv6
|
--provider-netcup-ipv6
|
||||||
Activates IPv6 support for Netcup Root Server. One unique IPv6 address MUST be provided in this case and MUST be
|
Activates IPv6 support for Netcup Root Server. One unique IPv6 address MUST be provided in this case and MUST be
|
||||||
encapsulated with [], e.g., [1234::abcd].
|
encapsulated with [], e.g., [1234::abcd].
|
||||||
@@ -122,7 +147,7 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
|||||||
--root-password-file </dev/shm/cdlb_secrets/password.txt>>
|
--root-password-file </dev/shm/cdlb_secrets/password.txt>>
|
||||||
Password file for 'root', if given, MUST be a string of 42 to 64 characters.
|
Password file for 'root', if given, MUST be a string of 42 to 64 characters.
|
||||||
If the argument is omitted, no further login authentication is required for the local console.
|
If the argument is omitted, no further login authentication is required for the local console.
|
||||||
MUST be placed in:
|
Safe absolute paths remain supported and are validated separately. RECOMMENDED path:
|
||||||
</dev/shm/cdlb_secrets/password.txt>
|
</dev/shm/cdlb_secrets/password.txt>
|
||||||
|
|
||||||
--secure-boot-profile <STRING> one of <debian-shim | ciss-uki>
|
--secure-boot-profile <STRING> one of <debian-shim | ciss-uki>
|
||||||
@@ -138,7 +163,8 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
|||||||
specified via '--signing_key=*'. If the keyring is protected, then provide the passphrase in its own file.
|
specified via '--signing_key=*'. If the keyring is protected, then provide the passphrase in its own file.
|
||||||
Specify the fingerprint of the key to use via '--signing_key_fpr=*'.
|
Specify the fingerprint of the key to use via '--signing_key_fpr=*'.
|
||||||
Optionally import an offline GPG CA signing public key via: '--signing_ca=*'.
|
Optionally import an offline GPG CA signing public key via: '--signing_ca=*'.
|
||||||
Change '*' to your desired files / fingerprint. Files MUST be placed in:
|
Change '*' to your desired filename-only files / fingerprint. Filename-only values MUST NOT contain slashes or traversal.
|
||||||
|
Files MUST be placed in:
|
||||||
</dev/shm/cdlb_secrets>
|
</dev/shm/cdlb_secrets>
|
||||||
|
|
||||||
--sshfp
|
--sshfp
|
||||||
@@ -164,11 +190,14 @@ A lightweight Shell Wrapper for building a hardened Debian Live ISO Image.
|
|||||||
|
|
||||||
💡 Notes:
|
💡 Notes:
|
||||||
🔵 You MUST be 'root' to run this script.
|
🔵 You MUST be 'root' to run this script.
|
||||||
|
🔵 Private operator control does not remove the requirement for strict local secret path validation.
|
||||||
|
🔵 '/dev/shm/cdlb_secrets' MUST be tmpfs-backed, root-owned, mode 0700, and contain only single-link regular non-symlink files
|
||||||
|
with mode 0400 or 0600. Secure deletion with shred is best-effort only on modern storage.
|
||||||
|
|
||||||
💷 Please consider donating to my work at:
|
💷 Please consider donating to my work at:
|
||||||
🌐 https://coresecret.eu/spenden/
|
🌐 https://coresecret.eu/spenden/
|
||||||
|
|
||||||
V9.14.020.2026.06.08 2026-05-17 CDLB(1)
|
V9.14.022.2026.06.10 2026-05-17 CDLB(1)
|
||||||
````
|
````
|
||||||
|
|
||||||
# 3. Booting
|
# 3. Booting
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. CISS.debian.live.builder – Boot & Trust Chain (Technical Documentation)
|
# 2. CISS.debian.live.builder – Boot & Trust Chain (Technical Documentation)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. SSH Host Key Policy – CISS.debian.live.builder / CISS.debian.installer
|
# 2. SSH Host Key Policy – CISS.debian.live.builder / CISS.debian.installer
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. Resources
|
# 2. Resources
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. ``30-ciss-hardening.conf``
|
# 2. ``30-ciss-hardening.conf``
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. ``90-ciss-local.hardened``
|
# 2. ``90-ciss-local.hardened``
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ include_toc: true
|
|||||||
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
**Centurion Intelligence Consulting Agency Information Security Standard**<br>
|
||||||
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
*Debian Live Build Generator for hardened live environment and CISS Debian Installer*<br>
|
||||||
**Master Version**: 9.14<br>
|
**Master Version**: 9.14<br>
|
||||||
**Build**: V9.14.020.2026.06.08<br>
|
**Build**: V9.14.022.2026.06.10<br>
|
||||||
|
|
||||||
# 2. ``ciss_live_builder.sh``
|
# 2. ``ciss_live_builder.sh``
|
||||||
|
|
||||||
|
|||||||
+125
-50
@@ -38,6 +38,9 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
|
|||||||
# VAR_ISO8601
|
# VAR_ISO8601
|
||||||
# VAR_LUKS
|
# VAR_LUKS
|
||||||
# VAR_LUKS_KEY
|
# VAR_LUKS_KEY
|
||||||
|
# VAR_PRIMORDIAL_KEY
|
||||||
|
# VAR_PRIMORDIAL_SSH_PORT
|
||||||
|
# VAR_PRIMORDIAL_URL
|
||||||
# VAR_REIONICE_CLASS
|
# VAR_REIONICE_CLASS
|
||||||
# VAR_REIONICE_PRIORITY
|
# VAR_REIONICE_PRIORITY
|
||||||
# VAR_SIGNER
|
# VAR_SIGNER
|
||||||
@@ -54,25 +57,25 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
|
|||||||
# None
|
# None
|
||||||
# Returns:
|
# Returns:
|
||||||
# ERR_ARG_MSMTCH: on failure
|
# ERR_ARG_MSMTCH: on failure
|
||||||
# ERR_ARG_MSMTCH: on failure
|
# ERR_BUILD_PATH: on failure
|
||||||
# ERR_CONTROL_CT: on failure
|
# ERR_CONTROL_CT: on failure
|
||||||
# ERR_DROPBEAR_V: on failure
|
# ERR_DROPBEAR_V: on failure
|
||||||
# ERR_MISS_PWD_F: on failure
|
|
||||||
# ERR_MISS_PWD_P: on failure
|
# ERR_MISS_PWD_P: on failure
|
||||||
# ERR_NOTABSPATH: on failure
|
|
||||||
# ERR_OWNS_PWD_F: on failure
|
|
||||||
# ERR_PASS_LENGH: on failure
|
# ERR_PASS_LENGH: on failure
|
||||||
# ERR_PASS_PLICY: on failure
|
# ERR_PASS_PLICY: on failure
|
||||||
# ERR_REIONICE_P: on failure
|
# ERR_REIONICE_P: on failure
|
||||||
# ERR_REIO_C_VAL: on failure
|
# ERR_REIO_C_VAL: on failure
|
||||||
# ERR_REIO_P_VAL: on failure
|
# ERR_REIO_P_VAL: on failure
|
||||||
# ERR_RENICE_PRI: on failure
|
# ERR_RENICE_PRI: on failure
|
||||||
# ERR_RGHT_PWD_F: on failure
|
# ERR_SECRET_PATH: on failure
|
||||||
# ERR_SPLASH_PNG: on failure
|
# ERR_SPLASH_PNG: on failure
|
||||||
# ERR__SOPS__VER: on failure
|
# ERR__SOPS__VER: on failure
|
||||||
# ERR__SSH__PORT: on failure
|
# ERR__SSH__PORT: on failure
|
||||||
#######################################
|
#######################################
|
||||||
arg_parser() {
|
arg_parser() {
|
||||||
|
declare primordial_key_regex='^[A-Za-z0-9._@%+=:,~-]+$'
|
||||||
|
declare primordial_url_regex='^https://[A-Za-z0-9.-]+/[A-Za-z0-9._~/%+=:@,-]+\.git$'
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
|
|
||||||
declare argument="${1}"
|
declare argument="${1}"
|
||||||
@@ -128,12 +131,9 @@ arg_parser() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
--build-directory)
|
--build-directory)
|
||||||
declare -gx VAR_HANDLER_BUILD_DIR="${2}"
|
declare build_directory="${2-}"
|
||||||
if [[ ! "${VAR_HANDLER_BUILD_DIR}" =~ ^/ ]]; then
|
validate_build_directory_path "${build_directory}" build_directory || exit "${ERR_BUILD_PATH}"
|
||||||
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
declare -gx VAR_HANDLER_BUILD_DIR="${build_directory}"
|
||||||
printf "\e[91m❌ Error: --build-directory MUST be an absolute path. Got: '%s'\n" "${VAR_HANDLER_BUILD_DIR}" >&2
|
|
||||||
exit "${ERR_NOTABSPATH}"
|
|
||||||
fi
|
|
||||||
declare -gx VAR_BUILD_LOG="${VAR_HANDLER_BUILD_DIR}/cdlb_${VAR_ISO8601}_build.log"
|
declare -gx VAR_BUILD_LOG="${VAR_HANDLER_BUILD_DIR}/cdlb_${VAR_ISO8601}_build.log"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
@@ -260,18 +260,22 @@ arg_parser() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
--key_age=*)
|
--key_age=*)
|
||||||
|
declare age_key="${1#*=}"
|
||||||
|
validate_secret_file_in_root "${age_key}" "SOPS Age key" || exit "${ERR_SECRET_PATH}"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_AGE="true"
|
declare -gx VAR_AGE="true"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_AGE_KEY="${1#*=}"
|
declare -gx VAR_AGE_KEY="${age_key}"
|
||||||
shift 1
|
shift 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
--key_luks=*)
|
--key_luks=*)
|
||||||
|
declare luks_key="${1#*=}"
|
||||||
|
validate_secret_file_in_root "${luks_key}" "LUKS key file" || exit "${ERR_SECRET_PATH}"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_LUKS="true"
|
declare -gx VAR_LUKS="true"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_LUKS_KEY="${1#*=}"
|
declare -gx VAR_LUKS_KEY="${luks_key}"
|
||||||
shift 1
|
shift 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -287,6 +291,99 @@ arg_parser() {
|
|||||||
shift 1
|
shift 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
--primordial-key)
|
||||||
|
declare primordial_key="${2-}"
|
||||||
|
|
||||||
|
if [[ -n "${primordial_key}" && "${primordial_key}" != -* && "${primordial_key}" != "." && "${primordial_key}" != ".." && "${primordial_key}" != */* && "${primordial_key}" =~ ${primordial_key_regex} ]]; then
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
declare -gx VAR_PRIMORDIAL_KEY="${primordial_key}"
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
||||||
|
printf "\e[91m❌ Error: --primordial-key MUST be a filename matching '^[A-Za-z0-9._@%%+=:,~-]+$' and MUST NOT be '.', '..', or contain '/'.\e[0m\n" >&2
|
||||||
|
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
||||||
|
exit "${ERR_ARG_MSMTCH}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
--primordial-key=*)
|
||||||
|
declare primordial_key="${1#*=}"
|
||||||
|
|
||||||
|
if [[ -n "${primordial_key}" && "${primordial_key}" != "." && "${primordial_key}" != ".." && "${primordial_key}" != */* && "${primordial_key}" =~ ${primordial_key_regex} ]]; then
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
declare -gx VAR_PRIMORDIAL_KEY="${primordial_key}"
|
||||||
|
shift 1
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
||||||
|
printf "\e[91m❌ Error: --primordial-key MUST be a filename matching '^[A-Za-z0-9._@%%+=:,~-]+$' and MUST NOT be '.', '..', or contain '/'.\e[0m\n" >&2
|
||||||
|
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
||||||
|
exit "${ERR_ARG_MSMTCH}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
--primordial-ssh)
|
||||||
|
if [[ -n "${2-}" && "${2}" =~ ^-?[0-9]+$ && "${2}" -ge 1 && "${2}" -le 65535 ]]; then
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
declare -gix VAR_PRIMORDIAL_SSH_PORT="${2}"
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
||||||
|
printf "\e[91m❌ Error: --primordial-ssh MUST be an integer between '1' and '65535'.\e[0m\n" >&2
|
||||||
|
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
||||||
|
exit "${ERR__SSH__PORT}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
--primordial-url)
|
||||||
|
declare primordial_url="${2-}"
|
||||||
|
|
||||||
|
if [[ -n "${primordial_url}" && "${primordial_url}" != -* && "${primordial_url}" =~ ${primordial_url_regex} ]]; then
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
declare -gx VAR_PRIMORDIAL_URL="${primordial_url}"
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
||||||
|
printf "\e[91m❌ Error: --primordial-url MUST be an HTTPS Git URL with non-empty host, non-empty path, and '.git' suffix.\e[0m\n" >&2
|
||||||
|
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
||||||
|
exit "${ERR_ARG_MSMTCH}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
--primordial-url=*)
|
||||||
|
declare primordial_url="${1#*=}"
|
||||||
|
|
||||||
|
if [[ -n "${primordial_url}" && "${primordial_url}" =~ ${primordial_url_regex} ]]; then
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
declare -gx VAR_PRIMORDIAL_URL="${primordial_url}"
|
||||||
|
shift 1
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
||||||
|
printf "\e[91m❌ Error: --primordial-url MUST be an HTTPS Git URL with non-empty host, non-empty path, and '.git' suffix.\e[0m\n" >&2
|
||||||
|
read -p -r $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
||||||
|
exit "${ERR_ARG_MSMTCH}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
--provider-netcup-ipv6)
|
--provider-netcup-ipv6)
|
||||||
if [[ -n "${2-}" && "${2}" != -* ]]; then
|
if [[ -n "${2-}" && "${2}" != -* ]]; then
|
||||||
declare -i count=0
|
declare -i count=0
|
||||||
@@ -374,39 +471,7 @@ arg_parser() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -f "${pw_file}" ]]; then
|
validate_secret_absolute_file "${pw_file}" "root password file" || exit "${ERR_SECRET_PATH}"
|
||||||
|
|
||||||
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
|
||||||
printf "\e[91m❌ Error: --root-password-file password file '%s' does not exist.\e[0m\n" "${pw_file}" >&2
|
|
||||||
# shellcheck disable=SC2162
|
|
||||||
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
|
||||||
exit "${ERR_MISS_PWD_F}"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
declare owner
|
|
||||||
owner=$(stat -c '%U:%G' "${pw_file}")
|
|
||||||
if [[ "${owner}" != "root:root" ]]; then
|
|
||||||
chown root:root "${pw_file}" || {
|
|
||||||
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
|
||||||
printf "\e[91m❌ Error: --root-password-file failed to set owner root:root on '%s'.\e[0m\n" "${pw_file}" >&2
|
|
||||||
# shellcheck disable=SC2162
|
|
||||||
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
|
||||||
exit "${ERR_OWNS_PWD_F}"
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
declare perms
|
|
||||||
perms=$(stat -c '%a' "${pw_file}")
|
|
||||||
if [[ "${perms}" -ne 400 ]]; then
|
|
||||||
chmod 0400 "${pw_file}" || {
|
|
||||||
if ! ${VAR_HANDLER_AUTOBUILD}; then boot_screen_cleaner; fi
|
|
||||||
printf "\e[91m❌ Error: --root-password-file failed to set permissions 0400 on '%s'.\e[0m\n" "${pw_file}" >&2
|
|
||||||
# shellcheck disable=SC2162
|
|
||||||
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
|
||||||
exit "${ERR_RGHT_PWD_F}"
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
declare plaintext_pw
|
declare plaintext_pw
|
||||||
### No tracing for security reasons ----------------------------------------------------------------------------------
|
### No tracing for security reasons ----------------------------------------------------------------------------------
|
||||||
@@ -459,6 +524,7 @@ arg_parser() {
|
|||||||
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set +x
|
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set +x
|
||||||
|
|
||||||
hash_temp=$(mkpasswd --method=sha-512 --salt="${salt}" --rounds=8388608 "${plaintext_pw}")
|
hash_temp=$(mkpasswd --method=sha-512 --salt="${salt}" --rounds=8388608 "${plaintext_pw}")
|
||||||
|
register_secret_value "${hash_temp}"
|
||||||
|
|
||||||
### Turn on tracing again --------------------------------------------------------------------------------------------
|
### Turn on tracing again --------------------------------------------------------------------------------------------
|
||||||
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set -x
|
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set -x
|
||||||
@@ -507,16 +573,20 @@ arg_parser() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
--signing_ca=*)
|
--signing_ca=*)
|
||||||
|
declare signing_ca="${1#*=}"
|
||||||
|
validate_secret_file_in_root "${signing_ca}" "signing CA file" || exit "${ERR_SECRET_PATH}"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_SIGNING_CA="${1#*=}"
|
declare -gx VAR_SIGNING_CA="${signing_ca}"
|
||||||
shift 1
|
shift 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
--signing_key=*)
|
--signing_key=*)
|
||||||
|
declare signing_key="${1#*=}"
|
||||||
|
validate_secret_file_in_root "${signing_key}" "signing key file" || exit "${ERR_SECRET_PATH}"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_SIGNER="true"
|
declare -gx VAR_SIGNER="true"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_SIGNING_KEY="${1#*=}"
|
declare -gx VAR_SIGNING_KEY="${signing_key}"
|
||||||
shift 1
|
shift 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -527,8 +597,10 @@ arg_parser() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
--signing_key_pass=*)
|
--signing_key_pass=*)
|
||||||
|
declare signing_key_pass="${1#*=}"
|
||||||
|
validate_secret_file_in_root "${signing_key_pass}" "signing passphrase file" || exit "${ERR_SECRET_PATH}"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_SIGNING_KEY_PASS="${1#*=}"
|
declare -gx VAR_SIGNING_KEY_PASS="${signing_key_pass}"
|
||||||
shift 1
|
shift 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -595,8 +667,11 @@ arg_parser() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
--ssh-pubkey)
|
--ssh-pubkey)
|
||||||
|
declare ssh_pubkey_dir="${2-}"
|
||||||
|
validate_secret_absolute_directory "${ssh_pubkey_dir}" "SSH public-key directory" || exit "${ERR_SECRET_PATH}"
|
||||||
|
validate_secret_file "${ssh_pubkey_dir}/authorized_keys" "SSH authorized_keys file" || exit "${ERR_SECRET_PATH}"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
declare -gx VAR_SSHPUBKEY="${2}"
|
declare -gx VAR_SSHPUBKEY="${ssh_pubkey_dir}"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,340 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-Version: 3.0
|
||||||
|
# SPDX-CreationInfo: 2026-06-11; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||||
|
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||||
|
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-FileType: SOURCE
|
||||||
|
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
|
||||||
|
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||||
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
|
guard_sourcing || return "${ERR_GUARD_SRCE}"
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Prints a generic build-directory validation error without disclosing a path.
|
||||||
|
# Arguments:
|
||||||
|
# 1: unsafe input class
|
||||||
|
# 2: quiet flag
|
||||||
|
# Returns:
|
||||||
|
# ERR_BUILD_PATH
|
||||||
|
#######################################
|
||||||
|
build_directory_validation_error() {
|
||||||
|
declare error_class="$1" quiet="${2:-false}"
|
||||||
|
|
||||||
|
if [[ "${quiet}" != "true" ]]; then
|
||||||
|
printf "\e[91m❌ Unsafe build-directory input rejected: %s. \e[0m\n" "${error_class}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f build_directory_validation_error
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Canonicalises an existing path or a path whose parent exists.
|
||||||
|
# Arguments:
|
||||||
|
# 1: candidate path
|
||||||
|
# 2: output variable name
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_BUILD_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
canonicalize_build_directory() {
|
||||||
|
declare candidate="$1" output_variable="$2" basename="" parent="" resolved_path=""
|
||||||
|
|
||||||
|
[[ -n "${candidate}" && "${candidate}" == /* ]] || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
[[ "${candidate}" == "/" ]] || candidate="${candidate%/}"
|
||||||
|
[[ ! -L "${candidate}" ]] || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
|
||||||
|
if [[ -e "${candidate}" ]]; then
|
||||||
|
resolved_path="$(realpath "${candidate}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
else
|
||||||
|
basename="${candidate##*/}"
|
||||||
|
parent="${candidate%/*}"
|
||||||
|
[[ -n "${parent}" ]] || parent="/"
|
||||||
|
[[ -n "${basename}" && "${basename}" != "." && "${basename}" != ".." && -d "${parent}" ]] || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
resolved_path="$(realpath "${parent}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
resolved_path="${resolved_path%/}/${basename}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ "${candidate}" == "${resolved_path}" ]] || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
printf -v "${output_variable}" '%s' "${resolved_path}"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f canonicalize_build_directory
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates a build directory against the repository cleanup policy.
|
||||||
|
# Globals:
|
||||||
|
# VAR_TMP_SECRET
|
||||||
|
# VAR_WORKDIR
|
||||||
|
# Arguments:
|
||||||
|
# 1: candidate path
|
||||||
|
# 2: output variable name
|
||||||
|
# 3: quiet flag
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_BUILD_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_build_directory_path() {
|
||||||
|
declare candidate="$1" output_variable="${2:-}" quiet="${3:-false}" secret_root="" validated_path="" workdir=""
|
||||||
|
declare -a rejected_paths=(
|
||||||
|
"/" "/bin" "/boot" "/dev" "/etc" "/home" "/lib" "/lib64" "/media" "/mnt" "/opt" "/proc" "/root" "/run" "/sbin" "/srv"
|
||||||
|
"/sys" "/tmp" "/usr" "/usr/local" "/var" "/var/lib" "/var/tmp"
|
||||||
|
)
|
||||||
|
declare rejected_path=""
|
||||||
|
|
||||||
|
canonicalize_build_directory "${candidate}" validated_path || {
|
||||||
|
build_directory_validation_error \
|
||||||
|
"path is empty, non-absolute, non-canonical, missing its parent, or is a symlink" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
}
|
||||||
|
|
||||||
|
for rejected_path in "${rejected_paths[@]}"; do
|
||||||
|
if [[ "${validated_path}" == "${rejected_path}" ]]; then
|
||||||
|
build_directory_validation_error "broad or system parent directory" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
workdir="$(realpath "${VAR_WORKDIR}" 2>/dev/null)" || {
|
||||||
|
build_directory_validation_error "repository work directory cannot be resolved" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
}
|
||||||
|
secret_root="$(realpath "${VAR_TMP_SECRET}" 2>/dev/null)" || {
|
||||||
|
build_directory_validation_error "secret root cannot be resolved" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${workdir}" == "${validated_path}" || "${workdir}" == "${validated_path}/"* || "${validated_path}" == "${workdir}/"* \
|
||||||
|
|| "${validated_path}" == "${secret_root}" || "${validated_path}" == "${secret_root}/"* ]]; then
|
||||||
|
build_directory_validation_error "path is outside the dedicated build-directory policy" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${output_variable}" ]]; then
|
||||||
|
printf -v "${output_variable}" '%s' "${validated_path}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_build_directory_path
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates the builder-owned marker for an exact build directory.
|
||||||
|
# Globals:
|
||||||
|
# EUID
|
||||||
|
# Arguments:
|
||||||
|
# 1: candidate path
|
||||||
|
# 2: quiet flag
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_BUILD_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_build_directory_marker() {
|
||||||
|
declare candidate="$1" quiet="${2:-false}" directory_mode="" directory_owner="" marker="" marker_build_dir=""
|
||||||
|
declare expected_marker_value="" marker_link_count="" marker_value="" mode="" owner=""
|
||||||
|
|
||||||
|
validate_build_directory_path "${candidate}" marker_build_dir "${quiet}" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
[[ -d "${marker_build_dir}" ]] || {
|
||||||
|
build_directory_validation_error "build directory does not exist" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
}
|
||||||
|
|
||||||
|
directory_owner="$(secure_stat -c '%u' "${marker_build_dir}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
directory_mode="$(secure_stat -c '%a' "${marker_build_dir}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
if [[ "${directory_owner}" != "${EUID}" ]] || (( (8#${directory_mode} & 022) != 0 )); then
|
||||||
|
build_directory_validation_error "build directory ownership or permissions are unsafe" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
marker="${marker_build_dir}/.ciss-live-builder-owned"
|
||||||
|
if [[ -L "${marker}" || ! -f "${marker}" ]]; then
|
||||||
|
build_directory_validation_error "builder-owned marker is missing or unsafe" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
owner="$(secure_stat -c '%u' "${marker}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
mode="$(secure_stat -c '%a' "${marker}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
marker_link_count="$(secure_stat -c '%h' "${marker}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
marker_value="$(cat "${marker}" || exit $?; printf '.')" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
marker_value="${marker_value%.}"
|
||||||
|
expected_marker_value="${marker_build_dir}"$'\n'
|
||||||
|
|
||||||
|
if [[ "${owner}" != "${EUID}" || "${mode}" != "400" || "${marker_link_count}" != "1" \
|
||||||
|
|| "${marker_value}" != "${expected_marker_value}" ]]; then
|
||||||
|
build_directory_validation_error "builder-owned marker does not match the exact directory" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_build_directory_marker
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates an existing exact subpath below a marker-owned build directory.
|
||||||
|
# Arguments:
|
||||||
|
# 1: build directory
|
||||||
|
# 2: relative subpath
|
||||||
|
# 3: output variable name
|
||||||
|
# 4: quiet flag
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_BUILD_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_build_directory_subpath() {
|
||||||
|
declare build_directory="$1" relative_path="$2" output_variable="$3" quiet="${4:-false}"
|
||||||
|
declare candidate_subpath="" resolved_subpath=""
|
||||||
|
|
||||||
|
validate_build_directory_marker "${build_directory}" "${quiet}" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
|
||||||
|
if [[ -z "${relative_path}" || "${relative_path}" == /* || "${relative_path}" == "." || "${relative_path}" == ".." \
|
||||||
|
|| "${relative_path}" == ../* || "${relative_path}" == */../* || "${relative_path}" == */.. \
|
||||||
|
|| "${relative_path}" == ./* || "${relative_path}" == */./* || "${relative_path}" == */. ]]; then
|
||||||
|
build_directory_validation_error "unsafe relative cleanup subpath" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
candidate_subpath="${build_directory}/${relative_path}"
|
||||||
|
if [[ -L "${candidate_subpath}" || ! -e "${candidate_subpath}" ]]; then
|
||||||
|
build_directory_validation_error "cleanup subpath is missing or is a symlink" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
resolved_subpath="$(realpath "${candidate_subpath}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
if [[ "${resolved_subpath}" != "${candidate_subpath}" || "${resolved_subpath}" != "${build_directory}/"* ]]; then
|
||||||
|
build_directory_validation_error "cleanup subpath escapes the exact build directory" "${quiet}"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf -v "${output_variable}" '%s' "${resolved_subpath}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_build_directory_subpath
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Initialises a new or empty build directory and its ownership marker.
|
||||||
|
# Arguments:
|
||||||
|
# 1: candidate path
|
||||||
|
# 2: output variable name
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_BUILD_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
initialize_build_directory() {
|
||||||
|
declare candidate="$1" output_variable="$2" directory_mode="" directory_owner="" existing_entry=""
|
||||||
|
declare initialized_build_dir="" marker=""
|
||||||
|
|
||||||
|
validate_build_directory_path "${candidate}" initialized_build_dir || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
|
||||||
|
if [[ ! -e "${initialized_build_dir}" ]]; then
|
||||||
|
mkdir -m 0700 "${initialized_build_dir}" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
validate_build_directory_path "${initialized_build_dir}" initialized_build_dir || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
[[ -d "${initialized_build_dir}" && ! -L "${initialized_build_dir}" ]] || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
|
||||||
|
directory_owner="$(secure_stat -c '%u' "${initialized_build_dir}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
directory_mode="$(secure_stat -c '%a' "${initialized_build_dir}" 2>/dev/null)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
if [[ "${directory_owner}" != "${EUID}" ]] || (( (8#${directory_mode} & 022) != 0 )); then
|
||||||
|
build_directory_validation_error "build directory ownership or permissions are unsafe"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
marker="${initialized_build_dir}/.ciss-live-builder-owned"
|
||||||
|
|
||||||
|
if [[ -e "${marker}" || -L "${marker}" ]]; then
|
||||||
|
validate_build_directory_marker "${initialized_build_dir}" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
else
|
||||||
|
existing_entry="$(find "${initialized_build_dir}" -mindepth 1 -maxdepth 1 -print -quit)" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
if [[ -n "${existing_entry}" ]]; then
|
||||||
|
build_directory_validation_error "non-empty directory has no builder-owned marker"
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
(umask 077; printf '%s\n' "${initialized_build_dir}" >| "${marker}") || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
chmod 0400 "${marker}" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
validate_build_directory_marker "${initialized_build_dir}" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf -v "${output_variable}" '%s' "${initialized_build_dir}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f initialize_build_directory
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Removes paths with a one-filesystem boundary where supported.
|
||||||
|
# Arguments:
|
||||||
|
# paths to remove
|
||||||
|
# Returns:
|
||||||
|
# rm exit status
|
||||||
|
#######################################
|
||||||
|
remove_build_paths() {
|
||||||
|
# shellcheck disable=SC2312
|
||||||
|
if rm --help 2>&1 | grep -q -- '--one-file-system'; then
|
||||||
|
rm -rf --one-file-system -- "$@"
|
||||||
|
else
|
||||||
|
rm -rf -- "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f remove_build_paths
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Deletes all content except the ownership marker from an exact build directory.
|
||||||
|
# Arguments:
|
||||||
|
# 1: candidate path
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_BUILD_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
clean_build_directory_contents() {
|
||||||
|
declare candidate="$1" build_entry=""
|
||||||
|
declare -a build_entries=()
|
||||||
|
declare -i old_dotglob=0 old_failglob=0 old_nullglob=0
|
||||||
|
|
||||||
|
validate_build_directory_marker "${candidate}" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
|
||||||
|
shopt -q dotglob && old_dotglob=1
|
||||||
|
shopt -q failglob && old_failglob=1
|
||||||
|
shopt -q nullglob && old_nullglob=1
|
||||||
|
shopt -s dotglob nullglob
|
||||||
|
shopt -u failglob
|
||||||
|
|
||||||
|
build_entries=("${candidate}"/*)
|
||||||
|
for build_entry in "${build_entries[@]}"; do
|
||||||
|
[[ "${build_entry}" == "${candidate}/.ciss-live-builder-owned" ]] && continue
|
||||||
|
remove_build_paths "${build_entry}" || {
|
||||||
|
if (( old_dotglob )); then shopt -s dotglob; else shopt -u dotglob; fi
|
||||||
|
if (( old_failglob )); then shopt -s failglob; else shopt -u failglob; fi
|
||||||
|
if (( old_nullglob )); then shopt -s nullglob; else shopt -u nullglob; fi
|
||||||
|
return "${ERR_BUILD_PATH:-217}"
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
|
if (( old_dotglob )); then shopt -s dotglob; else shopt -u dotglob; fi
|
||||||
|
if (( old_failglob )); then shopt -s failglob; else shopt -u failglob; fi
|
||||||
|
if (( old_nullglob )); then shopt -s nullglob; else shopt -u nullglob; fi
|
||||||
|
|
||||||
|
validate_build_directory_marker "${candidate}" || return "${ERR_BUILD_PATH:-217}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f clean_build_directory_contents
|
||||||
|
|
||||||
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||||
+17
-1
@@ -19,6 +19,9 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
|
|||||||
# VAR_HANDLER_BUILD_DIR
|
# VAR_HANDLER_BUILD_DIR
|
||||||
# VAR_HANDLER_CDI
|
# VAR_HANDLER_CDI
|
||||||
# VAR_KERNEL
|
# VAR_KERNEL
|
||||||
|
# VAR_PRIMORDIAL_KEY
|
||||||
|
# VAR_PRIMORDIAL_SSH_PORT
|
||||||
|
# VAR_PRIMORDIAL_URL
|
||||||
# VAR_WORKDIR
|
# VAR_WORKDIR
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# None
|
# None
|
||||||
@@ -38,7 +41,20 @@ cdi() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
install -m 0755 -o root -g root "${VAR_WORKDIR}/scripts/usr/local/sbin/9999_cdi_starter.sh" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/usr/local/sbin/9999_cdi_starter.sh"
|
declare var_cdi_starter="${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/usr/local/sbin/9999_cdi_starter.sh"
|
||||||
|
declare var_primordial_key_q="" var_primordial_ssh_port_q="" var_primordial_url_q=""
|
||||||
|
|
||||||
|
install -m 0755 -o root -g root "${VAR_WORKDIR}/scripts/usr/local/sbin/9999_cdi_starter.sh" "${var_cdi_starter}"
|
||||||
|
|
||||||
|
printf -v var_primordial_key_q '%q' "${VAR_PRIMORDIAL_KEY:-}"
|
||||||
|
printf -v var_primordial_ssh_port_q '%q' "${VAR_PRIMORDIAL_SSH_PORT:-}"
|
||||||
|
printf -v var_primordial_url_q '%q' "${VAR_PRIMORDIAL_URL:-}"
|
||||||
|
|
||||||
|
sed -i \
|
||||||
|
-e "s|^declare -gx VAR_PRIMORDIAL_KEY=.*$|declare -gx VAR_PRIMORDIAL_KEY=${var_primordial_key_q} # Primordial SSH identity filename.|" \
|
||||||
|
-e "s|^declare -gx VAR_PRIMORDIAL_SSH_PORT=.*$|declare -gx VAR_PRIMORDIAL_SSH_PORT=${var_primordial_ssh_port_q} # Primordial SSH port.|" \
|
||||||
|
-e "s|^declare -gx VAR_PRIMORDIAL_URL=.*$|declare -gx VAR_PRIMORDIAL_URL=${var_primordial_url_q} # Primordial HTTPS Git URL.|" \
|
||||||
|
"${var_cdi_starter}"
|
||||||
|
|
||||||
declare tmp_entry
|
declare tmp_entry
|
||||||
tmp_entry="$(mktemp)"
|
tmp_entry="$(mktemp)"
|
||||||
|
|||||||
+14
-24
@@ -23,36 +23,26 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
|
|||||||
# 0: on success
|
# 0: on success
|
||||||
#######################################
|
#######################################
|
||||||
x_remove() {
|
x_remove() {
|
||||||
|
declare luks_key_filename="${VAR_LUKS_KEY:-luks.txt}" luks_key_path="" signing_pass_path=""
|
||||||
|
declare -a find_args=("${VAR_TMP_SECRET}" -xdev -type f)
|
||||||
|
|
||||||
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
|
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
|
||||||
|
|
||||||
declare _old_nullglob="" _old_dotglob=""
|
validate_secret_staging_area || return "${ERR_SECRET_PATH}"
|
||||||
|
|
||||||
### Enable nullglob/dotglob, disable failglob for safe globbing.
|
|
||||||
_old_nullglob="$(shopt -p nullglob || true)"
|
|
||||||
_old_dotglob="$( shopt -p dotglob || true)"
|
|
||||||
|
|
||||||
shopt -s nullglob dotglob
|
|
||||||
|
|
||||||
if [[ "${VAR_SIGNER}" == "true" ]]; then
|
if [[ "${VAR_SIGNER}" == "true" ]]; then
|
||||||
|
validate_secret_file_in_root "${VAR_SIGNING_KEY_PASS}" "signing passphrase file" || return "${ERR_SECRET_PATH}"
|
||||||
# shellcheck disable=SC2312
|
signing_pass_path="${VAR_TMP_SECRET}/${VAR_SIGNING_KEY_PASS}"
|
||||||
find "${VAR_TMP_SECRET}" -xdev -type f \
|
find_args+=(! -path "${signing_pass_path}")
|
||||||
! -path "${VAR_TMP_SECRET}/signing_key_pass.txt" \
|
|
||||||
! -path "${VAR_TMP_SECRET}/luks.txt" \
|
|
||||||
-print0 \
|
|
||||||
| xargs -0 --no-run-if-empty shred -fzu -n 5 --
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
### Removes secrets securely.
|
|
||||||
# shellcheck disable=SC2312
|
|
||||||
find "${VAR_TMP_SECRET}" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 --
|
|
||||||
find "${VAR_TMP_SECRET}" -xdev -depth -type d -empty -delete
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
eval "${_old_nullglob}" 2>/dev/null || true
|
validate_secret_file_in_root "${luks_key_filename}" "LUKS key file" || return "${ERR_SECRET_PATH}"
|
||||||
eval "${_old_dotglob}" 2>/dev/null || true
|
luks_key_path="${VAR_TMP_SECRET}/${luks_key_filename}"
|
||||||
|
find_args+=(! -path "${luks_key_path}")
|
||||||
|
|
||||||
|
# shellcheck disable=SC2312
|
||||||
|
find "${find_args[@]}" -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 --
|
||||||
|
find "${VAR_TMP_SECRET}" -xdev -depth -type d -empty -delete
|
||||||
|
|
||||||
printf "\e[92m✅ %s successfully applied. \e[0m\n" "${BASH_SOURCE[0]}"
|
printf "\e[92m✅ %s successfully applied. \e[0m\n" "${BASH_SOURCE[0]}"
|
||||||
|
|
||||||
|
|||||||
+29
-32
@@ -32,15 +32,7 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
|
|||||||
# 0: on success
|
# 0: on success
|
||||||
#######################################
|
#######################################
|
||||||
clean_up() {
|
clean_up() {
|
||||||
declare clean_exit_code="$1" fs_type="" _old_nullglob="" _old_dotglob="" _old_failglob=""
|
declare chroot_directory="" clean_exit_code="$1" fs_type="" includes_directory=""
|
||||||
|
|
||||||
### Enable nullglob/dotglob, disable failglob for safe globbing.
|
|
||||||
_old_nullglob="$(shopt -p nullglob || true)"
|
|
||||||
_old_dotglob="$( shopt -p dotglob || true)"
|
|
||||||
_old_failglob="$(shopt -p failglob || true)"
|
|
||||||
|
|
||||||
shopt -s nullglob dotglob
|
|
||||||
shopt -u failglob
|
|
||||||
|
|
||||||
if [[ -e /dev/mapper/crypt_liveiso ]]; then
|
if [[ -e /dev/mapper/crypt_liveiso ]]; then
|
||||||
cryptsetup close crypt_liveiso || true
|
cryptsetup close crypt_liveiso || true
|
||||||
@@ -52,10 +44,10 @@ clean_up() {
|
|||||||
rm -f -- "${VAR_NOTES}"
|
rm -f -- "${VAR_NOTES}"
|
||||||
|
|
||||||
### Release advisory lock on FD 127.
|
### Release advisory lock on FD 127.
|
||||||
flock -u 127
|
flock -u 127 2>/dev/null || true
|
||||||
|
|
||||||
### Close file descriptor 127.
|
### Close file descriptor 127.
|
||||||
exec 127>&-
|
exec 127>&- 2>/dev/null || true
|
||||||
|
|
||||||
### Remove the lockfile artifact.
|
### Remove the lockfile artifact.
|
||||||
rm -f /run/lock/ciss_live_builder.lock
|
rm -f /run/lock/ciss_live_builder.lock
|
||||||
@@ -100,36 +92,41 @@ clean_up() {
|
|||||||
### No tracing for security reasons ------------------------------------------------------------------------------------------
|
### No tracing for security reasons ------------------------------------------------------------------------------------------
|
||||||
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set +x
|
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set +x
|
||||||
|
|
||||||
### Removes secrets securely.
|
### Removes secrets securely only after re-validating the fixed tmpfs staging area.
|
||||||
|
if validate_secret_staging_area "true"; then
|
||||||
# shellcheck disable=SC2312
|
# shellcheck disable=SC2312
|
||||||
find "${VAR_TMP_SECRET}" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 --
|
find "${VAR_TMP_SECRET}" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 -- || true
|
||||||
find "${VAR_TMP_SECRET}" -xdev -depth -type d -empty -delete
|
find "${VAR_TMP_SECRET}" -xdev -depth -type d -empty -delete || true
|
||||||
|
else
|
||||||
### Securely shred all regular files below ./includes.chroot, then remove empty dirs.
|
printf "\e[93m⚠ Secret cleanup skipped because the staging area failed validation. \e[0m\n" >&2
|
||||||
if [[ -d "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" ]]; then
|
|
||||||
|
|
||||||
# shellcheck disable=SC2312
|
|
||||||
find "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 --
|
|
||||||
|
|
||||||
### Remove empty directories (bottom-up).
|
|
||||||
find "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" -depth -xdev -type d -empty -delete
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
### Delete all files and directories below ./chroot.
|
### Destructive build cleanup requires the exact builder-owned directory marker.
|
||||||
if [[ -d "${VAR_HANDLER_BUILD_DIR}/chroot" ]]; then
|
if [[ -n "${VAR_HANDLER_BUILD_DIR}" ]] && validate_build_directory_marker "${VAR_HANDLER_BUILD_DIR}" "true"; then
|
||||||
|
if [[ -e "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" || -L "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot" ]]; then
|
||||||
rm -rf "${VAR_HANDLER_BUILD_DIR}/chroot"
|
if validate_build_directory_subpath "${VAR_HANDLER_BUILD_DIR}" "config/includes.chroot" includes_directory "true"; then
|
||||||
|
# shellcheck disable=SC2312
|
||||||
|
find "${includes_directory}" -xdev -type f -print0 | xargs -0 --no-run-if-empty shred -fzu -n 5 -- || true
|
||||||
|
find "${includes_directory}" -depth -xdev -type d -empty -delete || true
|
||||||
|
else
|
||||||
|
printf "\e[93m⚠ Build includes cleanup skipped because the exact subpath failed validation. \e[0m\n" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -e "${VAR_HANDLER_BUILD_DIR}/chroot" || -L "${VAR_HANDLER_BUILD_DIR}/chroot" ]]; then
|
||||||
|
if validate_build_directory_subpath "${VAR_HANDLER_BUILD_DIR}" "chroot" chroot_directory "true"; then
|
||||||
|
remove_build_paths "${chroot_directory}" || true
|
||||||
|
else
|
||||||
|
printf "\e[93m⚠ Build chroot cleanup skipped because the exact subpath failed validation. \e[0m\n" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
elif [[ -n "${VAR_HANDLER_BUILD_DIR}" ]]; then
|
||||||
|
printf "\e[93m⚠ Build-directory cleanup skipped because the exact builder-owned marker failed validation. \e[0m\n" >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
### Turn on tracing again ----------------------------------------------------------------------------------------------------
|
### Turn on tracing again ----------------------------------------------------------------------------------------------------
|
||||||
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set -x
|
[[ "${VAR_EARLY_DEBUG}" == "true" ]] && set -x
|
||||||
|
|
||||||
eval "${_old_nullglob}" 2>/dev/null || true
|
|
||||||
eval "${_old_dotglob}" 2>/dev/null || true
|
|
||||||
eval "${_old_failglob}" 2>/dev/null || true
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
### Prevents accidental 'unset -f'.
|
### Prevents accidental 'unset -f'.
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-Version: 3.0
|
||||||
|
# SPDX-CreationInfo: 2026-06-11; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||||
|
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||||
|
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-FileType: SOURCE
|
||||||
|
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
|
||||||
|
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||||
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
|
guard_sourcing || return "${ERR_GUARD_SRCE}"
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Replaces exact registered secret values in one controlled log file.
|
||||||
|
# Globals:
|
||||||
|
# _ARY_SECRET_REDACTION_VALUES
|
||||||
|
# Arguments:
|
||||||
|
# 1: log file
|
||||||
|
# Returns:
|
||||||
|
# 0: on success or missing log
|
||||||
|
# ERR_SANITIZING: on failure
|
||||||
|
#######################################
|
||||||
|
sanitize_debug_log() {
|
||||||
|
declare log_file="$1" log_text="" replacement="" secret_value="" tmp_file=""
|
||||||
|
|
||||||
|
[[ -n "${log_file}" && -f "${log_file}" ]] || return 0
|
||||||
|
[[ ! -L "${log_file}" ]] || return "${ERR_SANITIZING:-133}"
|
||||||
|
|
||||||
|
log_text="$(cat "${log_file}" || exit $?; printf '.')" || return "${ERR_SANITIZING:-133}"
|
||||||
|
log_text="${log_text%.}"
|
||||||
|
|
||||||
|
for secret_value in "${_ARY_SECRET_REDACTION_VALUES[@]}"; do
|
||||||
|
[[ -n "${secret_value}" ]] || continue
|
||||||
|
printf -v replacement '%*s' "${#secret_value}" ''
|
||||||
|
replacement="${replacement// /*}"
|
||||||
|
log_text="${log_text//"${secret_value}"/"${replacement}"}"
|
||||||
|
done
|
||||||
|
|
||||||
|
tmp_file="$(mktemp "${log_file}.sanitize.XXXXXX")" || return "${ERR_SANITIZING:-133}"
|
||||||
|
chmod 0600 "${tmp_file}" || {
|
||||||
|
rm -f "${tmp_file}"
|
||||||
|
return "${ERR_SANITIZING:-133}"
|
||||||
|
}
|
||||||
|
printf '%s' "${log_text}" >| "${tmp_file}" || {
|
||||||
|
rm -f "${tmp_file}"
|
||||||
|
return "${ERR_SANITIZING:-133}"
|
||||||
|
}
|
||||||
|
mv -f "${tmp_file}" "${log_file}" || {
|
||||||
|
rm -f "${tmp_file}"
|
||||||
|
return "${ERR_SANITIZING:-133}"
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f sanitize_debug_log
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Runs the final exact-value sanitisation pass for controlled logs.
|
||||||
|
# Globals:
|
||||||
|
# LOG_DEBUG
|
||||||
|
# LOG_ERROR
|
||||||
|
# LOG_VAR
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_SANITIZING: on failure
|
||||||
|
#######################################
|
||||||
|
sanitize_debug_logs() {
|
||||||
|
declare log_file=""
|
||||||
|
declare -a log_files=("${LOG_DEBUG:-}" "${LOG_VAR:-}" "${LOG_ERROR:-}")
|
||||||
|
|
||||||
|
set +x
|
||||||
|
if [[ -e "/proc/$$/fd/42" || -e "/dev/fd/42" ]]; then
|
||||||
|
exec 42>&-
|
||||||
|
fi
|
||||||
|
|
||||||
|
for log_file in "${log_files[@]}"; do
|
||||||
|
sanitize_debug_log "${log_file}" || return "${ERR_SANITIZING:-133}"
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f sanitize_debug_logs
|
||||||
|
|
||||||
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||||
@@ -41,6 +41,12 @@ init_gnupg() {
|
|||||||
|
|
||||||
if [[ "${VAR_SIGNER}" == "true" ]]; then
|
if [[ "${VAR_SIGNER}" == "true" ]]; then
|
||||||
|
|
||||||
|
validate_secret_file_in_root "${VAR_SIGNING_KEY}" "signing key file" || return "${ERR_SECRET_PATH}"
|
||||||
|
validate_secret_file_in_root "${VAR_SIGNING_KEY_PASS}" "signing passphrase file" || return "${ERR_SECRET_PATH}"
|
||||||
|
if [[ -n "${VAR_SIGNING_CA}" ]]; then
|
||||||
|
validate_secret_file_in_root "${VAR_SIGNING_CA}" "signing CA file" || return "${ERR_SECRET_PATH}"
|
||||||
|
fi
|
||||||
|
|
||||||
__umask=$(umask)
|
__umask=$(umask)
|
||||||
umask 0077
|
umask 0077
|
||||||
|
|
||||||
@@ -82,6 +88,7 @@ EOF
|
|||||||
|
|
||||||
declare __pw=""
|
declare __pw=""
|
||||||
__pw="$(<"${VAR_SIGNING_KEY_PASSFILE}")"; __pw="${__pw%$'\r'}"; printf '%s' "${__pw}" >| "${VAR_SIGNING_KEY_PASSFILE}"
|
__pw="$(<"${VAR_SIGNING_KEY_PASSFILE}")"; __pw="${__pw%$'\r'}"; printf '%s' "${__pw}" >| "${VAR_SIGNING_KEY_PASSFILE}"
|
||||||
|
register_secret_value "${__pw}"
|
||||||
__pw="" && unset __pw
|
__pw="" && unset __pw
|
||||||
|
|
||||||
### Turn on tracing again ----------------------------------------------------------------------------------------------------
|
### Turn on tracing again ----------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -13,13 +13,14 @@
|
|||||||
guard_sourcing || return "${ERR_GUARD_SRCE}"
|
guard_sourcing || return "${ERR_GUARD_SRCE}"
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Module for accompanying all 'CISS.debian.hardening' features into the Live ISO image.
|
# Module for following all 'CISS.debian.hardening' features into the Live ISO image.
|
||||||
# Globals:
|
# Globals:
|
||||||
# ARY_HANDLER_JUMPHOST
|
# ARY_HANDLER_JUMPHOST
|
||||||
# ARY_HANDLER_JUMPHOST_UNIQUE
|
# ARY_HANDLER_JUMPHOST_UNIQUE
|
||||||
# BASH_SOURCE
|
# BASH_SOURCE
|
||||||
# VAR_ARCHITECTURE
|
# VAR_ARCHITECTURE
|
||||||
# VAR_HANDLER_BUILD_DIR
|
# VAR_HANDLER_BUILD_DIR
|
||||||
|
# VAR_PRIMORDIAL_SSH_PORT
|
||||||
# VAR_SSHFP
|
# VAR_SSHFP
|
||||||
# VAR_SSHPORT
|
# VAR_SSHPORT
|
||||||
# VAR_SSHPUBKEY
|
# VAR_SSHPUBKEY
|
||||||
@@ -181,6 +182,8 @@ hardening_ultra() {
|
|||||||
printf "\e[95m🧪 Updating SSH Keys, Ports ... \e[0m\n"
|
printf "\e[95m🧪 Updating SSH Keys, Ports ... \e[0m\n"
|
||||||
|
|
||||||
### ./config/includes.chroot/root/.ssh ---------------------------------------------------------------------------------------
|
### ./config/includes.chroot/root/.ssh ---------------------------------------------------------------------------------------
|
||||||
|
validate_secret_absolute_directory "${VAR_SSHPUBKEY}" "SSH public-key directory" || return "${ERR_SECRET_PATH}"
|
||||||
|
validate_secret_file "${VAR_SSHPUBKEY}/authorized_keys" "SSH authorized_keys file" || return "${ERR_SECRET_PATH}"
|
||||||
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
|
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
|
||||||
install -m 0600 -o root -g root "${VAR_SSHPUBKEY}/authorized_keys" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/"
|
install -m 0600 -o root -g root "${VAR_SSHPUBKEY}/authorized_keys" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/"
|
||||||
|
|
||||||
@@ -196,12 +199,26 @@ hardening_ultra() {
|
|||||||
sed -i "s|PORT_MUST_BE_SET|${sshport}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_hardening_fail2ban.chroot"
|
sed -i "s|PORT_MUST_BE_SET|${sshport}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_hardening_fail2ban.chroot"
|
||||||
|
|
||||||
### /config/hooks/live/0900_ufw_setup.chroot
|
### /config/hooks/live/0900_ufw_setup.chroot
|
||||||
sed -i "s|SSHPORT_MUST_BE_SET|${sshport}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot"
|
declare ufw_file="${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot"
|
||||||
|
sed -i "s|SSHPORT_MUST_BE_SET|${sshport}|g" "${ufw_file}"
|
||||||
|
|
||||||
|
declare primordial_ssh_port="${VAR_PRIMORDIAL_SSH_PORT:-}"
|
||||||
|
if [[ -n "${primordial_ssh_port}" ]]; then
|
||||||
|
|
||||||
|
sed -i "s|^# PRIMORDIAL_SSH_PORT_DECLARATION_MUST_BE_SET$|declare -r PRIMORDIAL_SSH_PORT=\"${primordial_ssh_port}\"|" "${ufw_file}"
|
||||||
|
sed -i "s|^[[:space:]]*# PRIMORDIAL_SSH_RULE_MUST_BE_SET$| ufw allow out \"\${PRIMORDIAL_SSH_PORT}\"/tcp comment 'Outgoing Primordial SSH'|" "${ufw_file}"
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
sed -i '/^# PRIMORDIAL_SSH_PORT_DECLARATION_MUST_BE_SET$/d' "${ufw_file}"
|
||||||
|
sed -i '/^[[:space:]]*# PRIMORDIAL_SSH_RULE_MUST_BE_SET$/d' "${ufw_file}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
### /config/hooks/live/0900_ufw_setup.chroot
|
### /config/hooks/live/0900_ufw_setup.chroot
|
||||||
if [[ ${#ARY_HANDLER_JUMPHOST[@]} -gt 0 ]]; then
|
if [[ ${#ARY_HANDLER_JUMPHOST[@]} -gt 0 ]]; then
|
||||||
|
|
||||||
declare file="${VAR_HANDLER_BUILD_DIR}/config/hooks/live/0900_ufw_setup.chroot"
|
declare file="${ufw_file}"
|
||||||
|
|
||||||
sed -i "/^ufw allow in \"\${SSHPORT}\"\/tcp comment 'Incoming SSH (Custom-Port)'$/d" "${file}"
|
sed -i "/^ufw allow in \"\${SSHPORT}\"\/tcp comment 'Incoming SSH (Custom-Port)'$/d" "${file}"
|
||||||
|
|
||||||
@@ -251,7 +268,7 @@ hardening_ultra() {
|
|||||||
### ./config/hooks/live/9950_hardening_fail2ban.chroot -----------------------------------------------------------------------
|
### ./config/hooks/live/9950_hardening_fail2ban.chroot -----------------------------------------------------------------------
|
||||||
if ((${#ARY_HANDLER_JUMPHOST[@]} > 0)); then
|
if ((${#ARY_HANDLER_JUMPHOST[@]} > 0)); then
|
||||||
|
|
||||||
printf "\e[95m🧪 Updating fail2ban Jumphosts IPs ... \e[0m\n"
|
printf "\e[95m🧪 Updating fail2ban Jump-hosts IPs ... \e[0m\n"
|
||||||
|
|
||||||
# Join array entries with spaces, preserving any newlines
|
# Join array entries with spaces, preserving any newlines
|
||||||
declare ips="${ARY_HANDLER_JUMPHOST[*]}"
|
declare ips="${ARY_HANDLER_JUMPHOST[*]}"
|
||||||
@@ -265,7 +282,7 @@ hardening_ultra() {
|
|||||||
# Perform an in-place replacement of IGNORE_IP_MUST_BE_SET with the cleaned list
|
# Perform an in-place replacement of IGNORE_IP_MUST_BE_SET with the cleaned list
|
||||||
sed -i -E "/^[[:space:]]*ignoreip[[:space:]]*=/ s|IGNORE_IP_MUST_BE_SET|${flat_ips}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_hardening_fail2ban.chroot"
|
sed -i -E "/^[[:space:]]*ignoreip[[:space:]]*=/ s|IGNORE_IP_MUST_BE_SET|${flat_ips}|g" "${VAR_HANDLER_BUILD_DIR}/config/hooks/live/9950_hardening_fail2ban.chroot"
|
||||||
|
|
||||||
printf "\e[92m✅ Updating fail2ban Jumphosts IPs done. \e[0m\n"
|
printf "\e[92m✅ Updating fail2ban Jump-hosts IPs done. \e[0m\n"
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
|||||||
@@ -23,36 +23,22 @@ guard_sourcing || return "${ERR_GUARD_SRCE}"
|
|||||||
# 0: on success
|
# 0: on success
|
||||||
#######################################
|
#######################################
|
||||||
lb_config_start() {
|
lb_config_start() {
|
||||||
|
declare canonical_build_dir=""
|
||||||
|
|
||||||
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
|
printf "\e[95m🧪 %s starting ... \e[0m\n" "${BASH_SOURCE[0]}"
|
||||||
|
|
||||||
if [[ ! -d ${VAR_HANDLER_BUILD_DIR} ]]; then
|
initialize_build_directory "${VAR_HANDLER_BUILD_DIR}" canonical_build_dir || return "${ERR_BUILD_PATH}"
|
||||||
|
VAR_HANDLER_BUILD_DIR="${canonical_build_dir}"
|
||||||
mkdir -p "${VAR_HANDLER_BUILD_DIR}"
|
cd "${VAR_HANDLER_BUILD_DIR}" || return "${ERR_BUILD_PATH}"
|
||||||
# shellcheck disable=SC2164
|
|
||||||
cd "${VAR_HANDLER_BUILD_DIR}"
|
|
||||||
printf "\e[92m✅ '%s' created. \e[0m\n" "${VAR_HANDLER_BUILD_DIR}"
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
# shellcheck disable=SC2164
|
|
||||||
cd "${VAR_HANDLER_BUILD_DIR}"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -d "${VAR_HANDLER_BUILD_DIR}/.build" ]]; then
|
if [[ -d "${VAR_HANDLER_BUILD_DIR}/.build" ]]; then
|
||||||
|
|
||||||
# shellcheck disable=SC2164
|
validate_build_directory_marker "${VAR_HANDLER_BUILD_DIR}" || return "${ERR_BUILD_PATH}"
|
||||||
cd "${VAR_HANDLER_BUILD_DIR}"
|
|
||||||
|
|
||||||
printf "\e[95m🧪 Deleting former config, binary and cache ... \e[0m\n"
|
printf "\e[95m🧪 Deleting former config, binary and cache ... \e[0m\n"
|
||||||
|
|
||||||
lb clean --binary --cache --purge --source
|
lb clean --binary --cache --purge --source
|
||||||
|
clean_build_directory_contents "${VAR_HANDLER_BUILD_DIR}" || return "${ERR_BUILD_PATH}"
|
||||||
if [[ "${PWD}" == "${VAR_HANDLER_BUILD_DIR}" && "${PWD}" != "/" && -n "${PWD}" ]]; then
|
|
||||||
|
|
||||||
rm -rf -- ./* ./.??*
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf "\e[92m✅ Deleting former config, binary and cache done.\e[0m\n"
|
printf "\e[92m✅ Deleting former config, binary and cache done.\e[0m\n"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-Version: 3.0
|
||||||
|
# SPDX-CreationInfo: 2026-06-10; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||||
|
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||||
|
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-FileType: SOURCE
|
||||||
|
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
|
||||||
|
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||||
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Logo Wrapper CISS.debian.live.builder
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
#######################################
|
||||||
|
logo() {
|
||||||
|
clear
|
||||||
|
printf '\033[95m'
|
||||||
|
cat centurion.txt
|
||||||
|
printf '\033[0m\n'
|
||||||
|
sleep 4
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f logo
|
||||||
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||||
+25
-5
@@ -84,24 +84,44 @@ init_primordial() {
|
|||||||
### Check for SOPS AGE key integration ---------------------------------------------------------------------------------------
|
### Check for SOPS AGE key integration ---------------------------------------------------------------------------------------
|
||||||
if [[ "${VAR_AGE,,}" == "true" ]]; then
|
if [[ "${VAR_AGE,,}" == "true" ]]; then
|
||||||
|
|
||||||
|
validate_secret_file_in_root "${VAR_AGE_KEY}" "SOPS Age key" || return "${ERR_SECRET_PATH}"
|
||||||
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.config/sops/age"
|
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.config/sops/age"
|
||||||
install -m 0400 "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.config/sops/age/keys.txt"
|
install -m 0400 "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.config/sops/age/keys.txt"
|
||||||
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" 2>/dev/null || rm -f "${VAR_TMP_SECRET}/${VAR_AGE_KEY}"
|
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/${VAR_AGE_KEY}" 2>/dev/null || rm -f "${VAR_TMP_SECRET}/${VAR_AGE_KEY}"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
### Check for SSH CISS and PhysNet primordial-workflow(tm) integration -------------------------------------------------------
|
### Check for SSH CISS and PhysNet Primordial-Workflow™ integration -------------------------------------------------------
|
||||||
if [[ "${VAR_SSHFP,,}" == "true" ]]; then
|
if [[ "${VAR_SSHFP,,}" == "true" ]]; then
|
||||||
|
declare secret_key_file=""
|
||||||
|
declare -a identity_files=() host_key_files=()
|
||||||
|
|
||||||
|
validate_secret_directory "${VAR_TMP_SECRET}" "secret root" "true" || return "${ERR_SECRET_PATH}"
|
||||||
|
|
||||||
|
while IFS= read -r -d '' secret_key_file; do
|
||||||
|
validate_secret_file "${secret_key_file}" "primordial SSH identity file" || return "${ERR_SECRET_PATH}"
|
||||||
|
identity_files+=("${secret_key_file}")
|
||||||
|
done < <(find "${VAR_TMP_SECRET}" -maxdepth 1 -type f -name 'id*' -print0)
|
||||||
|
|
||||||
|
while IFS= read -r -d '' secret_key_file; do
|
||||||
|
validate_secret_file "${secret_key_file}" "primordial SSH host-key file" || return "${ERR_SECRET_PATH}"
|
||||||
|
host_key_files+=("${secret_key_file}")
|
||||||
|
done < <(find "${VAR_TMP_SECRET}" -maxdepth 1 -type f -name 'ssh_host_*' -print0)
|
||||||
|
|
||||||
|
(( ${#identity_files[@]} > 0 && ${#host_key_files[@]} > 0 )) || {
|
||||||
|
secret_validation_error "required primordial SSH key files are missing"
|
||||||
|
return "${ERR_SECRET_PATH}"
|
||||||
|
}
|
||||||
|
|
||||||
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
|
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
|
||||||
install -m 0600 "${VAR_TMP_SECRET}/id"* "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/"
|
install -m 0600 "${identity_files[@]}" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh/"
|
||||||
normalize_ssh_keys_in_dir "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
|
normalize_ssh_keys_in_dir "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/.ssh"
|
||||||
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/id"* 2>/dev/null || rm -f "${VAR_TMP_SECRET}/id"*
|
shred -fzu -n 5 -- "${identity_files[@]}" 2>/dev/null || rm -f "${identity_files[@]}"
|
||||||
|
|
||||||
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh"
|
install -d -m 0700 "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh"
|
||||||
install -m 0600 "${VAR_TMP_SECRET}/ssh_host_"* "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh/"
|
install -m 0600 "${host_key_files[@]}" "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh/"
|
||||||
normalize_ssh_keys_in_dir "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh/"
|
normalize_ssh_keys_in_dir "${VAR_HANDLER_BUILD_DIR}/config/includes.chroot/root/ssh/"
|
||||||
shred -fzu -n 5 -- "${VAR_TMP_SECRET}/ssh_host_"* 2>/dev/null || rm -f "${VAR_TMP_SECRET}/ssh_host_"*
|
shred -fzu -n 5 -- "${host_key_files[@]}" 2>/dev/null || rm -f "${host_key_files[@]}"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ sanitize_arg() {
|
|||||||
{
|
{
|
||||||
printf "❌ Control character : '%s'. \n" "${disallowed_ctrl}"
|
printf "❌ Control character : '%s'. \n" "${disallowed_ctrl}"
|
||||||
printf "❌ in argument : '%s'. \n" "${input}"
|
printf "❌ in argument : '%s'. \n" "${input}"
|
||||||
printf "❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" - + space' \n"
|
printf "❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" @ %% , ~ - + space' \n"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
} >> "${LOG_ERROR}"
|
} >> "${LOG_ERROR}"
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ sanitize_arg() {
|
|||||||
|
|
||||||
printf "\e[91m❌ Control character : '%s'. \e[0m\n" "${disallowed_ctrl}" >&2
|
printf "\e[91m❌ Control character : '%s'. \e[0m\n" "${disallowed_ctrl}" >&2
|
||||||
printf "\e[91m❌ in argument : '%s'. \e[0m\n" "${input}" >&2
|
printf "\e[91m❌ in argument : '%s'. \e[0m\n" "${input}" >&2
|
||||||
printf "\e[91m❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" - + space' \e[0m\n" >&2
|
printf "\e[91m❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" @ %% , ~ - + space' \e[0m\n" >&2
|
||||||
|
|
||||||
# shellcheck disable=SC2162
|
# shellcheck disable=SC2162
|
||||||
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
||||||
@@ -73,8 +73,8 @@ sanitize_arg() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
### Step 2: Define allowed characters:
|
### Step 2: Define allowed characters:
|
||||||
### letters, digits, dot, underscore, slash, equals, [, ], colon, double-quote, hyphen, space.
|
### letters, digits, dot, underscore, slash, equals, [, ], colon, double-quote, @, %, comma, tilde, hyphen, plus, space.
|
||||||
declare allowed='a-zA-Z0-9._/=\[\]:"\-+ '
|
declare allowed='a-zA-Z0-9._/=\[\]:"@%,~\-+ '
|
||||||
declare disallowed
|
declare disallowed
|
||||||
disallowed=$(printf '%s' "${input}" | tr -d "${allowed}")
|
disallowed=$(printf '%s' "${input}" | tr -d "${allowed}")
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ sanitize_arg() {
|
|||||||
{
|
{
|
||||||
printf "❌ Invalid character : '%s'. \n" "${disallowed//?/& }"
|
printf "❌ Invalid character : '%s'. \n" "${disallowed//?/& }"
|
||||||
printf "❌ in argument : '%s'. \n" "${input}"
|
printf "❌ in argument : '%s'. \n" "${input}"
|
||||||
printf "❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" - + space' \n"
|
printf "❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" @ %% , ~ - + space' \n"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
} >> "${LOG_ERROR}"
|
} >> "${LOG_ERROR}"
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ sanitize_arg() {
|
|||||||
|
|
||||||
printf "\e[91m❌ Invalid character : '%s'. \e[0m\n" "${disallowed//?/& }" >&2
|
printf "\e[91m❌ Invalid character : '%s'. \e[0m\n" "${disallowed//?/& }" >&2
|
||||||
printf "\e[91m❌ in argument : '%s'. \e[0m\n" "${input}" >&2
|
printf "\e[91m❌ in argument : '%s'. \e[0m\n" "${input}" >&2
|
||||||
printf "\e[91m❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" - + space' \e[0m\n" >&2
|
printf "\e[91m❌ Allowed Characters : 'a-z A-Z 0-9 . _ / = [ ] : \" @ %% , ~ - + space' \e[0m\n" >&2
|
||||||
|
|
||||||
# shellcheck disable=SC2162
|
# shellcheck disable=SC2162
|
||||||
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
read -p $'\e[92m✅ Press \'ENTER\' to exit the script ... \e[0m'
|
||||||
@@ -119,8 +119,8 @@ readonly -f sanitize_arg
|
|||||||
sanitize_string() {
|
sanitize_string() {
|
||||||
declare input="$1"
|
declare input="$1"
|
||||||
### Define allowed characters:
|
### Define allowed characters:
|
||||||
### letters, digits, dot, underscore, slash, equals, [, ], colon, double-quote, hyphen, space.
|
### letters, digits, dot, underscore, slash, equals, [, ], colon, double-quote, @, %, comma, tilde, hyphen, plus, space.
|
||||||
declare allowed='a-zA-Z0-9._/=\[\]:"\-+ '
|
declare allowed='a-zA-Z0-9._/=\[\]:"@%,~\-+ '
|
||||||
printf '%s' "${input}" | tr -cd "${allowed}"
|
printf '%s' "${input}" | tr -cd "${allowed}"
|
||||||
}
|
}
|
||||||
### Prevents accidental 'unset -f'.
|
### Prevents accidental 'unset -f'.
|
||||||
|
|||||||
@@ -0,0 +1,384 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-Version: 3.0
|
||||||
|
# SPDX-CreationInfo: 2026-06-11; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||||
|
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||||
|
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-FileType: SOURCE
|
||||||
|
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
|
||||||
|
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||||
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
|
||||||
|
guard_sourcing || return "${ERR_GUARD_SRCE}"
|
||||||
|
|
||||||
|
if ! declare -p _ARY_SECRET_REDACTION_VALUES >/dev/null 2>&1; then
|
||||||
|
declare -ga _ARY_SECRET_REDACTION_VALUES=()
|
||||||
|
fi
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Runs GNU stat on Debian and gstat on macOS development hosts.
|
||||||
|
# Arguments:
|
||||||
|
# stat arguments
|
||||||
|
# Returns:
|
||||||
|
# stat exit status
|
||||||
|
#######################################
|
||||||
|
secure_stat() {
|
||||||
|
if command -v gstat >/dev/null 2>&1; then
|
||||||
|
gstat "$@"
|
||||||
|
else
|
||||||
|
stat "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f secure_stat
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Prints a generic secret validation error without disclosing a path or value.
|
||||||
|
# Arguments:
|
||||||
|
# 1: unsafe input class
|
||||||
|
# 2: quiet flag
|
||||||
|
# Returns:
|
||||||
|
# ERR_SECRET_PATH
|
||||||
|
#######################################
|
||||||
|
secret_validation_error() {
|
||||||
|
declare error_class="$1" quiet="${2:-false}"
|
||||||
|
|
||||||
|
if [[ "${quiet}" != "true" ]]; then
|
||||||
|
printf "\e[91m❌ Unsafe secret input rejected: %s. \e[0m\n" "${error_class}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f secret_validation_error
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Registers an exact known secret value for final log redaction.
|
||||||
|
# Globals:
|
||||||
|
# _ARY_SECRET_REDACTION_VALUES
|
||||||
|
# Arguments:
|
||||||
|
# 1: secret value
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
#######################################
|
||||||
|
register_secret_value() {
|
||||||
|
declare secret_value="$1" registered_value="" was_traced="false"
|
||||||
|
|
||||||
|
[[ $- == *x* ]] && was_traced="true"
|
||||||
|
set +x
|
||||||
|
|
||||||
|
if [[ -n "${secret_value}" ]]; then
|
||||||
|
for registered_value in "${_ARY_SECRET_REDACTION_VALUES[@]}"; do
|
||||||
|
if [[ "${registered_value}" == "${secret_value}" ]]; then
|
||||||
|
[[ "${was_traced}" == "true" ]] && set -x
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
_ARY_SECRET_REDACTION_VALUES+=("${secret_value}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ "${was_traced}" == "true" ]] && set -x
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f register_secret_value
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Registers exact text values from a controlled secret file.
|
||||||
|
# Globals:
|
||||||
|
# _ARY_SECRET_REDACTION_VALUES
|
||||||
|
# Arguments:
|
||||||
|
# 1: secret file
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
#######################################
|
||||||
|
register_secret_file_for_redaction() {
|
||||||
|
declare secret_file="$1" secret_line="" secret_text="" was_traced="false"
|
||||||
|
|
||||||
|
[[ $- == *x* ]] && was_traced="true"
|
||||||
|
set +x
|
||||||
|
|
||||||
|
secret_text="$(cat "${secret_file}" || exit $?; printf '.')" || {
|
||||||
|
[[ "${was_traced}" == "true" ]] && set -x
|
||||||
|
return "${ERR_SANITIZING:-133}"
|
||||||
|
}
|
||||||
|
secret_text="${secret_text%.}"
|
||||||
|
register_secret_value "${secret_text}"
|
||||||
|
|
||||||
|
while IFS= read -r secret_line || [[ -n "${secret_line}" ]]; do
|
||||||
|
register_secret_value "${secret_line}"
|
||||||
|
done < "${secret_file}"
|
||||||
|
|
||||||
|
[[ "${was_traced}" == "true" ]] && set -x
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f register_secret_file_for_redaction
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates a filename-only secret argument.
|
||||||
|
# Arguments:
|
||||||
|
# 1: filename
|
||||||
|
# 2: input class
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_SECRET_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_secret_filename() {
|
||||||
|
declare filename="$1" input_class="${2:-filename-only secret argument}"
|
||||||
|
declare filename_regex='^[A-Za-z0-9._@%+=:,~-]+$'
|
||||||
|
|
||||||
|
if [[ -z "${filename}" || "${filename}" == "." || "${filename}" == ".." || "${filename}" == */* \
|
||||||
|
|| ! "${filename}" =~ ${filename_regex} ]]; then
|
||||||
|
secret_validation_error "${input_class}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_secret_filename
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates a restrictively permissioned secret directory.
|
||||||
|
# Arguments:
|
||||||
|
# 1: directory path
|
||||||
|
# 2: input class
|
||||||
|
# 3: require tmpfs
|
||||||
|
# 4: quiet flag
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_SECRET_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_secret_directory() {
|
||||||
|
declare directory="$1" input_class="${2:-secret directory}" require_tmpfs="${3:-false}" quiet="${4:-false}"
|
||||||
|
declare fs_type="" mode="" owner=""
|
||||||
|
|
||||||
|
if [[ -z "${directory}" || -L "${directory}" || ! -d "${directory}" ]]; then
|
||||||
|
secret_validation_error "${input_class}" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
owner="$(secure_stat -c '%u' "${directory}" 2>/dev/null)" || {
|
||||||
|
secret_validation_error "${input_class} ownership" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
mode="$(secure_stat -c '%a' "${directory}" 2>/dev/null)" || {
|
||||||
|
secret_validation_error "${input_class} permissions" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${owner}" != "${EUID}" || "${mode}" != "700" ]]; then
|
||||||
|
secret_validation_error "${input_class} ownership or permissions" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${require_tmpfs}" == "true" ]]; then
|
||||||
|
fs_type="$(secure_stat -f -c '%T' "${directory}" 2>/dev/null)" || {
|
||||||
|
secret_validation_error "${input_class} filesystem" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
if [[ "${fs_type}" != "tmpfs" && "${fs_type}" != "ramfs" ]]; then
|
||||||
|
secret_validation_error "${input_class} is not tmpfs-backed" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_secret_directory
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates and registers a secret file.
|
||||||
|
# Arguments:
|
||||||
|
# 1: file path
|
||||||
|
# 2: input class
|
||||||
|
# 3: register for redaction
|
||||||
|
# 4: quiet flag
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_SECRET_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_secret_file() {
|
||||||
|
declare secret_file="$1" input_class="${2:-secret file}" register_value="${3:-true}" quiet="${4:-false}"
|
||||||
|
declare link_count="" mode="" owner=""
|
||||||
|
|
||||||
|
if [[ -z "${secret_file}" || -L "${secret_file}" || ! -f "${secret_file}" ]]; then
|
||||||
|
secret_validation_error "${input_class}" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
owner="$(secure_stat -c '%u' "${secret_file}" 2>/dev/null)" || {
|
||||||
|
secret_validation_error "${input_class} ownership" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
mode="$(secure_stat -c '%a' "${secret_file}" 2>/dev/null)" || {
|
||||||
|
secret_validation_error "${input_class} permissions" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
link_count="$(secure_stat -c '%h' "${secret_file}" 2>/dev/null)" || {
|
||||||
|
secret_validation_error "${input_class} link count" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${owner}" != "${EUID}" || "${link_count}" != "1" || ( "${mode}" != "400" && "${mode}" != "600" ) ]]; then
|
||||||
|
secret_validation_error "${input_class} ownership, permissions, or link count" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${register_value}" == "true" ]]; then
|
||||||
|
register_secret_file_for_redaction "${secret_file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_secret_file
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates an explicitly supported absolute secret file path.
|
||||||
|
# Arguments:
|
||||||
|
# 1: file path
|
||||||
|
# 2: input class
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_SECRET_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_secret_absolute_file() {
|
||||||
|
declare secret_file="$1" input_class="${2:-absolute secret file}" resolved_file=""
|
||||||
|
|
||||||
|
if [[ -z "${secret_file}" || "${secret_file}" != /* ]]; then
|
||||||
|
secret_validation_error "${input_class} must be an absolute path"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
resolved_file="$(realpath "${secret_file}" 2>/dev/null)" || {
|
||||||
|
secret_validation_error "${input_class} cannot be resolved"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
if [[ "${resolved_file}" != "${secret_file}" ]]; then
|
||||||
|
secret_validation_error "${input_class} must be canonical and must not traverse symlinked parents"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
validate_secret_file "${secret_file}" "${input_class}" || return "${ERR_SECRET_PATH:-216}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_secret_absolute_file
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates an explicitly supported absolute secret directory path.
|
||||||
|
# Arguments:
|
||||||
|
# 1: directory path
|
||||||
|
# 2: input class
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_SECRET_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_secret_absolute_directory() {
|
||||||
|
declare directory="$1" input_class="${2:-absolute secret directory}" resolved_directory=""
|
||||||
|
|
||||||
|
if [[ -z "${directory}" || "${directory}" != /* ]]; then
|
||||||
|
secret_validation_error "${input_class} must be an absolute path"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
resolved_directory="$(realpath "${directory}" 2>/dev/null)" || {
|
||||||
|
secret_validation_error "${input_class} cannot be resolved"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
}
|
||||||
|
if [[ "${resolved_directory}" != "${directory}" ]]; then
|
||||||
|
secret_validation_error "${input_class} must be canonical and must not traverse symlinked parents"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
validate_secret_directory "${directory}" "${input_class}" || return "${ERR_SECRET_PATH:-216}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_secret_absolute_directory
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates a filename-only secret file below the fixed secret root.
|
||||||
|
# Globals:
|
||||||
|
# VAR_TMP_SECRET
|
||||||
|
# Arguments:
|
||||||
|
# 1: filename
|
||||||
|
# 2: input class
|
||||||
|
# 3: register for redaction
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_SECRET_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_secret_file_in_root() {
|
||||||
|
declare filename="$1" input_class="${2:-secret file}" register_value="${3:-true}"
|
||||||
|
|
||||||
|
validate_secret_directory "${VAR_TMP_SECRET}" "secret root" "true" || return "${ERR_SECRET_PATH:-216}"
|
||||||
|
validate_secret_filename "${filename}" "${input_class} filename" || return "${ERR_SECRET_PATH:-216}"
|
||||||
|
validate_secret_file "${VAR_TMP_SECRET}/${filename}" "${input_class}" "${register_value}" || return "${ERR_SECRET_PATH:-216}"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_secret_file_in_root
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validates the fixed tmpfs secret staging area and all entries below it.
|
||||||
|
# Globals:
|
||||||
|
# VAR_TMP_SECRET
|
||||||
|
# Arguments:
|
||||||
|
# 1: quiet flag
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# ERR_SECRET_PATH: on failure
|
||||||
|
#######################################
|
||||||
|
validate_secret_staging_area() {
|
||||||
|
declare quiet="${1:-false}" secret_entries_file="" secret_entry=""
|
||||||
|
declare -a secret_entries=()
|
||||||
|
|
||||||
|
validate_secret_directory "${VAR_TMP_SECRET}" "secret root" "true" "${quiet}" || return "${ERR_SECRET_PATH:-216}"
|
||||||
|
|
||||||
|
secret_entries_file="$(mktemp)" || return "${ERR_SECRET_PATH:-216}"
|
||||||
|
if ! find "${VAR_TMP_SECRET}" -xdev -mindepth 1 -print0 >| "${secret_entries_file}"; then
|
||||||
|
rm -f "${secret_entries_file}"
|
||||||
|
secret_validation_error "secret-root enumeration failed" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
mapfile -d '' -t secret_entries < "${secret_entries_file}"
|
||||||
|
rm -f "${secret_entries_file}"
|
||||||
|
|
||||||
|
for secret_entry in "${secret_entries[@]}"; do
|
||||||
|
if [[ -L "${secret_entry}" ]]; then
|
||||||
|
secret_validation_error "symlink below secret root" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
elif [[ -d "${secret_entry}" ]]; then
|
||||||
|
validate_secret_directory "${secret_entry}" "directory below secret root" "false" "${quiet}" \
|
||||||
|
|| return "${ERR_SECRET_PATH:-216}"
|
||||||
|
elif [[ -f "${secret_entry}" ]]; then
|
||||||
|
validate_secret_file "${secret_entry}" "file below secret root" "true" "${quiet}" || return "${ERR_SECRET_PATH:-216}"
|
||||||
|
else
|
||||||
|
secret_validation_error "non-regular entry below secret root" "${quiet}"
|
||||||
|
return "${ERR_SECRET_PATH:-216}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f validate_secret_staging_area
|
||||||
|
|
||||||
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
|
||||||
@@ -49,8 +49,6 @@ trap_on_exit() {
|
|||||||
|
|
||||||
print_scr_exit "${errcode}"
|
print_scr_exit "${errcode}"
|
||||||
|
|
||||||
exit "${errcode}"
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
if [[ "${ERRTRAP}" != "true" ]]; then
|
if [[ "${ERRTRAP}" != "true" ]]; then
|
||||||
@@ -63,9 +61,16 @@ trap_on_exit() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit "${errcode}"
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! sanitize_debug_logs; then
|
||||||
|
printf "\e[93m⚠ Final debug-log sanitisation failed; preserving original exit status %s. \e[0m\n" "${errcode}" >&2
|
||||||
|
if [[ -n "${LOG_ERROR:-}" && -f "${LOG_ERROR}" && ! -L "${LOG_ERROR}" ]]; then
|
||||||
|
printf "⚠ Final debug-log sanitisation failed; original exit status: %s.\n" "${errcode}" >> "${LOG_ERROR}" || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "${errcode}"
|
||||||
}
|
}
|
||||||
### Prevents accidental 'unset -f'.
|
### Prevents accidental 'unset -f'.
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
|
|||||||
+33
-4
@@ -39,13 +39,13 @@ usage() {
|
|||||||
# shellcheck disable=SC2155
|
# shellcheck disable=SC2155
|
||||||
declare var_header=$(center "CDLB(1) CISS.debian.live.builder CDLB(1)" "${var_cols}")
|
declare var_header=$(center "CDLB(1) CISS.debian.live.builder CDLB(1)" "${var_cols}")
|
||||||
# shellcheck disable=SC2155
|
# shellcheck disable=SC2155
|
||||||
declare var_footer=$(center "V9.14.020.2026.06.08 2026-06-08 CDLB(1)" "${var_cols}")
|
declare var_footer=$(center "V9.14.022.2026.06.10 2026-06-10 CDLB(1)" "${var_cols}")
|
||||||
|
|
||||||
{
|
{
|
||||||
echo -e "\e[1;97m${var_header}\e[0m"
|
echo -e "\e[1;97m${var_header}\e[0m"
|
||||||
echo
|
echo
|
||||||
echo -e "\e[92mCISS.debian.live.builder from https://git.coresecret.dev/msw \e[0m"
|
echo -e "\e[92mCISS.debian.live.builder from https://git.coresecret.dev/msw \e[0m"
|
||||||
echo -e "\e[92mMaster V9.14.020.2026.06.08\e[0m"
|
echo -e "\e[92mMaster V9.14.022.2026.06.10\e[0m"
|
||||||
echo -e "\e[92mA lightweight Shell Wrapper for building a hardened Debian Live ISO Image.\e[0m"
|
echo -e "\e[92mA lightweight Shell Wrapper for building a hardened Debian Live ISO Image.\e[0m"
|
||||||
echo
|
echo
|
||||||
echo -e "\e[97m(c) Marc S. Weidner, 2018 - 2026 \e[0m"
|
echo -e "\e[97m(c) Marc S. Weidner, 2018 - 2026 \e[0m"
|
||||||
@@ -67,6 +67,10 @@ usage() {
|
|||||||
echo
|
echo
|
||||||
echo -e "\e[97m --build-directory </path/to/build_directory> \e[0m"
|
echo -e "\e[97m --build-directory </path/to/build_directory> \e[0m"
|
||||||
echo " Where the Debian Live Build Image should be generated. RECOMMENDED path: </opt/cdlb>"
|
echo " Where the Debian Live Build Image should be generated. RECOMMENDED path: </opt/cdlb>"
|
||||||
|
echo " The path MUST be canonical and dedicated to the builder; a new directory's canonical parent MUST already exist."
|
||||||
|
echo " New or empty directories receive the"
|
||||||
|
echo " '.ciss-live-builder-owned' marker; populated unmarked directories are rejected. Cleanup is intentionally"
|
||||||
|
echo " destructive only inside the exact validated marker-owned directory."
|
||||||
echo " MUST be provided."
|
echo " MUST be provided."
|
||||||
echo
|
echo
|
||||||
echo -e "\e[97m --change-splash <STRING> one of <club | hexagon> \e[0m"
|
echo -e "\e[97m --change-splash <STRING> one of <club | hexagon> \e[0m"
|
||||||
@@ -87,6 +91,7 @@ usage() {
|
|||||||
echo -e "\e[97m --debug, -d \e[0m"
|
echo -e "\e[97m --debug, -d \e[0m"
|
||||||
echo " Enables debug logging for the main program routine. Detailed logging information are written to:"
|
echo " Enables debug logging for the main program routine. Detailed logging information are written to:"
|
||||||
echo " </tmp/ciss_live_builder_$$.log>"
|
echo " </tmp/ciss_live_builder_$$.log>"
|
||||||
|
echo " A final exact-value sanitisation pass is defence in depth and does not replace careful tracing discipline."
|
||||||
echo
|
echo
|
||||||
echo -e "\e[97m --dhcp-centurion \e[0m"
|
echo -e "\e[97m --dhcp-centurion \e[0m"
|
||||||
echo " If a DHCP lease is provided, the provider's name server will be overridden and the hardened, privacy-focused "
|
echo " If a DHCP lease is provided, the provider's name server will be overridden and the hardened, privacy-focused "
|
||||||
@@ -108,11 +113,13 @@ usage() {
|
|||||||
echo
|
echo
|
||||||
echo -e "\e[97m --key_age=* \e[0m"
|
echo -e "\e[97m --key_age=* \e[0m"
|
||||||
echo " The SOPS AGE private keyring for decryption operations. Change '*' to your desired SOPS AGE key file."
|
echo " The SOPS AGE private keyring for decryption operations. Change '*' to your desired SOPS AGE key file."
|
||||||
|
echo " '*' MUST be a filename only without slashes, '.' or '..' traversal."
|
||||||
echo " File MUST be placed in:"
|
echo " File MUST be placed in:"
|
||||||
echo " </dev/shm/cdlb_secrets>"
|
echo " </dev/shm/cdlb_secrets>"
|
||||||
echo
|
echo
|
||||||
echo -e "\e[97m --key_luks=* \e[0m"
|
echo -e "\e[97m --key_luks=* \e[0m"
|
||||||
echo " The LUKS encryption / decryption passphrase for '/'-fs-encryption. Change '*' to your desired passphrase file."
|
echo " The LUKS encryption / decryption passphrase for '/'-fs-encryption. Change '*' to your desired passphrase file."
|
||||||
|
echo " '*' MUST be a filename only without slashes, '.' or '..' traversal."
|
||||||
echo " File MUST be placed in:"
|
echo " File MUST be placed in:"
|
||||||
echo " </dev/shm/cdlb_secrets>"
|
echo " </dev/shm/cdlb_secrets>"
|
||||||
echo
|
echo
|
||||||
@@ -120,6 +127,24 @@ usage() {
|
|||||||
echo " Provides statistic only after successful building a CISS.debian.live-ISO. While enabling '--log-statistics-only'"
|
echo " Provides statistic only after successful building a CISS.debian.live-ISO. While enabling '--log-statistics-only'"
|
||||||
echo " the argument '--build-directory' MUST be provided."
|
echo " the argument '--build-directory' MUST be provided."
|
||||||
echo
|
echo
|
||||||
|
echo -e "\e[97m --primordial-key <ssh-identity-filename> \e[0m"
|
||||||
|
echo " SSH identity filename for the Primordial overlay clone. This MUST be a filename only; the runtime path is"
|
||||||
|
echo " derived as '/root/.ssh/<ssh-identity-filename>'."
|
||||||
|
echo " Example fragment:"
|
||||||
|
echo " ./ciss_live_builder.sh --primordial-url https://git.coresecret.dev/ahz/PhysNet.primordial.git \\"
|
||||||
|
echo " --primordial-key id--git.coresecret.dev--PhysNet.primordial_deploy--ed25519--newton--2025-10 \\"
|
||||||
|
echo " --primordial-ssh 42842"
|
||||||
|
echo
|
||||||
|
echo -e "\e[97m --primordial-ssh <INTEGER> \e[0m"
|
||||||
|
echo " Adds one outgoing UFW TCP exception for a bootstrap SSH port."
|
||||||
|
echo " Outgoing only: no incoming firewall rule is added, and this option does not replace '--ssh-port'."
|
||||||
|
echo " Effective only when the Live System's UFW outgoing policy is 'deny'."
|
||||||
|
echo " Port MUST be a decimal integer between '1' and '65535'."
|
||||||
|
echo
|
||||||
|
echo -e "\e[97m --primordial-url <https-git-url> \e[0m"
|
||||||
|
echo " HTTPS Git repository URL for the Primordial CDI overlay. MUST start with 'https://', include a host and"
|
||||||
|
echo " path, and end in '.git'. The CDI starter converts this URL to an SSH clone URL at runtime."
|
||||||
|
echo
|
||||||
echo -e "\e[97m --provider-netcup-ipv6 \e[0m"
|
echo -e "\e[97m --provider-netcup-ipv6 \e[0m"
|
||||||
echo " Activates IPv6 support for Netcup Root Server. One unique IPv6 address MUST be provided in this case and MUST be"
|
echo " Activates IPv6 support for Netcup Root Server. One unique IPv6 address MUST be provided in this case and MUST be"
|
||||||
echo " encapsulated with [], e.g., [1234::abcd]."
|
echo " encapsulated with [], e.g., [1234::abcd]."
|
||||||
@@ -144,7 +169,7 @@ usage() {
|
|||||||
echo -e "\e[97m --root-password-file </dev/shm/cdlb_secrets/password.txt>> \e[0m"
|
echo -e "\e[97m --root-password-file </dev/shm/cdlb_secrets/password.txt>> \e[0m"
|
||||||
echo " Password file for 'root', if given, MUST be a string of 42 to 64 characters."
|
echo " Password file for 'root', if given, MUST be a string of 42 to 64 characters."
|
||||||
echo " If the argument is omitted, no further login authentication is required for the local console."
|
echo " If the argument is omitted, no further login authentication is required for the local console."
|
||||||
echo " MUST be placed in:"
|
echo " Safe absolute paths remain supported and are validated separately. RECOMMENDED path:"
|
||||||
echo " </dev/shm/cdlb_secrets/password.txt>"
|
echo " </dev/shm/cdlb_secrets/password.txt>"
|
||||||
echo
|
echo
|
||||||
echo -e "\e[97m --secure-boot-profile <STRING> one of <debian-shim | ciss-uki> \e[0m"
|
echo -e "\e[97m --secure-boot-profile <STRING> one of <debian-shim | ciss-uki> \e[0m"
|
||||||
@@ -160,7 +185,8 @@ usage() {
|
|||||||
echo " specified via '--signing_key=*'. If the keyring is protected, then provide the passphrase in its own file."
|
echo " specified via '--signing_key=*'. If the keyring is protected, then provide the passphrase in its own file."
|
||||||
echo " Specify the fingerprint of the key to use via '--signing_key_fpr=*'."
|
echo " Specify the fingerprint of the key to use via '--signing_key_fpr=*'."
|
||||||
echo " Optionally import an offline GPG CA signing public key via: '--signing_ca=*'."
|
echo " Optionally import an offline GPG CA signing public key via: '--signing_ca=*'."
|
||||||
echo " Change '*' to your desired files / fingerprint. Files MUST be placed in:"
|
echo " Change '*' to your desired filename-only files / fingerprint. Filename-only values MUST NOT contain slashes"
|
||||||
|
echo " or traversal. Files MUST be placed in:"
|
||||||
echo " </dev/shm/cdlb_secrets>"
|
echo " </dev/shm/cdlb_secrets>"
|
||||||
echo
|
echo
|
||||||
echo -e "\e[97m --sops-version <STRING> \e[0m"
|
echo -e "\e[97m --sops-version <STRING> \e[0m"
|
||||||
@@ -194,6 +220,9 @@ usage() {
|
|||||||
echo
|
echo
|
||||||
echo -e "\e[93m💡 Notes: \e[0m"
|
echo -e "\e[93m💡 Notes: \e[0m"
|
||||||
echo -e "\e[93m🔵 You MUST be 'root' to run this script. \e[0m"
|
echo -e "\e[93m🔵 You MUST be 'root' to run this script. \e[0m"
|
||||||
|
echo -e "\e[93m🔵 Private operator control does not remove the requirement for strict local secret path validation. \e[0m"
|
||||||
|
echo -e "\e[93m🔵 '/dev/shm/cdlb_secrets' MUST be tmpfs-backed, root-owned, mode 0700, and contain only \e[0m"
|
||||||
|
echo -e "\e[93m single-link regular secret files with mode 0400 or 0600. Secure deletion with shred is best-effort only. \e[0m"
|
||||||
echo
|
echo
|
||||||
echo -e "\e[95m💷 Please consider donating to my work at: \e[0m"
|
echo -e "\e[95m💷 Please consider donating to my work at: \e[0m"
|
||||||
echo -e "\e[95m🌐 https://coresecret.eu/spenden/ \e[0m"
|
echo -e "\e[95m🌐 https://coresecret.eu/spenden/ \e[0m"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ TIMESTAMP ?= $(shell date -u +%Y-%m-%dT%H-%M-%S)
|
|||||||
|
|
||||||
### Core parameters (safe defaults; override in config.mk, rename config.mk.sample to config.mk and apply the remaining values):
|
### Core parameters (safe defaults; override in config.mk, rename config.mk.sample to config.mk and apply the remaining values):
|
||||||
ARCH ?= amd64
|
ARCH ?= amd64
|
||||||
AUTOBUILD ?= 6.16.3+deb13-amd64
|
AUTOBUILD ?= 7.0.10+deb13-amd64
|
||||||
CONTROL ?= $(TIMESTAMP)
|
CONTROL ?= $(TIMESTAMP)
|
||||||
DROPBEAR_VERSION ?= 2026.91
|
DROPBEAR_VERSION ?= 2026.91
|
||||||
SOPS_VERSION ?= 3.13.1
|
SOPS_VERSION ?= 3.13.1
|
||||||
@@ -63,6 +63,9 @@ define COMPOSE_AND
|
|||||||
[[ -n '$(FLAG_DEBUG)' ]] && cmd+=( --debug )
|
[[ -n '$(FLAG_DEBUG)' ]] && cmd+=( --debug )
|
||||||
[[ -n '$(FLAG_DHCP_CENTURION)' ]] && cmd+=( --dhcp-centurion )
|
[[ -n '$(FLAG_DHCP_CENTURION)' ]] && cmd+=( --dhcp-centurion )
|
||||||
[[ -n '$(FLAG_TRIXIE)' ]] && cmd+=( --trixie )
|
[[ -n '$(FLAG_TRIXIE)' ]] && cmd+=( --trixie )
|
||||||
|
[[ -n '$(PRIMORDIAL_URL)' ]] && cmd+=( --primordial-url '$(PRIMORDIAL_URL)' )
|
||||||
|
[[ -n '$(PRIMORDIAL_KEY)' ]] && cmd+=( --primordial-key '$(PRIMORDIAL_KEY)' )
|
||||||
|
[[ -n '$(PRIMORDIAL_SSH_PORT)' ]] && cmd+=( --primordial-ssh '$(PRIMORDIAL_SSH_PORT)' )
|
||||||
[[ -n '$(PROVIDER_NETCUP_IPV6)' ]] && cmd+=( --provider-netcup-ipv6 '$(PROVIDER_NETCUP_IPV6)' )
|
[[ -n '$(PROVIDER_NETCUP_IPV6)' ]] && cmd+=( --provider-netcup-ipv6 '$(PROVIDER_NETCUP_IPV6)' )
|
||||||
[[ -n '$(RENICE)' ]] && cmd+=( --renice-priority '$(RENICE)' )
|
[[ -n '$(RENICE)' ]] && cmd+=( --renice-priority '$(RENICE)' )
|
||||||
if [[ -n '$(REIONICE_CLASS)' && -n '$(REIONICE_PRIO)' ]]; then
|
if [[ -n '$(REIONICE_CLASS)' && -n '$(REIONICE_PRIO)' ]]; then
|
||||||
|
|||||||
@@ -13,6 +13,12 @@
|
|||||||
set -Ceuo pipefail
|
set -Ceuo pipefail
|
||||||
umask 0077
|
umask 0077
|
||||||
|
|
||||||
|
declare -gx VAR_RDNS_DOMAIN="" # Forward-confirmed reverse DNS domain.
|
||||||
|
declare -gx VAR_RDNS_IPV4="" # IPv4 address used for RDNS verification.
|
||||||
|
declare -gx VAR_RDNS_NORMALIZED="" # RDNS domain normalized for Primordial branch names.
|
||||||
|
declare -gx VAR_PRIMORDIAL_KEY="" # Primordial SSH identity filename.
|
||||||
|
declare -gx VAR_PRIMORDIAL_SSH_PORT="" # Primordial SSH port.
|
||||||
|
declare -gx VAR_PRIMORDIAL_URL="" # Primordial HTTPS Git URL.
|
||||||
declare -grx VAR_SEMAPHORE="/root/cdi.ciss" # Semaphore to appear.
|
declare -grx VAR_SEMAPHORE="/root/cdi.ciss" # Semaphore to appear.
|
||||||
declare -girx VAR_TIMEOUT=3600 # Semaphore timer in seconds.
|
declare -girx VAR_TIMEOUT=3600 # Semaphore timer in seconds.
|
||||||
|
|
||||||
@@ -90,6 +96,472 @@ net_wait() {
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
readonly -f net_wait
|
readonly -f net_wait
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validate an IPv4 address.
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# $1: IPv4 address
|
||||||
|
# Returns:
|
||||||
|
# 0: valid IPv4 address
|
||||||
|
# 1: invalid IPv4 address
|
||||||
|
#######################################
|
||||||
|
is_ipv4() {
|
||||||
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare -r var_ip="${1:-}"
|
||||||
|
declare -a ary_octets=()
|
||||||
|
declare var_octet=""
|
||||||
|
|
||||||
|
[[ "${var_ip}" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
|
||||||
|
|
||||||
|
IFS='.' read -r -a ary_octets <<< "${var_ip}"
|
||||||
|
|
||||||
|
for var_octet in "${ary_octets[@]}"; do
|
||||||
|
|
||||||
|
if ! ((10#${var_octet} <= 255)); then
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f is_ipv4
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Validate a DNS domain name returned by RDNS.
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# $1: domain name
|
||||||
|
# Returns:
|
||||||
|
# 0: valid domain name
|
||||||
|
# 1: invalid domain name
|
||||||
|
#######################################
|
||||||
|
is_dns_name() {
|
||||||
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare -r var_name="${1:-}"
|
||||||
|
|
||||||
|
[[ "${#var_name}" -le 253 ]] || return 1
|
||||||
|
[[ "${var_name}" =~ ^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$ ]] \
|
||||||
|
|| return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f is_dns_name
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Retrieve and forward-confirm reverse DNS for the active IPv4 route.
|
||||||
|
# Globals:
|
||||||
|
# VAR_RDNS_DOMAIN
|
||||||
|
# VAR_RDNS_IPV4
|
||||||
|
# Arguments:
|
||||||
|
# $1: module log file
|
||||||
|
# Returns:
|
||||||
|
# 0: on confirmed RDNS
|
||||||
|
# 1: on missing or unconfirmed RDNS
|
||||||
|
#######################################
|
||||||
|
# retrieve_rdns() intentionally probes optional resolver tools and validation helpers inside conditionals.
|
||||||
|
# shellcheck disable=SC2310,SC2312
|
||||||
|
retrieve_rdns() {
|
||||||
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare -r var_log="${1:-}"
|
||||||
|
declare -a ary_a=()
|
||||||
|
declare -a ary_rdns=()
|
||||||
|
declare -a ary_targets=()
|
||||||
|
declare var_a="" var_ipv4="" var_rdns="" var_target=""
|
||||||
|
|
||||||
|
VAR_RDNS_DOMAIN=""
|
||||||
|
VAR_RDNS_IPV4=""
|
||||||
|
|
||||||
|
mapfile -t ary_targets < <(
|
||||||
|
getent ahostsv4 git.coresecret.dev 2>/dev/null \
|
||||||
|
| awk '/^([0-9]{1,3}\.){3}[0-9]{1,3}[[:space:]]/ && !seen[$1]++ { print $1 }'
|
||||||
|
)
|
||||||
|
ary_targets+=( "1.1.1.1" "9.9.9.9" "8.8.8.8" )
|
||||||
|
|
||||||
|
if command -v ip >/dev/null 2>&1; then
|
||||||
|
|
||||||
|
for var_target in "${ary_targets[@]}"; do
|
||||||
|
|
||||||
|
if var_ipv4="$(
|
||||||
|
ip -o -4 route get "${var_target}" 2>/dev/null \
|
||||||
|
| awk '{ for (i = 1; i <= NF; i++) { if ($i == "src") { print $(i + 1); exit } } }'
|
||||||
|
)" && is_ipv4 "${var_ipv4}"; then
|
||||||
|
|
||||||
|
break
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
var_ipv4=""
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "${var_ipv4}" ]]; then
|
||||||
|
|
||||||
|
mapfile -t ary_targets < <(
|
||||||
|
ip -o -4 addr show scope global up 2>/dev/null \
|
||||||
|
| awk '{ split($4, addr, "/"); if (!seen[addr[1]]++) { print addr[1] } }'
|
||||||
|
)
|
||||||
|
|
||||||
|
for var_target in "${ary_targets[@]}"; do
|
||||||
|
|
||||||
|
if is_ipv4 "${var_target}"; then
|
||||||
|
|
||||||
|
var_ipv4="${var_target}"
|
||||||
|
break
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${var_ipv4}" ]]; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "retrieve_rdns(): no active IPv4 address found; continuing without RDNS."
|
||||||
|
printf "Command: [retrieve_rdns] no active IPv4 address found; continuing without RDNS.\n" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v dig >/dev/null 2>&1; then
|
||||||
|
|
||||||
|
mapfile -t ary_rdns < <(
|
||||||
|
dig +time=3 +tries=1 +short -x "${var_ipv4}" 2>/dev/null \
|
||||||
|
| sed 's/[.]$//' \
|
||||||
|
| awk 'NF && !seen[$0]++ { print $0 }'
|
||||||
|
)
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ((${#ary_rdns[@]} == 0)) && command -v host >/dev/null 2>&1; then
|
||||||
|
|
||||||
|
mapfile -t ary_rdns < <(
|
||||||
|
host "${var_ipv4}" 2>/dev/null \
|
||||||
|
| awk '/domain name pointer/ { sub(/[.]$/, "", $NF); if (!seen[$NF]++) { print $NF } }'
|
||||||
|
)
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ((${#ary_rdns[@]} == 0)); then
|
||||||
|
|
||||||
|
mapfile -t ary_rdns < <(
|
||||||
|
getent hosts "${var_ipv4}" 2>/dev/null \
|
||||||
|
| awk '{ for (i = 2; i <= NF; i++) { sub(/[.]$/, "", $i); if (!seen[$i]++) { print $i } } }'
|
||||||
|
)
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
for var_rdns in "${ary_rdns[@]}"; do
|
||||||
|
|
||||||
|
var_rdns="${var_rdns%.}"
|
||||||
|
var_rdns="${var_rdns,,}"
|
||||||
|
|
||||||
|
if ! is_dns_name "${var_rdns}"; then
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
ary_a=()
|
||||||
|
|
||||||
|
if command -v dig >/dev/null 2>&1; then
|
||||||
|
|
||||||
|
mapfile -t ary_a < <(
|
||||||
|
dig +time=3 +tries=1 +short A "${var_rdns}" 2>/dev/null \
|
||||||
|
| awk '/^([0-9]{1,3}\.){3}[0-9]{1,3}$/ && !seen[$0]++ { print $0 }'
|
||||||
|
)
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ((${#ary_a[@]} == 0)) && command -v host >/dev/null 2>&1; then
|
||||||
|
|
||||||
|
mapfile -t ary_a < <(
|
||||||
|
host -t A "${var_rdns}" 2>/dev/null \
|
||||||
|
| awk '/ has address / && !seen[$NF]++ { print $NF }'
|
||||||
|
)
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ((${#ary_a[@]} == 0)); then
|
||||||
|
|
||||||
|
mapfile -t ary_a < <(
|
||||||
|
getent ahostsv4 "${var_rdns}" 2>/dev/null \
|
||||||
|
| awk '!seen[$1]++ { print $1 }'
|
||||||
|
)
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
for var_a in "${ary_a[@]}"; do
|
||||||
|
|
||||||
|
if is_ipv4 "${var_a}" && [[ "${var_a}" == "${var_ipv4}" ]]; then
|
||||||
|
|
||||||
|
VAR_RDNS_IPV4="${var_ipv4}"
|
||||||
|
VAR_RDNS_DOMAIN="${var_rdns}"
|
||||||
|
logger -t cdi-watcher "retrieve_rdns(): confirmed IPv4 ${VAR_RDNS_IPV4} RDNS ${VAR_RDNS_DOMAIN}."
|
||||||
|
printf "Command: [retrieve_rdns] confirmed IPv4 [%s] RDNS [%s].\n" \
|
||||||
|
"${VAR_RDNS_IPV4}" "${VAR_RDNS_DOMAIN}" >> "${var_log}"
|
||||||
|
return 0
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
logger -t cdi-watcher "retrieve_rdns(): no forward-confirmed RDNS for IPv4 ${var_ipv4}; continuing without RDNS."
|
||||||
|
printf "Command: [retrieve_rdns] no forward-confirmed RDNS for IPv4 [%s]; continuing without RDNS.\n" \
|
||||||
|
"${var_ipv4}" >> "${var_log}"
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f retrieve_rdns
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Normalize a DNS domain into a Primordial branch name.
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# $1: DNS domain name
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# 1: on invalid DNS domain
|
||||||
|
#######################################
|
||||||
|
normalize_rdns_domain() {
|
||||||
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare var_domain="${1:-}"
|
||||||
|
|
||||||
|
var_domain="${var_domain%.}"
|
||||||
|
var_domain="${var_domain,,}"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2310
|
||||||
|
is_dns_name "${var_domain}" || return 1
|
||||||
|
|
||||||
|
printf '%s\n' "${var_domain//./_}"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f normalize_rdns_domain
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Convert an HTTPS Git URL into the SSH URL used for Primordial clone.
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# $1: HTTPS Git URL
|
||||||
|
# $2: SSH port
|
||||||
|
# Returns:
|
||||||
|
# 0: on success
|
||||||
|
# 1: on invalid URL or port
|
||||||
|
#######################################
|
||||||
|
derive_ssh_git_url() {
|
||||||
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare -r var_https_url="${1:-}"
|
||||||
|
declare -r var_ssh_port="${2:-}"
|
||||||
|
declare var_host="" var_path=""
|
||||||
|
|
||||||
|
if [[ ! "${var_https_url}" =~ ^https://([A-Za-z0-9.-]+)/([A-Za-z0-9._~/%+=:@,-]+\.git)$ ]]; then
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
var_host="${BASH_REMATCH[1]}"
|
||||||
|
var_path="${BASH_REMATCH[2]}"
|
||||||
|
|
||||||
|
if [[ -z "${var_host}" || -z "${var_path}" || ! "${var_ssh_port}" =~ ^[0-9]+$ ]] \
|
||||||
|
|| ((10#${var_ssh_port} < 1 || 10#${var_ssh_port} > 65535)); then
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'ssh://git@%s:%s/%s\n' "${var_host}" "${var_ssh_port}" "${var_path}"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f derive_ssh_git_url
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Apply the Primordial overlay and create the CDI semaphore only on success.
|
||||||
|
# Globals:
|
||||||
|
# VAR_PRIMORDIAL_KEY
|
||||||
|
# VAR_PRIMORDIAL_SSH_PORT
|
||||||
|
# VAR_PRIMORDIAL_URL
|
||||||
|
# VAR_RDNS_DOMAIN
|
||||||
|
# VAR_RDNS_NORMALIZED
|
||||||
|
# VAR_SEMAPHORE
|
||||||
|
# Arguments:
|
||||||
|
# $1: module log file
|
||||||
|
# $2: CISS.debian.installer directory
|
||||||
|
# Returns:
|
||||||
|
# 0: on success or optional skip
|
||||||
|
# 1: on failed configured Primordial overlay
|
||||||
|
#######################################
|
||||||
|
apply_primordial_overlay() {
|
||||||
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
|
declare -r var_log="${1:-}"
|
||||||
|
declare -r var_repo_dir="${2:-}"
|
||||||
|
declare -r var_overlay_dir="/root/git/overlay"
|
||||||
|
declare var_identity="" var_ssh_url="" var_rdns_normalized=""
|
||||||
|
|
||||||
|
if [[ -z "${VAR_PRIMORDIAL_URL}" && -z "${VAR_PRIMORDIAL_KEY}" && -z "${VAR_PRIMORDIAL_SSH_PORT}" ]]; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay not configured; continuing with existing semaphore polling."
|
||||||
|
printf "Command: [apply_primordial_overlay] skipped; Primordial overlay not configured.\n" >> "${var_log}"
|
||||||
|
return 0
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! rm -f -- "${VAR_SEMAPHORE}"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Failed to remove existing CDI semaphore; aborting CDI autostart."
|
||||||
|
printf "Command: [rm -f -- %s] failed; aborting CDI autostart.\n" "${VAR_SEMAPHORE}" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${VAR_PRIMORDIAL_URL}" || -z "${VAR_PRIMORDIAL_KEY}" || -z "${VAR_PRIMORDIAL_SSH_PORT}" || -z "${VAR_RDNS_DOMAIN}" ]]; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay configuration incomplete; aborting CDI autostart."
|
||||||
|
printf "Command: [apply_primordial_overlay] failed; Primordial URL, key, SSH port, and RDNS domain are required.\n" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2310
|
||||||
|
if ! var_rdns_normalized="$(normalize_rdns_domain "${VAR_RDNS_DOMAIN}")"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay RDNS branch derivation failed; aborting CDI autostart."
|
||||||
|
printf "Command: [normalize_rdns_domain %s] failed; aborting CDI autostart.\n" "${VAR_RDNS_DOMAIN}" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
declare -gx VAR_RDNS_NORMALIZED="${var_rdns_normalized}"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2310
|
||||||
|
if ! var_ssh_url="$(derive_ssh_git_url "${VAR_PRIMORDIAL_URL}" "${VAR_PRIMORDIAL_SSH_PORT}")"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial HTTPS Git URL conversion failed; aborting CDI autostart."
|
||||||
|
printf "Command: [derive_ssh_git_url] failed for configured Primordial URL; aborting CDI autostart.\n" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
var_identity="/root/.ssh/${VAR_PRIMORDIAL_KEY}"
|
||||||
|
|
||||||
|
if [[ ! -e "${var_identity}" ]]; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial SSH identity file is missing; aborting CDI autostart."
|
||||||
|
printf "Command: [test -e /root/.ssh/<primordial-key>] failed; aborting CDI autostart.\n" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "${var_identity}" ]]; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial SSH identity path is not a regular file; aborting CDI autostart."
|
||||||
|
printf "Command: [test -f /root/.ssh/<primordial-key>] failed; aborting CDI autostart.\n" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -r "${var_identity}" ]]; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial SSH identity file is not readable by root; aborting CDI autostart."
|
||||||
|
printf "Command: [test -r /root/.ssh/<primordial-key>] failed; aborting CDI autostart.\n" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! rm -rf -- "${var_overlay_dir}"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Failed to remove existing Primordial overlay directory; aborting CDI autostart."
|
||||||
|
printf "Command: [rm -rf -- %s] failed; aborting CDI autostart.\n" "${var_overlay_dir}" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! GIT_SSH_COMMAND="ssh -i ${var_identity} -p ${VAR_PRIMORDIAL_SSH_PORT}" \
|
||||||
|
git clone --branch "${VAR_RDNS_NORMALIZED}" "${var_ssh_url}" "${var_overlay_dir}"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay clone failed; aborting CDI autostart."
|
||||||
|
printf "Command: [git clone --branch %s <primordial-ssh-url> %s] failed; aborting CDI autostart.\n" \
|
||||||
|
"${VAR_RDNS_NORMALIZED}" "${var_overlay_dir}" >> "${var_log}"
|
||||||
|
rm -rf -- "${var_overlay_dir}" || true
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "${var_overlay_dir}/.preseed" ]]; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay .preseed directory is missing; aborting CDI autostart."
|
||||||
|
printf "Command: [test -d %s/.preseed] failed; aborting CDI autostart.\n" "${var_overlay_dir}" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "${var_overlay_dir}/includes" ]]; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay includes directory is missing; aborting CDI autostart."
|
||||||
|
printf "Command: [test -d %s/includes] failed; aborting CDI autostart.\n" "${var_overlay_dir}" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
install -d -m 0700 "${var_repo_dir}/.preseed" "${var_repo_dir}/includes"
|
||||||
|
|
||||||
|
if ! rsync -av "${var_overlay_dir}/.preseed/" "${var_repo_dir}/.preseed/"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay .preseed rsync failed; aborting CDI autostart."
|
||||||
|
printf "Command: [rsync -av %s/.preseed/ %s/.preseed/] failed; aborting CDI autostart.\n" \
|
||||||
|
"${var_overlay_dir}" "${var_repo_dir}" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! rsync -av "${var_overlay_dir}/includes/" "${var_repo_dir}/includes"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay includes rsync failed; aborting CDI autostart."
|
||||||
|
printf "Command: [rsync -av %s/includes/ %s/includes] failed; aborting CDI autostart.\n" \
|
||||||
|
"${var_overlay_dir}" "${var_repo_dir}" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! install -m 0600 /dev/null "${VAR_SEMAPHORE}"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay applied but semaphore creation failed; aborting CDI autostart."
|
||||||
|
printf "Command: [install -m 0600 /dev/null %s] failed; aborting CDI autostart.\n" "${VAR_SEMAPHORE}" >> "${var_log}"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay applied for branch ${VAR_RDNS_NORMALIZED}; CDI semaphore created."
|
||||||
|
printf "Command: [apply_primordial_overlay] executed for branch [%s].\n" "${VAR_RDNS_NORMALIZED}" >> "${var_log}"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
### Prevents accidental 'unset -f'.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
readonly -f apply_primordial_overlay
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Wrapper for loading CISS hardened Kernel Parameters.
|
# Wrapper for loading CISS hardened Kernel Parameters.
|
||||||
# Globals:
|
# Globals:
|
||||||
@@ -129,8 +601,7 @@ main() {
|
|||||||
var_log="/root/.ciss/cdi/log/9999-cdi-starter_$(date +"%Y-%m-%d_%H-%M-%S").log"
|
var_log="/root/.ciss/cdi/log/9999-cdi-starter_$(date +"%Y-%m-%d_%H-%M-%S").log"
|
||||||
touch "${var_log}"
|
touch "${var_log}"
|
||||||
|
|
||||||
|
printf "CISS.debian.live.builder V9.14.022.2026.06.10 calling CISS.debian.installer ... \n" >> "${var_log}"
|
||||||
printf "CISS.debian.installer Master V9.14.020.2026.06.08 is up! \n" >> "${var_log}"
|
|
||||||
|
|
||||||
### Sleep a moment to settle boot artifacts.
|
### Sleep a moment to settle boot artifacts.
|
||||||
sleep 8
|
sleep 8
|
||||||
@@ -153,6 +624,12 @@ main() {
|
|||||||
fi
|
fi
|
||||||
printf "Command: [net_wait] executed.\n" >> "${var_log}"
|
printf "Command: [net_wait] executed.\n" >> "${var_log}"
|
||||||
|
|
||||||
|
### Retrieve forward-confirmed reverse DNS.
|
||||||
|
printf "Command: [retrieve_rdns] to be executed ... \n" >> "${var_log}"
|
||||||
|
# shellcheck disable=SC2310
|
||||||
|
retrieve_rdns "${var_log}" || true
|
||||||
|
printf "Command: [retrieve_rdns] executed.\n" >> "${var_log}"
|
||||||
|
|
||||||
### apt update.
|
### apt update.
|
||||||
if ! apt-get update >> "${var_log}"; then
|
if ! apt-get update >> "${var_log}"; then
|
||||||
|
|
||||||
@@ -179,6 +656,16 @@ main() {
|
|||||||
cd "${var_repo_dir}"
|
cd "${var_repo_dir}"
|
||||||
printf "Command: [git clone %s %s] executed.\n" "${var_repo_url}" "${var_repo_dir}" >> "${var_log}"
|
printf "Command: [git clone %s %s] executed.\n" "${var_repo_url}" "${var_repo_dir}" >> "${var_log}"
|
||||||
|
|
||||||
|
### Apply Primordial overlay before allowing CDI autostart.
|
||||||
|
# shellcheck disable=SC2310
|
||||||
|
if ! apply_primordial_overlay "${var_log}" "${var_repo_dir}"; then
|
||||||
|
|
||||||
|
logger -t cdi-watcher "Primordial overlay failed; CDI autostart aborted before semaphore polling."
|
||||||
|
printf "Command: [apply_primordial_overlay] failed; CDI autostart aborted before semaphore polling.\n" >> "${var_log}"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
### Poll up to VAR_TIMEOUT seconds for the semaphore to appear and be mode 0600.
|
### Poll up to VAR_TIMEOUT seconds for the semaphore to appear and be mode 0600.
|
||||||
for ((i=0; i<VAR_TIMEOUT; i++)); do
|
for ((i=0; i<VAR_TIMEOUT; i++)); do
|
||||||
|
|
||||||
@@ -209,7 +696,7 @@ main() {
|
|||||||
|
|
||||||
### Timeout reached without acceptable semaphore.
|
### Timeout reached without acceptable semaphore.
|
||||||
logger -t cdi-watcher "No valid semaphore ${VAR_SEMAPHORE} (mode 0600) within ${VAR_TIMEOUT}s; exiting idle."
|
logger -t cdi-watcher "No valid semaphore ${VAR_SEMAPHORE} (mode 0600) within ${VAR_TIMEOUT}s; exiting idle."
|
||||||
printf "CISS.debian.installer Master V9.14.020.2026.06.08: No valid semaphore [%s] within [%s]s.\n" "${VAR_SEMAPHORE}" "${VAR_TIMEOUT}" >> "${var_log}"
|
printf "CISS.debian.live.builder V9.14.022.2026.06.10: No valid semaphore [%s] within [%s]s.\n" "${VAR_SEMAPHORE}" "${VAR_TIMEOUT}" >> "${var_log}"
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|||||||
Executable
+191
@@ -0,0 +1,191 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-Version: 3.0
|
||||||
|
# SPDX-CreationInfo: 2026-06-11; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git
|
||||||
|
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
|
||||||
|
# SPDX-FileCopyrightText: 2024-2026; WEIDNER, Marc S.; <msw@coresecret.dev>
|
||||||
|
# SPDX-FileType: SOURCE
|
||||||
|
# SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1
|
||||||
|
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
|
||||||
|
# SPDX-PackageName: CISS.debian.live.builder
|
||||||
|
# SPDX-Security-Contact: security@coresecret.eu
|
||||||
|
set -Ceuo pipefail
|
||||||
|
# shellcheck disable=SC1091,SC2034
|
||||||
|
|
||||||
|
declare TEST_ROOT=""
|
||||||
|
declare TEST_TMP=""
|
||||||
|
TEST_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
TEST_TMP="$(realpath "$(mktemp -d)")"
|
||||||
|
readonly TEST_ROOT TEST_TMP
|
||||||
|
declare -r ERR_BUILD_PATH=217
|
||||||
|
declare -r ERR_GUARD_SRCE=131
|
||||||
|
declare -r ERR_SANITIZING=133
|
||||||
|
declare -r ERR_SECRET_PATH=216
|
||||||
|
declare -r VAR_WORKDIR="${TEST_ROOT}"
|
||||||
|
declare VAR_TMP_SECRET="${TEST_TMP}/secret-root"
|
||||||
|
declare LOG_DEBUG=""
|
||||||
|
declare LOG_ERROR=""
|
||||||
|
declare LOG_VAR=""
|
||||||
|
declare VAR_EARLY_DEBUG="false"
|
||||||
|
declare ERRTRAP="true"
|
||||||
|
|
||||||
|
cleanup_test() {
|
||||||
|
chmod -R u+rwX "${TEST_TMP}" 2>/dev/null || true
|
||||||
|
rm -rf "${TEST_TMP}"
|
||||||
|
}
|
||||||
|
trap cleanup_test EXIT
|
||||||
|
|
||||||
|
guard_sourcing() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# shellcheck source=../lib/lib_secret_validation.sh
|
||||||
|
. "${TEST_ROOT}/lib/lib_secret_validation.sh"
|
||||||
|
# shellcheck source=../lib/lib_build_directory.sh
|
||||||
|
. "${TEST_ROOT}/lib/lib_build_directory.sh"
|
||||||
|
# shellcheck source=../lib/lib_debug_sanitizer.sh
|
||||||
|
. "${TEST_ROOT}/lib/lib_debug_sanitizer.sh"
|
||||||
|
# shellcheck source=../lib/lib_trap_on_exit.sh
|
||||||
|
. "${TEST_ROOT}/lib/lib_trap_on_exit.sh"
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
printf 'FAIL: %s\n' "$1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_failure() {
|
||||||
|
declare description="$1"
|
||||||
|
shift
|
||||||
|
if "$@" >/dev/null 2>&1; then
|
||||||
|
fail "${description}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -m 0700 "${VAR_TMP_SECRET}"
|
||||||
|
printf 'safe-private-value\n' > "${VAR_TMP_SECRET}/safe.txt"
|
||||||
|
chmod 0400 "${VAR_TMP_SECRET}/safe.txt"
|
||||||
|
|
||||||
|
validate_secret_directory "${VAR_TMP_SECRET}" "test secret root" "false" || fail "safe secret root rejected"
|
||||||
|
validate_secret_filename "safe.txt" "test secret filename" || fail "safe secret filename rejected"
|
||||||
|
validate_secret_file "${VAR_TMP_SECRET}/safe.txt" "test secret file" || fail "safe secret file rejected"
|
||||||
|
validate_secret_absolute_file "${VAR_TMP_SECRET}/safe.txt" "test absolute secret file" \
|
||||||
|
|| fail "safe absolute secret file rejected"
|
||||||
|
expect_failure "relative external secret path accepted" \
|
||||||
|
validate_secret_absolute_file "secret-root/safe.txt" "test absolute secret file"
|
||||||
|
mkdir -m 0700 "${TEST_TMP}/external-secret-dir"
|
||||||
|
printf 'external-private-value\n' > "${TEST_TMP}/external-secret-dir/external.txt"
|
||||||
|
chmod 0400 "${TEST_TMP}/external-secret-dir/external.txt"
|
||||||
|
ln -s "${TEST_TMP}/external-secret-dir" "${TEST_TMP}/external-secret-dir-link"
|
||||||
|
expect_failure "external secret file through a symlinked parent accepted" \
|
||||||
|
validate_secret_absolute_file "${TEST_TMP}/external-secret-dir-link/external.txt" "test absolute secret file"
|
||||||
|
expect_failure "external secret directory through a symlinked parent accepted" \
|
||||||
|
validate_secret_absolute_directory "${TEST_TMP}/external-secret-dir-link" "test absolute secret directory"
|
||||||
|
declare secret_root_fs=""
|
||||||
|
secret_root_fs="$(secure_stat -f -c '%T' "${VAR_TMP_SECRET}")"
|
||||||
|
if [[ "${secret_root_fs}" != "tmpfs" && "${secret_root_fs}" != "ramfs" ]]; then
|
||||||
|
expect_failure "persistent secret staging area accepted" validate_secret_staging_area
|
||||||
|
fi
|
||||||
|
expect_failure "secret filename traversal accepted" validate_secret_filename "../safe.txt" "test secret filename"
|
||||||
|
expect_failure "absolute filename-only secret accepted" validate_secret_filename "/tmp/safe.txt" "test secret filename"
|
||||||
|
expect_failure "slash in filename-only secret accepted" validate_secret_filename "subdir/safe.txt" "test secret filename"
|
||||||
|
|
||||||
|
ln -s "${VAR_TMP_SECRET}" "${TEST_TMP}/secret-root-link"
|
||||||
|
expect_failure "secret-root symlink accepted" \
|
||||||
|
validate_secret_directory "${TEST_TMP}/secret-root-link" "test secret root" "false"
|
||||||
|
mkdir -m 0700 "${TEST_TMP}/unsafe-secret-root-mode"
|
||||||
|
chmod 0755 "${TEST_TMP}/unsafe-secret-root-mode"
|
||||||
|
expect_failure "broad secret-root permissions accepted" \
|
||||||
|
validate_secret_directory "${TEST_TMP}/unsafe-secret-root-mode" "test secret root" "false"
|
||||||
|
ln -s "${VAR_TMP_SECRET}/safe.txt" "${VAR_TMP_SECRET}/unsafe-link"
|
||||||
|
expect_failure "secret-file symlink accepted" validate_secret_file "${VAR_TMP_SECRET}/unsafe-link" "test secret file"
|
||||||
|
rm "${VAR_TMP_SECRET}/unsafe-link"
|
||||||
|
ln "${VAR_TMP_SECRET}/safe.txt" "${VAR_TMP_SECRET}/unsafe-hardlink"
|
||||||
|
expect_failure "hardlinked secret file accepted" validate_secret_file "${VAR_TMP_SECRET}/safe.txt" "test secret file"
|
||||||
|
rm "${VAR_TMP_SECRET}/unsafe-hardlink"
|
||||||
|
|
||||||
|
declare fake_secret='CISS-CANARY-[exact]-value'
|
||||||
|
declare expected_redaction=""
|
||||||
|
declare sanitisation_status=0
|
||||||
|
printf -v expected_redaction '%*s' "${#fake_secret}" ''
|
||||||
|
expected_redaction="${expected_redaction// /*}"
|
||||||
|
register_secret_value "${fake_secret}"
|
||||||
|
|
||||||
|
LOG_DEBUG="${TEST_TMP}/debug.log"
|
||||||
|
LOG_VAR="${TEST_TMP}/var.log"
|
||||||
|
LOG_ERROR="${TEST_TMP}/error.log"
|
||||||
|
printf 'before %s after\nunrelated line\n' "${fake_secret}" > "${LOG_DEBUG}"
|
||||||
|
printf 'unrelated vars\n' > "${LOG_VAR}"
|
||||||
|
printf 'unrelated error\n' > "${LOG_ERROR}"
|
||||||
|
chmod 0600 "${LOG_DEBUG}" "${LOG_VAR}" "${LOG_ERROR}"
|
||||||
|
|
||||||
|
sanitize_debug_logs || fail "debug-log sanitisation failed"
|
||||||
|
grep -Fq "${fake_secret}" "${LOG_DEBUG}" && fail "debug-log canary remained"
|
||||||
|
grep -Fq "${expected_redaction}" "${LOG_DEBUG}" || fail "expected exact-value redaction missing"
|
||||||
|
grep -Fq 'unrelated line' "${LOG_DEBUG}" || fail "unrelated debug content changed"
|
||||||
|
|
||||||
|
ln -s "${LOG_DEBUG}" "${TEST_TMP}/unsafe-debug-link"
|
||||||
|
(
|
||||||
|
LOG_DEBUG="${TEST_TMP}/unsafe-debug-link"
|
||||||
|
trap_on_exit 73 "test" 1 "test" "false"
|
||||||
|
) 2>/dev/null || sanitisation_status=$?
|
||||||
|
[[ ${sanitisation_status} -eq 73 ]] || fail "sanitisation failure masked the original exit status"
|
||||||
|
|
||||||
|
expect_failure "empty build-directory path accepted" validate_build_directory_path ""
|
||||||
|
expect_failure "root build-directory path accepted" validate_build_directory_path "/"
|
||||||
|
expect_failure "broad parent build-directory path accepted" validate_build_directory_path "/tmp"
|
||||||
|
expect_failure "secret root accepted as build directory" validate_build_directory_path "${VAR_TMP_SECRET}"
|
||||||
|
mkdir -m 0700 "${VAR_TMP_SECRET}/unsafe-build-child"
|
||||||
|
expect_failure "secret-root descendant accepted as build directory" \
|
||||||
|
validate_build_directory_path "${VAR_TMP_SECRET}/unsafe-build-child"
|
||||||
|
|
||||||
|
mkdir -m 0700 "${TEST_TMP}/unmarked"
|
||||||
|
expect_failure "build directory without marker accepted" validate_build_directory_marker "${TEST_TMP}/unmarked"
|
||||||
|
printf 'do-not-adopt\n' > "${TEST_TMP}/unmarked/content"
|
||||||
|
expect_failure "non-empty unmarked build directory adopted" initialize_build_directory "${TEST_TMP}/unmarked" unsafe_result
|
||||||
|
|
||||||
|
mkdir -m 0700 "${TEST_TMP}/unsafe-build-mode"
|
||||||
|
chmod 0777 "${TEST_TMP}/unsafe-build-mode"
|
||||||
|
expect_failure "unsafe build-directory permissions accepted" \
|
||||||
|
initialize_build_directory "${TEST_TMP}/unsafe-build-mode" unsafe_result
|
||||||
|
|
||||||
|
mkdir -m 0700 "${TEST_TMP}/marker-link-dir"
|
||||||
|
printf '%s\n' "${TEST_TMP}/marker-link-dir" > "${TEST_TMP}/marker-target"
|
||||||
|
chmod 0400 "${TEST_TMP}/marker-target"
|
||||||
|
ln -s "${TEST_TMP}/marker-target" "${TEST_TMP}/marker-link-dir/.ciss-live-builder-owned"
|
||||||
|
expect_failure "symlinked builder-owned marker accepted" validate_build_directory_marker "${TEST_TMP}/marker-link-dir"
|
||||||
|
|
||||||
|
mkdir -m 0700 "${TEST_TMP}/marker-hardlink-dir"
|
||||||
|
printf '%s\n' "${TEST_TMP}/marker-hardlink-dir" > "${TEST_TMP}/marker-hardlink-target"
|
||||||
|
chmod 0400 "${TEST_TMP}/marker-hardlink-target"
|
||||||
|
ln "${TEST_TMP}/marker-hardlink-target" "${TEST_TMP}/marker-hardlink-dir/.ciss-live-builder-owned"
|
||||||
|
expect_failure "hardlinked builder-owned marker accepted" validate_build_directory_marker "${TEST_TMP}/marker-hardlink-dir"
|
||||||
|
|
||||||
|
mkdir -m 0700 "${TEST_TMP}/marker-extra-content-dir"
|
||||||
|
printf '%s\nunexpected\n' "${TEST_TMP}/marker-extra-content-dir" \
|
||||||
|
> "${TEST_TMP}/marker-extra-content-dir/.ciss-live-builder-owned"
|
||||||
|
chmod 0400 "${TEST_TMP}/marker-extra-content-dir/.ciss-live-builder-owned"
|
||||||
|
expect_failure "builder-owned marker with extra content accepted" \
|
||||||
|
validate_build_directory_marker "${TEST_TMP}/marker-extra-content-dir"
|
||||||
|
|
||||||
|
ln -s "${TEST_TMP}/unmarked" "${TEST_TMP}/build-link"
|
||||||
|
expect_failure "build-directory symlink accepted" validate_build_directory_path "${TEST_TMP}/build-link"
|
||||||
|
|
||||||
|
declare validated_build_dir=""
|
||||||
|
initialize_build_directory "${TEST_TMP}/owned-build" validated_build_dir || fail "safe builder-owned directory rejected"
|
||||||
|
validate_build_directory_marker "${validated_build_dir}" || fail "builder marker rejected"
|
||||||
|
mkdir "${validated_build_dir}/subdir"
|
||||||
|
printf 'remove me\n' > "${validated_build_dir}/artifact"
|
||||||
|
printf 'remove me too\n' > "${validated_build_dir}/.hidden-artifact"
|
||||||
|
printf 'nested\n' > "${validated_build_dir}/subdir/nested"
|
||||||
|
clean_build_directory_contents "${validated_build_dir}" || fail "safe builder-owned cleanup failed"
|
||||||
|
validate_build_directory_marker "${validated_build_dir}" || fail "builder marker removed by cleanup"
|
||||||
|
[[ -z "$(find "${validated_build_dir}" -mindepth 1 ! -name '.ciss-live-builder-owned' -print -quit)" ]] \
|
||||||
|
|| fail "builder-owned cleanup left unexpected content"
|
||||||
|
|
||||||
|
mkdir -m 0700 "${TEST_TMP}/outside-build"
|
||||||
|
mkdir "${TEST_TMP}/outside-build/includes.chroot"
|
||||||
|
ln -s "${TEST_TMP}/outside-build" "${validated_build_dir}/config"
|
||||||
|
expect_failure "cleanup subpath through a symlinked parent accepted" \
|
||||||
|
validate_build_directory_subpath "${validated_build_dir}" "config/includes.chroot" unsafe_subpath
|
||||||
|
|
||||||
|
printf 'PASS: secret validation, debug sanitisation, and build cleanup guards\n'
|
||||||
+1
-1
@@ -25,7 +25,7 @@ declare -grx VAR_GIT_HEAD_FULL="$(git rev-parse HEAD)"
|
|||||||
declare -grx VAR_HOST="$(uname -n)"
|
declare -grx VAR_HOST="$(uname -n)"
|
||||||
declare -grx VAR_ISO8601="$(date -u -d "@${VAR_DATE_EPOCH}" '+%Y-%m-%dT%H:%M:%SZ')"
|
declare -grx VAR_ISO8601="$(date -u -d "@${VAR_DATE_EPOCH}" '+%Y-%m-%dT%H:%M:%SZ')"
|
||||||
declare -grx VAR_SYSTEM="$(uname -mnosv)"
|
declare -grx VAR_SYSTEM="$(uname -mnosv)"
|
||||||
declare -grx VAR_VERSION="Master V9.14.020.2026.06.08"
|
declare -grx VAR_VERSION="Master V9.14.022.2026.06.10"
|
||||||
declare -grx VAR_VER_BASH="$(bash --version | head -n1 | awk '{
|
declare -grx VAR_VER_BASH="$(bash --version | head -n1 | awk '{
|
||||||
# Print $4 and $5; include $6 only if it exists
|
# Print $4 and $5; include $6 only if it exists
|
||||||
out = $4
|
out = $4
|
||||||
|
|||||||
@@ -28,12 +28,16 @@ touch "${LOG_ERROR}" && chmod 0600 "${LOG_ERROR}"
|
|||||||
|
|
||||||
declare -g __umask=""
|
declare -g __umask=""
|
||||||
declare -g VAR_ARCHITECTURE=""
|
declare -g VAR_ARCHITECTURE=""
|
||||||
|
declare -g VAR_ARG_SANITIZED=""
|
||||||
declare -g VAR_DROPBEAR_VERSION="2026.91"
|
declare -g VAR_DROPBEAR_VERSION="2026.91"
|
||||||
declare -g VAR_HANDLER_BUILD_DIR=""
|
declare -g VAR_HANDLER_BUILD_DIR=""
|
||||||
declare -g VAR_HANDLER_CDI="false"
|
declare -g VAR_HANDLER_CDI="false"
|
||||||
declare -g VAR_HANDLER_NETCUP_IPV6="false"
|
declare -g VAR_HANDLER_NETCUP_IPV6="false"
|
||||||
declare -g VAR_HANDLER_SPLASH=""
|
declare -g VAR_HANDLER_SPLASH=""
|
||||||
declare -g VAR_HASHED_PWD=""
|
declare -g VAR_HASHED_PWD=""
|
||||||
|
declare -g VAR_PRIMORDIAL_KEY=""
|
||||||
|
declare -g VAR_PRIMORDIAL_SSH_PORT=""
|
||||||
|
declare -g VAR_PRIMORDIAL_URL=""
|
||||||
declare -g VAR_SCRIPT_SUCCESS="false"
|
declare -g VAR_SCRIPT_SUCCESS="false"
|
||||||
declare -g VAR_SOPS_VERSION="3.13.1"
|
declare -g VAR_SOPS_VERSION="3.13.1"
|
||||||
declare -g VAR_SSHFP="false"
|
declare -g VAR_SSHFP="false"
|
||||||
@@ -88,6 +92,8 @@ declare -gir ERR__SSH__PORT=212 # --ssh-port MUST be an integer between '1' and
|
|||||||
declare -gir ERR_ARG_MSMTCH=213 # Wrong Number of optional Arguments provided
|
declare -gir ERR_ARG_MSMTCH=213 # Wrong Number of optional Arguments provided
|
||||||
declare -gir ERR_DROPBEAR_V=214 # --dropbear-version MUST match the bundled Dropbear tarball version format
|
declare -gir ERR_DROPBEAR_V=214 # --dropbear-version MUST match the bundled Dropbear tarball version format
|
||||||
declare -gir ERR__SOPS__VER=215 # --sops-version MUST match the upstream SOPS semantic version format
|
declare -gir ERR__SOPS__VER=215 # --sops-version MUST match the upstream SOPS semantic version format
|
||||||
|
declare -gir ERR_SECRET_PATH=216 # Unsafe secret root, filename, or file.
|
||||||
|
declare -gir ERR_BUILD_PATH=217 # Unsafe build-directory path or marker.
|
||||||
declare -gir ERR_SECRETSSYM=251 # VAR_TMP_SECRET is a symlink.
|
declare -gir ERR_SECRETSSYM=251 # VAR_TMP_SECRET is a symlink.
|
||||||
declare -gir ERR_NOTABSPATH=252 # Not an absolute path
|
declare -gir ERR_NOTABSPATH=252 # Not an absolute path
|
||||||
declare -gir ERR_INVLD_CHAR=253 # Invalid Character
|
declare -gir ERR_INVLD_CHAR=253 # Invalid Character
|
||||||
|
|||||||
Reference in New Issue
Block a user