Skip to content
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

feat: make models index a system index #25

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ jobs:
- 7.9.3
- 7.8.1
- 7.8.0
- 7.7.1
- 7.7.0
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ jobs:
- 7.9.2
- 7.8.1
- 7.8.0
- 7.7.1
- 7.7.0
steps:
- uses: actions/checkout@v2
- name: Set up JDK
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/io/zentity/common/FunctionalUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.elasticsearch.common.CheckedBiFunction;
import org.elasticsearch.common.CheckedConsumer;
import org.elasticsearch.common.CheckedFunction;
import org.elasticsearch.common.CheckedRunnable;
import org.elasticsearch.common.CheckedSupplier;

import java.util.function.BiFunction;
Expand Down Expand Up @@ -139,4 +140,20 @@ static <T, U, R, E extends Exception> UnCheckedBiFunction<T, U, R, E> from(Check
return f::apply;
}
}

@FunctionalInterface
public interface UnCheckedRunnable<E extends Exception> extends Runnable {
void runThrows() throws E;

default void run() {
sneakyWrap(() -> {
this.runThrows();
return null;
});
}

static <E extends Exception> UnCheckedRunnable<E> from(CheckedRunnable<E> runnable) {
return runnable::run;
}
}
}
23 changes: 23 additions & 0 deletions src/main/java/io/zentity/common/SecurityUtil.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package io.zentity.common;

import io.zentity.common.FunctionalUtil.UnCheckedRunnable;
import io.zentity.common.FunctionalUtil.UnCheckedSupplier;
import org.elasticsearch.SpecialPermission;
import org.elasticsearch.common.CheckedRunnable;
import org.elasticsearch.common.CheckedSupplier;

import java.security.AccessController;
Expand Down Expand Up @@ -37,4 +39,25 @@ public static <T> T doPrivileged(Supplier<T> func) {
public static <T> T doPrivileged(CheckedSupplier<T, ?> func) {
return doPrivileged(UnCheckedSupplier.from(func));
}

/**
* Run something with escalated privileges.
*
* @param runnable The runnable to run.
*/
public static void doPrivileged(Runnable runnable) {
doPrivileged((Supplier<Void>) () -> {
runnable.run();
return null;
});
}

/**
* Run something, that might throw a checked exception, with escalated privileges.
*
* @param runnable The runnable to run.
*/
public static void doPrivileged(CheckedRunnable<?> runnable) {
doPrivileged(UnCheckedRunnable.from(runnable));
}
}
4 changes: 2 additions & 2 deletions src/main/java/io/zentity/model/Attribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import io.zentity.common.Patterns;

import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
Expand All @@ -16,7 +16,7 @@
public class Attribute {

public static final Set<String> VALID_TYPES = new TreeSet<>(
Arrays.asList("boolean", "date", "number", "string")
List.of("boolean", "date", "number", "string")
);

private final String name;
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/io/zentity/resolution/input/Term.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Objects;

public class Term implements Comparable<Term> {

Expand Down Expand Up @@ -56,6 +57,7 @@ private static boolean isNumber(String term) {
}

private void validateTerm(String term) throws ValidationException {
Objects.requireNonNull(term, "term cannot be null");
if (Patterns.EMPTY_STRING.matcher(term).matches()) {
throw new ValidationException("A term must be a non-empty string.");
}
Expand Down Expand Up @@ -150,7 +152,7 @@ public NumberValue numberValue() throws IOException, ValidationException {
*/
public StringValue stringValue() throws ValidationException {
if (this.stringValue == null) {
this.stringValue = new StringValue(new TextNode(this.term));
this.stringValue = new StringValue(TextNode.valueOf(this.term));
}
return this.stringValue;
}
Expand All @@ -166,7 +168,19 @@ public String toString() {
}

@Override
public boolean equals(Object o) { return this.hashCode() == o.hashCode(); }
public boolean equals(Object o) {
if (o == null) {
return false;
}

if (o.getClass() != this.getClass()) {
return false;
}

Term otherTerm = (Term) o;

return otherTerm.term.equals(term);
}

@Override
public int hashCode() { return this.term.hashCode(); }
Expand Down
22 changes: 19 additions & 3 deletions src/main/java/io/zentity/resolution/input/value/Value.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.fasterxml.jackson.databind.JsonNode;
import io.zentity.model.ValidationException;

import java.util.Objects;

public abstract class Value implements ValueInterface {

protected final String type = "value";
Expand All @@ -15,6 +17,7 @@ public abstract class Value implements ValueInterface {
* @param value Attribute value.
*/
Value(JsonNode value) throws ValidationException {
Objects.requireNonNull(value, "Value node cannot be null");
this.validate(value);
this.value = value;
}
Expand Down Expand Up @@ -78,9 +81,22 @@ public String toString() {
}

@Override
public boolean equals(Object o) { return this.hashCode() == o.hashCode(); }
public boolean equals(Object o) {
if (o == null) {
return false;
}

@Override
public int hashCode() { return this.serialized().hashCode(); }
if (o.getClass() != this.getClass()) {
return false;
}

Value otherVal = (Value) o;

return serialized().equals(otherVal.serialized());
}

@Override
public int hashCode() {
return this.serialized().hashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,9 @@ protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient

final boolean pretty = restRequest.paramAsBoolean("pretty", false);

final UnaryOperator<XContentBuilder> prettyPrintModifier = (builder) -> {
if (pretty) {
return builder.prettyPrint();
}
return builder;
};
final UnaryOperator<XContentBuilder> prettyPrintModifier = pretty
? XContentBuilder::prettyPrint
: UnaryOperator.identity();

final UnaryOperator<XContentBuilder> propsResponseModifier = UnCheckedUnaryOperator.from((builder) -> {
builder.startObject();
Expand Down
18 changes: 10 additions & 8 deletions src/main/java/org/elasticsearch/plugin/zentity/ModelsAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@

public class ModelsAction extends BaseZentityAction {

public static final String INDEX_NAME = ".zentity-models";

public ModelsAction(ZentityConfig config) {
super(config);
}
Expand Down Expand Up @@ -186,21 +184,25 @@ public String getName() {
return "zentity_models_action";
}

@Override
public boolean allowSystemIndexAccessByDefault() {
return true;
}

@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) {
// Allow access the model system index
client.threadPool().getThreadContext().markAsSystemContext();

// Parse request
String entityType = restRequest.param("entity_type");
boolean pretty = restRequest.paramAsBoolean("pretty", false);
Method method = restRequest.method();
String requestBody = restRequest.content().utf8ToString();

final UnaryOperator<XContentBuilder> prettyPrintModifier = (builder) -> {
if (pretty) {
return builder.prettyPrint();
}
return builder;
};
final UnaryOperator<XContentBuilder> prettyPrintModifier = pretty
? XContentBuilder::prettyPrint
: UnaryOperator.identity();

return errorHandlingConsumer(channel -> {
// Validate input
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ CompletableFuture<RestResponse> handleSingleJobRequest(NodeClient client, Object
return buildAndRunJobAsync(client, body, reqParams, emptyMap())
.thenApply(UnCheckedFunction.from((res) -> {
// Jackson needs reflection access, which requires escalated security
String responseJson = SecurityUtil.doPrivileged((
CheckedSupplier<String, ?>) () -> responseWriter.writeValueAsString(res)
String responseJson = SecurityUtil.doPrivileged(
(CheckedSupplier<String, ?>) () -> responseWriter.writeValueAsString(res)
);

RestStatus status = res.isFailure() ? RestStatus.INTERNAL_SERVER_ERROR : RestStatus.OK;
Expand All @@ -261,6 +261,11 @@ public String getName() {
return "zentity_resolution_action";
}

@Override
public boolean allowSystemIndexAccessByDefault() {
return true;
}

@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) {
if (!restRequest.hasContent()) {
Expand Down
28 changes: 17 additions & 11 deletions src/main/java/org/elasticsearch/plugin/zentity/SetupAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import io.zentity.common.ActionRequestUtil;
import io.zentity.common.CompletableFutureUtil;
import io.zentity.common.FunctionalUtil;
import io.zentity.common.FunctionalUtil.UnCheckedFunction;
import io.zentity.common.FunctionalUtil.UnCheckedUnaryOperator;
import io.zentity.common.XContentUtil;
import org.elasticsearch.ElasticsearchSecurityException;
Expand Down Expand Up @@ -92,8 +92,10 @@ CompletableFuture<CreateIndexResponse> createIndex(NodeClient client, int number
.exceptionally(ex -> {
Throwable cause = CompletableFutureUtil.getCause(ex);
if (cause instanceof ElasticsearchSecurityException) {
cause = new ForbiddenException("The " + config.getModelsIndexName() + " index does not exist and you do not have the 'create_index' privilege. An authorized user must create the index by submitting: POST _zentity/_setup");
cause.initCause(ex);
String message = "The " + config.getModelsIndexName() + " index does not exist" +
" and you do not have the 'create_index' privilege." +
" An authorized user must create the index by submitting: POST _zentity/_setup";
cause = new ForbiddenException(message, cause);
}
throw new CompletionException(cause);
});
Expand Down Expand Up @@ -136,25 +138,29 @@ public String getName() {
}

@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) {
public boolean allowSystemIndexAccessByDefault() {
return true;
}

@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) {
// Parse request
final boolean pretty = restRequest.paramAsBoolean("pretty", false);
final int numberOfShards = restRequest.paramAsInt("number_of_shards", config.getModelsIndexDefaultNumberOfShards());
final int numberOfReplicas = restRequest.paramAsInt("number_of_replicas", config.getModelsIndexDefaultNumberOfReplicas());
final Method method = restRequest.method();

final UnaryOperator<XContentBuilder> prettyPrintModifier = (builder) -> {
if (pretty) {
return builder.prettyPrint();
}
return builder;
};
// Configure an XContentBuilder to use pretty print if the request says to
final UnaryOperator<XContentBuilder> prettyPrintModifier = pretty
? XContentBuilder::prettyPrint
: UnaryOperator.identity();

// Build the AcknowledgedResponse given an XContentBuilder
final UnaryOperator<XContentBuilder> ackResponseModifier = UnCheckedUnaryOperator.from(
(builder) -> new AcknowledgedResponse(true).toXContent(builder, ToXContent.EMPTY_PARAMS)
);

// Put together the pretty-printer and the ack response builder
final UnaryOperator<XContentBuilder> responseBuilderFunc = XContentUtil.composeModifiers(
List.of(prettyPrintModifier, ackResponseModifier)
);
Expand All @@ -169,7 +175,7 @@ protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient
throw new NotImplementedException("Method and endpoint not implemented.");
}

fut.thenApply(FunctionalUtil.UnCheckedFunction.from(res -> XContentUtil.jsonBuilder(responseBuilderFunc)))
fut.thenApply(UnCheckedFunction.from(res -> XContentUtil.jsonBuilder(responseBuilderFunc)))
.thenAccept(builder -> channel.sendResponse(new BytesRestResponse(RestStatus.OK, builder)))
.get();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;

public class ZentityConfig {
Expand Down Expand Up @@ -69,7 +68,7 @@ public int getModelsIndexDefaultNumberOfReplicas() {
}

public List<Setting<?>> getSettings() {
return Arrays.asList(
return List.of(
RESOLUTION_MAX_CONCURRENT_JOBS,
RESOLUTION_MAX_CONCURRENT_JOBS_PER_REQUEST,
MODELS_INDEX_NAME,
Expand Down
Loading