Skip to content

Commit

Permalink
feat(rust): isolate member data by authority
Browse files Browse the repository at this point in the history
  • Loading branch information
etorreborre committed Jan 14, 2025
1 parent b5cc227 commit dbdaa6e
Show file tree
Hide file tree
Showing 25 changed files with 729 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ impl EnrollerAccessControlChecks {
}

pub(crate) async fn check_is_member(
authority: &Identifier,
members: Arc<dyn AuthorityMembersRepository>,
identifier: &Identifier,
) -> Result<EnrollerCheckResult> {
let r = match members.get_member(identifier).await? {
let r = match members.get_member(authority, identifier).await? {
Some(member) => {
let is_enroller = Self::check_bin_attributes_is_enroller(member.attributes());
EnrollerCheckResult {
Expand All @@ -65,12 +66,13 @@ impl EnrollerAccessControlChecks {
}

pub(crate) async fn check_identifier(
authority: &Identifier,
members: Arc<dyn AuthorityMembersRepository>,
identities_attributes: Arc<IdentitiesAttributes>,
identifier: &Identifier,
account_authority: &Option<AccountAuthorityInfo>,
) -> Result<EnrollerCheckResult> {
let mut r = Self::check_is_member(members, identifier).await?;
let mut r = Self::check_is_member(authority, members, identifier).await?;

if let Some(info) = account_authority {
if let Some(attrs) = identities_attributes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl CredentialIssuer {

// Otherwise, check if it's a member managed by this authority

let member = match self.members.get_member(subject).await? {
let member = match self.members.get_member(&self.issuer, subject).await? {
Some(member) => member,
None => return Ok(None),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct DirectAuthenticatorError(pub String);
pub type DirectAuthenticatorResult<T> = Either<T, DirectAuthenticatorError>;

pub struct DirectAuthenticator {
authority: Identifier,
members: Arc<dyn AuthorityMembersRepository>,
identities_attributes: Arc<IdentitiesAttributes>,
account_authority: Option<AccountAuthorityInfo>,
Expand Down Expand Up @@ -62,11 +63,13 @@ impl AccountAuthorityInfo {

impl DirectAuthenticator {
pub fn new(
authority: &Identifier,
members: Arc<dyn AuthorityMembersRepository>,
identities_attributes: Arc<IdentitiesAttributes>,
account_authority: Option<AccountAuthorityInfo>,
) -> Self {
Self {
authority: authority.clone(),
members,
identities_attributes,
account_authority,
Expand All @@ -81,6 +84,7 @@ impl DirectAuthenticator {
attributes: &BTreeMap<String, String>,
) -> Result<DirectAuthenticatorResult<()>> {
let check = EnrollerAccessControlChecks::check_identifier(
&self.authority,
self.members.clone(),
self.identities_attributes.clone(),
enroller,
Expand Down Expand Up @@ -122,7 +126,7 @@ impl DirectAuthenticator {
let member =
AuthorityMember::new(identifier.clone(), attrs, enroller.clone(), now()?, false);

if let Err(err) = self.members.add_member(member).await {
if let Err(err) = self.members.add_member(&self.authority, member).await {
warn!("Error adding member {} directly: {}", identifier, err);
return Ok(Either::Right(DirectAuthenticatorError(
"Error adding member".to_string(),
Expand All @@ -144,6 +148,7 @@ impl DirectAuthenticator {
identifier: &Identifier,
) -> Result<DirectAuthenticatorResult<AttributesEntry>> {
let check = EnrollerAccessControlChecks::check_identifier(
&self.authority,
self.members.clone(),
self.identities_attributes.clone(),
enroller,
Expand All @@ -158,7 +163,7 @@ impl DirectAuthenticator {
)));
}

match self.members.get_member(identifier).await? {
match self.members.get_member(&self.authority, identifier).await? {
Some(member) => {
let entry = AttributesEntry::new(
member.attributes().clone(),
Expand All @@ -184,6 +189,7 @@ impl DirectAuthenticator {
enroller: &Identifier,
) -> Result<DirectAuthenticatorResult<HashMap<Identifier, AttributesEntry>>> {
let check = EnrollerAccessControlChecks::check_identifier(
&self.authority,
self.members.clone(),
self.identities_attributes.clone(),
enroller,
Expand All @@ -198,7 +204,7 @@ impl DirectAuthenticator {
)));
}

let all_members = self.members.get_members().await?;
let all_members = self.members.get_members(&self.authority).await?;

let mut res = HashMap::<Identifier, AttributesEntry>::default();
for member in all_members {
Expand Down Expand Up @@ -239,6 +245,7 @@ impl DirectAuthenticator {
identifier: &Identifier,
) -> Result<DirectAuthenticatorResult<()>> {
let check_enroller = EnrollerAccessControlChecks::check_identifier(
&self.authority,
self.members.clone(),
self.identities_attributes.clone(),
enroller,
Expand All @@ -257,6 +264,7 @@ impl DirectAuthenticator {
}

let check_member = EnrollerAccessControlChecks::check_identifier(
&self.authority,
self.members.clone(),
self.identities_attributes.clone(),
identifier,
Expand Down Expand Up @@ -284,7 +292,9 @@ impl DirectAuthenticator {
)));
}

self.members.delete_member(identifier).await?;
self.members
.delete_member(&self.authority, identifier)
.await?;

info!("Successfully deleted member {}", identifier);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ pub struct DirectAuthenticatorWorker {

impl DirectAuthenticatorWorker {
pub fn new(
authority: &Identifier,
members: Arc<dyn AuthorityMembersRepository>,
identities_attributes: Arc<IdentitiesAttributes>,
account_authority: Option<AccountAuthorityInfo>,
) -> Self {
Self {
authenticator: DirectAuthenticator::new(
authority,
members,
identities_attributes,
account_authority,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,22 @@ pub struct EnrollmentTokenAcceptorError(pub String);
pub type EnrollmentTokenAcceptorResult<T> = Either<T, EnrollmentTokenAcceptorError>;

pub struct EnrollmentTokenAcceptor {
authority: Identifier,
pub(super) tokens: Arc<dyn AuthorityEnrollmentTokenRepository>,
pub(super) members: Arc<dyn AuthorityMembersRepository>,
}

impl EnrollmentTokenAcceptor {
pub fn new(
authority: &Identifier,
tokens: Arc<dyn AuthorityEnrollmentTokenRepository>,
members: Arc<dyn AuthorityMembersRepository>,
) -> Self {
Self { tokens, members }
Self {
authority: authority.clone(),
tokens,
members,
}
}

#[instrument(skip_all, fields(from = %from))]
Expand All @@ -33,8 +39,12 @@ impl EnrollmentTokenAcceptor {
otc: OneTimeCode,
from: &Identifier,
) -> Result<EnrollmentTokenAcceptorResult<()>> {
let check =
EnrollerAccessControlChecks::check_is_member(self.members.clone(), from).await?;
let check = EnrollerAccessControlChecks::check_is_member(
&self.authority,
self.members.clone(),
from,
)
.await?;

// Not allow updating existing members
if check.is_member {
Expand Down Expand Up @@ -72,7 +82,7 @@ impl EnrollmentTokenAcceptor {

let member = AuthorityMember::new(from.clone(), attrs, token.issued_by, now()?, false);

if let Err(err) = self.members.add_member(member).await {
if let Err(err) = self.members.add_member(&self.authority, member).await {
warn!(
"Error adding member {} using enrollment token: {}",
from, err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ pub struct EnrollmentTokenAcceptorWorker {

impl EnrollmentTokenAcceptorWorker {
pub fn new(
authority: &Identifier,
tokens: Arc<dyn AuthorityEnrollmentTokenRepository>,
members: Arc<dyn AuthorityMembersRepository>,
) -> Self {
Self {
acceptor: EnrollmentTokenAcceptor::new(tokens, members),
acceptor: EnrollmentTokenAcceptor::new(authority, tokens, members),
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct EnrollmentTokenIssuerError(pub String);
pub type EnrollmentTokenIssuerResult<T> = Either<T, EnrollmentTokenIssuerError>;

pub struct EnrollmentTokenIssuer {
authority: Identifier,
pub(super) tokens: Arc<dyn AuthorityEnrollmentTokenRepository>,
pub(super) members: Arc<dyn AuthorityMembersRepository>,
pub(super) identities_attributes: Arc<IdentitiesAttributes>,
Expand All @@ -34,12 +35,14 @@ pub struct EnrollmentTokenIssuer {

impl EnrollmentTokenIssuer {
pub fn new(
authority: &Identifier,
tokens: Arc<dyn AuthorityEnrollmentTokenRepository>,
members: Arc<dyn AuthorityMembersRepository>,
identities_attributes: Arc<IdentitiesAttributes>,
account_authority: Option<AccountAuthorityInfo>,
) -> Self {
Self {
authority: authority.clone(),
tokens,
members,
identities_attributes,
Expand All @@ -56,6 +59,7 @@ impl EnrollmentTokenIssuer {
ttl_count: Option<u64>,
) -> Result<EnrollmentTokenIssuerResult<OneTimeCode>> {
let check = EnrollerAccessControlChecks::check_identifier(
&self.authority,
self.members.clone(),
self.identities_attributes.clone(),
enroller,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ pub struct EnrollmentTokenIssuerWorker {

impl EnrollmentTokenIssuerWorker {
pub fn new(
authority: &Identifier,
tokens: Arc<dyn AuthorityEnrollmentTokenRepository>,
members: Arc<dyn AuthorityMembersRepository>,
identities_attributes: Arc<IdentitiesAttributes>,
account_authority: Option<AccountAuthorityInfo>,
) -> Self {
Self {
issuer: EnrollmentTokenIssuer::new(
authority,
tokens,
members,
identities_attributes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,48 +11,58 @@ use ockam_node::retry;
#[async_trait]
pub trait AuthorityMembersRepository: Send + Sync + 'static {
/// Return an existing member of the Project
async fn get_member(&self, identifier: &Identifier) -> Result<Option<AuthorityMember>>;
async fn get_member(
&self,
authority: &Identifier,
identifier: &Identifier,
) -> Result<Option<AuthorityMember>>;

/// Return all members of the Project
async fn get_members(&self) -> Result<Vec<AuthorityMember>>;
async fn get_members(&self, authority: &Identifier) -> Result<Vec<AuthorityMember>>;

/// Delete a member from the Project (unless it's pre-trusted)
async fn delete_member(&self, identifier: &Identifier) -> Result<()>;
async fn delete_member(&self, authority: &Identifier, identifier: &Identifier) -> Result<()>;

/// Add a member to the Project
async fn add_member(&self, member: AuthorityMember) -> Result<()>;
async fn add_member(&self, authority: &Identifier, member: AuthorityMember) -> Result<()>;

/// Remove the old pre-trusted members and store new pre-trusted members
async fn bootstrap_pre_trusted_members(
&self,
authority: &Identifier,
pre_trusted_identities: &PreTrustedIdentities,
) -> Result<()>;
}

#[async_trait]
impl<T: AuthorityMembersRepository> AuthorityMembersRepository for AutoRetry<T> {
async fn get_member(&self, identifier: &Identifier) -> Result<Option<AuthorityMember>> {
retry!(self.wrapped.get_member(identifier))
async fn get_member(
&self,
authority: &Identifier,
identifier: &Identifier,
) -> Result<Option<AuthorityMember>> {
retry!(self.wrapped.get_member(authority, identifier))
}

async fn get_members(&self) -> Result<Vec<AuthorityMember>> {
retry!(self.wrapped.get_members())
async fn get_members(&self, authority: &Identifier) -> Result<Vec<AuthorityMember>> {
retry!(self.wrapped.get_members(authority))
}

async fn delete_member(&self, identifier: &Identifier) -> Result<()> {
retry!(self.wrapped.delete_member(identifier))
async fn delete_member(&self, authority: &Identifier, identifier: &Identifier) -> Result<()> {
retry!(self.wrapped.delete_member(authority, identifier))
}

async fn add_member(&self, member: AuthorityMember) -> Result<()> {
retry!(self.wrapped.add_member(member.clone()))
async fn add_member(&self, authority: &Identifier, member: AuthorityMember) -> Result<()> {
retry!(self.wrapped.add_member(authority, member.clone()))
}

async fn bootstrap_pre_trusted_members(
&self,
authority: &Identifier,
pre_trusted_identities: &PreTrustedIdentities,
) -> Result<()> {
retry!(self
.wrapped
.bootstrap_pre_trusted_members(pre_trusted_identities))
.bootstrap_pre_trusted_members(authority, pre_trusted_identities))
}
}
Loading

0 comments on commit dbdaa6e

Please sign in to comment.