-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
Add BulkPutRoles API #109339
Add BulkPutRoles API #109339
Conversation
f91d111
to
cdb65b1
Compare
622acb5
to
bcb39f2
Compare
bcb39f2
to
d2c1751
Compare
return new BulkPutRoleRequestBuilder(client); | ||
} | ||
} | ||
} |
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 needed to allow us to inject another builder through SPI when running in serverless to enforce custom roles validation for the bulk api.
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.
My suggestion is to make this PR simpler and not think about validation for serverless roles. Your call.
} | ||
|
||
public RoleDescriptor parse(String name, XContentParser parser, boolean validate) throws IOException { | ||
if (validate) { |
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 want to postpone validation until we handle the rest of the request so we can merge actual results with validation errors and produce a single stream of results. The boolean here provides a way to skip validation that will be done later.
} | ||
} | ||
|
||
private Exception validateRequest(final PutRoleRequest request) { |
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 now handled in the roles store instead, so the logic can be shared between bulk and single inserts. The benefit of keeping it in the roles store is that we can then merge the failed validation items with successful inserts.
@@ -92,109 +82,6 @@ protected NamedXContentRegistry xContentRegistry() { | |||
); | |||
} | |||
|
|||
public void testReservedRole() { |
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.
All these tests have been moved to NativeRolesStoreTests
.
Pinging @elastic/es-security (Team:Security) |
Hi @jfreden, I've created a changelog YAML for you. |
This is trying to look like the bulk index api as much as possible. Open to modifying things if some of the naming is confusing. |
Pinging @elastic/es-docs (Team:Docs) |
...java/org/elasticsearch/xpack/core/security/action/role/BulkPutRoleRequestBuilderFactory.java
Outdated
Show resolved
Hide resolved
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.
A couple of small notes from the docs side!
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
Only minor nits that are optional to address.
I think we should discuss (in a GH issue, or the team meeting) what to do when (bulk) creating roles succeeds but cache clearing fails. Can you raise an issue to track this discussion, please?
try { | ||
rolesStore.putRoles(request.getRefreshPolicy(), request.getRoles(), listener); | ||
} catch (IOException e) { | ||
listener.onFailure(e); | ||
} |
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: can you please make putRoles
both throw an exception and take a listener parameter. It avoids code like this and should make the method itself clearer.
validationException = RoleDescriptorRequestValidator.validate(role, validationException); | ||
|
||
if (reservedRoleNameChecker.isReserved(role.getName())) { | ||
throw addValidationError("Role [" + role.getName() + "] is reserved and may not be used.", validationException); |
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: maybe not throw here, looks dissimilar to the prevailing convention around here to return the validation exception.
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, this is to match the existing behaviour from when this lived in the TransportPutRoleAction, but I agree this is not very nice. I'm a little worried to change existing behaviour of the PutRole
so I rather keep it as is for now. WDYT?
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.
Hmmm, OK, lets keep the existing behavior.
Iterator<BulkItemResponse> bulkItemResponses = bulkResponse.iterator(); | ||
BulkPutRolesResponse.Builder bulkPutRolesResponseBuilder = new BulkPutRolesResponse.Builder(); | ||
|
||
roles.stream().map(RoleDescriptor::getName).map(roleName -> { |
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: can you please create a roleNames
list outside the response handler here, to avoid keeping the list of RoleDescriptor
around for the response for the names only? (also, I would assert that the list of role names contains unique elements).
clearRoleCache(rolesToRefreshInCache.toArray(String[]::new), ActionListener.wrap(res -> { | ||
listener.onResponse(bulkPutRolesResponseBuilder.build()); | ||
}, listener::onFailure), bulkResponse); |
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 we should return the bulk response when the cache clear operation failed.
We can discuss separately, but please raise an issue to track it.
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.
Ah yes. Hmm that's a little tricky. I'll add an item to our weekly + a jira ticket to make sure I don't forget.
Thanks for the review @albertzaharovits ! |
This PR adds a new
POST _security/role
API that can be used to bulk insert roles.Example
Request
Response
Under the hood it uses a
BulkRequest
with a collection ofUpdateRequest
withdoc_as_upsert
to allow for noops against the Lucene index when no changes are detected in the payload.This doesn't yet support serveless (set to internal) since a separate request builder need to be added to build put role requests that satisfy custom roles. This should ideally use the new
manage_roles
privilege when available and should no be enabled in serverless until then.Ater Merge
manage_roles
privilege to allow us to use this in serverless and enhance security.