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

tests: Replace TransportClient by NodeClient #11

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
8 changes: 1 addition & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,10 @@ jobs:
uses: github/codeql-action/analyze@v1

- name: Test
run: OPENDISTRO_SECURITY_TEST_OPENSSL_OPT=true ./gradlew test
run: OPENDISTRO_SECURITY_TEST_OPENSSL_OPT=true ./gradlew test -i

- name: Coverage
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./build/jacoco/test/jacocoTestReport.xml

- name: Upload Artifacts
uses: actions/upload-artifact@v1
with:
name: artifacts
path: build/distributions/
18 changes: 0 additions & 18 deletions .github/workflows/dco.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ deploy_all.sh
*.log
.externalToolBuilders
maven-eclipse.xml
plugin-descriptor.properties

## eclipse ignores (use 'mvn eclipse:eclipse' to build eclipse projects)
## The only configuration files which are not ignored are certain files in
Expand Down
4 changes: 1 addition & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ repositories {
}

ext {
opensearch_version = System.getProperty("opensearch_version", "1.3.0-SNAPSHOT")
opensearch_version = System.getProperty("opensearch.version", "1.3.0-SNAPSHOT")
}

configurations.all {
Expand Down Expand Up @@ -121,8 +121,6 @@ dependencies {
testImplementation 'org.apache.kafka:kafka_2.13:2.8.1'
testImplementation 'org.apache.kafka:kafka_2.13:2.8.1:test'
testImplementation 'org.apache.kafka:kafka-clients:2.8.1:test'
compileOnly "io.netty:netty-tcnative:2.0.25.Final:${osdetector.classifier}"
testImplementation "io.netty:netty-tcnative:2.0.25.Final:${osdetector.classifier}"
compileOnly "org.opensearch:opensearch:${opensearch_version}"
}

Expand Down
22 changes: 22 additions & 0 deletions securityconfig/roles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,25 @@ cross_cluster_replication_follower_full_access:
- "indices:admin/plugins/replication/index/stop"
- "indices:admin/plugins/replication/index/update"
- "indices:admin/plugins/replication/index/status_check"

# Allow users to read ML stats/models/tasks
ml_read_access:
reserved: true
cluster_permissions:
- 'cluster:admin/openserach/ml/stats'
- 'cluster:admin/opensearch/ml/models/get'
- 'cluster:admin/opensearch/ml/models/search'
- 'cluster:admin/opensearch/ml/tasks/get'
- 'cluster:admin/opensearch/ml/tasks/search'

# Allows users to use all ML functionality
ml_full_access:
reserved: true
cluster_permissions:
- 'cluster_monitor'
- 'cluster:admin/opensearch/ml/*'
index_permissions:
- index_patterns:
- '*'
allowed_actions:
- 'indices_monitor'
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
import org.opensearch.security.dlic.rest.api.SecurityRestApiActions;
import org.opensearch.security.filter.SecurityRestFilter;
import org.opensearch.security.http.SecurityHttpServerTransport;
import org.opensearch.security.rest.SecurityConfigUpdateAction;
import org.opensearch.security.rest.SecurityWhoAmIAction;
import org.opensearch.security.ssl.OpenSearchSecuritySSLPlugin;
import org.opensearch.security.ssl.rest.SecuritySSLReloadCertsAction;
import org.opensearch.security.ssl.rest.SecuritySSLCertsInfoAction;
Expand Down Expand Up @@ -459,7 +461,8 @@ public List<RestHandler> getRestHandlers(Settings settings, RestController restC
handlers.add(new DashboardsInfoAction(settings, restController, Objects.requireNonNull(evaluator), Objects.requireNonNull(threadPool)));
handlers.add(new TenantInfoAction(settings, restController, Objects.requireNonNull(evaluator), Objects.requireNonNull(threadPool),
Objects.requireNonNull(cs), Objects.requireNonNull(adminDns), Objects.requireNonNull(cr)));

handlers.add(new SecurityConfigUpdateAction(settings, restController,Objects.requireNonNull(threadPool), adminDns, configPath, principalExtractor));
handlers.add(new SecurityWhoAmIAction(settings ,restController,Objects.requireNonNull(threadPool), adminDns, configPath, principalExtractor));
if (sslCertReloadEnabled) {
handlers.add(new SecuritySSLReloadCertsAction(settings, restController, sks, Objects.requireNonNull(threadPool), Objects.requireNonNull(adminDns)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@
import org.opensearch.cluster.node.DiscoveryNode;
import org.opensearch.common.io.stream.StreamInput;
import org.opensearch.common.io.stream.StreamOutput;
import org.opensearch.common.xcontent.ToXContentObject;
import org.opensearch.common.xcontent.XContentBuilder;

public class ConfigUpdateNodeResponse extends BaseNodeResponse {
public class ConfigUpdateNodeResponse extends BaseNodeResponse implements ToXContentObject {

private String[] updatedConfigTypes;
private String message;
Expand Down Expand Up @@ -78,4 +80,14 @@ public void writeTo(StreamOutput out) throws IOException {
public String toString() {
return "ConfigUpdateNodeResponse [updatedConfigTypes=" + Arrays.toString(updatedConfigTypes) + ", message=" + message + "]";
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field("updated_config_types", updatedConfigTypes);
builder.field("updated_config_size", updatedConfigTypes == null ? 0: updatedConfigTypes.length);
builder.field("message", message);
builder.endObject();
return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@
import org.opensearch.cluster.ClusterName;
import org.opensearch.common.io.stream.StreamInput;
import org.opensearch.common.io.stream.StreamOutput;
import org.opensearch.common.xcontent.ToXContentObject;
import org.opensearch.common.xcontent.XContentBuilder;

public class ConfigUpdateResponse extends BaseNodesResponse<ConfigUpdateNodeResponse> {
public class ConfigUpdateResponse extends BaseNodesResponse<ConfigUpdateNodeResponse> implements ToXContentObject {

public ConfigUpdateResponse(StreamInput in) throws IOException {
super(in);
}

public ConfigUpdateResponse(final ClusterName clusterName, List<ConfigUpdateNodeResponse> nodes, List<FailedNodeException> failures) {
super(clusterName, nodes, failures);
}
Expand All @@ -58,4 +60,16 @@ public List<ConfigUpdateNodeResponse> readNodesFrom(final StreamInput in) throws
public void writeNodesTo(final StreamOutput out, List<ConfigUpdateNodeResponse> nodes) throws IOException {
out.writeList(nodes);
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject("configupdate_response");
builder.field("nodes", getNodesMap());
builder.field("node_size", getNodes().size());
builder.field("has_failures", hasFailures());
builder.field("failures_size", failures().size());
builder.endObject();

return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ public class SecurityRestFilter {
private WhitelistingSettings whitelistingSettings;

private static final String HEALTH_SUFFIX = "health";
private static final String WHO_AM_I_SUFFIX = "whoami";

private static final String REGEX_PATH_PREFIX = "/("+ LEGACY_OPENDISTRO_PREFIX + "|" + PLUGINS_PREFIX + ")/" +"(.*)";
private static final Pattern PATTERN_PATH_PREFIX = Pattern.compile(REGEX_PATH_PREFIX);

Expand Down Expand Up @@ -184,7 +186,9 @@ private boolean checkAndAuthenticateRequest(RestRequest request, RestChannel cha

Matcher matcher = PATTERN_PATH_PREFIX.matcher(request.path());
final String suffix = matcher.matches() ? matcher.group(2) : null;
if(request.method() != Method.OPTIONS && !(HEALTH_SUFFIX.equals(suffix))) {
if(request.method() != Method.OPTIONS
&& !(HEALTH_SUFFIX.equals(suffix))
&& !(WHO_AM_I_SUFFIX.equals(suffix))) {
if (!registry.authenticate(request, channel, threadContext)) {
// another roundtrip
org.apache.logging.log4j.ThreadContext.remove("user");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.security.rest;

import com.google.common.collect.ImmutableList;
import org.opensearch.client.node.NodeClient;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.util.concurrent.ThreadContext;
import org.opensearch.rest.*;
import org.opensearch.rest.action.RestActions.NodesResponseRestListener;
import org.opensearch.security.action.configupdate.ConfigUpdateAction;
import org.opensearch.security.action.configupdate.ConfigUpdateRequest;
import org.opensearch.security.configuration.AdminDNs;
import org.opensearch.security.ssl.transport.PrincipalExtractor;
import org.opensearch.security.ssl.util.SSLRequestHelper;
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.security.user.User;
import org.opensearch.threadpool.ThreadPool;

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

import static org.opensearch.rest.RestRequest.Method.PUT;
import static org.opensearch.security.dlic.rest.support.Utils.addRoutesPrefix;

public class SecurityConfigUpdateAction extends BaseRestHandler {

private static final List<Route> routes = addRoutesPrefix(ImmutableList.of(
new Route(PUT, "/configupdate")),
"/_plugins/_security");

private final ThreadContext threadContext;
private final AdminDNs adminDns;
private final Settings settings;
private final Path configPath;
private final PrincipalExtractor principalExtractor;

public SecurityConfigUpdateAction(final Settings settings, final RestController controller, final ThreadPool threadPool, final AdminDNs adminDns,
Path configPath, PrincipalExtractor principalExtractor) {
super();
this.threadContext = threadPool.getThreadContext();
this.adminDns = adminDns;
this.settings = settings;
this.configPath = configPath;
this.principalExtractor = principalExtractor;
}

@Override public List<Route> routes() {
return routes;
}

@Override protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
String[] configTypes = request.paramAsStringArrayOrEmptyIfAll("config_types");

SSLRequestHelper.SSLInfo sslInfo = SSLRequestHelper.getSSLInfo(settings, configPath, request, principalExtractor);

if (sslInfo == null) {
return channel -> channel.sendResponse(new BytesRestResponse(RestStatus.FORBIDDEN, ""));
}

final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER);

//only allowed for admins
if (user == null || !adminDns.isAdmin(user)) {
return channel -> channel.sendResponse(new BytesRestResponse(RestStatus.FORBIDDEN, ""));
} else {
ConfigUpdateRequest configUpdateRequest = new ConfigUpdateRequest(configTypes);
return channel -> {
client.execute(ConfigUpdateAction.INSTANCE, configUpdateRequest, new NodesResponseRestListener<>(channel));
};
}
}

@Override public String getName() {
return "Security config update";
}

}
121 changes: 121 additions & 0 deletions src/main/java/org/opensearch/security/rest/SecurityWhoAmIAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.security.rest;

import com.google.common.collect.ImmutableList;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.client.node.NodeClient;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.xcontent.XContentBuilder;
import org.opensearch.rest.BaseRestHandler;
import org.opensearch.rest.BytesRestResponse;
import org.opensearch.rest.RestChannel;
import org.opensearch.rest.RestController;
import org.opensearch.rest.RestRequest;
import org.opensearch.rest.RestStatus;
import org.opensearch.security.configuration.AdminDNs;
import org.opensearch.security.ssl.transport.PrincipalExtractor;
import org.opensearch.security.ssl.util.SSLRequestHelper;
import org.opensearch.security.ssl.util.SSLRequestHelper.SSLInfo;
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.security.support.WildcardMatcher;
import org.opensearch.threadpool.ThreadPool;

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

import static org.opensearch.rest.RestRequest.Method.GET;
import static org.opensearch.rest.RestRequest.Method.POST;
import static org.opensearch.security.dlic.rest.support.Utils.addRoutesPrefix;


public class SecurityWhoAmIAction extends BaseRestHandler {

private static final List<Route> routes = addRoutesPrefix(ImmutableList.of(
new Route(GET, "/whoami"),
new Route(POST, "/whoami")),
"/_plugins/_security");

private final Logger log = LogManager.getLogger(this.getClass());
private final AdminDNs adminDns;
private final Settings settings;
private final Path configPath;
private final PrincipalExtractor principalExtractor;
private final List<String> nodesDn ;

public SecurityWhoAmIAction(final Settings settings, final RestController controller,
final ThreadPool threadPool, final AdminDNs adminDns, Path configPath, PrincipalExtractor principalExtractor) {
super();
this.adminDns = adminDns;
this.settings = settings;
this.configPath = configPath;
this.principalExtractor = principalExtractor;

nodesDn = settings.getAsList(ConfigConstants.SECURITY_NODES_DN, Collections.emptyList());
}

@Override
public List<Route> routes() {
return routes;
}

@Override
protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
return new RestChannelConsumer() {

@Override
public void accept(RestChannel channel) throws Exception {
XContentBuilder builder = channel.newBuilder();
BytesRestResponse response = null;

try {

SSLInfo sslInfo = SSLRequestHelper.getSSLInfo(settings, configPath, request, principalExtractor);

if(sslInfo == null) {
response = new BytesRestResponse(RestStatus.FORBIDDEN, "No security data");
} else {

final String dn = sslInfo.getPrincipal();
final boolean isAdmin = adminDns.isAdminDN(dn);
final boolean isNodeCertificateRequest = dn != null && WildcardMatcher.from(nodesDn, true).matchAny(dn);

builder.startObject();
builder.field("dn", dn);
builder.field("is_admin", isAdmin);
builder.field("is_node_certificate_request", isNodeCertificateRequest);
builder.endObject();

response = new BytesRestResponse(RestStatus.OK, builder);

}
} catch (final Exception e1) {
log.error(e1.toString(), e1);
builder = channel.newBuilder();
builder.startObject();
builder.field("error", e1.toString());
builder.endObject();
response = new BytesRestResponse(RestStatus.INTERNAL_SERVER_ERROR, builder);
} finally {
if (builder != null) {
builder.close();
}
}

channel.sendResponse(response);
}
};
}

@Override
public String getName() {
return "Security Plugin Who am i";
}

}
Loading