feat: add secure agent enrollment
This commit is contained in:
1 parent
82309db79a
commit
d9f0da694b
26 files changed
+2942
-76
No files matched your search
Executable
+327
@@ -0,0 +1,327 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "${repo_root}"
|
||||
|
||||
project="minerops-agent-enrollment-migration-$$"
|
||||
compose=(
|
||||
docker compose
|
||||
--project-name "${project}"
|
||||
--env-file .env.dev
|
||||
-f compose.dev.yaml
|
||||
)
|
||||
|
||||
cleanup() {
|
||||
"${compose[@]}" down -v --remove-orphans >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source .env.dev
|
||||
set +a
|
||||
|
||||
echo "Starting disposable PostgreSQL..."
|
||||
"${compose[@]}" up -d postgres
|
||||
|
||||
echo "Waiting for PostgreSQL..."
|
||||
for attempt in $(seq 1 60); do
|
||||
if "${compose[@]}" exec -T postgres \
|
||||
pg_isready -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
if [[ "${attempt}" -eq 60 ]]; then
|
||||
echo "PostgreSQL did not become ready" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Building backend with migration 0017..."
|
||||
"${compose[@]}" build backend >/dev/null
|
||||
|
||||
run_backend() {
|
||||
"${compose[@]}" run --rm --no-deps backend "$@"
|
||||
}
|
||||
|
||||
psql_exec() {
|
||||
"${compose[@]}" exec -T postgres \
|
||||
psql -v ON_ERROR_STOP=1 \
|
||||
-U "${POSTGRES_USER}" \
|
||||
-d "${POSTGRES_DB}" "$@"
|
||||
}
|
||||
|
||||
echo "Testing upgrade through 0016..."
|
||||
run_backend alembic upgrade 0016_agent_zones
|
||||
|
||||
revision="$(
|
||||
psql_exec -Atc "SELECT version_num FROM alembic_version"
|
||||
)"
|
||||
[[ "${revision}" == "0016_agent_zones" ]]
|
||||
|
||||
echo "Testing 0016 -> 0017..."
|
||||
run_backend alembic upgrade 0017_agent_enrollment
|
||||
|
||||
revision="$(
|
||||
psql_exec -Atc "SELECT version_num FROM alembic_version"
|
||||
)"
|
||||
[[ "${revision}" == "0017_agent_enrollment" ]]
|
||||
|
||||
echo "Checking new Agent credential columns..."
|
||||
for column in \
|
||||
display_name \
|
||||
agent_secret_hash \
|
||||
credential_created_at \
|
||||
credential_revoked_at
|
||||
do
|
||||
count="$(
|
||||
psql_exec -Atc "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'minerops_site_agents'
|
||||
AND column_name = '${column}'
|
||||
"
|
||||
)"
|
||||
[[ "${count}" == "1" ]]
|
||||
done
|
||||
|
||||
echo "Checking enrollment table..."
|
||||
count="$(
|
||||
psql_exec -Atc "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'agent_enrollments'
|
||||
"
|
||||
)"
|
||||
[[ "${count}" == "1" ]]
|
||||
|
||||
echo "Checking expected indexes..."
|
||||
for index in \
|
||||
uq_minerops_site_agents_agent_secret_hash \
|
||||
uq_agent_enrollments_token_hash \
|
||||
uq_agent_enrollments_open_zone \
|
||||
uq_agent_enrollments_enrolled_agent \
|
||||
idx_agent_enrollments_site_id \
|
||||
idx_agent_enrollments_created_at
|
||||
do
|
||||
count="$(
|
||||
psql_exec -Atc "
|
||||
SELECT COUNT(*)
|
||||
FROM pg_indexes
|
||||
WHERE schemaname = 'public'
|
||||
AND indexname = '${index}'
|
||||
"
|
||||
)"
|
||||
[[ "${count}" == "1" ]]
|
||||
done
|
||||
|
||||
echo "Testing immediate legal downgrade..."
|
||||
run_backend alembic downgrade 0016_agent_zones
|
||||
|
||||
revision="$(
|
||||
psql_exec -Atc "SELECT version_num FROM alembic_version"
|
||||
)"
|
||||
[[ "${revision}" == "0016_agent_zones" ]]
|
||||
|
||||
count="$(
|
||||
psql_exec -Atc "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'agent_enrollments'
|
||||
"
|
||||
)"
|
||||
[[ "${count}" == "0" ]]
|
||||
|
||||
echo "Re-upgrading to 0017..."
|
||||
run_backend alembic upgrade 0017_agent_enrollment
|
||||
|
||||
echo "Creating isolated Site and Agent Zone fixtures..."
|
||||
psql_exec <<'SQL'
|
||||
INSERT INTO sites (id, name)
|
||||
VALUES (
|
||||
'00000000-0000-4000-8000-000000001700',
|
||||
'Enrollment Migration Test Site'
|
||||
);
|
||||
|
||||
INSERT INTO agent_zones (
|
||||
id,
|
||||
site_id,
|
||||
name,
|
||||
description,
|
||||
is_enabled
|
||||
)
|
||||
VALUES (
|
||||
'00000000-0000-4000-8000-000000001701',
|
||||
'00000000-0000-4000-8000-000000001700',
|
||||
'Enrollment Test Zone',
|
||||
'Disposable migration test',
|
||||
true
|
||||
);
|
||||
SQL
|
||||
|
||||
echo "Testing database constraints..."
|
||||
|
||||
psql_exec <<'SQL'
|
||||
DO $$
|
||||
BEGIN
|
||||
BEGIN
|
||||
INSERT INTO agent_enrollments (
|
||||
token_hash,
|
||||
site_id,
|
||||
agent_zone_id,
|
||||
display_name,
|
||||
expires_at
|
||||
)
|
||||
VALUES (
|
||||
'not-a-sha256-hash',
|
||||
'00000000-0000-4000-8000-000000001700',
|
||||
'00000000-0000-4000-8000-000000001701',
|
||||
'Invalid Hash',
|
||||
now() + interval '30 minutes'
|
||||
);
|
||||
RAISE EXCEPTION 'invalid token hash was accepted';
|
||||
EXCEPTION
|
||||
WHEN check_violation THEN NULL;
|
||||
END;
|
||||
END $$;
|
||||
SQL
|
||||
|
||||
psql_exec <<'SQL'
|
||||
INSERT INTO agent_enrollments (
|
||||
id,
|
||||
token_hash,
|
||||
site_id,
|
||||
agent_zone_id,
|
||||
display_name,
|
||||
expires_at
|
||||
)
|
||||
VALUES (
|
||||
'00000000-0000-4000-8000-000000001710',
|
||||
repeat('a', 64),
|
||||
'00000000-0000-4000-8000-000000001700',
|
||||
'00000000-0000-4000-8000-000000001701',
|
||||
'Enrollment Test Agent',
|
||||
now() + interval '30 minutes'
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
BEGIN
|
||||
INSERT INTO agent_enrollments (
|
||||
token_hash,
|
||||
site_id,
|
||||
agent_zone_id,
|
||||
display_name,
|
||||
expires_at
|
||||
)
|
||||
VALUES (
|
||||
repeat('b', 64),
|
||||
'00000000-0000-4000-8000-000000001700',
|
||||
'00000000-0000-4000-8000-000000001701',
|
||||
'Second Open Enrollment',
|
||||
now() + interval '30 minutes'
|
||||
);
|
||||
RAISE EXCEPTION 'second open enrollment was accepted';
|
||||
EXCEPTION
|
||||
WHEN unique_violation THEN NULL;
|
||||
END;
|
||||
END $$;
|
||||
SQL
|
||||
|
||||
echo "Testing credential hash integrity and uniqueness..."
|
||||
|
||||
psql_exec <<'SQL'
|
||||
INSERT INTO minerops_site_agents (
|
||||
agent_id,
|
||||
site_id,
|
||||
agent_zone_id,
|
||||
site_name,
|
||||
display_name,
|
||||
agent_secret_hash,
|
||||
credential_created_at
|
||||
)
|
||||
VALUES (
|
||||
'agent-enrollment-test',
|
||||
'00000000-0000-4000-8000-000000001700',
|
||||
'00000000-0000-4000-8000-000000001701',
|
||||
'Enrollment Migration Test Site',
|
||||
'Enrollment Test Agent',
|
||||
repeat('c', 64),
|
||||
now()
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
BEGIN
|
||||
INSERT INTO minerops_site_agents (
|
||||
agent_id,
|
||||
site_name,
|
||||
display_name,
|
||||
agent_secret_hash,
|
||||
credential_created_at
|
||||
)
|
||||
VALUES (
|
||||
'agent-enrollment-duplicate-secret',
|
||||
'Enrollment Migration Test Site',
|
||||
'Duplicate Secret',
|
||||
repeat('c', 64),
|
||||
now()
|
||||
);
|
||||
RAISE EXCEPTION 'duplicate Agent secret hash was accepted';
|
||||
EXCEPTION
|
||||
WHEN unique_violation THEN NULL;
|
||||
END;
|
||||
END $$;
|
||||
SQL
|
||||
|
||||
echo "Testing downgrade refusal after feature use..."
|
||||
|
||||
set +e
|
||||
downgrade_output="$(
|
||||
run_backend alembic downgrade 0016_agent_zones 2>&1
|
||||
)"
|
||||
downgrade_status=$?
|
||||
set -e
|
||||
|
||||
if [[ "${downgrade_status}" -eq 0 ]]; then
|
||||
echo "Downgrade unexpectedly succeeded after enrollment/credential use" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
grep -Eq \
|
||||
'Cannot downgrade 0017: Agent enrollment history exists|Cannot downgrade 0017: per-Agent credentials exist' \
|
||||
<<<"${downgrade_output}"
|
||||
|
||||
revision="$(
|
||||
psql_exec -Atc "SELECT version_num FROM alembic_version"
|
||||
)"
|
||||
[[ "${revision}" == "0017_agent_enrollment" ]]
|
||||
|
||||
echo "Confirming refusal happened before destructive schema changes..."
|
||||
|
||||
count="$(
|
||||
psql_exec -Atc "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'agent_enrollments'
|
||||
"
|
||||
)"
|
||||
[[ "${count}" == "1" ]]
|
||||
|
||||
count="$(
|
||||
psql_exec -Atc "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'minerops_site_agents'
|
||||
AND column_name = 'agent_secret_hash'
|
||||
"
|
||||
)"
|
||||
[[ "${count}" == "1" ]]
|
||||
|
||||
echo "Agent enrollment migration lifecycle checks passed."
|
||||
Reference in new issue
Block a user