-
Notifications
You must be signed in to change notification settings - Fork 25.6k
RCS 2.0 - add remote indices privileges to role models #90614
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
RCS 2.0 - add remote indices privileges to role models #90614
Conversation
|
@justincr-elastic regarding:
I don't think so. We want to enforce the feature flag "at the boundaries" such that end-users can't specify remote indices via our APIs w/o the feature flag (or set RCS2.0-specific settings etc.). So long as we enforce the feature flag correctly at the boundaries, this guards internal classes such as In this PR, the logic in The other place it's critical to enforce the feature flag in this PR is inside SecuritySystemIndices to only apply the index mapping if the flag is set. I've also added stop gap measure for built-in roles and file-based roles. |
|
@elasticsearchmachine run elasticsearch-ci/release-tests |
Do you mean mixed QC vs FC, or multiple mixed FC versions? Doing that in a QC connected to two mixed FCs is complicated.
The QC decides to use RCS 2.0 on a per-FC basis. We would need to check the QC setting, and finish two transport handshakes to each FC. At that point, we have enough info to allow a remote index privilege for FC1, and prevent for FC2. And that assumes no changes to the QC setting or FC1 version later on. |
The issue @ywangd raised is a querying cluster with mixed-version nodes. For example, suppose you have node A and B where A is on 8.6 and B is on 8.5. Node A saves a role descriptor with remote index privileges in the security index. Later, node B attempts to read it and fails because it can't deserialize |
jakelandis
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.
I didn't quite all the through the review (I should be able to finish tomorrow) but looking good so far. A couple minor comments.
| } | ||
|
|
||
| private static RoleDescriptor.IndicesPrivileges parseIndex(String roleName, XContentParser parser, boolean allow2xFormat) | ||
| private static IndicesPrivileges parseIndex(final String roleName, final XContentParser parser, final boolean allow2xFormat) |
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 so much related to this PR, but .... do we need to preserve allow2xFormat in these method signatures ? It is not very descriptive to what this does or how/why you would set it true/false. For this PR is it possible to just hard code true/false and omit from the method signatures ? (if not that's fine , just trying to prevent carrying forward unnecessary cruft if this is indeed cruft)
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.
Unfortunately no clean way to omit it for parseIndex but I did omit it for parseRemoteIndex as per @ywangd's suggestion in a separate comment.
Just for context, allow2xFormat is there because we used a different format for field-level security definitions in the past. Most callers of the parse method do not allow legacy format, but FileRolesStore does since we don't want to fail parsing roles defined in files, even when legacy.
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 really should remove it and there is an open issue for it #30104 (and 2 old PRs ...)
But it does not have to be part of this PR. Something for tech debt week? :)
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.
Yup, I still haven't signed up for any issues other than test failures for tech debt week. I'll pick this one up (and create a Jira issue if needed)
...ck/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/RoleDescriptor.java
Show resolved
Hide resolved
| innerPutRole(request, role, listener); | ||
| } | ||
| } else if (role.hasRemoteIndicesPrivileges() | ||
| && clusterService.state().nodes().getMinNodeVersion().before(RoleDescriptor.VERSION_REMOTE_INDICES)) { |
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.
just double checking that this in only ever called from a user's action to add/update a role, right ? (if not then we should be really careful about which workflows throw during mixed clusters)
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.
yup this is only ever called via TransportPutRoleAction which in turn is only ever invoked through PUT role API calls
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 workflow do you have in mind? Internally (ILM, ML), I don't think we have anything that mutates security entities. Externally, creating and granting API keys are probably the most used security operations by stack and solutions. API keys will be supporting remote indices, so theorectically it could be an issue. Enterprise search also manages user roles. We should communicate this clearly to other teams, but I don't think it should not affect our decision here.
ywangd
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.
LGTM
The indices privilege collating code is quite verbose. But I think it works for now and we can come back to it later if necessary. Collating has limited value. It helps hasPrivileges but still not enough because it does not actually collate per index name. The same now goes for remote cluster names. But we can look for ways of improvements when we are at it.
| // Deliberately passing EMPTY here since *which* indices are restricted is determined not on the querying cluster | ||
| // but rather on the fulfilling cluster | ||
| new RestrictedIndices(Automatons.EMPTY), |
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 am a bit unsure about this. By itself, it won't fully work anyway for hasPrivileges check (assuming that is the intention). Because in IndicesPermission#checkResourcePrivileges, we also perform operations with QC's restrictedIndices. So this method also needs to be changed for hasPrivileges to work. That would be two places for special handling. But I'd prefer having special logic in one place if possible. I don't have any good suggestion right now. Just a point that we can revisit in future PRs.
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.
Agreed that we will need to revisit this. I think when we get to implementing the pre-flight authorization check on the querying cluster it will become clearer what to do about restricted indices here. Will keep your concern in mind. Thanks for raising!
| private Builder(RoleDescriptor rd, @Nullable FieldPermissionsCache fieldPermissionsCache, RestrictedIndices restrictedIndices) { | ||
| // TODO handle this when we introduce remote index privileges for built-in users and roles. That's the only production code | ||
| // using this builder | ||
| assert false == rd.hasRemoteIndicesPrivileges(); |
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 constructor works totally different from the other one and it always confuses me. I think it is worthwhile to split this out to be its own Builder when time comes.
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 can fold this into a preamble PR for when I work on dealing with remote indices for built-in roles. I'll collect this and other RCS 2.0-tangential refactor opportunities under a new Jira issue.
...ore/src/test/java/org/elasticsearch/xpack/core/security/action/role/PutRoleRequestTests.java
Outdated
Show resolved
Hide resolved
...ore/src/test/java/org/elasticsearch/xpack/core/security/action/role/PutRoleRequestTests.java
Outdated
Show resolved
Hide resolved
| IllegalArgumentException.class, | ||
| () -> RoleDescriptor.RemoteIndicesPrivileges.builder().indices("idx").privileges("priv").build() | ||
| ); | ||
| assertThat(ex.getMessage(), containsString("[clusters] must refer to at least one cluster alias or cluster alias pattern")); |
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 the error message be a bit more specific to about which clusters field this is? e.g. the [cluster] field under remote_indices must ...
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.
Tweaked to "the [remote_indices] sub-field [clusters] must refer to at least one cluster alias or cluster alias pattern"
| if (BuildParams.isSnapshotBuild() == false) { | ||
| tasks.named("test").configure { | ||
| systemProperty 'es.untrusted_remote_cluster_feature_flag_registered', '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.
I think this does not work when running tests in IDE? Is it not a problem? For user profiles, we used to configure the feature flag system property explicitly in test setup. Not advocating it as the right way to do things. But do we need a way to test in IDE? Running through Gradle for unit tests is slower.
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.
| if (isExplicitDenial) { | ||
| return; | ||
| } | ||
| for (final IndicesPrivileges indicesPrivilege : indicesPrivileges) { |
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.
These variable names and class name are very much confusing. No need to tackle it in this PR. But a good tech debt item.
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.
Agreed, the plural is unfortunate. No good alternative comes to mind off the top of my head though, so future tech debt item it is.
| innerPutRole(request, role, listener); | ||
| } | ||
| } else if (role.hasRemoteIndicesPrivileges() | ||
| && clusterService.state().nodes().getMinNodeVersion().before(RoleDescriptor.VERSION_REMOTE_INDICES)) { |
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 workflow do you have in mind? Internally (ILM, ML), I don't think we have anything that mutates security entities. Externally, creating and granting API keys are probably the most used security operations by stack and solutions. API keys will be supporting remote indices, so theorectically it could be an issue. Enterprise search also manages user roles. We should communicate this clearly to other teams, but I don't think it should not affect our decision here.
...ity/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java
Show resolved
Hide resolved
| } | ||
|
|
||
| private static RoleDescriptor.IndicesPrivileges parseIndex(String roleName, XContentParser parser, boolean allow2xFormat) | ||
| private static IndicesPrivileges parseIndex(final String roleName, final XContentParser parser, final boolean allow2xFormat) |
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 really should remove it and there is an open issue for it #30104 (and 2 old PRs ...)
But it does not have to be part of this PR. Something for tech debt week? :)
|
@elasticsearchmachine run elasticsearch-ci/part-1-fips |
|
@elasticsearchmachine run elasticsearch-ci/part-1 |
justincr-elastic
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.
LGTM
justincr-elastic
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.
LGTM
This PR refactors functionality for building a role from a single role descriptor. This used to be handled by a specialized constructor of the Role.Builder class that accessed internal fields. This PR consolidates this logic into a static method that uses the builder's canonical methods instead. The method is used to construct the roles of internal users, from static role descriptors, as well as in test code. Relates: #90614 (comment)
This PR enables support for defining remote_indices for API keys in order to be able to use them to authenticate cross cluster calls. The main change is made to the role classes (SimpleRole and LimitedRole), which now support constructing RoleDescriptorsIntersection on the querying cluster side. This RoleDescriptorsIntersection is sent to the fulfilling cluster as part of the RemoteAccessAuthentication. Relates to #90614

This PR updates role-related data models to allow specifying remote
index privileges.
The change is only concerned with allowing end-users to specify a
remote cluster target via the API (i.e., not files), and to exclude
remote index privileges from local authorization. Fetching the relevant
remote index privileges and serializing them for cross cluster requests
will come in a separate PR.
The changes in this PR support specifying
remote_indicesin the RolesAPI:
A key decision in this PR is separating
RemoteIndicesPermissionentirely from
IndicesPermissionwithinRoleand the implementingclasses. The primary reason for this is that
RemoteIndicesPermissionand
IndicesPermissionrepresent fairly different concepts, in termsof business logic. This approach also makes it easier to ensure that
remote indices permissions do not impact local authorization, since
remote index permissions are handled as a separate category altogether.
The alternative would have been extending
IndicesPermissionwithremote clusters but that would require to "ad-hoc" exclude them from
performing local authorization actions and make this change more
invasive and complex.
To keep the scope of the PR down, I will address below items in follow up PRs: