-
Notifications
You must be signed in to change notification settings - Fork 26k
Add a new API to create RCS specific API keys #95714
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
Merged
Merged
Changes from 15 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
4b8d326
wip
ywangd 09aa797
Merge remote-tracking branch 'origin/main' into rcs-create-api-key
ywangd f425082
Working version
ywangd 6457d9d
put API behind feature flag
ywangd a32b8e4
tweak validation
ywangd baf4044
tweak role descriptor name
ywangd 58c4c46
more tweak
ywangd 31485f3
more test
ywangd 48f5ecb
Merge remote-tracking branch 'origin/main' into rcs-create-api-key
ywangd 014d9af
update for main branch changes
ywangd 947add2
tweak
ywangd 8b56555
fix test
ywangd 4916c4b
subclass createCrossClusterApiKeyRequest
ywangd 3d6223e
tweak
ywangd 2dee69d
more tweak
ywangd ef45654
address feedback
ywangd 3c2d0ba
Merge remote-tracking branch 'origin/main' into rcs-create-api-key
ywangd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
139 changes: 139 additions & 0 deletions
139
...java/org/elasticsearch/xpack/core/security/action/apikey/AbstractCreateApiKeyRequest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| package org.elasticsearch.xpack.core.security.action.apikey; | ||
|
|
||
| import org.elasticsearch.TransportVersion; | ||
| import org.elasticsearch.action.ActionRequest; | ||
| import org.elasticsearch.action.ActionRequestValidationException; | ||
| import org.elasticsearch.action.support.WriteRequest; | ||
| import org.elasticsearch.common.Strings; | ||
| import org.elasticsearch.common.UUIDs; | ||
| import org.elasticsearch.common.io.stream.StreamInput; | ||
| import org.elasticsearch.common.io.stream.StreamOutput; | ||
| import org.elasticsearch.core.TimeValue; | ||
| import org.elasticsearch.xpack.core.security.action.role.RoleDescriptorRequestValidator; | ||
| import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; | ||
| import org.elasticsearch.xpack.core.security.support.MetadataUtils; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| import static org.elasticsearch.action.ValidateActions.addValidationError; | ||
|
|
||
| public abstract class AbstractCreateApiKeyRequest extends ActionRequest { | ||
| public static final WriteRequest.RefreshPolicy DEFAULT_REFRESH_POLICY = WriteRequest.RefreshPolicy.WAIT_UNTIL; | ||
| protected final String id; | ||
| protected String name; | ||
| protected TimeValue expiration; | ||
| protected Map<String, Object> metadata; | ||
| protected List<RoleDescriptor> roleDescriptors = Collections.emptyList(); | ||
| protected WriteRequest.RefreshPolicy refreshPolicy = DEFAULT_REFRESH_POLICY; | ||
|
|
||
| public AbstractCreateApiKeyRequest() { | ||
| super(); | ||
| // we generate the API key id soonest so it's part of the request body so it is audited | ||
| this.id = UUIDs.base64UUID(); // because auditing can currently only catch requests but not responses, | ||
| } | ||
|
|
||
| public AbstractCreateApiKeyRequest(StreamInput in) throws IOException { | ||
| super(in); | ||
| if (in.getTransportVersion().onOrAfter(TransportVersion.V_7_10_0)) { | ||
| this.id = in.readString(); | ||
| } else { | ||
| this.id = UUIDs.base64UUID(); | ||
| } | ||
| if (in.getTransportVersion().onOrAfter(TransportVersion.V_7_5_0)) { | ||
| this.name = in.readOptionalString(); | ||
| } else { | ||
| this.name = in.readString(); | ||
| } | ||
| this.expiration = in.readOptionalTimeValue(); | ||
| this.roleDescriptors = in.readImmutableList(RoleDescriptor::new); | ||
| this.refreshPolicy = WriteRequest.RefreshPolicy.readFrom(in); | ||
| if (in.getTransportVersion().onOrAfter(TransportVersion.V_8_0_0)) { | ||
| this.metadata = in.readMap(); | ||
| } else { | ||
| this.metadata = null; | ||
| } | ||
| } | ||
|
|
||
| public String getId() { | ||
| return id; | ||
| } | ||
|
|
||
| public String getName() { | ||
| return name; | ||
| } | ||
|
|
||
| public abstract ApiKey.Type getType(); | ||
|
|
||
| public TimeValue getExpiration() { | ||
| return expiration; | ||
| } | ||
|
|
||
| public List<RoleDescriptor> getRoleDescriptors() { | ||
| return roleDescriptors; | ||
| } | ||
|
|
||
| public WriteRequest.RefreshPolicy getRefreshPolicy() { | ||
| return refreshPolicy; | ||
| } | ||
|
|
||
| public Map<String, Object> getMetadata() { | ||
| return metadata; | ||
| } | ||
|
|
||
| @Override | ||
| public ActionRequestValidationException validate() { | ||
| ActionRequestValidationException validationException = null; | ||
| if (Strings.isNullOrEmpty(name)) { | ||
| validationException = addValidationError("api key name is required", validationException); | ||
| } else { | ||
| if (name.length() > 256) { | ||
| validationException = addValidationError("api key name may not be more than 256 characters long", validationException); | ||
| } | ||
| if (name.equals(name.trim()) == false) { | ||
| validationException = addValidationError("api key name may not begin or end with whitespace", validationException); | ||
| } | ||
| if (name.startsWith("_")) { | ||
| validationException = addValidationError("api key name may not begin with an underscore", validationException); | ||
| } | ||
| } | ||
| if (metadata != null && MetadataUtils.containsReservedMetadata(metadata)) { | ||
| validationException = addValidationError( | ||
| "API key metadata keys may not start with [" + MetadataUtils.RESERVED_PREFIX + "]", | ||
| validationException | ||
| ); | ||
| } | ||
| for (RoleDescriptor roleDescriptor : getRoleDescriptors()) { | ||
| validationException = RoleDescriptorRequestValidator.validate(roleDescriptor, validationException); | ||
| } | ||
| return validationException; | ||
| } | ||
|
|
||
| @Override | ||
| public void writeTo(StreamOutput out) throws IOException { | ||
| super.writeTo(out); | ||
| if (out.getTransportVersion().onOrAfter(TransportVersion.V_7_10_0)) { | ||
| out.writeString(id); | ||
| } | ||
| if (out.getTransportVersion().onOrAfter(TransportVersion.V_7_5_0)) { | ||
| out.writeOptionalString(name); | ||
| } else { | ||
| out.writeString(name); | ||
| } | ||
| out.writeOptionalTimeValue(expiration); | ||
| out.writeList(getRoleDescriptors()); | ||
| refreshPolicy.writeTo(out); | ||
| if (out.getTransportVersion().onOrAfter(TransportVersion.V_7_13_0)) { | ||
| out.writeGenericMap(metadata); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
...a/org/elasticsearch/xpack/core/security/action/apikey/CreateCrossClusterApiKeyAction.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| package org.elasticsearch.xpack.core.security.action.apikey; | ||
|
|
||
| import org.elasticsearch.action.ActionType; | ||
|
|
||
| /** | ||
| * ActionType for the creation of a cross-cluster API key | ||
| */ | ||
| public final class CreateCrossClusterApiKeyAction extends ActionType<CreateApiKeyResponse> { | ||
|
|
||
| public static final String NAME = "cluster:admin/xpack/security/cross_cluster/api_key/create"; | ||
| public static final CreateCrossClusterApiKeyAction INSTANCE = new CreateCrossClusterApiKeyAction(); | ||
|
|
||
| private CreateCrossClusterApiKeyAction() { | ||
| super(NAME, CreateApiKeyResponse::new); | ||
| } | ||
|
|
||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 wondering if the cross cluster class should override this and throw if the target version is too old (similar to what we do we e.g.,
PutRoleRequest). This should never happen in practice so I don't feel strongly.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.
No because we have a new action here. Since the action won't be available in an old node, the code will fail before it even attempts to decode the request. It's like when we add any other new TransportAction, we don't need any BWC handling for its request class.
Strictly speaking, the new CreateCrossApiKeyRequest can override this method to drop existing checks for old verions, e.g.:
But that means duplicating a bunch code (for both read and write) in subclasses. So I didn't do it since the benefit is rather marginal.
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.
On a second thought, I decided to have overridden
writeToand corresponding constructor for the new Request and drop these obsolete version checks. Since we are introducing a new class, might as well takes more advantage of it.