-
Notifications
You must be signed in to change notification settings - Fork 340
Store Scheduled Job User Information in an index owned by the Security plugin #2773
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
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
…ross indices Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
|
@peternied I'm curious on your thoughts to this approach for scheduled job security - this approach offloads the responsibility of storing user info on a plugin/extension. |
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
|
@joshpalis Tagging to keep you in the loop. This is a Draft PR that shows the approach to scheduled job security for extensions. It would be useful for plugins today as well and offloads plugins needing to keep track of user info themselves. |
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
| } else if (totalHits == 1) { | ||
| logger.info("Scheduled Job Identity already exists in " + SCHEDULED_JOB_IDENTITY_INDEX + " for job with jobId " + jobId); | ||
| } else { | ||
| final User user = threadPool.getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); |
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.
@davidlago Made a good comment that if an extension/plugin is writing to its Jobs Index that the user in the threadcontext may not be the right user to persist for the job identity index. I'm looking into ways that the correct user information can be provided.
DarshitChanpura
left a 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.
took a first pass and left some comments.
| private final String indexName; | ||
| private final String mapping; | ||
|
|
||
| SecurityIndex(String name, Supplier<String> mappingSupplier) { |
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.
Why use Supplier here? Asking because we are just returning a String and not a custom class object
| // keep track of whether the mapping version is up-to-date | ||
| private EnumMap<SecurityIndex, IndexState> indexStates; | ||
|
|
||
| class IndexState { |
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 please explain the purpose of this class?
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 is based off some similar code in AD. I will take a deeper dive and reply back with findings.
| if (createdResponse.isAcknowledged()) { | ||
| IndexState indexState = indexStates.computeIfAbsent(index, IndexState::new); | ||
| if (Boolean.FALSE.equals(indexState.mappingUpToDate)) { | ||
| indexState.mappingUpToDate = Boolean.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.
Why set it to true if it was false? Asking because i'm not sure where are we updating the mapping
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
peternied
left a 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.
Nice work getting Security to support Identity!
| } | ||
| final User user = (User) threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); | ||
| if (user == null) { | ||
| return NamedPrincipal.UNAUTHENTICATED; |
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.
When there is no user in the thread context isn't this when we are running as 'root' in OpenSearch? I really like that we'd be patching this hole, but want to double check there aren't implications
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.
That's partially true, what really defines superuser is:
- Lack of User in the threadcontext
- Lack of Origin in the threadcontext or Origin === LOCAL
- No injected roles
See https://github.com/opensearch-project/security/blob/main/src/main/java/org/opensearch/security/filter/SecurityFilter.java#L258-L266 - this is the block that skips PrivilegeEvaluation after a plugin stashes its threadcontext and executes a TransportAction
I think you are correct though that if a plugin calls on getSubject() and there is no User in the threadcontext that that would mean that the plugin is in superuser mode.
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.
While I don't like the behavior of falling back to superuser on a null, I think we should keep the relationship subject <-> security user consistent otherwise we might have logging that says the user is unauthenticated alongside system-only changes.
Note; I think changing the default behavior would be very good for the security posture, but we would likely need to make this a breaking change ala 3.0.
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 about None since that's technically the case? If the threadcontext is stashed then there is no subject. Contrast that to doing clientcert auth with a certificate that matches an admin_dn configured in opensearch.yml. That would truly be the root user.
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'm fine with either approach - I had to implement the IdentityPlugin as part of this PR so this code is tangentially related to the meat of the PR
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.
While tangentially related there are a lot of implications of these values that can create confusion, if you'd prefer not to address this now, how about a follow up issue?
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.
Changed this to ROOT and introduced that NamedPrincipal in the companion PR for core.
Working on providing those data flow diagrams now for job creation, job execution and job deletion.
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
RyanL1997
left a 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.
Hi @cwperks, thanks for putting this together! According to this comment, I would like to ask some of the general questions about this approach for information storage.
| private final Instant lastUpdateTime; | ||
| private final User user; | ||
|
|
||
| public ScheduledJobIdentity( |
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.
Refer to the idea of information storage, is this the identity of the job? (including all the basic informations). I'm asking this because I was thinking, if we create a token management index, what kinds of information we should store? Should it be some general information from the claims? (such as, iat, default exp or the token itself?)
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
|
Closing for now. Will re-open at a later date with updates. |
Description
Companion PR in Core: opensearch-project/OpenSearch#7573
Companion PR in Job Scheduler: opensearch-project/job-scheduler#394
This PR implements one of the methods introduced in a new interface in core (See companion PR) around Scheduled Job Identity Management. This PR shows an implementation of
saveUserDetailswhich is present on an interface calledScheduledJobIdentityManager. This method can be called within Job Scheduler to save user info into an index owned by the security plugin that tracks user info alongside thejob_idandjob_indexwhich is a reference to where the scheduled job details are stored in indices owned by respective plugins that extend job scheduler.With this security model, plugins and extensions will not need to store user information alongside job details as many plugins do today. With this model, an Identity plugin can implement 3 methods:
ScheduledJobIdentityManager.saveUserDetails(String jobId, String jobIndex)ScheduledJobIdentityManager.deleteUserDetails(String jobId, String jobIndex)ScheduledJobIdentityManager.issueAccessTokenOnBehalfOfUser(String jobId, String jobIndex)to implement scheduled job security. For the security plugin, that will mean creating a new protected index (
.opendistro-security-scheduled-job-identityin this Draft PR) and keeping a full catalog of all registered scheduled jobs (jobIdandjobIndexas compound key for referential integrity) and the User information of the user that owns the job.New Feature
Issues Resolved
#2528
#2626
Is this a backport? If so, please add backport PR # and/or commits #
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.