Skip to content

Commit

Permalink
nexus: Create read-write and read-only built-in users for OMDB
Browse files Browse the repository at this point in the history
As described and suggested in oxidecomputer#6600, create two built-in users to
replace the test user for OMDB's purposes. Follows USER_INTERNAL_API and its
read-only counterpart.

Signed-off-by: Andriy Sultanov <[email protected]>
  • Loading branch information
last-genius committed Nov 13, 2024
1 parent 69de8b6 commit 47da4ba
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 0 deletions.
22 changes: 22 additions & 0 deletions nexus/auth/src/authn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub use nexus_db_fixed_data::user_builtin::USER_DB_INIT;
pub use nexus_db_fixed_data::user_builtin::USER_EXTERNAL_AUTHN;
pub use nexus_db_fixed_data::user_builtin::USER_INTERNAL_API;
pub use nexus_db_fixed_data::user_builtin::USER_INTERNAL_READ;
pub use nexus_db_fixed_data::user_builtin::USER_OMDB;
pub use nexus_db_fixed_data::user_builtin::USER_OMDB_READ;
pub use nexus_db_fixed_data::user_builtin::USER_SAGA_RECOVERY;
pub use nexus_db_fixed_data::user_builtin::USER_SERVICE_BALANCER;

Expand Down Expand Up @@ -171,6 +173,16 @@ impl Context {
Context::context_for_builtin_user(USER_INTERNAL_READ.id)
}

/// Returns an authenticated context for use by the debugger
pub fn omdb_user() -> Context {
Context::context_for_builtin_user(USER_OMDB.id)
}

/// Returns an authenticated context for use by the debugger (read-only)
pub fn omdb_read() -> Context {
Context::context_for_builtin_user(USER_OMDB_READ.id)
}

/// Returns an authenticated context for use for authenticating external
/// requests
pub fn external_authn() -> Context {
Expand Down Expand Up @@ -284,6 +296,8 @@ mod test {
use super::USER_DB_INIT;
use super::USER_INTERNAL_API;
use super::USER_INTERNAL_READ;
use super::USER_OMDB;
use super::USER_OMDB_READ;
use super::USER_SAGA_RECOVERY;
use super::USER_SERVICE_BALANCER;
use super::USER_TEST_PRIVILEGED;
Expand Down Expand Up @@ -312,6 +326,14 @@ mod test {
let actor = authn.actor().unwrap();
assert_eq!(actor.actor_id(), USER_INTERNAL_READ.id);

let authn = Context::omdb_user();
let actor = authn.actor().unwrap();
assert_eq!(actor.actor_id(), USER_OMDB.id);

let authn = Context::omdb_read();
let actor = authn.actor().unwrap();
assert_eq!(actor.actor_id(), USER_OMDB_READ.id);

let authn = Context::external_authn();
let actor = authn.actor().unwrap();
assert_eq!(actor.actor_id(), USER_EXTERNAL_AUTHN.id);
Expand Down
9 changes: 9 additions & 0 deletions nexus/auth/src/authz/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ impl oso::PolarClass for AuthenticatedActor {
},
"USER_INTERNAL_API",
)
.add_constant(
AuthenticatedActor {
actor_id: authn::USER_OMDB.id,
silo_id: None,
roles: RoleSet::new(),
silo_policy: None,
},
"USER_OMDB",
)
.add_attribute_getter("silo", |a: &AuthenticatedActor| {
a.silo_id.map(|silo_id| {
super::Silo::new(
Expand Down
3 changes: 3 additions & 0 deletions nexus/auth/src/authz/omicron.polar
Original file line number Diff line number Diff line change
Expand Up @@ -579,3 +579,6 @@ has_role(USER_DB_INIT: AuthenticatedActor, "admin", _silo: Silo);

# Allow the internal API admin permissions on all silos.
has_role(USER_INTERNAL_API: AuthenticatedActor, "admin", _silo: Silo);

# Allow the debugger API admin permissions on all silos.
has_role(USER_OMDB: AuthenticatedActor, "admin", _silo: Silo);
20 changes: 20 additions & 0 deletions nexus/db-fixed-data/src/role_assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ pub static BUILTIN_ROLE_ASSIGNMENTS: Lazy<Vec<RoleAssignment>> =
*FLEET_ID,
role_builtin::FLEET_VIEWER.role_name,
),
// The OMDB user gets the "admin" role on the Fleet.
// This is needed to access siloed resources from all silos instead
// of reimplementing authenticated queries specifically for OMDB's use
RoleAssignment::new(
IdentityType::UserBuiltin,
user_builtin::USER_OMDB.id,
role_builtin::FLEET_ADMIN.resource_type,
*FLEET_ID,
role_builtin::FLEET_ADMIN.role_name,
),
// The "USER_OMDB_READ" user gets the "viewer" role on the fleet. This is
// needed as a user separate from the read-write OMDB to avoid destructive
// actions unless forced to.
RoleAssignment::new(
IdentityType::UserBuiltin,
user_builtin::USER_OMDB_READ.id,
role_builtin::FLEET_VIEWER.resource_type,
*FLEET_ID,
role_builtin::FLEET_VIEWER.role_name,
),
// The "external-authenticator" user gets the "authenticator" role
// on the sole fleet. This grants them the ability to create
// sessions.
Expand Down
22 changes: 22 additions & 0 deletions nexus/db-fixed-data/src/user_builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ pub static USER_INTERNAL_READ: Lazy<UserBuiltinConfig> = Lazy::new(|| {
)
});

/// Internal user used by OMDB
pub static USER_OMDB: Lazy<UserBuiltinConfig> = Lazy::new(|| {
UserBuiltinConfig::new_static(
"001de000-05e4-4000-8000-0000000009db",
"omdb-user",
"used by OMDB",
)
});

/// Internal user used by OMDB to read privileged resources
pub static USER_OMDB_READ: Lazy<UserBuiltinConfig> = Lazy::new(|| {
UserBuiltinConfig::new_static(
"001de000-05e4-4000-8000-0000000003db",
"omdb-read",
"used by OMDB",
)
});

/// Internal user used by Nexus when recovering sagas
pub static USER_SAGA_RECOVERY: Lazy<UserBuiltinConfig> = Lazy::new(|| {
UserBuiltinConfig::new_static(
Expand All @@ -94,6 +112,8 @@ mod test {
use super::USER_EXTERNAL_AUTHN;
use super::USER_INTERNAL_API;
use super::USER_INTERNAL_READ;
use super::USER_OMDB;
use super::USER_OMDB_READ;
use super::USER_SAGA_RECOVERY;
use super::USER_SERVICE_BALANCER;

Expand All @@ -104,6 +124,8 @@ mod test {
assert_valid_uuid(&USER_INTERNAL_API.id);
assert_valid_uuid(&USER_EXTERNAL_AUTHN.id);
assert_valid_uuid(&USER_INTERNAL_READ.id);
assert_valid_uuid(&USER_OMDB.id);
assert_valid_uuid(&USER_OMDB_READ.id);
assert_valid_uuid(&USER_SAGA_RECOVERY.id);
}
}
2 changes: 2 additions & 0 deletions nexus/db-queries/src/db/datastore/silo_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ impl DataStore {
&authn::USER_SERVICE_BALANCER,
&authn::USER_INTERNAL_API,
&authn::USER_INTERNAL_READ,
&authn::USER_OMDB,
&authn::USER_OMDB_READ,
&authn::USER_EXTERNAL_AUTHN,
&authn::USER_SAGA_RECOVERY,
]
Expand Down
4 changes: 4 additions & 0 deletions nexus/tests/integration_tests/users_builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ async fn test_users_builtin(cptestctx: &ControlPlaneTestContext) {
assert_eq!(u.identity.id, authn::USER_INTERNAL_API.id);
let u = users.remove(&authn::USER_INTERNAL_READ.name.to_string()).unwrap();
assert_eq!(u.identity.id, authn::USER_INTERNAL_READ.id);
let u = users.remove(&authn::USER_OMDB.name.to_string()).unwrap();
assert_eq!(u.identity.id, authn::USER_OMDB.id);
let u = users.remove(&authn::USER_OMDB_READ.name.to_string()).unwrap();
assert_eq!(u.identity.id, authn::USER_OMDB_READ.id);
let u = users.remove(&authn::USER_EXTERNAL_AUTHN.name.to_string()).unwrap();
assert_eq!(u.identity.id, authn::USER_EXTERNAL_AUTHN.id);
let u = users.remove(&authn::USER_SAGA_RECOVERY.name.to_string()).unwrap();
Expand Down

0 comments on commit 47da4ba

Please sign in to comment.