-
Notifications
You must be signed in to change notification settings - Fork 25.2k
Add support for secondary authentication #52093
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
Conversation
Pinging @elastic/es-security (:Security/Authentication) |
Draft/WIP because it builds on #52032 which is not merged yet |
e5f483c
to
de24408
Compare
Not yet, I need to rebase first
…On Thu, 13 Feb 2020, 8:49 pm Ioannis Kakavas, ***@***.***> wrote:
@tvernum <https://github.com/tvernum> is this good to be reviewed now
that #52032 <#52032> is
merged or do you want to make adjustments first ?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#52093?email_source=notifications&email_token=AARD6KMG7KHVCATTKBRJWATRCUJQZA5CNFSM4KRYQXM2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELUCZJY#issuecomment-585641127>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AARD6KKEODAFAWNK3I5R2ETRCUJQZANCNFSM4KRYQXMQ>
.
|
This change makes it possible to send secondary authentication credentials to select endpoints that need to perform a single action in the context of two users. Typically this need arises when a server process needs to call an endpoint that users should not (or might not) have direct access to, but some part of that action must be performed using the logged-in user's identity.
de24408
to
6fd9b62
Compare
(It's ready now, sorry, I forgot to ping) |
Ping @jkakavas |
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.
LGTM!
Sorry it took me a while, I wanted to go through and understand all changes and interactions. I left some nitpicking suggestions and a question
*/ | ||
public class SecondaryAuthentication { | ||
|
||
private static final String THREAD_CTX_KEY = "_xpack_security_2nd_authc"; |
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.
nit:
private static final String THREAD_CTX_KEY = "_xpack_security_2nd_authc"; | |
private static final String THREAD_CTX_KEY = "_xpack_security_secondary_authc"; |
purely personal preference, that 2nd
doesn't read well
} | ||
|
||
@Nullable | ||
public static SecondaryAuthentication restoreFromContext(SecurityContext securityContext) throws IOException { |
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.
Should we name this readFromContext
in order to not imply that it does anything more?
|
||
private static final String THREAD_CTX_KEY = "_xpack_security_2nd_authc"; | ||
|
||
public interface Authenticator { |
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 of a legitimate question than feedback, what value does this interface add?
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.
It existed so that x-pack-core had something usable even though the implementation was in security.
But actually that doesn't matter anymore because the only use the authentication from within security.
authenticate(authListener -> authenticationService.authenticate(action, request, false, authListener), listener); | ||
} | ||
|
||
/** |
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.
/** | |
/** |
)); | ||
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) { | ||
logger.trace("found secondary authentication credentials, placing them in the internal [{}] header for authentication", | ||
UsernamePasswordToken.BASIC_AUTH_HEADER); |
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.
Unrelated to this change but we should move BASIC_AUTH_HEADER
away from UsernamePasswordToken
, it confused me for more time than I'd like to admit :/
@@ -150,6 +150,7 @@ the system itself (e.g. pings, update mappings, share relocation, etc...) and we | |||
it to the action without an associated user (not via REST or transport - this is taken care of by | |||
the {@link Rest} filter and the {@link ServerTransport} filter respectively), it's safe to assume a system user | |||
here if a request is not associated with any other user. | |||
Because we want to fallback to the SystemUser, we don't allow anonymous (AnonymousUser) requests. |
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 comment found its way back here : #52094 (comment)
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.
Splitting this branch up ended up being hard work.
It was worth it because each of the changes was substantial, but there was a lot of rebasing and merging.
*/ | ||
@Override | ||
public void authenticate(String action, TransportRequest request, ActionListener<SecondaryAuthentication> listener) { | ||
authenticate(authListener -> authenticationService.authenticate(action, request, false, authListener), listener); |
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.
Would it be worth adding a comment or jdoc to mention that allowAnonymous
is set to false
for a reason?
.put(buildEnvSettings(Settings.EMPTY)) | ||
.put("xpack.security.authc.realms.dummy.test_realm.order", 1) | ||
.put("xpack.security.authc.token.enabled", true) | ||
.put("xpack.security.authc.api_key.enabled", true) |
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.
We don't actually use ApiKeyService here so we could just mock it below and return false on isEnabled()
?
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.
Yes. I originally expected to include a test for ApiKey authentication, but Bearer Token is sufficient to verify that we're not restricted to the realm chain.
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.
Actually, this is not as easy as it sounds.
authenticateWithApiKeyIfPresent
is package protected, so it's really hard to mock.
@@ -48,7 +49,9 @@ | |||
|
|||
public class SecurityRestFilterTests extends ESTestCase { |
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.
Should we add a test here to verify we process secondary authentication failures correctly?
This change makes it possible to send secondary authentication credentials to select endpoints that need to perform a single action in the context of two users. Typically this need arises when a server process needs to call an endpoint that users should not (or might not) have direct access to, but some part of that action must be performed using the logged-in user's identity. Backport of: elastic#52093
This change makes it possible to send secondary authentication credentials to select endpoints that need to perform a single action in the context of two users. Typically this need arises when a server process needs to call an endpoint that users should not (or might not) have direct access to, but some part of that action must be performed using the logged-in user's identity. Backport of: #52093
This change makes it possible to send secondary authentication
credentials to select endpoints that need to perform a single action
in the context of two users.
Typically this need arises when a server process needs to call an
endpoint that users should not (or might not) have direct access to,
but some part of that action must be performed using the logged-in
user's identity.