-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Security: add create api key transport action (#34572)
In order to support api keys for access to elasticsearch, we need the ability to generate these api keys. A transport action has been added along with the request and response objects that allow for the generation of api keys. The api keys require a name and optionally allow a role to be specified which defines the amount of access the key has. Additionally an expiration may also be provided. This change does not include the restriction that the role needs to be a subset of the user's permissions, which will be added seperately. As it exists in this change, the api key is currently not usable which is another aspect that will come later. Relates #34383
- Loading branch information
Showing
24 changed files
with
951 additions
and
50 deletions.
There are no files selected for viewing
This file contains 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 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 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 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 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 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 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
33 changes: 33 additions & 0 deletions
33
...n/core/src/main/java/org/elasticsearch/xpack/core/security/action/CreateApiKeyAction.java
This file contains 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,33 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.core.security.action; | ||
|
||
import org.elasticsearch.action.Action; | ||
import org.elasticsearch.common.io.stream.Writeable; | ||
|
||
/** | ||
* Action for the creation of an API key | ||
*/ | ||
public final class CreateApiKeyAction extends Action<CreateApiKeyResponse> { | ||
|
||
public static final String NAME = "cluster:admin/xpack/security/api_key/create"; | ||
public static final CreateApiKeyAction INSTANCE = new CreateApiKeyAction(); | ||
|
||
private CreateApiKeyAction() { | ||
super(NAME); | ||
} | ||
|
||
@Override | ||
public CreateApiKeyResponse newResponse() { | ||
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable"); | ||
} | ||
|
||
@Override | ||
public Writeable.Reader<CreateApiKeyResponse> getResponseReader() { | ||
return CreateApiKeyResponse::new; | ||
} | ||
} |
114 changes: 114 additions & 0 deletions
114
.../core/src/main/java/org/elasticsearch/xpack/core/security/action/CreateApiKeyRequest.java
This file contains 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,114 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.core.security.action; | ||
|
||
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.io.stream.StreamInput; | ||
import org.elasticsearch.common.io.stream.StreamOutput; | ||
import org.elasticsearch.common.unit.TimeValue; | ||
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; | ||
|
||
import java.io.IOException; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
import static org.elasticsearch.action.ValidateActions.addValidationError; | ||
|
||
/** | ||
* Request class used for the creation of an API key. The request requires a name to be provided | ||
* and optionally an expiration time and permission limitation can be provided. | ||
*/ | ||
public final class CreateApiKeyRequest extends ActionRequest { | ||
|
||
private String name; | ||
private TimeValue expiration; | ||
private List<RoleDescriptor> roleDescriptors = Collections.emptyList(); | ||
private WriteRequest.RefreshPolicy refreshPolicy = WriteRequest.RefreshPolicy.WAIT_UNTIL; | ||
|
||
public CreateApiKeyRequest() {} | ||
|
||
public CreateApiKeyRequest(StreamInput in) throws IOException { | ||
super(in); | ||
this.name = in.readString(); | ||
this.expiration = in.readOptionalTimeValue(); | ||
this.roleDescriptors = Collections.unmodifiableList(in.readList(RoleDescriptor::new)); | ||
this.refreshPolicy = WriteRequest.RefreshPolicy.readFrom(in); | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
if (Strings.hasText(name)) { | ||
this.name = name; | ||
} else { | ||
throw new IllegalArgumentException("name must not be null or empty"); | ||
} | ||
} | ||
|
||
public TimeValue getExpiration() { | ||
return expiration; | ||
} | ||
|
||
public void setExpiration(TimeValue expiration) { | ||
this.expiration = expiration; | ||
} | ||
|
||
public List<RoleDescriptor> getRoleDescriptors() { | ||
return roleDescriptors; | ||
} | ||
|
||
public void setRoleDescriptors(List<RoleDescriptor> roleDescriptors) { | ||
this.roleDescriptors = Collections.unmodifiableList(Objects.requireNonNull(roleDescriptors, "role descriptors may not be null")); | ||
} | ||
|
||
public WriteRequest.RefreshPolicy getRefreshPolicy() { | ||
return refreshPolicy; | ||
} | ||
|
||
public void setRefreshPolicy(WriteRequest.RefreshPolicy refreshPolicy) { | ||
this.refreshPolicy = Objects.requireNonNull(refreshPolicy, "refresh policy may not be null"); | ||
} | ||
|
||
@Override | ||
public ActionRequestValidationException validate() { | ||
ActionRequestValidationException validationException = null; | ||
if (Strings.isNullOrEmpty(name)) { | ||
validationException = addValidationError("name is required", validationException); | ||
} else { | ||
if (name.length() > 256) { | ||
validationException = addValidationError("name may not be more than 256 characters long", validationException); | ||
} | ||
if (name.equals(name.trim()) == false) { | ||
validationException = addValidationError("name may not begin or end with whitespace", validationException); | ||
} | ||
if (name.startsWith("_")) { | ||
validationException = addValidationError("name may not begin with an underscore", validationException); | ||
} | ||
} | ||
return validationException; | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
super.writeTo(out); | ||
out.writeString(name); | ||
out.writeOptionalTimeValue(expiration); | ||
out.writeList(roleDescriptors); | ||
refreshPolicy.writeTo(out); | ||
} | ||
|
||
@Override | ||
public void readFrom(StreamInput in) { | ||
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable"); | ||
} | ||
} |
Oops, something went wrong.