Skip to content

Commit

Permalink
Rely on FakeStorage more
Browse files Browse the repository at this point in the history
  • Loading branch information
smklein committed May 31, 2024
1 parent 805c090 commit a1868ac
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 92 deletions.
119 changes: 119 additions & 0 deletions nexus/auth/src/authz/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,122 @@ pub trait AuthorizedResource: oso::ToPolar + Send + Sync + 'static {
/// Returns the Polar class that implements this resource
fn polar_class(&self) -> oso::Class;
}

#[cfg(test)]
mod test {
use crate::authn;
use crate::authz::Action;
use crate::authz::AnyActor;
use crate::authz::Authz;
use crate::authz::Context;
use crate::authz::RoleSet;
use crate::context::OpContext;
use omicron_test_utils::dev;
use std::sync::Arc;

use nexus_db_model::IdentityType;
use nexus_db_model::RoleAssignment;
use omicron_common::api::external::Error;
use omicron_common::api::external::ResourceType;
use uuid::Uuid;

struct FakeStorage {}

impl FakeStorage {
fn new() -> Arc<dyn crate::storage::Storage> {
Arc::new(Self {})
}
}

#[async_trait::async_trait]
impl crate::storage::Storage for FakeStorage {
async fn role_asgn_list_for(
&self,
_opctx: &OpContext,
_identity_type: IdentityType,
_identity_id: Uuid,
_resource_type: ResourceType,
_resource_id: Uuid,
) -> Result<Vec<RoleAssignment>, Error> {
todo!();
}
}

fn authz_context_for_actor(
log: &slog::Logger,
authn: authn::Context,
datastore: Arc<dyn crate::storage::Storage>,
) -> Context {
let authz = Authz::new(log);
Context::new(Arc::new(authn), Arc::new(authz), datastore)
}

#[tokio::test]
async fn test_unregistered_resource() {
let logctx = dev::test_setup_log("test_unregistered_resource");
let datastore = FakeStorage::new();
let opctx = OpContext::for_background(
logctx.log.new(o!()),
Arc::new(Authz::new(&logctx.log)),
authn::Context::internal_db_init(),
Arc::clone(&datastore) as Arc<dyn crate::storage::Storage>,
);

// Define a resource that we "forget" to register with Oso.
use crate::authz::AuthorizedResource;
use oso::PolarClass;
#[derive(Clone, PolarClass)]
struct UnregisteredResource;
impl AuthorizedResource for UnregisteredResource {
fn load_roles<'a, 'b, 'c, 'd, 'e>(
&'a self,
_: &'b OpContext,
_: &'c authn::Context,
_: &'d mut RoleSet,
) -> futures::future::BoxFuture<'e, Result<(), Error>>
where
'a: 'e,
'b: 'e,
'c: 'e,
'd: 'e,
{
// authorize() shouldn't get far enough to call this.
unimplemented!();
}

fn on_unauthorized(
&self,
_: &Authz,
_: Error,
_: AnyActor,
_: Action,
) -> Error {
// authorize() shouldn't get far enough to call this.
unimplemented!();
}

fn polar_class(&self) -> oso::Class {
Self::get_polar_class()
}
}

// Make sure an authz check with this resource fails with a clear
// message.
let unregistered_resource = UnregisteredResource {};
let authz_privileged = authz_context_for_actor(
&logctx.log,
authn::Context::privileged_test_user(),
Arc::clone(&datastore) as Arc<dyn crate::storage::Storage>,
);
let error = authz_privileged
.authorize(&opctx, Action::Read, unregistered_resource)
.await;
println!("{:?}", error);
assert!(matches!(error, Err(Error::InternalError {
internal_message
}) if internal_message == "attempted authz check \
on unregistered resource: \"UnregisteredResource\""));

logctx.cleanup_successful();
}
}
92 changes: 0 additions & 92 deletions nexus/db-queries/src/db/datastore/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,95 +79,3 @@ impl Storage for super::DataStore {
}
}
}

#[cfg(test)]
mod test {
use crate::db::DataStore;
use nexus_auth::authn;
use nexus_auth::authz::Action;
use nexus_auth::authz::AnyActor;
use nexus_auth::authz::Authz;
use nexus_auth::authz::Context;
use nexus_auth::authz::RoleSet;
use nexus_test_utils::db::test_setup_database;
use omicron_test_utils::dev;
use std::sync::Arc;

fn authz_context_for_actor(
log: &slog::Logger,
authn: authn::Context,
datastore: Arc<DataStore>,
) -> Context {
let authz = Authz::new(log);
Context::new(Arc::new(authn), Arc::new(authz), datastore)
}

#[tokio::test]
async fn test_unregistered_resource() {
let logctx = dev::test_setup_log("test_unregistered_resource");
let mut db = test_setup_database(&logctx.log).await;
let (opctx, datastore) =
crate::db::datastore::test_utils::datastore_test(&logctx, &db)
.await;

// Define a resource that we "forget" to register with Oso.
use crate::context::OpContext;
use nexus_auth::authz::AuthorizedResource;
use omicron_common::api::external::Error;
use oso::PolarClass;
#[derive(Clone, PolarClass)]
struct UnregisteredResource;
impl AuthorizedResource for UnregisteredResource {
fn load_roles<'a, 'b, 'c, 'd, 'e>(
&'a self,
_: &'b OpContext,
_: &'c authn::Context,
_: &'d mut RoleSet,
) -> futures::future::BoxFuture<'e, Result<(), Error>>
where
'a: 'e,
'b: 'e,
'c: 'e,
'd: 'e,
{
// authorize() shouldn't get far enough to call this.
unimplemented!();
}

fn on_unauthorized(
&self,
_: &Authz,
_: Error,
_: AnyActor,
_: Action,
) -> Error {
// authorize() shouldn't get far enough to call this.
unimplemented!();
}

fn polar_class(&self) -> oso::Class {
Self::get_polar_class()
}
}

// Make sure an authz check with this resource fails with a clear
// message.
let unregistered_resource = UnregisteredResource {};
let authz_privileged = authz_context_for_actor(
&logctx.log,
authn::Context::privileged_test_user(),
Arc::clone(&datastore),
);
let error = authz_privileged
.authorize(&opctx, Action::Read, unregistered_resource)
.await;
println!("{:?}", error);
assert!(matches!(error, Err(Error::InternalError {
internal_message
}) if internal_message == "attempted authz check \
on unregistered resource: \"UnregisteredResource\""));

db.cleanup().await.unwrap();
logctx.cleanup_successful();
}
}

0 comments on commit a1868ac

Please sign in to comment.