Adopt the portal owner on attach, rather than demanding a re-enrolment
Playwright Tests / test-playwright (1, 2) (push) Canceled after 0s
Playwright Tests / test-playwright (2, 2) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s
Playwright Tests / test-playwright (1, 2) (push) Canceled after 0s
Playwright Tests / test-playwright (2, 2) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s
An installation enrolled before per-user mapping has nobody mapped, and fail-closed means its owner is refused. Re-enrolling fixes it and can only be done from the machine's own network, which is the wrong thing to require of a machine whose only route in is the portal. The hub names the owner in the handshake now, and this takes it: if the enrolling account has no portal identity and nobody else holds that one, it is written once and every later attach is a no-op. A mapping somebody else holds is never moved - enrolment was told who that is, and this is only a repair. A failure to write one does not drop the link. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -281,3 +281,39 @@ def test_enrolling_against_a_portal_without_an_owner_is_refused(
|
||||
assert not settings.CLOUD_CONFIG_FILE.exists()
|
||||
finally:
|
||||
settings.CLOUD_CONFIG_FILE = original
|
||||
|
||||
|
||||
def test_an_older_enrolment_adopts_the_owner_on_attach(
|
||||
enrolled: User, db: Session, portal_key: rsa.RSAPrivateKey
|
||||
) -> None:
|
||||
"""An enrolment made before per-user mapping is fixed by reconnecting.
|
||||
|
||||
Without this its owner would be refused until somebody enrolled the machine
|
||||
again, which for a machine reached only through the portal means standing in
|
||||
front of it.
|
||||
"""
|
||||
from app.cloud.connector import CloudConnector
|
||||
|
||||
enrolled.portal_sub = None
|
||||
db.add(enrolled)
|
||||
db.commit()
|
||||
config = cloud_config.load()
|
||||
assert config is not None
|
||||
assert user_from_token(db, portal_token(portal_key)) is None
|
||||
|
||||
CloudConnector._adopt_owner(config, "portal-user-1")
|
||||
db.expire_all()
|
||||
assert user_from_token(db, portal_token(portal_key)) == enrolled
|
||||
|
||||
# Somebody else already holding that identity is left alone: enrolment was
|
||||
# told who this is, and this is only ever a repair.
|
||||
other = User(
|
||||
email="other@example.com", hashed_password="x", portal_sub="portal-user-2"
|
||||
)
|
||||
db.add(other)
|
||||
db.commit()
|
||||
CloudConnector._adopt_owner(config, "portal-user-2")
|
||||
db.expire_all()
|
||||
assert db.get(User, enrolled.id).portal_sub == "portal-user-1"
|
||||
db.delete(other)
|
||||
db.commit()
|
||||
|
||||
Reference in New Issue
Block a user