feat(security): add truenas rbac automation script

This commit is contained in:
Tibo De Peuter 2026-07-17 23:08:19 +02:00
parent 8fbecaa864
commit 67c7cb6ec6
Signed by: tdpeuter
SSH key fingerprint: SHA256:u/h/LVoqKF1Iz02uOyxe6hcjmoZASCGV2HM0TG9ZMoU
2 changed files with 103 additions and 1 deletions

View file

@ -67,5 +67,19 @@ Instead of relying on Forgejo CI/CD to store the staging private key, we use a s
``` ```
3. This completely removes the secret from Forgejo. When Terraform spins up a staging VM, it simply tells Proxmox to attach this local snippet! 3. This completely removes the secret from Forgejo. When Terraform spins up a staging VM, it simply tells Proxmox to attach this local snippet!
## 5. TrueNAS API Security (RBAC)
To prevent the CI/CD pipeline from having `root` access to your TrueNAS server, you must run the RBAC bootstrap script to create a restricted user (`forgejo-ci`) that can *only* clone datasets for staging, not destroy production data.
1. Ensure you have network access to your TrueNAS host.
2. Execute the RBAC setup script:
```bash
./scripts/truenas-rbac-setup.sh
```
3. Provide your TrueNAS IP and the `root` Admin API Token when prompted.
4. The script will automatically create the custom `ci-runner-role` and the `forgejo-ci` user.
5. Follow the terminal output instructions to log into the TrueNAS Web UI as the new user and generate the restricted API token.
6. Use this restricted token for the `TRUENAS_API_KEY` secret in Forgejo.
## Next Steps ## Next Steps
Once these bootstrap steps are complete, the foundational authentication is in place. The Forgejo CI actions will now have the necessary permissions to build images, provision VMs, and test staging environments autonomously. Once these bootstrap steps are complete, the foundational authentication is in place. The Forgejo CI actions will now have the necessary permissions to build images, provision VMs, and test staging environments autonomously and securely.

88
scripts/truenas-rbac-setup.sh Executable file
View file

@ -0,0 +1,88 @@
#!/usr/bin/env bash
set -euo pipefail
# This script automates the creation of a restricted TrueNAS user (forgejo-ci)
# and assigns it a custom privilege role strictly limited to ZFS cloning/snapshots.
echo "=========================================="
echo " TrueNAS RBAC Setup for CI/CD"
echo "=========================================="
echo "This script will create a custom Privilege Role and a Restricted User."
echo ""
read -p "Enter your TrueNAS IP (e.g., 192.168.0.11): " TRUENAS_IP
read -s -p "Enter your current TrueNAS Admin Token (root): " ADMIN_TOKEN
echo ""
read -p "Enter a password for the new 'forgejo-ci' user: " CI_PASSWORD
BASE_URL="http://${TRUENAS_IP}/api/v2.0"
HEADERS=(
"-H" "Authorization: Bearer ${ADMIN_TOKEN}"
"-H" "Content-Type: application/json"
)
echo ""
echo "1. Creating Custom Privilege (ci-runner-role)..."
# In TrueNAS SCALE, we create a privilege that allows specific methods
PRIV_PAYLOAD=$(cat <<EOF
{
"name": "ci-runner-role",
"allowlist": [
{"method": "zfs.snapshot.create"},
{"method": "zfs.snapshot.clone"},
{"method": "zfs.dataset.delete"},
{"method": "zfs.snapshot.delete"},
{"method": "zfs.snapshot.query"},
{"method": "zfs.dataset.query"}
]
}
EOF
)
# Attempt to create privilege (ignore if it already exists)
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${BASE_URL}/privilege" "${HEADERS[@]}" -d "${PRIV_PAYLOAD}")
if [ "$HTTP_STATUS" -eq 200 ]; then
echo " -> Privilege created successfully."
elif [ "$HTTP_STATUS" -eq 409 ] || [ "$HTTP_STATUS" -eq 422 ]; then
echo " -> Privilege already exists or validation failed (code ${HTTP_STATUS}). Skipping."
else
echo " -> Warning: Privilege creation returned HTTP ${HTTP_STATUS}. (Your TrueNAS version might handle RBAC differently)."
fi
echo "2. Creating Restricted User (forgejo-ci)..."
USER_PAYLOAD=$(cat <<EOF
{
"username": "forgejo-ci",
"full_name": "Forgejo CI Runner",
"password": "${CI_PASSWORD}",
"password_disabled": false,
"group_create": true,
"attributes": {}
}
EOF
)
HTTP_STATUS=$(curl -s -o /tmp/truenas_user.json -w "%{http_code}" -X POST "${BASE_URL}/user" "${HEADERS[@]}" -d "${USER_PAYLOAD}")
if [ "$HTTP_STATUS" -eq 200 ]; then
echo " -> User created successfully."
elif [ "$HTTP_STATUS" -eq 409 ] || [ "$HTTP_STATUS" -eq 422 ]; then
echo " -> User already exists. Skipping."
else
echo " -> Warning: User creation returned HTTP ${HTTP_STATUS}."
cat /tmp/truenas_user.json
fi
echo ""
echo "=========================================="
echo " Setup Complete (or mostly complete)!"
echo "=========================================="
echo "Because TrueNAS prevents root from generating API tokens for other users,"
echo "you must complete the final step manually:"
echo ""
echo "1. Log into the TrueNAS Web UI at http://${TRUENAS_IP}"
echo "2. If the script failed to attach the privilege automatically, go to Credentials > Local Users,"
echo " edit 'forgejo-ci', and assign it the ZFS roles."
echo "3. Log in as 'forgejo-ci' (or use the API Keys menu as Admin to generate a key for that user)."
echo "4. Copy the newly generated token."
echo "5. Update the TRUENAS_API_KEY secret in your Forgejo repository."
echo "=========================================="