fix(mosaic): serialize credential lifecycle mutations
This commit is contained in:
@@ -548,10 +548,12 @@ get_gitea_token() {
|
||||
printf '%s\n' "$_resolved_token"
|
||||
return 0
|
||||
fi
|
||||
if [[ -r "$_idtok" ]]; then
|
||||
if [[ -e "$_idtok" || -L "$_idtok" ]]; then
|
||||
local _resolved_token
|
||||
_resolved_token=$(python3 "$script_dir/resolve-legacy-token.py" "$_idtok") || return 1
|
||||
_resolution_path=identity
|
||||
_trace_credential_resolution credential-resolved "$_ident" "$host" "$_ident_src"
|
||||
cat "$_idtok"
|
||||
printf '%s\n' "$_resolved_token"
|
||||
return 0
|
||||
fi
|
||||
# FAIL LOUD: an explicit git identity was requested for a recognized Gitea host,
|
||||
|
||||
@@ -66,11 +66,12 @@ if [ -n "$ident" ]; then
|
||||
echo "password=${token}"
|
||||
exit 0
|
||||
fi
|
||||
if [ -r "$idtok" ]; then
|
||||
if [ -e "$idtok" ] || [ -L "$idtok" ]; then
|
||||
token=$(python3 "$script_dir/resolve-legacy-token.py" "$idtok") || exit 1
|
||||
resolution_path=identity
|
||||
trace_resolution credential-resolved "$ident" "$host" git-credential-mosaic
|
||||
echo "username=${ident}"
|
||||
echo "password=$(cat "$idtok")"
|
||||
echo "password=${token}"
|
||||
exit 0
|
||||
fi
|
||||
if [ -n "${MOSAIC_AGENT_NAME:-}" ]; then
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fail-closed reader for one legacy per-seat token file."""
|
||||
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
|
||||
MAX_BYTES = 16 * 1024
|
||||
|
||||
|
||||
def refuse(message: str) -> None:
|
||||
print(f"legacy credential refused: {message}", file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
refuse("expected token path")
|
||||
path = sys.argv[1]
|
||||
parent = os.path.dirname(path)
|
||||
try:
|
||||
parent_stat = os.stat(parent, follow_symlinks=False)
|
||||
except OSError:
|
||||
refuse("credential directory unavailable")
|
||||
if not stat.S_ISDIR(parent_stat.st_mode) or stat.S_ISLNK(parent_stat.st_mode):
|
||||
refuse("credential directory is not a real directory")
|
||||
if parent_stat.st_uid != os.getuid() or parent_stat.st_mode & 0o022:
|
||||
refuse("credential directory owner or mode is unsafe")
|
||||
try:
|
||||
fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_CLOEXEC)
|
||||
except OSError:
|
||||
refuse("credential file unavailable or symbolic")
|
||||
try:
|
||||
file_stat = os.fstat(fd)
|
||||
if not stat.S_ISREG(file_stat.st_mode):
|
||||
refuse("credential is not a regular file")
|
||||
if file_stat.st_uid != os.getuid() or file_stat.st_mode & 0o077:
|
||||
refuse("credential owner or mode is unsafe")
|
||||
content = os.read(fd, MAX_BYTES + 1)
|
||||
if len(content) > MAX_BYTES:
|
||||
refuse("credential exceeds size limit")
|
||||
finally:
|
||||
os.close(fd)
|
||||
try:
|
||||
token = content.decode("utf-8").strip()
|
||||
except UnicodeDecodeError:
|
||||
refuse("credential is not UTF-8")
|
||||
if not token or any(ch.isspace() for ch in token):
|
||||
refuse("credential token is invalid")
|
||||
sys.stdout.write(token + "\n")
|
||||
@@ -16,6 +16,7 @@
|
||||
# NEVER reads real secrets or touches the real ~/.config/mosaic/secrets.
|
||||
|
||||
set -euo pipefail
|
||||
umask 077
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
WORK_DIR="${MOSAIC_TEST_WORK_DIR:-$PWD/.mosaic-test-work/git-credential-mosaic}"
|
||||
@@ -35,6 +36,7 @@ mkdir -p "$FAKE_HOME/.config/mosaic/secrets/gitea-tokens" \
|
||||
|
||||
cp "$SCRIPT_DIR/git-credential-mosaic" "$HELPER"
|
||||
cp "$SCRIPT_DIR/resolve-credential-envelope.py" "$FAKE_HOME/.config/mosaic/tools/git/resolve-credential-envelope.py"
|
||||
cp "$SCRIPT_DIR/resolve-legacy-token.py" "$FAKE_HOME/.config/mosaic/tools/git/resolve-legacy-token.py"
|
||||
chmod +x "$HELPER"
|
||||
|
||||
git -C "$REPO_DIR" init -q
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
# HOME. NEVER reads real secrets or touches the real ~/.config/mosaic/secrets.
|
||||
|
||||
set -euo pipefail
|
||||
umask 077
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
WORK_DIR="${MOSAIC_TEST_WORK_DIR:-$PWD/.mosaic-test-work/gitea-token-identity}"
|
||||
|
||||
Reference in New Issue
Block a user