-
Notifications
You must be signed in to change notification settings - Fork 45
authz: add OpContext::for_saga_action #672
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
//! Serialization of authentication context for sagas | ||
// TODO-security: This is not fully baked. Right now, we serialize the actor | ||
// id. We should think through that a little more. Should we instead preload a | ||
// bunch of roles and then serialize that, for example? | ||
|
||
use crate::authn; | ||
use crate::context::OpContext; | ||
use serde::Deserialize; | ||
use serde::Serialize; | ||
|
||
/// Serialized form of an `OpContext` | ||
// NOTE: This structure must be versioned carefully. (That's true of all saga | ||
// structures, but this one has a particularly large blast radius.) | ||
#[derive(Debug, Deserialize, Serialize)] | ||
pub struct Serialized { | ||
kind: authn::Kind, | ||
} | ||
|
||
impl Serialized { | ||
pub fn for_opctx(opctx: &OpContext) -> Serialized { | ||
Serialized { kind: opctx.authn.kind.clone() } | ||
} | ||
|
||
pub fn to_authn(&self) -> authn::Context { | ||
authn::Context { kind: self.kind.clone(), schemes_tried: vec![] } | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the rationale behind creating a new struct instead of:
authn::Kind
from anauthn::Context
From<authn::Kind>
forauthn::Context
?(I know the comment says
OpContext
, but this seems much more specifically targetingauthn::Context
)That's basically what this is right? Something which should stay 1:1 with the "current authentication information", or some scheme to re-acquire it? Since
Kind
includes "all the possible ways the user may be authenticated", that seems like a reasonable proxy.Either way - could we change some of the names being used here?
Serialized
seems a bit generic, no? Tons of structures which are serializable exist in theauthn
module.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with your feeling that there's something off about the structure and name here. Let me address your specific points first:
...
I've been trying to keep the internal details of
authn::Context
as private as possible because I expect them to change as we flesh out authn. What you said is currently true. I don't know if that will be true going forward.There are different reasons that someone might want a serialized idea of "who authenticated an operation". These use cases might have very different security properties. You might want this information for a debug log, a formal audit log, or to do an authz check in the context of the request, or to propagate the authentication to some other context, possibly at a later time (as in the case of a saga action, but could also be true if we passed this information in a request to some other control plane service). Some of these representations could involve actual secrets (e.g., a bearer token), while others absolutely should never include a secret (the debug log entry). This change creates one representation that's (barely) suitable for one of these purposes. As you said it's simple enough to be used for many of them today. But it seems unlikely that will be true in the future.
Now, we could go either way on this. If we expect to have multiple representations in the future, we could label this structure as general-purpose today and trust that our future selves will be careful enough to recognize when security demands a different representation and build new representations as needed. Or we could label it today as "suitable for use in this specific case only" and trust our future selves, with a second use case in hand, to decide whether it's suitable and refactor as needed. I generally tend towards the latter -- I don't like to describe something as generic when I only really know about one use case.
Yeah, as we've previously discussed, I'd been trying to let the module name describe it. It's
authn::saga::Serialized
-- a serialized authn [context] for use in sagas.authn::saga::SerializedIdentity
?authn::SerializedIdentityForSaga
?authn::SagaIdentity
?So like I said, I agree with you that there's something funny about the structure or naming here. But I'm not sure how better to phrase it. To restate my goals:
OpContext
and to reconstruct anOpContext
from it [along with other information that's also part of the OpContext]authn::Context
directly or as you saidauthn::Kind
. That sort of ties the in-memory form (which is mainly intended for the use case of authorizing an operation in the context of this request) to the serialized form (which is intended for storing to disk and reusing at a later time in some other context).authn::Context
to somewhere else (e.g., the public API or some other database record or a log file) without considering the consequences -- i.e., if somebody wants to do that, I want them to ask "hmm, maybeauthn::Context
[orauthn::Kind
] doesn't impl Serialize for a reason?"