-
Notifications
You must be signed in to change notification settings - Fork 151
Feat[MQB]: Make authentication workflow use plugins #773
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
base: integration/authn-authz
Are you sure you want to change the base?
Feat[MQB]: Make authentication workflow use plugins #773
Conversation
d8e0447
to
0f8a365
Compare
057a7c2
to
ec64999
Compare
d74e1fe
to
2d81dff
Compare
85e7ca0
to
6441933
Compare
a6885dd
to
c2820a5
Compare
6441933
to
dae302b
Compare
c2820a5
to
1217636
Compare
9f73e62
to
3508355
Compare
09f7274
to
57a2d8f
Compare
57a2d8f
to
57e5b06
Compare
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.
partial review
STOP_OBJ(d_configProvider_mp, "ConfigProvider"); | ||
STOP_OBJ(d_statController_mp, "StatController"); | ||
STOP_OBJ(d_authenticationController_mp, "AuthenticationController"); | ||
STOP_OBJ(d_statController_mp, "StatController"); |
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.
This and the DESTROY_OBJ
change below look important. Is this because we use stats in our auth controller?
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.
Not yet. This change is made since StatController
starts first before AuthenticationController
, so when stopping I wanted to have them in reverse order.
a873f88
to
fbb6bec
Compare
1217636
to
1128950
Compare
Signed-off-by: dorjesinpo <129227380+dorjesinpo@users.noreply.github.com>
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
348789c
to
5d15c0d
Compare
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
86a08e2
to
b31b0a5
Compare
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
c53a634
to
224314f
Compare
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
224314f
to
6965cc7
Compare
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
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.
Could you also rebase the branch to the latest main to allow Solaris build?
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.
Could you also rebase the branch to the latest main to allow Solaris build?
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
9360453
to
6715100
Compare
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.
Addressed the review from @678098 and responded to some questions.
int rc = decodeInitialConnectionMessage(errorDescription, &message, blob); | ||
|
||
if (rc != rc_SUCCESS) { | ||
return (rc * 10) + rc_INVALID_INITIALCONNECTION_MESSAGE; // RETURN |
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.
Not sure what you mean. Isn't errorDescription
populated from decodeInitialConnectionMessage
?
{ | ||
// PRECONDITIONS | ||
BSLS_ASSERT_OPT(!d_isStarted && | ||
"start() can only be called once on this object"); |
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 thought that's what I'm doing here?
|
||
/// Return the anonymous credential used for authentication. | ||
/// If no anonymous credential is set, return an empty optional. | ||
const bsl::optional<mqbcfg::Credential>& anonymousCredential(); |
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.
optional
doesn't help to bypass including this file. mqbplug_pluginmanager
does include it tho if you think we can just use the one from mqbplug_pluginmanager
.
bdlmt::EventScheduler* d_scheduler; | ||
|
||
/// Allocator to use. | ||
bslma::Allocator* d_allocator_p; |
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 don't mind reordering but kind of want to keep d_allocator_p
at the end cuz it helps to eliminate one extra parameter when calling allocate_shared
.
namespace mqbnet { | ||
|
||
namespace { | ||
BALL_LOG_SET_NAMESPACE_CATEGORY("MQBNET.AUTHENTICATIONCONTEXT"); |
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.
Yeah this was a misused but I'm sure there's no error or crash.
const mqbcfg::AuthenticatorPluginConfig* d_authenticatorConfig_p; | ||
|
||
bool d_isStarted; | ||
|
||
bslma::Allocator* d_allocator_p; |
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.
Maybe not a big deal but putting d_allocator_p
to the front would cause one extra variable provided toallocate_shared
.
{ | ||
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); // LOCKED | ||
|
||
if (d_state == State::e_CLOSED) { |
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.
The point of using a single mutex was bcz it's simpler to reason about the potential race condition between scheduling a reauthn event and closing a channel, making sure changing the state to e_CLOSED
and cancelEventAndWait
happen at the same time. We could use an atomic but there's a few places I still have to hold a mutex while accessing it. So I'm leaning towards just use one mutex unless you have a strong opinion against this idea. Thanks!
{ | ||
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); | ||
|
||
return d_state == state; |
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.
See the comments above.
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.
More comments
I can test the build on Solaris when the branch is rebased from the latest main
class Authenticator : public mqbnet::Authenticator { | ||
private: | ||
// CLASS-SCOPE CATEGORY | ||
BALL_LOG_SET_CLASS_CATEGORY("MQBNET.AUTHENTICATIONCONTEXT"); |
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.
BALL_LOG_SET_CLASS_CATEGORY("MQBNET.AUTHENTICATIONCONTEXT"); | |
BALL_LOG_SET_CLASS_CATEGORY("MQBA.AUTHENTICATOR"); |
bdlmt::EventScheduler* d_scheduler; | ||
|
||
/// Allocator to use. | ||
bslma::Allocator* d_allocator_p; |
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.
Do you mean the fact that we omit the last allocator arg when calling allocate_shared
? allocate_shared
looks at class traits and if there is allocator trait it always passes an allocator as the last arg to constructor automatically.
The important thing is to keep allocator arg the last in the constructor, but it can be placed in the first place in the class fields.
{ | ||
// PRECONDITIONS | ||
BSLS_ASSERT_OPT(!d_isStarted && | ||
"start() can only be called once on this object"); |
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 think it should be symmetrical, to make the codebase simpler and predictable.
Might either gracefully handle multiple start
/stop
, or assert in both cases.
Probably it's better to handle without crash.
|
||
public: | ||
// TRAITS | ||
BSLMF_NESTED_TRAIT_DECLARATION(Authenticator, bslma::UsesBslmaAllocator) |
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.
BSLMF_NESTED_TRAIT_DECLARATION(Authenticator, bslma::UsesBslmaAllocator) | |
BSLMF_NESTED_TRAIT_DECLARATION(AnonPassAuthenticator, bslma::UsesBslmaAllocator) |
const mqbcfg::AuthenticatorPluginConfig* d_authenticatorConfig_p; | ||
|
||
bool d_isStarted; | ||
|
||
bslma::Allocator* d_allocator_p; |
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.
The problem might be with missing/incorrect allocated nested trait that is used by allocate_shared
, if it is present and correct, there should be no last allocator arg in allocate_shared
|
||
public: | ||
// TRAITS | ||
BSLMF_NESTED_TRAIT_DECLARATION(AuthenticationContext, |
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.
BSLMF_NESTED_TRAIT_DECLARATION(AuthenticationContext, | |
BSLMF_NESTED_TRAIT_DECLARATION(InitialConnectionContext, |
|
||
public: | ||
// TRAITS | ||
BSLMF_NESTED_TRAIT_DECLARATION(PassAuthenticationResult, |
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.
BSLMF_NESTED_TRAIT_DECLARATION(PassAuthenticationResult, | |
BSLMF_NESTED_TRAIT_DECLARATION(PassAuthenticator, |
If the provided class name doesn't match the current class name the trait will not work
|
||
public: | ||
// TRAITS | ||
BSLMF_NESTED_TRAIT_DECLARATION(FailAuthenticationResult, |
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.
BSLMF_NESTED_TRAIT_DECLARATION(FailAuthenticationResult, | |
BSLMF_NESTED_TRAIT_DECLARATION(FailAuthenticator, |
|
||
public: | ||
// TRAITS | ||
BSLMF_NESTED_TRAIT_DECLARATION(BasicAuthenticationResult, |
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.
BSLMF_NESTED_TRAIT_DECLARATION(BasicAuthenticationResult, | |
BSLMF_NESTED_TRAIT_DECLARATION(BasicAuthenticator, |
// BMQ | ||
|
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.
// BMQ |
This PR apply plugin into authentication and reauthentication when we as a broker receives authentication requests from clients.
rawclient
to support integration testtest_authn.py
.bmqauthnbasic
for testing. It uses "basic" as mechanism and creates an in-memory map for username and password.Authenticator
is managed byTransportManager
and referred to byInitialConnectionContext
.AuthenticationRequest
.channel
is closed when there's a failure.AuthenticationContext
is created during initial connection, create areauthenticateCb
to be called when a client session later receives anAuthenticationEvent
.AuthenticationContext::State
to indicate the state of authentication. This is used as to make sure only one authentication is run for a given context, and when a channel closes, no more reauthentication timer will be scheduled.ClientIdentity
prior to anyAuthenticateRequest
, we use default credential to authenticate, unless it's explicitly set toDisallow
.AnonyPassAuthenticator
(implementingmqbplug::Authenticator
) and the corresponding factory and result undermqbauthn
as defaultAuthenticator
.TransportManager
instead ofInitialConnectionHandler
own theNegotiator
.InitialConnectionContext::State
to indicate the state of initial connection.