Skip to content
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

[ML] prefer secondary authorization header for data[feed|frame] authz #54121

Merged

Conversation

benwtrent
Copy link
Member

Secondary authorization headers are to be used to facilitate Kibana spaces support + ML jobs/datafeeds.

Now on PUT/Update/Preview datafeed, and PUT data frame analytics the secondary authorization is preferred over the primary (if provided).

closes #53801

@benwtrent benwtrent requested a review from droberts195 March 24, 2020 19:00
@@ -24,7 +24,7 @@
*/
public class SecondaryAuthentication {

private static final String THREAD_CTX_KEY = "_xpack_security_secondary_authc";
public static final String THREAD_CTX_KEY = "_xpack_security_secondary_authc";
Copy link
Member Author

@benwtrent benwtrent Mar 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tvernum I made this public so that it is accessible to the ML plugin

if (secondaryAuth != null) {
headers.put(AuthenticationField.AUTHENTICATION_KEY, secondaryAuth);
}
return headers;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tvernum We are storing _xpack_security_secondary_authc as the primary auth for some of our tasks. This way we "prefer" the secondary auth if it was provided.

Is simply replacing _xpack_security_authentication with the contents of _xpack_security_secondary_authc acceptable? Or are there technical limitations/details that I am missing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the test you did yesterday this looks like it works as intended now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't how I expected you would do it...

I had presumed that you would activate the secondary authentication so that it became the only authentication and then just do what you've always done.

Something like:

Runnable body = () -> {
   final Map<String, String> headers = threadPool.getThreadContext().getHeaders();   
   datafeedConfigProvider.updateDatefeedConfig(
            request.getUpdate().getId(),
            request.getUpdate(),
            headers,
            jobConfigProvider::validateDatafeedJob,
            ActionListener.wrap(
                updatedConfig -> listener.onResponse(new PutDatafeedAction.Response(updatedConfig)),
                listener::onFailure));
};
SecondaryAuthentication secondaryAuth = SecondaryAuthentication.readFromContext(securityContext);
if (secondaryAuth != null) {
 body = secondaryAuth.wrap(body);
}
body.run();

We could definitely, reduce some of that boilerplate and move it into SecondaryAuthentication if it would help, but the above is how I expected secondary auth to be used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tvernum we need the headers to be respected by _search and apply the roles that are stored in that context.

Do the other APIs respect secondary auth headers?

Another pain point is BWC. As a 'new' datafeed created with secondary auth headers could be used on an 'old' node. Then security would know nothing of the secondary auth concept and the datafeed would fail.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think I understand. secondaryAuth.wrap changes the stored headers so that the secondary auth header becomes the Authorization header.

Seems more idiomatic than iterating a map :). Let experiment and see if I can get it to work this way.

@benwtrent
Copy link
Member Author

@elasticmachine update branch

@elasticmachine
Copy link
Collaborator

Pinging @elastic/ml-core (:ml)

@@ -35,6 +35,12 @@ IMPORTANT: When {es} {security-features} are enabled, your {dfeed} remembers
which roles the user who updated it had at the time of update and runs the query
using those same roles.

+
--
NOTE: It is possible that secondary authorization headers are supplied in the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since "secondary authorization headers" are an ES thing, not a global standard, I think we should have a paragraph somewhere in the security docs that says the header name is es-secondary-authorization and the format is the same as for basic auth, and then "secondary authorization headers" in this sentence and the equivalent one in the other 3 files should be a link to that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the new paragraph should go at the bottom of https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html?

Copy link
Contributor

@droberts195 droberts195 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Java code LGTM now

I think the docs side needs more work though - something along the lines of what I said in https://github.com/elastic/elasticsearch/pull/54121/files#r399264654

@lcawl or @szabosteve please could you advise on where it would be best to explain the secondary authentication header concept?

if (secondaryAuth != null) {
headers.put(AuthenticationField.AUTHENTICATION_KEY, secondaryAuth);
}
return headers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the test you did yesterday this looks like it works as intended now.

String jobId = "secondary-privs-put-job";
createJob(jobId, "airline.keyword");
String datafeedId = "datafeed-" + jobId;
// Primary auth header does not have accesss, but secondary auth does
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 3 s's

@benwtrent benwtrent merged commit 1d24960 into elastic:master Apr 2, 2020
@benwtrent benwtrent deleted the feature/ml-allow-secondary-auth-header branch April 2, 2020 14:10
benwtrent added a commit to benwtrent/elasticsearch that referenced this pull request Apr 2, 2020
…elastic#54121)

Secondary authorization headers are to be used to facilitate Kibana spaces support + ML jobs/datafeeds.

Now on PUT/Update/Preview datafeed, and PUT data frame analytics the secondary authorization is preferred over the primary (if provided).

closes elastic#53801
benwtrent added a commit that referenced this pull request Apr 2, 2020
… authz (#54121) (#54645)

* [ML] prefer secondary authorization header for data[feed|frame] authz (#54121)

Secondary authorization headers are to be used to facilitate Kibana spaces support + ML jobs/datafeeds.

Now on PUT/Update/Preview datafeed, and PUT data frame analytics the secondary authorization is preferred over the primary (if provided).

closes #53801

* fixing for backport
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ML] Prefer secondary credentials when storing security headers for background tasks
5 participants