From 9b4492bfb4999f21780557d216e6d821215c71c2 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 7 Aug 2024 15:42:20 -0400 Subject: [PATCH 01/80] WIP adding security resource sharing SPI and sample-extension-plugin Signed-off-by: Craig Perkins --- build.gradle | 1 + sample-extension-plugin/build.gradle | 188 ++++++++++++++ .../SampleExtensionPlugin.java | 92 +++++++ .../SampleExtensionRestHandler.java | 60 +++++ ...arch.security.spi.ResourceSharingExtension | 6 + .../sampleextension/ODFERestTestCase.java | 206 +++++++++++++++ .../SampleExtensionPluginIT.java | 38 +++ .../SecureRestClientBuilder.java | 236 ++++++++++++++++++ .../security/sampleextension/TrustStore.java | 71 ++++++ .../test/resources/security/esnode-key.pem | 28 +++ .../src/test/resources/security/esnode.pem | 25 ++ .../src/test/resources/security/kirk-key.pem | 28 +++ .../src/test/resources/security/kirk.pem | 27 ++ .../src/test/resources/security/root-ca.pem | 28 +++ .../src/test/resources/security/sample.pem | 25 ++ .../src/test/resources/security/test-kirk.jks | Bin 0 -> 3766 bytes settings.gradle | 6 + spi/build.gradle | 150 +++++++++++ .../spi/ResourceSharingExtension.java | 24 ++ 19 files changed, 1239 insertions(+) create mode 100644 sample-extension-plugin/build.gradle create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java create mode 100644 sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension create mode 100644 sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/ODFERestTestCase.java create mode 100644 sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java create mode 100644 sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SecureRestClientBuilder.java create mode 100644 sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/TrustStore.java create mode 100644 sample-extension-plugin/src/test/resources/security/esnode-key.pem create mode 100644 sample-extension-plugin/src/test/resources/security/esnode.pem create mode 100644 sample-extension-plugin/src/test/resources/security/kirk-key.pem create mode 100644 sample-extension-plugin/src/test/resources/security/kirk.pem create mode 100644 sample-extension-plugin/src/test/resources/security/root-ca.pem create mode 100644 sample-extension-plugin/src/test/resources/security/sample.pem create mode 100644 sample-extension-plugin/src/test/resources/security/test-kirk.jks create mode 100644 spi/build.gradle create mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java diff --git a/build.gradle b/build.gradle index fa48dd6bbd..375370c6f9 100644 --- a/build.gradle +++ b/build.gradle @@ -569,6 +569,7 @@ tasks.integrationTest.finalizedBy(jacocoTestReport) // report is always generate check.dependsOn integrationTest dependencies { + implementation project(path: ":${rootProject.name}-spi", configuration: 'shadow') implementation "org.opensearch.plugin:transport-netty4-client:${opensearch_version}" implementation "org.opensearch.client:opensearch-rest-high-level-client:${opensearch_version}" implementation "org.apache.httpcomponents.client5:httpclient5-cache:${versions.httpclient5}" diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle new file mode 100644 index 0000000000..7420afb315 --- /dev/null +++ b/sample-extension-plugin/build.gradle @@ -0,0 +1,188 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +apply plugin: 'opensearch.opensearchplugin' +apply plugin: 'opensearch.testclusters' +apply plugin: 'opensearch.java-rest-test' + +import org.opensearch.gradle.test.RestIntegTestTask +import org.opensearch.gradle.testclusters.StandaloneRestIntegTestTask +import org.apache.tools.ant.taskdefs.condition.Os + +import java.util.concurrent.Callable + + +opensearchplugin { + name 'opensearch-security-sample-extension' + description 'Sample plugin that extends OpenSearch Security Resource Sharing plugin' + classname 'org.opensearch.security.sampleextension.SampleExtensionPlugin' + // extendedPlugins = ['opensearch-security'] +} + +ext { + projectSubstitutions = [:] + licenseFile = rootProject.file('LICENSE.txt') + noticeFile = rootProject.file('NOTICE.txt') +} + +repositories { + mavenLocal() + mavenCentral() + maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } +} + +dependencies { + implementation project(path: ":${rootProject.name}-spi", configuration: 'shadow') +} + +def es_tmp_dir = rootProject.file('build/private/es_tmp').absoluteFile +es_tmp_dir.mkdirs() + +File repo = file("$buildDir/testclusters/repo") +def _numNodes = findProperty('numNodes') as Integer ?: 1 + +licenseHeaders.enabled = true +validateNebulaPom.enabled = false +testingConventions.enabled = false +loggerUsageCheck.enabled = false + +javaRestTest.dependsOn(rootProject.assemble) +javaRestTest { + systemProperty 'tests.security.manager', 'false' +} +testClusters.javaRestTest { + testDistribution = 'INTEG_TEST' +} + +task integTest(type: RestIntegTestTask) { + description = "Run tests against a cluster" + testClassesDirs = sourceSets.test.output.classesDirs + classpath = sourceSets.test.runtimeClasspath +} +tasks.named("check").configure { dependsOn(integTest) } + +integTest { + if (project.hasProperty('excludeTests')) { + project.properties['excludeTests']?.replaceAll('\\s', '')?.split('[,;]')?.each { + exclude "${it}" + } + } + systemProperty 'tests.security.manager', 'false' + systemProperty 'java.io.tmpdir', es_tmp_dir.absolutePath + + systemProperty "https", System.getProperty("https") + systemProperty "user", System.getProperty("user") + systemProperty "password", System.getProperty("password") + // Tell the test JVM if the cluster JVM is running under a debugger so that tests can use longer timeouts for + // requests. The 'doFirst' delays reading the debug setting on the cluster till execution time. + doFirst { + // Tell the test JVM if the cluster JVM is running under a debugger so that tests can + // use longer timeouts for requests. + def isDebuggingCluster = getDebug() || System.getProperty("test.debug") != null + systemProperty 'cluster.debug', isDebuggingCluster + // Set number of nodes system property to be used in tests + systemProperty 'cluster.number_of_nodes', "${_numNodes}" + // There seems to be an issue when running multi node run or integ tasks with unicast_hosts + // not being written, the waitForAllConditions ensures it's written + getClusters().forEach { cluster -> + cluster.waitForAllConditions() + } + } + + // The -Dcluster.debug option makes the cluster debuggable; this makes the tests debuggable + if (System.getProperty("test.debug") != null) { + jvmArgs '-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=8000' + } + if (System.getProperty("tests.rest.bwcsuite") == null) { + filter { + excludeTestsMatching "org.opensearch.security.sampleextension.bwc.*IT" + } + } +} +project.getTasks().getByName('bundlePlugin').dependsOn(rootProject.tasks.getByName('build')) +Zip bundle = (Zip) project.getTasks().getByName("bundlePlugin"); +Zip rootBundle = (Zip) rootProject.getTasks().getByName("bundlePlugin"); +integTest.dependsOn(bundle) +integTest.getClusters().forEach{c -> { + c.plugin(rootProject.getObjects().fileProperty().value(rootBundle.getArchiveFile())) + c.plugin(project.getObjects().fileProperty().value(bundle.getArchiveFile())) +}} + +testClusters.integTest { + testDistribution = 'INTEG_TEST' + + // Cluster shrink exception thrown if we try to set numberOfNodes to 1, so only apply if > 1 + if (_numNodes > 1) numberOfNodes = _numNodes + // When running integration tests it doesn't forward the --debug-jvm to the cluster anymore + // i.e. we have to use a custom property to flag when we want to debug OpenSearch JVM + // since we also support multi node integration tests we increase debugPort per node + if (System.getProperty("cluster.debug") != null) { + def debugPort = 5005 + nodes.forEach { node -> + node.jvmArgs("-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=*:${debugPort}") + debugPort += 1 + } + } + setting 'path.repo', repo.absolutePath +} + +afterEvaluate { + testClusters.integTest.nodes.each { node -> + def plugins = node.plugins + def firstPlugin = plugins.get(0) + if (firstPlugin.provider == project.bundlePlugin.archiveFile) { + plugins.remove(0) + plugins.add(firstPlugin) + } + + node.extraConfigFile("kirk.pem", file("src/test/resources/security/kirk.pem")) + node.extraConfigFile("kirk-key.pem", file("src/test/resources/security/kirk-key.pem")) + node.extraConfigFile("esnode.pem", file("src/test/resources/security/esnode.pem")) + node.extraConfigFile("esnode-key.pem", file("src/test/resources/security/esnode-key.pem")) + node.extraConfigFile("root-ca.pem", file("src/test/resources/security/root-ca.pem")) + node.setting("plugins.security.ssl.transport.pemcert_filepath", "esnode.pem") + node.setting("plugins.security.ssl.transport.pemkey_filepath", "esnode-key.pem") + node.setting("plugins.security.ssl.transport.pemtrustedcas_filepath", "root-ca.pem") + node.setting("plugins.security.ssl.transport.enforce_hostname_verification", "false") + node.setting("plugins.security.ssl.http.enabled", "true") + node.setting("plugins.security.ssl.http.pemcert_filepath", "esnode.pem") + node.setting("plugins.security.ssl.http.pemkey_filepath", "esnode-key.pem") + node.setting("plugins.security.ssl.http.pemtrustedcas_filepath", "root-ca.pem") + node.setting("plugins.security.allow_unsafe_democertificates", "true") + node.setting("plugins.security.allow_default_init_securityindex", "true") + node.setting("plugins.security.authcz.admin_dn", "\n - CN=kirk,OU=client,O=client,L=test,C=de") + node.setting("plugins.security.audit.type", "internal_opensearch") + node.setting("plugins.security.enable_snapshot_restore_privilege", "true") + node.setting("plugins.security.check_snapshot_restore_write_privileges", "true") + node.setting("plugins.security.restapi.roles_enabled", "[\"all_access\", \"security_rest_api_access\"]") + } +} + +run { + doFirst { + // There seems to be an issue when running multi node run or integ tasks with unicast_hosts + // not being written, the waitForAllConditions ensures it's written + getClusters().forEach { cluster -> + cluster.waitForAllConditions() + } + } + useCluster testClusters.integTest +} + +// As of ES 7.7 the sample-extension-plugin is being added to the list of plugins for the testCluster during build before +// the security plugin is causing build failures. +// The security zip is added explicitly above but the sample-extension-plugin is added implicitly at some time during evaluation. +// Will need to do a deep dive to find out exactly what task adds the sample-extension-plugin and add security there but a temporary hack is to +// reorder the plugins list after evaluation but prior to task execution when the plugins are installed. +afterEvaluate { + testClusters.javaRestTest.nodes.each { node -> + def nodePlugins = node.plugins + def firstPlugin = nodePlugins.get(0) + if (firstPlugin.provider == project.bundlePlugin.archiveFile) { + nodePlugins.remove(0) + nodePlugins.add(firstPlugin) + } + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java new file mode 100644 index 0000000000..3fd552bad9 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -0,0 +1,92 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.security.sampleextension; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.function.Supplier; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.client.Client; +import org.opensearch.cluster.metadata.IndexNameExpressionResolver; +import org.opensearch.cluster.node.DiscoveryNodes; +import org.opensearch.cluster.service.ClusterService; +import org.opensearch.common.settings.ClusterSettings; +import org.opensearch.common.settings.IndexScopedSettings; +import org.opensearch.common.settings.Settings; +import org.opensearch.common.settings.SettingsFilter; +import org.opensearch.core.common.io.stream.NamedWriteableRegistry; +import org.opensearch.core.xcontent.NamedXContentRegistry; +import org.opensearch.env.Environment; +import org.opensearch.env.NodeEnvironment; +import org.opensearch.plugins.ActionPlugin; +import org.opensearch.plugins.Plugin; +import org.opensearch.repositories.RepositoriesService; +import org.opensearch.rest.RestController; +import org.opensearch.rest.RestHandler; +import org.opensearch.script.ScriptService; +import org.opensearch.security.spi.ResourceSharingExtension; +import org.opensearch.threadpool.ThreadPool; +import org.opensearch.watcher.ResourceWatcherService; + +/** + * Sample Security Resource Sharing extension plugin. + * + * It use ".sample_extension_resources" index to manage its resources, and exposes a REST API + * endpoint using {@link SampleExtensionRestHandler}. + * + */ +public class SampleExtensionPlugin extends Plugin implements ActionPlugin, ResourceSharingExtension { + private static final Logger log = LogManager.getLogger(SampleExtensionPlugin.class); + + static final String RESOURCE_INDEX_NAME = ".sample_extension_resources"; + + @Override + public Collection createComponents( + Client client, + ClusterService clusterService, + ThreadPool threadPool, + ResourceWatcherService resourceWatcherService, + ScriptService scriptService, + NamedXContentRegistry xContentRegistry, + Environment environment, + NodeEnvironment nodeEnvironment, + NamedWriteableRegistry namedWriteableRegistry, + IndexNameExpressionResolver indexNameExpressionResolver, + Supplier repositoriesServiceSupplier + ) { + return Collections.emptyList(); + } + + @Override + public String getResourceType() { + return "sample_resource"; + } + + @Override + public String getResourceIndex() { + return RESOURCE_INDEX_NAME; + } + + @Override + public List getRestHandlers( + Settings settings, + RestController restController, + ClusterSettings clusterSettings, + IndexScopedSettings indexScopedSettings, + SettingsFilter settingsFilter, + IndexNameExpressionResolver indexNameExpressionResolver, + Supplier nodesInCluster + ) { + return Collections.singletonList(new SampleExtensionRestHandler()); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java new file mode 100644 index 0000000000..f2906c6eca --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java @@ -0,0 +1,60 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.security.sampleextension; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.opensearch.client.node.NodeClient; +import org.opensearch.core.rest.RestStatus; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.BytesRestResponse; +import org.opensearch.rest.RestRequest; + +/** + * A sample rest handler that supports schedule and deschedule job operation + * + * Users need to provide "id", "index", "job_name", and "interval" parameter to schedule + * a job. e.g. + * {@code + * POST /_plugins/scheduler_sample/watch?id=dashboards-job-id&job_name=watch dashboards index&index=.opensearch_dashboards_1&interval=1 + * } + * + * creates a job with id "dashboards-job-id" and job name "watch dashboards index", + * which logs ".opensearch_dashboards_1" index's shards info every 1 minute + * + * Users can remove that job by calling + * {@code DELETE /_plugins/scheduler_sample/watch?id=dashboards-job-id} + */ +public class SampleExtensionRestHandler extends BaseRestHandler { + public static final String LIST_RESOURCE_URI = "/_plugins/resource_sample/resource"; + + @Override + public String getName() { + return "Sample Security Resource Sharing extension handler"; + } + + @Override + public List routes() { + return Collections.unmodifiableList(Arrays.asList(new Route(RestRequest.Method.GET, LIST_RESOURCE_URI))); + } + + @Override + protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + if (request.method().equals(RestRequest.Method.GET)) { + return restChannel -> { restChannel.sendResponse(new BytesRestResponse(RestStatus.OK, "List Resources called")); }; + } else { + return restChannel -> { + restChannel.sendResponse(new BytesRestResponse(RestStatus.METHOD_NOT_ALLOWED, request.method() + " is not allowed.")); + }; + } + } +} diff --git a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension new file mode 100644 index 0000000000..e32f06ee56 --- /dev/null +++ b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension @@ -0,0 +1,6 @@ +# +# Copyright OpenSearch Contributors +# SPDX-License-Identifier: Apache-2.0 +# + +org.opensearch.security.sampleextension.SampleExtensionPlugin \ No newline at end of file diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/ODFERestTestCase.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/ODFERestTestCase.java new file mode 100644 index 0000000000..0dda33b230 --- /dev/null +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/ODFERestTestCase.java @@ -0,0 +1,206 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.security.sampleextension; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; +import javax.net.ssl.SSLEngine; + +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; +import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; +import org.apache.hc.core5.function.Factory; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.http.nio.ssl.TlsStrategy; +import org.apache.hc.core5.reactor.ssl.TlsDetails; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.util.Timeout; +import org.junit.After; + +import org.opensearch.client.Request; +import org.opensearch.client.Response; +import org.opensearch.client.RestClient; +import org.opensearch.client.RestClientBuilder; +import org.opensearch.client.WarningFailureException; +import org.opensearch.common.io.PathUtils; +import org.opensearch.common.settings.Settings; +import org.opensearch.common.unit.TimeValue; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.xcontent.DeprecationHandler; +import org.opensearch.core.xcontent.MediaType; +import org.opensearch.core.xcontent.NamedXContentRegistry; +import org.opensearch.core.xcontent.XContentParser; +import org.opensearch.test.rest.OpenSearchRestTestCase; + +public abstract class ODFERestTestCase extends OpenSearchRestTestCase { + + protected boolean isHttps() { + boolean isHttps = Optional.ofNullable(System.getProperty("https")).map("true"::equalsIgnoreCase).orElse(false); + if (isHttps) { + // currently only external cluster is supported for security enabled testing + if (!Optional.ofNullable(System.getProperty("tests.rest.cluster")).isPresent()) { + throw new RuntimeException("cluster url should be provided for security enabled testing"); + } + } + + return isHttps; + } + + @Override + protected String getProtocol() { + return isHttps() ? "https" : "http"; + } + + @Override + protected Settings restAdminSettings() { + return Settings.builder() + .put("http.port", 9200) + .put("plugins.security.ssl.http.enabled", isHttps()) + .put("plugins.security.ssl.http.pemcert_filepath", "sample.pem") + .put("plugins.security.ssl.http.keystore_filepath", "test-kirk.jks") + .put("plugins.security.ssl.http.keystore_password", "changeit") + .build(); + // return Settings.builder().put("strictDeprecationMode", false).put("http.port", 9200).build(); + } + + @Override + protected RestClient buildClient(Settings settings, HttpHost[] hosts) throws IOException { + boolean strictDeprecationMode = settings.getAsBoolean("strictDeprecationMode", true); + RestClientBuilder builder = RestClient.builder(hosts); + if (isHttps()) { + String keystore = settings.get("plugins.security.ssl.http.keystore_filepath"); + if (Objects.nonNull(keystore)) { + URI uri = null; + try { + uri = this.getClass().getClassLoader().getResource("security/sample.pem").toURI(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + Path configPath = PathUtils.get(uri).getParent().toAbsolutePath(); + return new SecureRestClientBuilder(settings, configPath, hosts).build(); + } else { + configureHttpsClient(builder, settings); + builder.setStrictDeprecationMode(strictDeprecationMode); + return builder.build(); + } + } else { + configureClient(builder, settings); + builder.setStrictDeprecationMode(strictDeprecationMode); + return builder.build(); + } + + } + + @SuppressWarnings("unchecked") + @After + protected void wipeAllODFEIndices() throws IOException { + Response response = adminClient().performRequest(new Request("GET", "/_cat/indices?format=json&expand_wildcards=all")); + MediaType mediaType = MediaType.fromMediaType(response.getEntity().getContentType()); + try ( + XContentParser parser = mediaType.xContent() + .createParser( + NamedXContentRegistry.EMPTY, + DeprecationHandler.THROW_UNSUPPORTED_OPERATION, + response.getEntity().getContent() + ) + ) { + XContentParser.Token token = parser.nextToken(); + List> parserList = null; + if (token == XContentParser.Token.START_ARRAY) { + parserList = parser.listOrderedMap().stream().map(obj -> (Map) obj).collect(Collectors.toList()); + } else { + parserList = Collections.singletonList(parser.mapOrdered()); + } + + for (Map index : parserList) { + String indexName = (String) index.get("index"); + if (indexName != null && !".opendistro_security".equals(indexName)) { + try { + adminClient().performRequest(new Request("DELETE", "/" + indexName)); + } catch (WarningFailureException ignore) {} + } + } + } + } + + protected static void configureHttpsClient(RestClientBuilder builder, Settings settings) throws IOException { + Map headers = new HashMap<>(ThreadContext.buildDefaultHeaders(settings)); + String userName = Optional.ofNullable(System.getProperty("user")).orElseThrow(() -> new RuntimeException("user name is missing")); + String password = Optional.ofNullable(System.getProperty("password")) + .orElseThrow(() -> new RuntimeException("password is missing")); + headers.put( + "Authorization", + "Basic " + Base64.getEncoder().encodeToString((userName + ":" + password).getBytes(StandardCharsets.UTF_8)) + ); + Header[] defaultHeaders = new Header[headers.size()]; + int i = 0; + for (Map.Entry entry : headers.entrySet()) { + defaultHeaders[i++] = new BasicHeader(entry.getKey(), entry.getValue()); + } + builder.setDefaultHeaders(defaultHeaders); + builder.setHttpClientConfigCallback(httpClientBuilder -> { + try { + final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() + .setSslContext(SSLContextBuilder.create().loadTrustMaterial(null, (chains, authType) -> true).build()) + // disable the certificate since our testing cluster just uses the default security configuration + .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) + // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 + .setTlsDetailsFactory(new Factory() { + @Override + public TlsDetails create(final SSLEngine sslEngine) { + return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); + } + }) + .build(); + + final PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create() + .setTlsStrategy(tlsStrategy) + .build(); + + return httpClientBuilder.setConnectionManager(connectionManager); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + + final String socketTimeoutString = settings.get(CLIENT_SOCKET_TIMEOUT); + final TimeValue socketTimeout = TimeValue.parseTimeValue( + socketTimeoutString == null ? "60s" : socketTimeoutString, + CLIENT_SOCKET_TIMEOUT + ); + builder.setRequestConfigCallback( + conf -> conf.setResponseTimeout(Timeout.ofMilliseconds(Math.toIntExact(socketTimeout.getMillis()))) + ); + if (settings.hasValue(CLIENT_PATH_PREFIX)) { + builder.setPathPrefix(settings.get(CLIENT_PATH_PREFIX)); + } + } + + /** + * wipeAllIndices won't work since it cannot delete security index. Use wipeAllODFEIndices instead. + */ + @Override + protected boolean preserveIndicesUponCompletion() { + return true; + } +} diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java new file mode 100644 index 0000000000..ad73e5f695 --- /dev/null +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -0,0 +1,38 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.security.sampleextension; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; + +import org.opensearch.client.Request; +import org.opensearch.client.Response; +import org.opensearch.common.xcontent.LoggingDeprecationHandler; +import org.opensearch.common.xcontent.json.JsonXContent; +import org.opensearch.core.xcontent.NamedXContentRegistry; + +public class SampleExtensionPluginIT extends ODFERestTestCase { + + @SuppressWarnings("unchecked") + public void testPluginsAreInstalled() throws IOException { + Request request = new Request("GET", "/_cat/plugins?s=component&h=name,component,version,description&format=json"); + Response response = client().performRequest(request); + List pluginsList = JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + response.getEntity().getContent() + ).list(); + Assert.assertTrue( + pluginsList.stream().map(o -> (Map) o).anyMatch(plugin -> plugin.get("component").equals("opensearch-security")) + ); + } +} diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SecureRestClientBuilder.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SecureRestClientBuilder.java new file mode 100644 index 0000000000..6a0a6d33e1 --- /dev/null +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SecureRestClientBuilder.java @@ -0,0 +1,236 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.security.sampleextension; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.ArrayList; +import java.util.Arrays; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; + +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.CredentialsProvider; +import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; +import org.apache.hc.client5.http.ssl.TrustSelfSignedStrategy; +import org.apache.hc.core5.function.Factory; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.nio.ssl.TlsStrategy; +import org.apache.hc.core5.reactor.ssl.TlsDetails; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.util.Timeout; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.OpenSearchException; +import org.opensearch.client.RestClient; +import org.opensearch.client.RestClientBuilder; +import org.opensearch.common.settings.Settings; +import org.opensearch.core.common.Strings; + +/** + * Provides builder to create low-level and high-level REST client to make calls to OpenSearch. + * + * Sample usage: + * SecureRestClientBuilder builder = new SecureRestClientBuilder(settings).build() + * RestClient restClient = builder.build(); + * + * Other usage: + * RestClient restClient = new SecureRestClientBuilder("localhost", 9200, false) + * .setUserPassword("admin", "myStrongPassword123") + * .setTrustCerts(trustStorePath) + * .build(); + * + * + * If https is enabled, creates RestClientBuilder using self-signed certificates or passed pem + * as trusted. + * + * If https is not enabled, creates a http based client. + */ +public class SecureRestClientBuilder { + + private final boolean httpSSLEnabled; + private final String user; + private final String passwd; + private final ArrayList hosts = new ArrayList<>(); + + private final Path configPath; + private final Settings settings; + + private int defaultConnectTimeOutMSecs = 5000; + private int defaultSoTimeoutMSecs = 10000; + private int defaultConnRequestTimeoutMSecs = 3 * 60 * 1000; /* 3 mins */ + private int defaultMaxConnPerRoute = RestClientBuilder.DEFAULT_MAX_CONN_PER_ROUTE; + private int defaultMaxConnTotal = RestClientBuilder.DEFAULT_MAX_CONN_TOTAL; + + private static final Logger log = LogManager.getLogger(SecureRestClientBuilder.class); + + public SecureRestClientBuilder(Settings settings, Path configPath, HttpHost[] httpHosts) { + this.httpSSLEnabled = settings.getAsBoolean("plugins.security.ssl.http.enabled", false); + this.settings = settings; + this.configPath = configPath; + this.user = null; + this.passwd = null; + hosts.addAll(Arrays.asList(httpHosts)); + } + + /** + * Creates a low-level Rest client. + * @return + * @throws IOException + */ + public RestClient build() throws IOException { + return createRestClientBuilder().build(); + } + + private RestClientBuilder createRestClientBuilder() throws IOException { + RestClientBuilder builder = RestClient.builder(hosts.toArray(new HttpHost[hosts.size()])); + + builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() { + @Override + public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) { + return requestConfigBuilder.setConnectTimeout(Timeout.ofMilliseconds(defaultConnectTimeOutMSecs)) + .setResponseTimeout(Timeout.ofMilliseconds(defaultSoTimeoutMSecs)) + .setConnectionRequestTimeout(Timeout.ofMilliseconds(defaultConnRequestTimeoutMSecs)); + } + }); + + final SSLContext sslContext; + try { + sslContext = createSSLContext(); + } catch (GeneralSecurityException | IOException ex) { + throw new IOException(ex); + } + final CredentialsProvider credentialsProvider = createCredsProvider(); + builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { + @Override + public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { + if (sslContext != null) { + TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() + .setSslContext(sslContext) + // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 + .setTlsDetailsFactory(new Factory() { + @Override + public TlsDetails create(final SSLEngine sslEngine) { + return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); + } + }) + .build(); + PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create() + .setTlsStrategy(tlsStrategy) + .setMaxConnPerRoute(defaultMaxConnPerRoute) + .setMaxConnTotal(defaultMaxConnTotal) + .build(); + httpClientBuilder.setConnectionManager(connectionManager); + } + if (credentialsProvider != null) { + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } + return httpClientBuilder; + } + }); + return builder; + } + + private SSLContext createSSLContext() throws IOException, GeneralSecurityException { + SSLContextBuilder builder = new SSLContextBuilder(); + if (httpSSLEnabled) { + // Handle trust store + String pemFile = getTrustPem(); + if (Strings.isNullOrEmpty(pemFile)) { + builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); + } else { + String pem = resolve(pemFile, configPath); + KeyStore trustStore = new TrustStore(pem).create(); + builder.loadTrustMaterial(trustStore, null); + } + + // Handle key store. + KeyStore keyStore = getKeyStore(); + if (keyStore != null) { + builder.loadKeyMaterial(keyStore, getKeystorePasswd().toCharArray()); + } + + } + return builder.build(); + } + + private CredentialsProvider createCredsProvider() { + if (Strings.isNullOrEmpty(user) || Strings.isNullOrEmpty(passwd)) return null; + + final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(user, passwd.toCharArray())); + return credentialsProvider; + } + + private String resolve(final String originalFile, final Path configPath) { + String path = null; + if (originalFile != null && originalFile.length() > 0) { + path = configPath.resolve(originalFile).toAbsolutePath().toString(); + log.debug("Resolved {} to {} against {}", originalFile, path, configPath.toAbsolutePath().toString()); + } + + if (path == null || path.length() == 0) { + throw new OpenSearchException("Empty file path for " + originalFile); + } + + if (Files.isDirectory(Paths.get(path), LinkOption.NOFOLLOW_LINKS)) { + throw new OpenSearchException("Is a directory: " + path + " Expected a file for " + originalFile); + } + + if (!Files.isReadable(Paths.get(path))) { + throw new OpenSearchException( + "Unable to read " + + path + + " (" + + Paths.get(path) + + "). Please make sure this files exists and is readable regarding to permissions. Property: " + + originalFile + ); + } + if ("".equals(path)) { + path = null; + } + return path; + } + + private String getTrustPem() { + return settings.get("plugins.security.ssl.http.pemcert_filepath", null); + } + + private String getKeystorePasswd() { + return settings.get("plugins.security.ssl.http.keystore_password", null); + } + + private KeyStore getKeyStore() throws IOException, GeneralSecurityException { + KeyStore keyStore = KeyStore.getInstance("jks"); + String keyStoreFile = settings.get("plugins.security.ssl.http.keystore_filepath", null); + String passwd = settings.get("plugins.security.ssl.http.keystore_password", null); + if (Strings.isNullOrEmpty(keyStoreFile) || Strings.isNullOrEmpty(passwd)) { + return null; + } + String keyStorePath = resolve(keyStoreFile, configPath); + try (InputStream is = Files.newInputStream(Paths.get(keyStorePath))) { + keyStore.load(is, passwd.toCharArray()); + } + return keyStore; + } +} diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/TrustStore.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/TrustStore.java new file mode 100644 index 0000000000..2bee6291d1 --- /dev/null +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/TrustStore.java @@ -0,0 +1,71 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.security.sampleextension; + +import java.io.FileInputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Collection; + +/** + * Helper class to read raw pem files to keystore. + */ +public class TrustStore { + + private final String effectiveKeyAlias = "al"; + private final String storeType = "JKS"; + private final String certType = "X.509"; + private final String cert; + + public TrustStore(final String file) { + cert = file; + } + + public KeyStore create() throws IOException, GeneralSecurityException { + X509Certificate[] trustCerts = loadCertificatesFromFile(cert); + return toTrustStore(effectiveKeyAlias, trustCerts); + } + + private X509Certificate[] loadCertificatesFromFile(String file) throws IOException, GeneralSecurityException { + if (file == null) { + return null; + } + CertificateFactory fact = CertificateFactory.getInstance(certType); + try (FileInputStream is = new FileInputStream(file)) { + Collection certs = fact.generateCertificates(is); + X509Certificate[] x509Certs = new X509Certificate[certs.size()]; + int i = 0; + for (Certificate cert : certs) { + x509Certs[i++] = (X509Certificate) cert; + } + return x509Certs; + } + } + + private KeyStore toTrustStore(final String trustCertificatesAliasPrefix, final X509Certificate[] trustCertificates) throws IOException, + GeneralSecurityException { + if (trustCertificates == null) { + return null; + } + KeyStore ks = KeyStore.getInstance(storeType); + ks.load(null); + + if (trustCertificates != null) { + for (int i = 0; i < trustCertificates.length; i++) { + X509Certificate x509Certificate = trustCertificates[i]; + ks.setCertificateEntry(trustCertificatesAliasPrefix + "_" + i, x509Certificate); + } + } + return ks; + } +} diff --git a/sample-extension-plugin/src/test/resources/security/esnode-key.pem b/sample-extension-plugin/src/test/resources/security/esnode-key.pem new file mode 100644 index 0000000000..e90562be43 --- /dev/null +++ b/sample-extension-plugin/src/test/resources/security/esnode-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCm93kXteDQHMAv +bUPNPW5pyRHKDD42XGWSgq0k1D29C/UdyL21HLzTJa49ZU2ldIkSKs9JqbkHdyK0 +o8MO6L8dotLoYbxDWbJFW8bp1w6tDTU0HGkn47XVu3EwbfrTENg3jFu+Oem6a/50 +1SzITzJWtS0cn2dIFOBimTVpT/4Zv5qrXA6Cp4biOmoTYWhi/qQl8d0IaADiqoZ1 +MvZbZ6x76qTrRAbg+UWkpTEXoH1xTc8ndibR7+HP6OTqCKvo1NhE8uP4pY+fWd6b +6l+KLo3IKpfTbAIJXIO+M67FLtWKtttDao94B069skzKk6FPgW/OZh6PRCD0oxOa +vV+ld2SjAgMBAAECggEAQK1+uAOZeaSZggW2jQut+MaN4JHLi61RH2cFgU3COLgo +FIiNjFn8f2KKU3gpkt1It8PjlmprpYut4wHI7r6UQfuv7ZrmncRiPWHm9PB82+ZQ +5MXYqj4YUxoQJ62Cyz4sM6BobZDrjG6HHGTzuwiKvHHkbsEE9jQ4E5m7yfbVvM0O +zvwrSOM1tkZihKSTpR0j2+taji914tjBssbn12TMZQL5ItGnhR3luY8mEwT9MNkZ +xg0VcREoAH+pu9FE0vPUgLVzhJ3be7qZTTSRqv08bmW+y1plu80GbppePcgYhEow +dlW4l6XPJaHVSn1lSFHE6QAx6sqiAnBz0NoTPIaLyQKBgQDZqDOlhCRciMRicSXn +7yid9rhEmdMkySJHTVFOidFWwlBcp0fGxxn8UNSBcXdSy7GLlUtH41W9PWl8tp9U +hQiiXORxOJ7ZcB80uNKXF01hpPj2DpFPWyHFxpDkWiTAYpZl68rOlYujxZUjJIej +VvcykBC2BlEOG9uZv2kxcqLyJwKBgQDEYULTxaTuLIa17wU3nAhaainKB3vHxw9B +Ksy5p3ND43UNEKkQm7K/WENx0q47TA1mKD9i+BhaLod98mu0YZ+BCUNgWKcBHK8c +uXpauvM/pLhFLXZ2jvEJVpFY3J79FSRK8bwE9RgKfVKMMgEk4zOyZowS8WScOqiy +hnQn1vKTJQKBgElhYuAnl9a2qXcC7KOwRsJS3rcKIVxijzL4xzOyVShp5IwIPbOv +hnxBiBOH/JGmaNpFYBcBdvORE9JfA4KMQ2fx53agfzWRjoPI1/7mdUk5RFI4gRb/ +A3jZRBoopgFSe6ArCbnyQxzYzToG48/Wzwp19ZxYrtUR4UyJct6f5n27AoGBAJDh +KIpQQDOvCdtjcbfrF4aM2DPCfaGPzENJriwxy6oEPzDaX8Bu/dqI5Ykt43i/zQrX +GpyLaHvv4+oZVTiI5UIvcVO9U8hQPyiz9f7F+fu0LHZs6f7hyhYXlbe3XFxeop3f +5dTKdWgXuTTRF2L9dABkA2deS9mutRKwezWBMQk5AoGBALPtX0FrT1zIosibmlud +tu49A/0KZu4PBjrFMYTSEWGNJez3Fb2VsJwylVl6HivwbP61FhlYfyksCzQQFU71 ++x7Nmybp7PmpEBECr3deoZKQ/acNHn0iwb0It+YqV5+TquQebqgwK6WCLsMuiYKT +bg/ch9Rhxbq22yrVgWHh6epp +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/sample-extension-plugin/src/test/resources/security/esnode.pem b/sample-extension-plugin/src/test/resources/security/esnode.pem new file mode 100644 index 0000000000..44101f0b37 --- /dev/null +++ b/sample-extension-plugin/src/test/resources/security/esnode.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIUaYSlET3nzsotWTrWueVPPh10yLYwDQYJKoZIhvcNAQEL +BQAwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYDVQQLDBhFeGFtcGxl +IENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUgQ29tIEluYy4gUm9v +dCBDQTAeFw0yNDAyMjAxNzAzMjVaFw0zNDAyMTcxNzAzMjVaMFcxCzAJBgNVBAYT +AmRlMQ0wCwYDVQQHDAR0ZXN0MQ0wCwYDVQQKDARub2RlMQ0wCwYDVQQLDARub2Rl +MRswGQYDVQQDDBJub2RlLTAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCm93kXteDQHMAvbUPNPW5pyRHKDD42XGWSgq0k1D29C/Ud +yL21HLzTJa49ZU2ldIkSKs9JqbkHdyK0o8MO6L8dotLoYbxDWbJFW8bp1w6tDTU0 +HGkn47XVu3EwbfrTENg3jFu+Oem6a/501SzITzJWtS0cn2dIFOBimTVpT/4Zv5qr +XA6Cp4biOmoTYWhi/qQl8d0IaADiqoZ1MvZbZ6x76qTrRAbg+UWkpTEXoH1xTc8n +dibR7+HP6OTqCKvo1NhE8uP4pY+fWd6b6l+KLo3IKpfTbAIJXIO+M67FLtWKtttD +ao94B069skzKk6FPgW/OZh6PRCD0oxOavV+ld2SjAgMBAAGjgcYwgcMwRwYDVR0R +BEAwPogFKgMEBQWCEm5vZGUtMC5leGFtcGxlLmNvbYIJbG9jYWxob3N0hxAAAAAA +AAAAAAAAAAAAAAABhwR/AAABMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU0/qDQaY10jIo +wCjLUpz/HfQXyt8wHwYDVR0jBBgwFoAUF4ffoFrrZhKn1dD4uhJFPLcrAJwwDQYJ +KoZIhvcNAQELBQADggEBAGbij5WyF0dKhQodQfTiFDb73ygU6IyeJkFSnxF67gDz +pQJZKFvXuVBa3cGP5e7Qp3TK50N+blXGH0xXeIV9lXeYUk4hVfBlp9LclZGX8tGi +7Xa2enMvIt5q/Yg3Hh755ZxnDYxCoGkNOXUmnMusKstE0YzvZ5Gv6fcRKFBUgZLh +hUBqIEAYly1EqH/y45APiRt3Nor1yF6zEI4TnL0yNrHw6LyQkUNCHIGMJLfnJQ9L +camMGIXOx60kXNMTigF9oXXwixWAnDM9y3QT8QXA7hej/4zkbO+vIeV/7lGUdkyg +PAi92EvyxmsliEMyMR0VINl8emyobvfwa7oMeWMR+hg= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/sample-extension-plugin/src/test/resources/security/kirk-key.pem b/sample-extension-plugin/src/test/resources/security/kirk-key.pem new file mode 100644 index 0000000000..1949c26139 --- /dev/null +++ b/sample-extension-plugin/src/test/resources/security/kirk-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCVXDgEJQorgfXp +gpY0TgF55bD2xuzxN5Dc9rDfgWxrsOvOloMpd7k6FR71bKWjJi1KptSmM/cDElky +AWYKSfYWGiGxsQ+EQW+6kwCfEOHXQldn+0+JcWqP+osSPjtJfwRvRN5kRqP69MPo +7U0N2kdqenqMWjmG1chDGLRSOEGU5HIBiDxsZtOcvMaJ8b1eaW0lvS+6gFQ80AvB +GBkDDCOHHLtDXBylrZk2CQP8AzxNicIZ4B8G3CG3OHA8+nBtEtxZoIihrrkqlMt+ +b/5N8u8zB0Encew0kdrc4R/2wS//ahr6U+9Siq8T7WsUtGwKj3BJClg6OyDJRhlu +y2gFnxoPAgMBAAECggEAP5TOycDkx+megAWVoHV2fmgvgZXkBrlzQwUG/VZQi7V4 +ZGzBMBVltdqI38wc5MtbK3TCgHANnnKgor9iq02Z4wXDwytPIiti/ycV9CDRKvv0 +TnD2hllQFjN/IUh5n4thHWbRTxmdM7cfcNgX3aZGkYbLBVVhOMtn4VwyYu/Mxy8j +xClZT2xKOHkxqwmWPmdDTbAeZIbSv7RkIGfrKuQyUGUaWhrPslvYzFkYZ0umaDgQ +OAthZew5Bz3OfUGOMPLH61SVPuJZh9zN1hTWOvT65WFWfsPd2yStI+WD/5PU1Doo +1RyeHJO7s3ug8JPbtNJmaJwHe9nXBb/HXFdqb976yQKBgQDNYhpu+MYSYupaYqjs +9YFmHQNKpNZqgZ4ceRFZ6cMJoqpI5dpEMqToFH7tpor72Lturct2U9nc2WR0HeEs +/6tiptyMPTFEiMFb1opQlXF2ae7LeJllntDGN0Q6vxKnQV+7VMcXA0Y8F7tvGDy3 +qJu5lfvB1mNM2I6y/eMxjBuQhwKBgQC6K41DXMFro0UnoO879pOQYMydCErJRmjG +/tZSy3Wj4KA/QJsDSViwGfvdPuHZRaG9WtxdL6kn0w1exM9Rb0bBKl36lvi7o7xv +M+Lw9eyXMkww8/F5d7YYH77gIhGo+RITkKI3+5BxeBaUnrGvmHrpmpgRXWmINqr0 +0jsnN3u0OQKBgCf45vIgItSjQb8zonLz2SpZjTFy4XQ7I92gxnq8X0Q5z3B+o7tQ +K/4rNwTju/sGFHyXAJlX+nfcK4vZ4OBUJjP+C8CTjEotX4yTNbo3S6zjMyGQqDI5 +9aIOUY4pb+TzeUFJX7If5gR+DfGyQubvvtcg1K3GHu9u2l8FwLj87sRzAoGAflQF +RHuRiG+/AngTPnZAhc0Zq0kwLkpH2Rid6IrFZhGLy8AUL/O6aa0IGoaMDLpSWUJp +nBY2S57MSM11/MVslrEgGmYNnI4r1K25xlaqV6K6ztEJv6n69327MS4NG8L/gCU5 +3pEm38hkUi8pVYU7in7rx4TCkrq94OkzWJYurAkCgYATQCL/rJLQAlJIGulp8s6h +mQGwy8vIqMjAdHGLrCS35sVYBXG13knS52LJHvbVee39AbD5/LlWvjJGlQMzCLrw +F7oILW5kXxhb8S73GWcuMbuQMFVHFONbZAZgn+C9FW4l7XyRdkrbR1MRZ2km8YMs +/AHmo368d4PSNRMMzLHw8Q== +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/sample-extension-plugin/src/test/resources/security/kirk.pem b/sample-extension-plugin/src/test/resources/security/kirk.pem new file mode 100644 index 0000000000..36b7e19a75 --- /dev/null +++ b/sample-extension-plugin/src/test/resources/security/kirk.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEmDCCA4CgAwIBAgIUaYSlET3nzsotWTrWueVPPh10yLcwDQYJKoZIhvcNAQEL +BQAwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYDVQQLDBhFeGFtcGxl +IENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUgQ29tIEluYy4gUm9v +dCBDQTAeFw0yNDAyMjAxNzA0MjRaFw0zNDAyMTcxNzA0MjRaME0xCzAJBgNVBAYT +AmRlMQ0wCwYDVQQHDAR0ZXN0MQ8wDQYDVQQKDAZjbGllbnQxDzANBgNVBAsMBmNs +aWVudDENMAsGA1UEAwwEa2lyazCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAJVcOAQlCiuB9emCljROAXnlsPbG7PE3kNz2sN+BbGuw686Wgyl3uToVHvVs +paMmLUqm1KYz9wMSWTIBZgpJ9hYaIbGxD4RBb7qTAJ8Q4ddCV2f7T4lxao/6ixI+ +O0l/BG9E3mRGo/r0w+jtTQ3aR2p6eoxaOYbVyEMYtFI4QZTkcgGIPGxm05y8xonx +vV5pbSW9L7qAVDzQC8EYGQMMI4ccu0NcHKWtmTYJA/wDPE2JwhngHwbcIbc4cDz6 +cG0S3FmgiKGuuSqUy35v/k3y7zMHQSdx7DSR2tzhH/bBL/9qGvpT71KKrxPtaxS0 +bAqPcEkKWDo7IMlGGW7LaAWfGg8CAwEAAaOCASswggEnMAwGA1UdEwEB/wQCMAAw +DgYDVR0PAQH/BAQDAgXgMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMB0GA1UdDgQW +BBSjMS8tgguX/V7KSGLoGg7K6XMzIDCBzwYDVR0jBIHHMIHEgBQXh9+gWutmEqfV +0Pi6EkU8tysAnKGBlaSBkjCBjzETMBEGCgmSJomT8ixkARkWA2NvbTEXMBUGCgmS +JomT8ixkARkWB2V4YW1wbGUxGTAXBgNVBAoMEEV4YW1wbGUgQ29tIEluYy4xITAf +BgNVBAsMGEV4YW1wbGUgQ29tIEluYy4gUm9vdCBDQTEhMB8GA1UEAwwYRXhhbXBs +ZSBDb20gSW5jLiBSb290IENBghQNZAmZZn3EFOxBR4630XlhI+mo4jANBgkqhkiG +9w0BAQsFAAOCAQEACEUPPE66/Ot3vZqRGpjDjPHAdtOq+ebaglQhvYcnDw8LOZm8 +Gbh9M88CiO6UxC8ipQLTPh2yyeWArkpJzJK/Pi1eoF1XLiAa0sQ/RaJfQWPm9dvl +1ZQeK5vfD4147b3iBobwEV+CR04SKow0YeEEzAJvzr8YdKI6jqr+2GjjVqzxvRBy +KRVHWCFiR7bZhHGLq3br8hSu0hwjb3oGa1ZI8dui6ujyZt6nm6BoEkau3G/6+zq9 +E6vX3+8Fj4HKCAL6i0SwfGmEpTNp5WUhqibK/fMhhmMT4Mx6MxkT+OFnIjdUU0S/ +e3kgnG8qjficUr38CyEli1U0M7koIXUZI7r+LQ== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/sample-extension-plugin/src/test/resources/security/root-ca.pem b/sample-extension-plugin/src/test/resources/security/root-ca.pem new file mode 100644 index 0000000000..d33f5f7216 --- /dev/null +++ b/sample-extension-plugin/src/test/resources/security/root-ca.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIExjCCA66gAwIBAgIUDWQJmWZ9xBTsQUeOt9F5YSPpqOIwDQYJKoZIhvcNAQEL +BQAwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYDVQQLDBhFeGFtcGxl +IENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUgQ29tIEluYy4gUm9v +dCBDQTAeFw0yNDAyMjAxNzAwMzZaFw0zNDAyMTcxNzAwMzZaMIGPMRMwEQYKCZIm +iZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQ +RXhhbXBsZSBDb20gSW5jLjEhMB8GA1UECwwYRXhhbXBsZSBDb20gSW5jLiBSb290 +IENBMSEwHwYDVQQDDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEPyN7J9VGPyJcQmCBl5TGwfSzvVdWwoQU +j9aEsdfFJ6pBCDQSsj8Lv4RqL0dZra7h7SpZLLX/YZcnjikrYC+rP5OwsI9xEE/4 +U98CsTBPhIMgqFK6SzNE5494BsAk4cL72dOOc8tX19oDS/PvBULbNkthQ0aAF1dg +vbrHvu7hq7LisB5ZRGHVE1k/AbCs2PaaKkn2jCw/b+U0Ml9qPuuEgz2mAqJDGYoA +WSR4YXrOcrmPuRqbws464YZbJW898/0Pn/U300ed+4YHiNYLLJp51AMkR4YEw969 +VRPbWIvLrd0PQBooC/eLrL6rvud/GpYhdQEUx8qcNCKd4bz3OaQ5AgMBAAGjggEW +MIIBEjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +F4ffoFrrZhKn1dD4uhJFPLcrAJwwgc8GA1UdIwSBxzCBxIAUF4ffoFrrZhKn1dD4 +uhJFPLcrAJyhgZWkgZIwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJ +k/IsZAEZFgdleGFtcGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYD +VQQLDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUg +Q29tIEluYy4gUm9vdCBDQYIUDWQJmWZ9xBTsQUeOt9F5YSPpqOIwDQYJKoZIhvcN +AQELBQADggEBAL3Q3AHUhMiLUy6OlLSt8wX9I2oNGDKbBu0atpUNDztk/0s3YLQC +YuXgN4KrIcMXQIuAXCx407c+pIlT/T1FNn+VQXwi56PYzxQKtlpoKUL3oPQE1d0V +6EoiNk+6UodvyZqpdQu7fXVentRMk1QX7D9otmiiNuX+GSxJhJC2Lyzw65O9EUgG +1yVJon6RkUGtqBqKIuLksKwEr//ELnjmXit4LQKSnqKr0FTCB7seIrKJNyb35Qnq +qy9a/Unhokrmdda1tr6MbqU8l7HmxLuSd/Ky+L0eDNtYv6YfMewtjg0TtAnFyQov +rdXmeq1dy9HLo3Ds4AFz3Gx9076TxcRS/iI= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/sample-extension-plugin/src/test/resources/security/sample.pem b/sample-extension-plugin/src/test/resources/security/sample.pem new file mode 100644 index 0000000000..44101f0b37 --- /dev/null +++ b/sample-extension-plugin/src/test/resources/security/sample.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIUaYSlET3nzsotWTrWueVPPh10yLYwDQYJKoZIhvcNAQEL +BQAwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYDVQQLDBhFeGFtcGxl +IENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUgQ29tIEluYy4gUm9v +dCBDQTAeFw0yNDAyMjAxNzAzMjVaFw0zNDAyMTcxNzAzMjVaMFcxCzAJBgNVBAYT +AmRlMQ0wCwYDVQQHDAR0ZXN0MQ0wCwYDVQQKDARub2RlMQ0wCwYDVQQLDARub2Rl +MRswGQYDVQQDDBJub2RlLTAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCm93kXteDQHMAvbUPNPW5pyRHKDD42XGWSgq0k1D29C/Ud +yL21HLzTJa49ZU2ldIkSKs9JqbkHdyK0o8MO6L8dotLoYbxDWbJFW8bp1w6tDTU0 +HGkn47XVu3EwbfrTENg3jFu+Oem6a/501SzITzJWtS0cn2dIFOBimTVpT/4Zv5qr +XA6Cp4biOmoTYWhi/qQl8d0IaADiqoZ1MvZbZ6x76qTrRAbg+UWkpTEXoH1xTc8n +dibR7+HP6OTqCKvo1NhE8uP4pY+fWd6b6l+KLo3IKpfTbAIJXIO+M67FLtWKtttD +ao94B069skzKk6FPgW/OZh6PRCD0oxOavV+ld2SjAgMBAAGjgcYwgcMwRwYDVR0R +BEAwPogFKgMEBQWCEm5vZGUtMC5leGFtcGxlLmNvbYIJbG9jYWxob3N0hxAAAAAA +AAAAAAAAAAAAAAABhwR/AAABMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU0/qDQaY10jIo +wCjLUpz/HfQXyt8wHwYDVR0jBBgwFoAUF4ffoFrrZhKn1dD4uhJFPLcrAJwwDQYJ +KoZIhvcNAQELBQADggEBAGbij5WyF0dKhQodQfTiFDb73ygU6IyeJkFSnxF67gDz +pQJZKFvXuVBa3cGP5e7Qp3TK50N+blXGH0xXeIV9lXeYUk4hVfBlp9LclZGX8tGi +7Xa2enMvIt5q/Yg3Hh755ZxnDYxCoGkNOXUmnMusKstE0YzvZ5Gv6fcRKFBUgZLh +hUBqIEAYly1EqH/y45APiRt3Nor1yF6zEI4TnL0yNrHw6LyQkUNCHIGMJLfnJQ9L +camMGIXOx60kXNMTigF9oXXwixWAnDM9y3QT8QXA7hej/4zkbO+vIeV/7lGUdkyg +PAi92EvyxmsliEMyMR0VINl8emyobvfwa7oMeWMR+hg= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/sample-extension-plugin/src/test/resources/security/test-kirk.jks b/sample-extension-plugin/src/test/resources/security/test-kirk.jks new file mode 100644 index 0000000000000000000000000000000000000000..6c8c5ef77e20980f8c78295b159256b805da6a28 GIT binary patch literal 3766 zcmd^=c{r47AIImJ%`(PV###wuU&o%k$xbMgr4m`Pk2Tv-j4?=zEwY?!X|aVw)I`=A zPAY52Rt6yODkPjhAQ%WsfbL*f;mp!-018Nf*#Q6sf)b!}Nv;s_8gzOC@mTmi+D9F}jyYkhL=#Xk3eYM2csmxKA&W!xAdE{tZ2mEGS z;L%QU`DHcrbdbw$3GsKUvmfQu0Z^?sH7B)!W)eLbG*fXB^G$&6CbCnj4~ z*J>Rkut6vL1EvT!JqAq#X=O~#!JHQ#QVSPuOGlnLrXXB~{{FsGRq?o?I;>^GFEhMB zw;z!v1sXap8nq3zz&+prKs-DRPm*XsS4BaP6Z{8tM~n@m|rxMA=p6*i(w=7 z*2&*Yg-uWU$5|W>>g5h)Fn{3B={`skAJ5_wXB5pDwyj{vG1_{{Y-`wB_i^B!5PA|= zrx=_>rprb&75BQ=J)SKPAJI;?(D#46)o+a?SsR^-&qJjXY2ER8S*1ZvU`t7~M6?NKULuzlAZ8C#X9>8j2;WDY z(TY-^!`&0%67`u|U_-Y(knWVcSlh-kwZQ6KG@S?L`W!iVl>Gyd(LnpMc@C!QeY{(E z)uAwF_CcqH#00}jer2dQk3}R|p^87XCxR8`n4c@g9rASTt9$8}SuGW!!+QQ&w&G!P zvv5Mft<&pzv^&XuuQAj&ieoa*3nI-hx}0`4kym=(cd>?v6yM3v43y@5@;yPeJ_N{@ z622W$@5Z4VqliMF3GAf_RcB;$HX^%cwTCgxg^4)5I0?*&oW|giBB@nUNBO+IX=iON zo~;L}HOwhyeqH4GHvAQ5i=|0c+_5*661aDyT_tr=I#+Zog%!9nRiuBb8m&SS4qp2fv7HJMG zwJFuqV*Hoq3`|Mayml;So|9W4Um6Lu8(k+(Hc2}p@&>?!7!7H~9*O%@BrKNAOa-~e z$e6#G)fJ+wNz5x9zU;#>&V}d z?!F1W_eNN;&LI9$!kWa0Zqa)0CVM4D=x(r>aXgW=XQ)PTRsJJ&MC?WjjoMwLRh`-I z8yD|^&(r#NU|pRpRF%wn&t%X`)8HQe%uxEKnXxIu9yui1s$eH0*YZ^Wvt25yOg6{5 zPefKstjqam-PRDz=&-BVb^xZe>{C{$cza!_sV&3M*l0ocMJVr!l~TlJi4JChDn9Nn zc&la1caY}0P&Ho=r;)l;mKBf$V<6A*R6XC}s98g%I7ZIAFI=e6SqQ4;oevw)nw0%^ zKq9#$;{3R0zJv}#mr7@}e+5-(`{C?^vEE#xb7uBY=X#_1v+@~@l?W@Zaq+Yo9bpu& zR<0us_T`(Q6qp1xYb)Rq;tJ|aTZ&y5xqx<_j-|>1$SEi@3!A|| z9YH<3ub_#ai=2WG_V9iQ!NU8mB|$4ZK3Gr>_s15;6W-XV-*##3TjwoMP&yb zq!L{!sQoUn<_ZWb)BbzloM2Zs1tb=+FBn*$!EQmp3Ml#oe;g0);^XP&_osni`NR1A z0SL>FG{F)8;h%d#4-g0eK+%&0UD-=ghUr~yDQ?!lNE5tKiJ_rjY{@`Q1vjbVAFU;|?Qs;w|1hFx_ z`*jR7rVAU>9*yRSpD1)#aOb!)@ak(5hk;guG$_9)=K8Ie^uOP<63|FjrX2UEcJw07 zD5c?bxHD${?)1+CMgPg@0|kH>4NzJZO*;#rl-xA_8*SHCS}ygKZP7*uHbRtmaTE%n zp7Vt7QIt|IIN?)fyS#8IxKHO$?TeY{DpQl5^kyAd$HH^Aa)SJC+I0!ULR znF7*z6R6~{CCW6M^qKuU!N`I`>YB3i6toA7f7#3%T&$5&wm0nY{&d9(g)LB$%g9dX zf>HfjVn9;)rG-^=)tiGDd<5M4wDHPl@yEGU_whSh78l$%S*WCqjvj^Xt?_VKp0T{pQGU!F;?_^4EMT$__$E zH0hMGQlo@W2p^_tPZsnirl@pGb<#0a^*g5ihYtSzKKx%Wg;i4h8B_c6Z+PPWM!I%g zOr-dLp|0@RV@@&InVrwRJfPT~ZY840gT$Jl4)HP^qcTUWE~1&}C2wS3Sv9pJWiRva zyK}a9ilnrYe7SB$bu~GF&GM`D1h@ukNsJY|Yt>|?q(4gzgSUuGwSIfsmlD)%J2V0@ zTU&-58&x%P)-#Oev2~&}bv^wwRbD$?Enu(jJiuwM3shGOZ{$juY+RGk#m^`!p7+vO zAjWFn1{dq`T?N^TggHmN3~VGf^5?a_)R-cj5yfk-?V<|S)%uKn{YGL)7(~eAhWA56 zj7ZS7amp#qQM;t>%6F)v{1S-Gq>88IPiL?2X9=q_r$vhc4{Pd3$WssBMbZaV2W zu&8||{U99-3!x+JudoA1KSAx^0qg$*YLr)FKtJ($lC@k)W?khPY!~B&3F~Xnxs_WH)b*(MC{~@>r={U4@A6+2p8il>0lojdT`r8~C>rA6;jw^lZK9gk<_y!v za(Rbclc{1;TFBtT`lr|YO0}|UXzh>FLsx6RQUq8=?V4{NR#=oxL2}kHb-ZAfuN + project.shadow.component(publication) + artifact sourcesJar + artifact javadocJar + + pom { + name = "OpenSearch Security Resource Sharing SPI" + packaging = "jar" + url = "https://github.com/opensearch-project/security" + description = "OpenSearch Security" + scm { + connection = "scm:git@github.com:opensearch-project/security.git" + developerConnection = "scm:git@github.com:opensearch-project/security.git" + url = "git@github.com:opensearch-project/security.git" + } + licenses { + license { + name = "The Apache License, Version 2.0" + url = "http://www.apache.org/licenses/LICENSE-2.0.txt" + } + } + developers { + developer { + name = "OpenSearch" + url = "https://github.com/opensearch-project/security" + } + } + } + } + } + + // TODO - enabled debug logging for the time being, remove this eventually + gradle.startParameter.setShowStacktrace(ShowStacktrace.ALWAYS) + gradle.startParameter.setLogLevel(LogLevel.DEBUG) +} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java new file mode 100644 index 0000000000..cddc9bfc7e --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java @@ -0,0 +1,24 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ +package org.opensearch.security.spi; + +/** + * SPI of security. + */ +public interface ResourceSharingExtension { + /** + * @return resource type string. + */ + String getResourceType(); + + /** + * @return resource index name. + */ + String getResourceIndex(); +} From 3fd702d311c5abc6b7de6b4e13f3ef7f94dc74ef Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 7 Aug 2024 15:48:01 -0400 Subject: [PATCH 02/80] Also assert sample extension Signed-off-by: Craig Perkins --- .../security/sampleextension/SampleExtensionPluginIT.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index ad73e5f695..fc4e32ed0d 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -34,5 +34,10 @@ public void testPluginsAreInstalled() throws IOException { Assert.assertTrue( pluginsList.stream().map(o -> (Map) o).anyMatch(plugin -> plugin.get("component").equals("opensearch-security")) ); + Assert.assertTrue( + pluginsList.stream() + .map(o -> (Map) o) + .anyMatch(plugin -> plugin.get("component").equals("opensearch-security-sample-extension")) + ); } } From 69f6105eb1b88fe3a86ef9e373921d7c69cf1b87 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 7 Aug 2024 16:34:24 -0400 Subject: [PATCH 03/80] WIP on add create resource handler Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 15 ++++- .../SampleExtensionRestHandler.java | 4 +- .../actions/CreateSampleResourceAction.java | 29 ++++++++++ .../actions/CreateSampleResourceRequest.java | 50 +++++++++++++++++ .../actions/CreateSampleResourceResponse.java | 55 +++++++++++++++++++ .../CreateSampleResourceRestAction.java | 45 +++++++++++++++ .../CreateSampleResourceTransportAction.java | 37 +++++++++++++ 7 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 3fd552bad9..117c98c68f 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -16,6 +16,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.opensearch.action.ActionRequest; import org.opensearch.client.Client; import org.opensearch.cluster.metadata.IndexNameExpressionResolver; import org.opensearch.cluster.node.DiscoveryNodes; @@ -24,6 +25,7 @@ import org.opensearch.common.settings.IndexScopedSettings; import org.opensearch.common.settings.Settings; import org.opensearch.common.settings.SettingsFilter; +import org.opensearch.core.action.ActionResponse; import org.opensearch.core.common.io.stream.NamedWriteableRegistry; import org.opensearch.core.xcontent.NamedXContentRegistry; import org.opensearch.env.Environment; @@ -34,6 +36,9 @@ import org.opensearch.rest.RestController; import org.opensearch.rest.RestHandler; import org.opensearch.script.ScriptService; +import org.opensearch.security.sampleextension.actions.CreateSampleResourceAction; +import org.opensearch.security.sampleextension.actions.CreateSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.CreateSampleResourceTransportAction; import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.threadpool.ThreadPool; import org.opensearch.watcher.ResourceWatcherService; @@ -50,6 +55,8 @@ public class SampleExtensionPlugin extends Plugin implements ActionPlugin, Resou static final String RESOURCE_INDEX_NAME = ".sample_extension_resources"; + private Client client; + @Override public Collection createComponents( Client client, @@ -64,6 +71,7 @@ public Collection createComponents( IndexNameExpressionResolver indexNameExpressionResolver, Supplier repositoriesServiceSupplier ) { + this.client = client; return Collections.emptyList(); } @@ -87,6 +95,11 @@ public List getRestHandlers( IndexNameExpressionResolver indexNameExpressionResolver, Supplier nodesInCluster ) { - return Collections.singletonList(new SampleExtensionRestHandler()); + return List.of(new SampleExtensionRestHandler(), new CreateSampleResourceRestAction()); + } + + @Override + public List> getActions() { + return List.of(new ActionHandler<>(CreateSampleResourceAction.INSTANCE, CreateSampleResourceTransportAction.class)); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java index f2906c6eca..ee53f5af21 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java @@ -35,7 +35,7 @@ * {@code DELETE /_plugins/scheduler_sample/watch?id=dashboards-job-id} */ public class SampleExtensionRestHandler extends BaseRestHandler { - public static final String LIST_RESOURCE_URI = "/_plugins/resource_sample/resource"; + public static final String RESOURCE_URI = "/_plugins/resource_sample/resource"; @Override public String getName() { @@ -44,7 +44,7 @@ public String getName() { @Override public List routes() { - return Collections.unmodifiableList(Arrays.asList(new Route(RestRequest.Method.GET, LIST_RESOURCE_URI))); + return Collections.unmodifiableList(Arrays.asList(new Route(RestRequest.Method.GET, RESOURCE_URI))); } @Override diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java new file mode 100644 index 0000000000..1a706e981c --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import org.opensearch.action.ActionType; + +/** + * Action to create a sample resource + */ +public class CreateSampleResourceAction extends ActionType { + /** + * Create sample resource action instance + */ + public static final CreateSampleResourceAction INSTANCE = new CreateSampleResourceAction(); + /** + * Create sample resource action name + */ + public static final String NAME = "cluster:admin/sampleresource/create"; + + private CreateSampleResourceAction() { + super(NAME, CreateSampleResourceResponse::new); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java new file mode 100644 index 0000000000..d44b59dcc7 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java @@ -0,0 +1,50 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import java.io.IOException; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; + +/** + * Request object for CreateSampleResource transport action + */ +public class CreateSampleResourceRequest extends ActionRequest { + + private final String name; + + /** + * Default constructor + */ + public CreateSampleResourceRequest(String name) { + this.name = name; + } + + /** + * Constructor with stream input + * @param in the stream input + * @throws IOException IOException + */ + public CreateSampleResourceRequest(final StreamInput in) throws IOException { + this.name = in.readString(); + } + + @Override + public void writeTo(final StreamOutput out) throws IOException { + out.writeString(name); + } + + @Override + public ActionRequestValidationException validate() { + return null; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java new file mode 100644 index 0000000000..b2b018d849 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java @@ -0,0 +1,55 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import java.io.IOException; + +import org.opensearch.core.action.ActionResponse; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; + +/** + * Response to a CreateSampleResourceRequest + */ +public class CreateSampleResourceResponse extends ActionResponse implements ToXContentObject { + private final String message; + + /** + * Default constructor + * + * @param message The message + */ + public CreateSampleResourceResponse(String message) { + this.message = message; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeString(message); + } + + /** + * Constructor with StreamInput + * + * @param in the stream input + */ + public CreateSampleResourceResponse(final StreamInput in) throws IOException { + message = in.readString(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field("message", message); + builder.endObject(); + return builder; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java new file mode 100644 index 0000000000..24641d82e1 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import java.util.List; + +import org.opensearch.client.node.NodeClient; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.RestRequest; +import org.opensearch.rest.action.RestToXContentListener; + +import static java.util.Collections.singletonList; +import static org.opensearch.rest.RestRequest.Method.POST; + +public class CreateSampleResourceRestAction extends BaseRestHandler { + + public CreateSampleResourceRestAction() {} + + @Override + public List routes() { + return singletonList(new Route(POST, "/_plugins/resource_sharing_example/resource")); + } + + @Override + public String getName() { + return "create_sample_resource"; + } + + @Override + public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) { + String name = request.param("name"); + final CreateSampleResourceRequest createSampleResourceRequest = new CreateSampleResourceRequest(name); + return channel -> client.executeLocally( + CreateSampleResourceAction.INSTANCE, + createSampleResourceRequest, + new RestToXContentListener<>(channel) + ); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java new file mode 100644 index 0000000000..a5bb6b9641 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java @@ -0,0 +1,37 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.common.inject.Inject; +import org.opensearch.core.action.ActionListener; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +/** + * Transport action for GetExecutionContext. + * + * Returns the canonical class name of the plugin that is currently executing the transport action. + */ +public class CreateSampleResourceTransportAction extends HandledTransportAction { + private final TransportService transportService; + + @Inject + public CreateSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters) { + super(CreateSampleResourceAction.NAME, transportService, actionFilters, CreateSampleResourceRequest::new); + this.transportService = transportService; + } + + @Override + protected void doExecute(Task task, CreateSampleResourceRequest request, ActionListener listener) { + System.out.println("HERE"); + listener.onResponse(new CreateSampleResourceResponse("Hello, world!")); + } +} From c850f1d76a3baca07ab8c1d460809132f79ec466 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 8 Aug 2024 14:27:56 -0400 Subject: [PATCH 04/80] WIP on Create Resource Transport action Signed-off-by: Craig Perkins --- .../CreateSampleResourceTransportAction.java | 1 - .../security/sampleextension/ODFERestTestCase.java | 1 + .../sampleextension/SampleExtensionPluginIT.java | 13 +++++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java index a5bb6b9641..d8d0ec856b 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java @@ -31,7 +31,6 @@ public CreateSampleResourceTransportAction(TransportService transportService, Ac @Override protected void doExecute(Task task, CreateSampleResourceRequest request, ActionListener listener) { - System.out.println("HERE"); listener.onResponse(new CreateSampleResourceResponse("Hello, world!")); } } diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/ODFERestTestCase.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/ODFERestTestCase.java index 0dda33b230..39a3b97810 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/ODFERestTestCase.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/ODFERestTestCase.java @@ -152,6 +152,7 @@ protected static void configureHttpsClient(RestClientBuilder builder, Settings s "Authorization", "Basic " + Base64.getEncoder().encodeToString((userName + ":" + password).getBytes(StandardCharsets.UTF_8)) ); + headers.put("Content-Type", "application/json"); Header[] defaultHeaders = new Header[headers.size()]; int i = 0; for (Map.Entry entry : headers.entrySet()) { diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index fc4e32ed0d..9182006773 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Map; +import org.apache.hc.core5.http.io.entity.StringEntity; import org.junit.Assert; import org.opensearch.client.Request; @@ -40,4 +41,16 @@ public void testPluginsAreInstalled() throws IOException { .anyMatch(plugin -> plugin.get("component").equals("opensearch-security-sample-extension")) ); } + + public void testCreateSampleResource() throws IOException { + Request request = new Request("POST", "/_plugins/resource_sharing_example/resource"); + request.setEntity(new StringEntity("{\"name\":\"Craig\"}")); + Response response = client().performRequest(request); + Map createResourceResponse = JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + response.getEntity().getContent() + ).mapStrings(); + System.out.println("createResourceResponse: " + createResourceResponse); + } } From 334504b8f7a78e4eb6aab2aba06273b47ad6c086 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 8 Aug 2024 15:47:21 -0400 Subject: [PATCH 05/80] Create index Signed-off-by: Craig Perkins --- .../CreateSampleResourceTransportAction.java | 19 +++++++++++++++++-- .../SampleExtensionPluginIT.java | 4 ++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java index d8d0ec856b..c6f14948bd 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java @@ -8,8 +8,11 @@ package org.opensearch.security.sampleextension.actions; +import org.opensearch.action.admin.indices.create.CreateIndexRequest; +import org.opensearch.action.admin.indices.create.CreateIndexResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; import org.opensearch.core.action.ActionListener; import org.opensearch.tasks.Task; @@ -22,15 +25,27 @@ */ public class CreateSampleResourceTransportAction extends HandledTransportAction { private final TransportService transportService; + private final Client nodeClient; @Inject - public CreateSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters) { + public CreateSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { super(CreateSampleResourceAction.NAME, transportService, actionFilters, CreateSampleResourceRequest::new); this.transportService = transportService; + this.nodeClient = nodeClient; } @Override protected void doExecute(Task task, CreateSampleResourceRequest request, ActionListener listener) { - listener.onResponse(new CreateSampleResourceResponse("Hello, world!")); + CreateIndexRequest cir = new CreateIndexRequest(".resource-sharing"); + ActionListener cirListener = ActionListener.wrap(response -> { + if (response.isAcknowledged()) { + System.out.println("Created .resource-sharing"); + } else { + System.out.println("Created .resource-sharing call not acknowledged."); + } + listener.onResponse(new CreateSampleResourceResponse("Created .resource-sharing")); + }, listener::onFailure); + System.out.println("Calling create index for .resource-sharing"); + nodeClient.admin().indices().create(cir, cirListener); } } diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 9182006773..4e40cc4157 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -16,6 +16,7 @@ import org.junit.Assert; import org.opensearch.client.Request; +import org.opensearch.client.RequestOptions; import org.opensearch.client.Response; import org.opensearch.common.xcontent.LoggingDeprecationHandler; import org.opensearch.common.xcontent.json.JsonXContent; @@ -45,6 +46,9 @@ public void testPluginsAreInstalled() throws IOException { public void testCreateSampleResource() throws IOException { Request request = new Request("POST", "/_plugins/resource_sharing_example/resource"); request.setEntity(new StringEntity("{\"name\":\"Craig\"}")); + RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder(); + requestOptions.setWarningsHandler((warnings) -> false); + request.setOptions(requestOptions); Response response = client().performRequest(request); Map createResourceResponse = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, From cf528004a99546c258da71c8f20e785464bed60f Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 8 Aug 2024 16:59:39 -0400 Subject: [PATCH 06/80] Example of usage of why threadContext.stashContext is needed Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 12 +++++-- .../CreateSampleResourceTransportAction.java | 36 +++++++++++++------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 117c98c68f..382a8b70f0 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -30,8 +30,10 @@ import org.opensearch.core.xcontent.NamedXContentRegistry; import org.opensearch.env.Environment; import org.opensearch.env.NodeEnvironment; +import org.opensearch.indices.SystemIndexDescriptor; import org.opensearch.plugins.ActionPlugin; import org.opensearch.plugins.Plugin; +import org.opensearch.plugins.SystemIndexPlugin; import org.opensearch.repositories.RepositoriesService; import org.opensearch.rest.RestController; import org.opensearch.rest.RestHandler; @@ -50,10 +52,10 @@ * endpoint using {@link SampleExtensionRestHandler}. * */ -public class SampleExtensionPlugin extends Plugin implements ActionPlugin, ResourceSharingExtension { +public class SampleExtensionPlugin extends Plugin implements ActionPlugin, SystemIndexPlugin, ResourceSharingExtension { private static final Logger log = LogManager.getLogger(SampleExtensionPlugin.class); - static final String RESOURCE_INDEX_NAME = ".sample_extension_resources"; + public static final String RESOURCE_INDEX_NAME = ".sample_extension_resources"; private Client client; @@ -102,4 +104,10 @@ public List getRestHandlers( public List> getActions() { return List.of(new ActionHandler<>(CreateSampleResourceAction.INSTANCE, CreateSampleResourceTransportAction.class)); } + + @Override + public Collection getSystemIndexDescriptors(Settings settings) { + final SystemIndexDescriptor systemIndexDescriptor = new SystemIndexDescriptor(RESOURCE_INDEX_NAME, "Example index with resources"); + return Collections.singletonList(systemIndexDescriptor); + } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java index c6f14948bd..28dfa30318 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java @@ -10,14 +10,19 @@ import org.opensearch.action.admin.indices.create.CreateIndexRequest; import org.opensearch.action.admin.indices.create.CreateIndexResponse; +import org.opensearch.action.admin.indices.delete.DeleteIndexRequest; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.action.support.master.AcknowledgedResponse; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; +import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; + /** * Transport action for GetExecutionContext. * @@ -36,16 +41,25 @@ public CreateSampleResourceTransportAction(TransportService transportService, Ac @Override protected void doExecute(Task task, CreateSampleResourceRequest request, ActionListener listener) { - CreateIndexRequest cir = new CreateIndexRequest(".resource-sharing"); - ActionListener cirListener = ActionListener.wrap(response -> { - if (response.isAcknowledged()) { - System.out.println("Created .resource-sharing"); - } else { - System.out.println("Created .resource-sharing call not acknowledged."); - } - listener.onResponse(new CreateSampleResourceResponse("Created .resource-sharing")); - }, listener::onFailure); - System.out.println("Calling create index for .resource-sharing"); - nodeClient.admin().indices().create(cir, cirListener); + try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { + CreateIndexRequest cir = new CreateIndexRequest(RESOURCE_INDEX_NAME); + ActionListener cirListener = ActionListener.wrap(response -> { + if (response.isAcknowledged()) { + System.out.println("Created " + RESOURCE_INDEX_NAME); + } else { + System.out.println("Created " + RESOURCE_INDEX_NAME + " call not acknowledged."); + } + DeleteIndexRequest dir = new DeleteIndexRequest(RESOURCE_INDEX_NAME); + ActionListener dirListener = ActionListener.wrap(deletedResponse -> { + listener.onResponse(new CreateSampleResourceResponse("Created and Deleted " + RESOURCE_INDEX_NAME)); + }, listener::onFailure); + + System.out.println("Calling delete index for " + RESOURCE_INDEX_NAME); + nodeClient.admin().indices().delete(dir, dirListener); + // listener.onResponse(new CreateSampleResourceResponse("Created " + RESOURCE_INDEX_NAME)); + }, listener::onFailure); + System.out.println("Calling create index for " + RESOURCE_INDEX_NAME); + nodeClient.admin().indices().create(cir, cirListener); + } } } From 36455cc024400f2faaf5646e5170c28ad0618c93 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 13 Aug 2024 17:09:50 -0400 Subject: [PATCH 07/80] Implement create resource Signed-off-by: Craig Perkins --- .../actions/CreateSampleResourceRequest.java | 4 ++ .../CreateSampleResourceTransportAction.java | 40 +++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java index d44b59dcc7..a771680750 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java @@ -47,4 +47,8 @@ public void writeTo(final StreamOutput out) throws IOException { public ActionRequestValidationException validate() { return null; } + + public String getName() { + return this.name; + } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java index 28dfa30318..220b9ceb82 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java @@ -8,12 +8,14 @@ package org.opensearch.security.sampleextension.actions; +import java.io.IOException; + import org.opensearch.action.admin.indices.create.CreateIndexRequest; import org.opensearch.action.admin.indices.create.CreateIndexResponse; -import org.opensearch.action.admin.indices.delete.DeleteIndexRequest; +import org.opensearch.action.index.IndexRequest; +import org.opensearch.action.index.IndexResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; -import org.opensearch.action.support.master.AcknowledgedResponse; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; import org.opensearch.common.util.concurrent.ThreadContext; @@ -21,6 +23,7 @@ import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; +import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; /** @@ -43,23 +46,28 @@ public CreateSampleResourceTransportAction(TransportService transportService, Ac protected void doExecute(Task task, CreateSampleResourceRequest request, ActionListener listener) { try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { CreateIndexRequest cir = new CreateIndexRequest(RESOURCE_INDEX_NAME); - ActionListener cirListener = ActionListener.wrap(response -> { - if (response.isAcknowledged()) { - System.out.println("Created " + RESOURCE_INDEX_NAME); - } else { - System.out.println("Created " + RESOURCE_INDEX_NAME + " call not acknowledged."); + ActionListener cirListener = ActionListener.wrap( + response -> { createResource(request, listener); }, + (failResponse) -> { + /* Index already exists, ignore and continue */ + createResource(request, listener); } - DeleteIndexRequest dir = new DeleteIndexRequest(RESOURCE_INDEX_NAME); - ActionListener dirListener = ActionListener.wrap(deletedResponse -> { - listener.onResponse(new CreateSampleResourceResponse("Created and Deleted " + RESOURCE_INDEX_NAME)); - }, listener::onFailure); + ); + nodeClient.admin().indices().create(cir, cirListener); + } + } - System.out.println("Calling delete index for " + RESOURCE_INDEX_NAME); - nodeClient.admin().indices().delete(dir, dirListener); - // listener.onResponse(new CreateSampleResourceResponse("Created " + RESOURCE_INDEX_NAME)); + private void createResource(CreateSampleResourceRequest request, ActionListener listener) { + try { + IndexRequest ir = nodeClient.prepareIndex(RESOURCE_INDEX_NAME) + .setSource(jsonBuilder().startObject().field("name", request.getName()).endObject()) + .request(); + ActionListener irListener = ActionListener.wrap(idxResponse -> { + listener.onResponse(new CreateSampleResourceResponse("Created resource: " + idxResponse.toString())); }, listener::onFailure); - System.out.println("Calling create index for " + RESOURCE_INDEX_NAME); - nodeClient.admin().indices().create(cir, cirListener); + nodeClient.index(ir, irListener); + } catch (IOException e) { + throw new RuntimeException(e); } } } From 04232ffb5e730aa3725f701c2609900e8c5af24d Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 14 Aug 2024 16:02:38 -0400 Subject: [PATCH 08/80] Create SampleResource Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 13 +----- .../CreateSampleResourceTransportAction.java | 6 ++- .../resource/SampleResource.java | 40 +++++++++++++++++++ ...arch.security.spi.ResourceSharingExtension | 2 +- 4 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 382a8b70f0..a81ff808e0 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -41,7 +41,6 @@ import org.opensearch.security.sampleextension.actions.CreateSampleResourceAction; import org.opensearch.security.sampleextension.actions.CreateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.CreateSampleResourceTransportAction; -import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.threadpool.ThreadPool; import org.opensearch.watcher.ResourceWatcherService; @@ -52,7 +51,7 @@ * endpoint using {@link SampleExtensionRestHandler}. * */ -public class SampleExtensionPlugin extends Plugin implements ActionPlugin, SystemIndexPlugin, ResourceSharingExtension { +public class SampleExtensionPlugin extends Plugin implements ActionPlugin, SystemIndexPlugin { private static final Logger log = LogManager.getLogger(SampleExtensionPlugin.class); public static final String RESOURCE_INDEX_NAME = ".sample_extension_resources"; @@ -77,16 +76,6 @@ public Collection createComponents( return Collections.emptyList(); } - @Override - public String getResourceType() { - return "sample_resource"; - } - - @Override - public String getResourceIndex() { - return RESOURCE_INDEX_NAME; - } - @Override public List getRestHandlers( Settings settings, diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java index 220b9ceb82..b5bf29260a 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java @@ -20,6 +20,8 @@ import org.opensearch.common.inject.Inject; import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; +import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -58,10 +60,12 @@ protected void doExecute(Task task, CreateSampleResourceRequest request, ActionL } private void createResource(CreateSampleResourceRequest request, ActionListener listener) { + SampleResource sample = new SampleResource(request.getName()); try { IndexRequest ir = nodeClient.prepareIndex(RESOURCE_INDEX_NAME) - .setSource(jsonBuilder().startObject().field("name", request.getName()).endObject()) + .setSource(sample.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) .request(); + ActionListener irListener = ActionListener.wrap(idxResponse -> { listener.onResponse(new CreateSampleResourceResponse("Created resource: " + idxResponse.toString())); }, listener::onFailure); diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java new file mode 100644 index 0000000000..ca1954bd12 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java @@ -0,0 +1,40 @@ +package org.opensearch.security.sampleextension.resource; + +import java.io.IOException; + +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.common.io.stream.Writeable; +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.spi.ResourceSharingExtension; + +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; + +public class SampleResource implements ResourceSharingExtension, Writeable, ToXContentFragment { + + private String name; + + public SampleResource(String name) { + this.name = name; + } + + @Override + public String getResourceType() { + return "sample_resource"; + } + + @Override + public String getResourceIndex() { + return RESOURCE_INDEX_NAME; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject().field("name", name).endObject(); + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + streamOutput.writeString(name); + } +} diff --git a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension index e32f06ee56..904fb99e99 100644 --- a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension +++ b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension @@ -3,4 +3,4 @@ # SPDX-License-Identifier: Apache-2.0 # -org.opensearch.security.sampleextension.SampleExtensionPlugin \ No newline at end of file +org.opensearch.security.sampleextension.resource.SampleResource \ No newline at end of file From a0e0386d30ea29b81d20021b7fda11b2087c4a1a Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 14 Aug 2024 16:36:37 -0400 Subject: [PATCH 09/80] Add list resource Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 16 +++-- .../SampleExtensionRestHandler.java | 60 ------------------- .../CreateSampleResourceAction.java | 2 +- .../CreateSampleResourceRequest.java | 2 +- .../CreateSampleResourceResponse.java | 2 +- .../CreateSampleResourceRestAction.java | 14 ++++- .../CreateSampleResourceTransportAction.java | 16 +++-- .../list/ListSampleResourceAction.java | 29 +++++++++ .../list/ListSampleResourceRequest.java | 39 ++++++++++++ .../list/ListSampleResourceResponse.java | 55 +++++++++++++++++ .../list/ListSampleResourceRestAction.java | 44 ++++++++++++++ .../ListSampleResourceTransportAction.java | 54 +++++++++++++++++ .../resource/SampleResource.java | 2 +- .../SampleExtensionPluginIT.java | 20 +++++-- 14 files changed, 275 insertions(+), 80 deletions(-) delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => create}/CreateSampleResourceAction.java (92%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => create}/CreateSampleResourceRequest.java (95%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => create}/CreateSampleResourceResponse.java (95%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => create}/CreateSampleResourceRestAction.java (76%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => create}/CreateSampleResourceTransportAction.java (86%) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index a81ff808e0..98918bda09 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -38,9 +38,12 @@ import org.opensearch.rest.RestController; import org.opensearch.rest.RestHandler; import org.opensearch.script.ScriptService; -import org.opensearch.security.sampleextension.actions.CreateSampleResourceAction; -import org.opensearch.security.sampleextension.actions.CreateSampleResourceRestAction; -import org.opensearch.security.sampleextension.actions.CreateSampleResourceTransportAction; +import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceAction; +import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceTransportAction; +import org.opensearch.security.sampleextension.actions.list.ListSampleResourceAction; +import org.opensearch.security.sampleextension.actions.list.ListSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.list.ListSampleResourceTransportAction; import org.opensearch.threadpool.ThreadPool; import org.opensearch.watcher.ResourceWatcherService; @@ -86,12 +89,15 @@ public List getRestHandlers( IndexNameExpressionResolver indexNameExpressionResolver, Supplier nodesInCluster ) { - return List.of(new SampleExtensionRestHandler(), new CreateSampleResourceRestAction()); + return List.of(new CreateSampleResourceRestAction(), new ListSampleResourceRestAction()); } @Override public List> getActions() { - return List.of(new ActionHandler<>(CreateSampleResourceAction.INSTANCE, CreateSampleResourceTransportAction.class)); + return List.of( + new ActionHandler<>(CreateSampleResourceAction.INSTANCE, CreateSampleResourceTransportAction.class), + new ActionHandler<>(ListSampleResourceAction.INSTANCE, ListSampleResourceTransportAction.class) + ); } @Override diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java deleted file mode 100644 index ee53f5af21..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionRestHandler.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ -package org.opensearch.security.sampleextension; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.opensearch.client.node.NodeClient; -import org.opensearch.core.rest.RestStatus; -import org.opensearch.rest.BaseRestHandler; -import org.opensearch.rest.BytesRestResponse; -import org.opensearch.rest.RestRequest; - -/** - * A sample rest handler that supports schedule and deschedule job operation - * - * Users need to provide "id", "index", "job_name", and "interval" parameter to schedule - * a job. e.g. - * {@code - * POST /_plugins/scheduler_sample/watch?id=dashboards-job-id&job_name=watch dashboards index&index=.opensearch_dashboards_1&interval=1 - * } - * - * creates a job with id "dashboards-job-id" and job name "watch dashboards index", - * which logs ".opensearch_dashboards_1" index's shards info every 1 minute - * - * Users can remove that job by calling - * {@code DELETE /_plugins/scheduler_sample/watch?id=dashboards-job-id} - */ -public class SampleExtensionRestHandler extends BaseRestHandler { - public static final String RESOURCE_URI = "/_plugins/resource_sample/resource"; - - @Override - public String getName() { - return "Sample Security Resource Sharing extension handler"; - } - - @Override - public List routes() { - return Collections.unmodifiableList(Arrays.asList(new Route(RestRequest.Method.GET, RESOURCE_URI))); - } - - @Override - protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { - if (request.method().equals(RestRequest.Method.GET)) { - return restChannel -> { restChannel.sendResponse(new BytesRestResponse(RestStatus.OK, "List Resources called")); }; - } else { - return restChannel -> { - restChannel.sendResponse(new BytesRestResponse(RestStatus.METHOD_NOT_ALLOWED, request.method() + " is not allowed.")); - }; - } - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java similarity index 92% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java index 1a706e981c..214bd4d660 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.create; import org.opensearch.action.ActionType; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java similarity index 95% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java index a771680750..0fbe375fed 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.create; import java.io.IOException; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceResponse.java similarity index 95% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceResponse.java index b2b018d849..54cc5746f2 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceResponse.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.create; import java.io.IOException; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java similarity index 76% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java index 24641d82e1..d6618c413d 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java @@ -6,11 +6,14 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.create; +import java.io.IOException; import java.util.List; +import java.util.Map; import org.opensearch.client.node.NodeClient; +import org.opensearch.core.xcontent.XContentParser; import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; @@ -33,8 +36,13 @@ public String getName() { } @Override - public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) { - String name = request.param("name"); + public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + Map source; + try (XContentParser parser = request.contentParser()) { + source = parser.map(); + } + + String name = (String) source.get("name"); final CreateSampleResourceRequest createSampleResourceRequest = new CreateSampleResourceRequest(name); return channel -> client.executeLocally( CreateSampleResourceAction.INSTANCE, diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java similarity index 86% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index b5bf29260a..3e3aeaa15e 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -6,16 +6,20 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.create; import java.io.IOException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import org.opensearch.action.admin.indices.create.CreateIndexRequest; import org.opensearch.action.admin.indices.create.CreateIndexResponse; import org.opensearch.action.index.IndexRequest; import org.opensearch.action.index.IndexResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.action.support.WriteRequest; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; import org.opensearch.common.util.concurrent.ThreadContext; @@ -29,11 +33,11 @@ import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; /** - * Transport action for GetExecutionContext. - * - * Returns the canonical class name of the plugin that is currently executing the transport action. + * Transport action for CreateSampleResource. */ public class CreateSampleResourceTransportAction extends HandledTransportAction { + private static final Logger log = LogManager.getLogger(CreateSampleResourceTransportAction.class); + private final TransportService transportService; private final Client nodeClient; @@ -60,12 +64,16 @@ protected void doExecute(Task task, CreateSampleResourceRequest request, ActionL } private void createResource(CreateSampleResourceRequest request, ActionListener listener) { + log.warn("Sample name: " + request.getName()); SampleResource sample = new SampleResource(request.getName()); try { IndexRequest ir = nodeClient.prepareIndex(RESOURCE_INDEX_NAME) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) .setSource(sample.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) .request(); + log.warn("Index Request: " + ir.toString()); + ActionListener irListener = ActionListener.wrap(idxResponse -> { listener.onResponse(new CreateSampleResourceResponse("Created resource: " + idxResponse.toString())); }, listener::onFailure); diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java new file mode 100644 index 0000000000..aac9ab10d9 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.list; + +import org.opensearch.action.ActionType; + +/** + * Action to list sample resources + */ +public class ListSampleResourceAction extends ActionType { + /** + * List sample resource action instance + */ + public static final ListSampleResourceAction INSTANCE = new ListSampleResourceAction(); + /** + * List sample resource action name + */ + public static final String NAME = "cluster:admin/sampleresource/list"; + + private ListSampleResourceAction() { + super(NAME, ListSampleResourceResponse::new); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java new file mode 100644 index 0000000000..3a6acb5cfb --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.list; + +import java.io.IOException; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; + +/** + * Request object for ListSampleResource transport action + */ +public class ListSampleResourceRequest extends ActionRequest { + + public ListSampleResourceRequest() {} + + /** + * Constructor with stream input + * @param in the stream input + * @throws IOException IOException + */ + public ListSampleResourceRequest(final StreamInput in) throws IOException {} + + @Override + public void writeTo(final StreamOutput out) throws IOException {} + + @Override + public ActionRequestValidationException validate() { + return null; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java new file mode 100644 index 0000000000..eb1150a379 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java @@ -0,0 +1,55 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.list; + +import java.io.IOException; + +import org.opensearch.core.action.ActionResponse; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; + +/** + * Response to a ListSampleResourceRequest + */ +public class ListSampleResourceResponse extends ActionResponse implements ToXContentObject { + private final String message; + + /** + * Default constructor + * + * @param message The message + */ + public ListSampleResourceResponse(String message) { + this.message = message; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeString(message); + } + + /** + * Constructor with StreamInput + * + * @param in the stream input + */ + public ListSampleResourceResponse(final StreamInput in) throws IOException { + message = in.readString(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field("message", message); + builder.endObject(); + return builder; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java new file mode 100644 index 0000000000..4bab2c9ce6 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.list; + +import java.util.List; + +import org.opensearch.client.node.NodeClient; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.RestRequest; +import org.opensearch.rest.action.RestToXContentListener; + +import static java.util.Collections.singletonList; +import static org.opensearch.rest.RestRequest.Method.GET; + +public class ListSampleResourceRestAction extends BaseRestHandler { + + public ListSampleResourceRestAction() {} + + @Override + public List routes() { + return singletonList(new Route(GET, "/_plugins/resource_sharing_example/resource")); + } + + @Override + public String getName() { + return "list_sample_resources"; + } + + @Override + public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) { + final ListSampleResourceRequest listSampleResourceRequest = new ListSampleResourceRequest(); + return channel -> client.executeLocally( + ListSampleResourceAction.INSTANCE, + listSampleResourceRequest, + new RestToXContentListener<>(channel) + ); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java new file mode 100644 index 0000000000..8f102eef14 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java @@ -0,0 +1,54 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.list; + +import org.opensearch.action.search.SearchRequest; +import org.opensearch.action.search.SearchResponse; +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.client.Client; +import org.opensearch.common.inject.Inject; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.action.ActionListener; +import org.opensearch.index.query.MatchAllQueryBuilder; +import org.opensearch.search.builder.SearchSourceBuilder; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; + +/** + * Transport action for ListSampleResource. + */ +public class ListSampleResourceTransportAction extends HandledTransportAction { + private final TransportService transportService; + private final Client nodeClient; + + @Inject + public ListSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { + super(ListSampleResourceAction.NAME, transportService, actionFilters, ListSampleResourceRequest::new); + this.transportService = transportService; + this.nodeClient = nodeClient; + } + + @Override + protected void doExecute(Task task, ListSampleResourceRequest request, ActionListener listener) { + try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { + SearchRequest sr = new SearchRequest(RESOURCE_INDEX_NAME); + SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); + matchAllQuery.query(new MatchAllQueryBuilder()); + sr.source(matchAllQuery); + /* Index already exists, ignore and continue */ + ActionListener searchListener = ActionListener.wrap(response -> { + listener.onResponse(new ListSampleResourceResponse(response.toString())); + }, listener::onFailure); + nodeClient.search(sr, searchListener); + } + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java index ca1954bd12..360d3357a2 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java @@ -12,7 +12,7 @@ public class SampleResource implements ResourceSharingExtension, Writeable, ToXContentFragment { - private String name; + private final String name; public SampleResource(String name) { this.name = name; diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 4e40cc4157..9b418eeb04 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -44,17 +44,29 @@ public void testPluginsAreInstalled() throws IOException { } public void testCreateSampleResource() throws IOException { - Request request = new Request("POST", "/_plugins/resource_sharing_example/resource"); - request.setEntity(new StringEntity("{\"name\":\"Craig\"}")); + Request createRequest = new Request("POST", "/_plugins/resource_sharing_example/resource"); + createRequest.setEntity(new StringEntity("{\"name\":\"Craig\"}")); RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder(); requestOptions.setWarningsHandler((warnings) -> false); - request.setOptions(requestOptions); - Response response = client().performRequest(request); + createRequest.setOptions(requestOptions); + Response response = client().performRequest(createRequest); Map createResourceResponse = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getEntity().getContent() ).mapStrings(); System.out.println("createResourceResponse: " + createResourceResponse); + + Request listRequest = new Request("GET", "/_plugins/resource_sharing_example/resource"); + RequestOptions.Builder listRequestOptions = RequestOptions.DEFAULT.toBuilder(); + requestOptions.setWarningsHandler((warnings) -> false); + listRequest.setOptions(listRequestOptions); + Response listResponse = client().performRequest(listRequest); + Map listResourceResponse = JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + listResponse.getEntity().getContent() + ).mapStrings(); + System.out.println("listResourceResponse: " + listResourceResponse); } } From 2610ed04cff32411732053c8888f00d895046f46 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 14 Aug 2024 21:08:31 -0400 Subject: [PATCH 10/80] Create Abstract resource Signed-off-by: Craig Perkins --- .../create/CreateSampleResourceRequest.java | 16 +++++++++------- .../create/CreateSampleResourceRestAction.java | 4 +++- .../CreateSampleResourceTransportAction.java | 4 ++-- .../sampleextension/resource/Resource.java | 6 ++++++ .../sampleextension/resource/SampleResource.java | 9 ++++++--- 5 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/Resource.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java index 0fbe375fed..84363f4cad 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java @@ -14,19 +14,21 @@ import org.opensearch.action.ActionRequestValidationException; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.security.sampleextension.resource.Resource; +import org.opensearch.security.sampleextension.resource.SampleResource; /** * Request object for CreateSampleResource transport action */ public class CreateSampleResourceRequest extends ActionRequest { - private final String name; + private final Resource resource; /** * Default constructor */ - public CreateSampleResourceRequest(String name) { - this.name = name; + public CreateSampleResourceRequest(Resource resource) { + this.resource = resource; } /** @@ -35,12 +37,12 @@ public CreateSampleResourceRequest(String name) { * @throws IOException IOException */ public CreateSampleResourceRequest(final StreamInput in) throws IOException { - this.name = in.readString(); + this.resource = new SampleResource(in); } @Override public void writeTo(final StreamOutput out) throws IOException { - out.writeString(name); + resource.writeTo(out); } @Override @@ -48,7 +50,7 @@ public ActionRequestValidationException validate() { return null; } - public String getName() { - return this.name; + public Resource getResource() { + return this.resource; } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java index d6618c413d..28801f3e79 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java @@ -17,6 +17,7 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; +import org.opensearch.security.sampleextension.resource.SampleResource; import static java.util.Collections.singletonList; import static org.opensearch.rest.RestRequest.Method.POST; @@ -43,7 +44,8 @@ public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client } String name = (String) source.get("name"); - final CreateSampleResourceRequest createSampleResourceRequest = new CreateSampleResourceRequest(name); + SampleResource resource = new SampleResource(name); + final CreateSampleResourceRequest createSampleResourceRequest = new CreateSampleResourceRequest(resource); return channel -> client.executeLocally( CreateSampleResourceAction.INSTANCE, createSampleResourceRequest, diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index 3e3aeaa15e..ad72a290b1 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -64,8 +64,8 @@ protected void doExecute(Task task, CreateSampleResourceRequest request, ActionL } private void createResource(CreateSampleResourceRequest request, ActionListener listener) { - log.warn("Sample name: " + request.getName()); - SampleResource sample = new SampleResource(request.getName()); + log.warn("Sample name: " + request.getResource()); + SampleResource sample = (SampleResource) request.getResource(); try { IndexRequest ir = nodeClient.prepareIndex(RESOURCE_INDEX_NAME) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/Resource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/Resource.java new file mode 100644 index 0000000000..ec8a2b48c4 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/Resource.java @@ -0,0 +1,6 @@ +package org.opensearch.security.sampleextension.resource; + +import org.opensearch.core.common.io.stream.Writeable; +import org.opensearch.core.xcontent.ToXContentFragment; + +public abstract class Resource implements Writeable, ToXContentFragment {} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java index 360d3357a2..a709b7b894 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java @@ -2,15 +2,14 @@ import java.io.IOException; +import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.core.common.io.stream.Writeable; -import org.opensearch.core.xcontent.ToXContentFragment; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.security.spi.ResourceSharingExtension; import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; -public class SampleResource implements ResourceSharingExtension, Writeable, ToXContentFragment { +public class SampleResource extends Resource implements ResourceSharingExtension { private final String name; @@ -18,6 +17,10 @@ public SampleResource(String name) { this.name = name; } + public SampleResource(StreamInput in) throws IOException { + this.name = in.readString(); + } + @Override public String getResourceType() { return "sample_resource"; From 487e468f48162fcccbe979703745e6323f124260 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 14 Aug 2024 21:17:05 -0400 Subject: [PATCH 11/80] Remove cast Signed-off-by: Craig Perkins --- .../actions/create/CreateSampleResourceTransportAction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index ad72a290b1..6f7d99c516 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -25,7 +25,7 @@ import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.sampleextension.resource.Resource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -65,7 +65,7 @@ protected void doExecute(Task task, CreateSampleResourceRequest request, ActionL private void createResource(CreateSampleResourceRequest request, ActionListener listener) { log.warn("Sample name: " + request.getResource()); - SampleResource sample = (SampleResource) request.getResource(); + Resource sample = request.getResource(); try { IndexRequest ir = nodeClient.prepareIndex(RESOURCE_INDEX_NAME) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) From 3361e93cc22550ae304f3a4a583f4775f9793766 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Wed, 14 Aug 2024 23:15:59 -0400 Subject: [PATCH 12/80] Create abstract transport action Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 1 - .../create/CreateSampleResourceAction.java | 5 +- .../create/CreateSampleResourceRequest.java | 2 +- .../CreateSampleResourceRestAction.java | 3 +- .../CreateSampleResourceTransportAction.java | 60 +----------- .../sampleextension/resource/Resource.java | 6 -- .../resource/SampleResource.java | 6 ++ .../org/opensearch/security/spi/Resource.java | 6 ++ .../spi/actions/CreateResourceRequest.java | 51 ++++++++++ .../spi/actions/CreateResourceResponse.java | 55 +++++++++++ .../CreateResourceTransportAction.java | 94 +++++++++++++++++++ 11 files changed, 222 insertions(+), 67 deletions(-) delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/Resource.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/Resource.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 98918bda09..0c7162c0e9 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -51,7 +51,6 @@ * Sample Security Resource Sharing extension plugin. * * It use ".sample_extension_resources" index to manage its resources, and exposes a REST API - * endpoint using {@link SampleExtensionRestHandler}. * */ public class SampleExtensionPlugin extends Plugin implements ActionPlugin, SystemIndexPlugin { diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java index 214bd4d660..19c2685ec3 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java @@ -9,11 +9,12 @@ package org.opensearch.security.sampleextension.actions.create; import org.opensearch.action.ActionType; +import org.opensearch.security.spi.actions.CreateResourceResponse; /** * Action to create a sample resource */ -public class CreateSampleResourceAction extends ActionType { +public class CreateSampleResourceAction extends ActionType { /** * Create sample resource action instance */ @@ -24,6 +25,6 @@ public class CreateSampleResourceAction extends ActionType createSampleResourceRequest = new CreateResourceRequest<>(resource); return channel -> client.executeLocally( CreateSampleResourceAction.INSTANCE, createSampleResourceRequest, diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index 6f7d99c516..f4b2a90fa0 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -8,78 +8,26 @@ package org.opensearch.security.sampleextension.actions.create; -import java.io.IOException; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.opensearch.action.admin.indices.create.CreateIndexRequest; -import org.opensearch.action.admin.indices.create.CreateIndexResponse; -import org.opensearch.action.index.IndexRequest; -import org.opensearch.action.index.IndexResponse; import org.opensearch.action.support.ActionFilters; -import org.opensearch.action.support.HandledTransportAction; -import org.opensearch.action.support.WriteRequest; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; -import org.opensearch.common.util.concurrent.ThreadContext; -import org.opensearch.core.action.ActionListener; -import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.security.sampleextension.resource.Resource; -import org.opensearch.tasks.Task; +import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.spi.actions.CreateResourceTransportAction; import org.opensearch.transport.TransportService; -import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; /** * Transport action for CreateSampleResource. */ -public class CreateSampleResourceTransportAction extends HandledTransportAction { +public class CreateSampleResourceTransportAction extends CreateResourceTransportAction { private static final Logger log = LogManager.getLogger(CreateSampleResourceTransportAction.class); - private final TransportService transportService; - private final Client nodeClient; - @Inject public CreateSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { - super(CreateSampleResourceAction.NAME, transportService, actionFilters, CreateSampleResourceRequest::new); - this.transportService = transportService; - this.nodeClient = nodeClient; - } - - @Override - protected void doExecute(Task task, CreateSampleResourceRequest request, ActionListener listener) { - try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { - CreateIndexRequest cir = new CreateIndexRequest(RESOURCE_INDEX_NAME); - ActionListener cirListener = ActionListener.wrap( - response -> { createResource(request, listener); }, - (failResponse) -> { - /* Index already exists, ignore and continue */ - createResource(request, listener); - } - ); - nodeClient.admin().indices().create(cir, cirListener); - } - } - - private void createResource(CreateSampleResourceRequest request, ActionListener listener) { - log.warn("Sample name: " + request.getResource()); - Resource sample = request.getResource(); - try { - IndexRequest ir = nodeClient.prepareIndex(RESOURCE_INDEX_NAME) - .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) - .setSource(sample.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) - .request(); - - log.warn("Index Request: " + ir.toString()); - - ActionListener irListener = ActionListener.wrap(idxResponse -> { - listener.onResponse(new CreateSampleResourceResponse("Created resource: " + idxResponse.toString())); - }, listener::onFailure); - nodeClient.index(ir, irListener); - } catch (IOException e) { - throw new RuntimeException(e); - } + super(transportService, actionFilters, nodeClient, CreateSampleResourceAction.NAME, RESOURCE_INDEX_NAME, SampleResource::new); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/Resource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/Resource.java deleted file mode 100644 index ec8a2b48c4..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/Resource.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.opensearch.security.sampleextension.resource; - -import org.opensearch.core.common.io.stream.Writeable; -import org.opensearch.core.xcontent.ToXContentFragment; - -public abstract class Resource implements Writeable, ToXContentFragment {} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java index a709b7b894..4b21953f83 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java @@ -5,6 +5,7 @@ import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceSharingExtension; import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; @@ -40,4 +41,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws public void writeTo(StreamOutput streamOutput) throws IOException { streamOutput.writeString(name); } + + @Override + public String getWriteableName() { + return "sampled_resource"; + } } diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java new file mode 100644 index 0000000000..39482b4232 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/Resource.java @@ -0,0 +1,6 @@ +package org.opensearch.security.spi; + +import org.opensearch.core.common.io.stream.NamedWriteable; +import org.opensearch.core.xcontent.ToXContentFragment; + +public abstract class Resource implements NamedWriteable, ToXContentFragment {} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java new file mode 100644 index 0000000000..e930cf1ecf --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.common.io.stream.Writeable; +import org.opensearch.security.spi.Resource; + +/** + * Request object for CreateSampleResource transport action + */ +public class CreateResourceRequest extends ActionRequest { + + private final T resource; + + /** + * Default constructor + */ + public CreateResourceRequest(T resource) { + this.resource = resource; + } + + public CreateResourceRequest(StreamInput in, Writeable.Reader resourceReader) throws IOException { + this.resource = resourceReader.read(in); + } + + @Override + public void writeTo(final StreamOutput out) throws IOException { + resource.writeTo(out); + } + + @Override + public ActionRequestValidationException validate() { + return null; + } + + public Resource getResource() { + return this.resource; + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java new file mode 100644 index 0000000000..958ca9fbbf --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java @@ -0,0 +1,55 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.opensearch.core.action.ActionResponse; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; + +/** + * Response to a CreateSampleResourceRequest + */ +public class CreateResourceResponse extends ActionResponse implements ToXContentObject { + private final String message; + + /** + * Default constructor + * + * @param message The message + */ + public CreateResourceResponse(String message) { + this.message = message; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeString(message); + } + + /** + * Constructor with StreamInput + * + * @param in the stream input + */ + public CreateResourceResponse(final StreamInput in) throws IOException { + message = in.readString(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field("message", message); + builder.endObject(); + return builder; + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java new file mode 100644 index 0000000000..5fbab4c4f9 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java @@ -0,0 +1,94 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.action.admin.indices.create.CreateIndexRequest; +import org.opensearch.action.admin.indices.create.CreateIndexResponse; +import org.opensearch.action.index.IndexRequest; +import org.opensearch.action.index.IndexResponse; +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.action.support.WriteRequest; +import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.action.ActionListener; +import org.opensearch.core.common.io.stream.Writeable; +import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.security.spi.Resource; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; + +/** + * Transport action for CreateSampleResource. + */ +public class CreateResourceTransportAction extends HandledTransportAction< + CreateResourceRequest, + CreateResourceResponse> { + private static final Logger log = LogManager.getLogger(CreateResourceTransportAction.class); + + private final TransportService transportService; + private final Client nodeClient; + private final String resourceIndex; + + public CreateResourceTransportAction( + TransportService transportService, + ActionFilters actionFilters, + Client nodeClient, + String actionName, + String resourceIndex, + Writeable.Reader resourceReader + ) { + super(actionName, transportService, actionFilters, (in) -> new CreateResourceRequest(in, resourceReader)); + this.transportService = transportService; + this.nodeClient = nodeClient; + this.resourceIndex = resourceIndex; + } + + @Override + protected void doExecute(Task task, CreateResourceRequest request, ActionListener listener) { + try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { + CreateIndexRequest cir = new CreateIndexRequest(resourceIndex); + ActionListener cirListener = ActionListener.wrap( + response -> { createResource(request, listener); }, + (failResponse) -> { + /* Index already exists, ignore and continue */ + createResource(request, listener); + } + ); + nodeClient.admin().indices().create(cir, cirListener); + } + } + + private void createResource(CreateResourceRequest request, ActionListener listener) { + log.warn("Sample name: " + request.getResource()); + Resource sample = request.getResource(); + try { + IndexRequest ir = nodeClient.prepareIndex(resourceIndex) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .setSource(sample.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) + .request(); + + log.warn("Index Request: " + ir.toString()); + + ActionListener irListener = ActionListener.wrap(idxResponse -> { + listener.onResponse(new CreateResourceResponse("Created resource: " + idxResponse.toString())); + }, listener::onFailure); + nodeClient.index(ir, irListener); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} From e14532f8efc06b1526873e02efd000a995abca9e Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 15 Aug 2024 16:54:45 -0400 Subject: [PATCH 13/80] Create ResourceSharingUtils Signed-off-by: Craig Perkins --- .../resource/ResourceSharingUtils.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java new file mode 100644 index 0000000000..2b3f0744db --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java @@ -0,0 +1,26 @@ +package org.opensearch.security.sampleextension.resource; + +import org.opensearch.OpenSearchSecurityException; +import org.opensearch.threadpool.ThreadPool; + +public class ResourceSharingUtils { + private static final ResourceSharingUtils INSTANCE = new ResourceSharingUtils(); + + public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; + + private ThreadPool threadPool; + + private ResourceSharingUtils() {} + + // Public method to provide access to the singleton instance + public static ResourceSharingUtils getInstance() { + return ResourceSharingUtils.INSTANCE; + } + + public void initialize(ThreadPool threadPool) { + if (threadPool != null) { + throw new OpenSearchSecurityException("ResourceSharingUtils can only be initialized once."); + } + this.threadPool = threadPool; + } +} From c0c8db1ee7f282b4b4c8011d5e5c0fdc2a3955c1 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 15 Aug 2024 17:14:14 -0400 Subject: [PATCH 14/80] Create .resource-sharing index Signed-off-by: Craig Perkins --- .../resource/ResourceSharingUtils.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java index 2b3f0744db..9ed643d4a9 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java @@ -1,9 +1,19 @@ package org.opensearch.security.sampleextension.resource; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import org.opensearch.OpenSearchSecurityException; +import org.opensearch.action.admin.indices.create.CreateIndexRequest; +import org.opensearch.action.admin.indices.create.CreateIndexResponse; +import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.action.ActionListener; import org.opensearch.threadpool.ThreadPool; public class ResourceSharingUtils { + private final static Logger log = LogManager.getLogger(ResourceSharingUtils.class); + private static final ResourceSharingUtils INSTANCE = new ResourceSharingUtils(); public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; @@ -17,10 +27,22 @@ public static ResourceSharingUtils getInstance() { return ResourceSharingUtils.INSTANCE; } - public void initialize(ThreadPool threadPool) { - if (threadPool != null) { + public void initialize(ThreadPool threadPool, Client client) { + if (this.threadPool != null) { throw new OpenSearchSecurityException("ResourceSharingUtils can only be initialized once."); } this.threadPool = threadPool; + + try (ThreadContext.StoredContext ctx = threadPool.getThreadContext().stashContext()) { + CreateIndexRequest cir = new CreateIndexRequest(RESOURCE_SHARING_INDEX); + ActionListener cirListener = ActionListener.wrap( + response -> { log.info(RESOURCE_SHARING_INDEX + " created."); }, + (failResponse) -> { + /* Index already exists, ignore and continue */ + log.info(RESOURCE_SHARING_INDEX + " exists."); + } + ); + client.admin().indices().create(cir, cirListener); + } } } From efb6937ebce9480ae50db514e98fe62a4624a4cb Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 15 Aug 2024 18:00:15 -0400 Subject: [PATCH 15/80] Initialize ResourceSharingUtils Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 2 ++ .../security/spi}/ResourceSharingUtils.java | 27 ++++++++++++++----- .../CreateResourceTransportAction.java | 2 ++ .../security/OpenSearchSecurityPlugin.java | 3 +++ 4 files changed, 27 insertions(+), 7 deletions(-) rename {sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource => spi/src/main/java/org/opensearch/security/spi}/ResourceSharingUtils.java (69%) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 0c7162c0e9..a38cf18ab8 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -44,6 +44,7 @@ import org.opensearch.security.sampleextension.actions.list.ListSampleResourceAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceTransportAction; +import org.opensearch.security.spi.ResourceSharingUtils; import org.opensearch.threadpool.ThreadPool; import org.opensearch.watcher.ResourceWatcherService; @@ -75,6 +76,7 @@ public Collection createComponents( Supplier repositoriesServiceSupplier ) { this.client = client; + ResourceSharingUtils.getInstance().initialize(threadPool, client); return Collections.emptyList(); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java similarity index 69% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java rename to spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java index 9ed643d4a9..8d398fd64f 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/ResourceSharingUtils.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java @@ -1,9 +1,8 @@ -package org.opensearch.security.sampleextension.resource; +package org.opensearch.security.spi; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.opensearch.OpenSearchSecurityException; import org.opensearch.action.admin.indices.create.CreateIndexRequest; import org.opensearch.action.admin.indices.create.CreateIndexResponse; import org.opensearch.client.Client; @@ -18,22 +17,31 @@ public class ResourceSharingUtils { public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; + private boolean initialized; private ThreadPool threadPool; + private Client client; private ResourceSharingUtils() {} - // Public method to provide access to the singleton instance public static ResourceSharingUtils getInstance() { return ResourceSharingUtils.INSTANCE; } public void initialize(ThreadPool threadPool, Client client) { - if (this.threadPool != null) { - throw new OpenSearchSecurityException("ResourceSharingUtils can only be initialized once."); + if (initialized) { + return; } + initialized = true; this.threadPool = threadPool; + this.client = client; + } + + public boolean isInitialized() { + return initialized; + } - try (ThreadContext.StoredContext ctx = threadPool.getThreadContext().stashContext()) { + private void createResourceSharingIndexIfNotExists() { + try (ThreadContext.StoredContext ctx = this.threadPool.getThreadContext().stashContext()) { CreateIndexRequest cir = new CreateIndexRequest(RESOURCE_SHARING_INDEX); ActionListener cirListener = ActionListener.wrap( response -> { log.info(RESOURCE_SHARING_INDEX + " created."); }, @@ -42,7 +50,12 @@ public void initialize(ThreadPool threadPool, Client client) { log.info(RESOURCE_SHARING_INDEX + " exists."); } ); - client.admin().indices().create(cir, cirListener); + this.client.admin().indices().create(cir, cirListener); } } + + public boolean indexResourceSharing(Resource resource) { + createResourceSharingIndexIfNotExists(); + return true; + } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java index 5fbab4c4f9..0c7230cb9f 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java @@ -26,6 +26,7 @@ import org.opensearch.core.common.io.stream.Writeable; import org.opensearch.core.xcontent.ToXContent; import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ResourceSharingUtils; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -75,6 +76,7 @@ protected void doExecute(Task task, CreateResourceRequest request, ActionList private void createResource(CreateResourceRequest request, ActionListener listener) { log.warn("Sample name: " + request.getResource()); Resource sample = request.getResource(); + ResourceSharingUtils.getInstance().indexResourceSharing(sample); try { IndexRequest ir = nodeClient.prepareIndex(resourceIndex) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 509b98f12e..c5af70b99b 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -178,6 +178,7 @@ import org.opensearch.security.securityconf.DynamicConfigFactory; import org.opensearch.security.setting.OpensearchDynamicSetting; import org.opensearch.security.setting.TransportPassiveAuthSetting; +import org.opensearch.security.spi.ResourceSharingUtils; import org.opensearch.security.ssl.ExternalSecurityKeyStore; import org.opensearch.security.ssl.OpenSearchSecureSettingsFactory; import org.opensearch.security.ssl.OpenSearchSecuritySSLPlugin; @@ -1056,6 +1057,8 @@ public Collection createComponents( return components; } + ResourceSharingUtils.getInstance().initialize(threadPool, localClient); + // Register opensearch dynamic settings transportPassiveAuthSetting.registerClusterSettingsChangeListener(clusterService.getClusterSettings()); From 5cf03159b3a0b7c453faf0bf4269ea415e7dda44 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 15 Aug 2024 22:08:10 -0400 Subject: [PATCH 16/80] Create .resource-sharing entry Signed-off-by: Craig Perkins --- .../ListSampleResourceTransportAction.java | 4 +- .../org/opensearch/security/spi/Resource.java | 4 +- .../security/spi/ResourceSharingEntry.java | 27 ++++++++++ .../security/spi/ResourceSharingUtils.java | 53 +++++++++++++++---- .../opensearch/security/spi/ShareWith.java | 40 ++++++++++++++ .../CreateResourceTransportAction.java | 15 +++++- 6 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceSharingEntry.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/ShareWith.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java index 8f102eef14..8160fe2854 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java @@ -21,8 +21,6 @@ import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; -import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; - /** * Transport action for ListSampleResource. */ @@ -40,7 +38,7 @@ public ListSampleResourceTransportAction(TransportService transportService, Acti @Override protected void doExecute(Task task, ListSampleResourceRequest request, ActionListener listener) { try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { - SearchRequest sr = new SearchRequest(RESOURCE_INDEX_NAME); + SearchRequest sr = new SearchRequest(".resource-sharing"); SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); matchAllQuery.query(new MatchAllQueryBuilder()); sr.source(matchAllQuery); diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java index 39482b4232..98d2b9958d 100644 --- a/spi/src/main/java/org/opensearch/security/spi/Resource.java +++ b/spi/src/main/java/org/opensearch/security/spi/Resource.java @@ -3,4 +3,6 @@ import org.opensearch.core.common.io.stream.NamedWriteable; import org.opensearch.core.xcontent.ToXContentFragment; -public abstract class Resource implements NamedWriteable, ToXContentFragment {} +public abstract class Resource implements NamedWriteable, ToXContentFragment { + protected abstract String getResourceIndex(); +} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingEntry.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingEntry.java new file mode 100644 index 0000000000..dc3df82c75 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingEntry.java @@ -0,0 +1,27 @@ +package org.opensearch.security.spi; + +import java.io.IOException; + +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; + +public class ResourceSharingEntry implements ToXContentFragment { + private final String resourceIndex; + private final String resourceId; + private final ShareWith shareWith; + + public ResourceSharingEntry(String resourceIndex, String resourceId, ShareWith shareWith) { + this.resourceIndex = resourceIndex; + this.resourceId = resourceId; + this.shareWith = shareWith; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject() + .field("resource_index", resourceIndex) + .field("resource_id", resourceId) + .field("share_with", shareWith) + .endObject(); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java index 8d398fd64f..3cd81eccde 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java @@ -1,15 +1,24 @@ package org.opensearch.security.spi; +import java.io.IOException; +import java.util.concurrent.Callable; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.opensearch.action.admin.indices.create.CreateIndexRequest; import org.opensearch.action.admin.indices.create.CreateIndexResponse; +import org.opensearch.action.index.IndexRequest; +import org.opensearch.action.index.IndexResponse; +import org.opensearch.action.support.WriteRequest; import org.opensearch.client.Client; import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; +import org.opensearch.core.xcontent.ToXContent; import org.opensearch.threadpool.ThreadPool; +import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; + public class ResourceSharingUtils { private final static Logger log = LogManager.getLogger(ResourceSharingUtils.class); @@ -40,22 +49,48 @@ public boolean isInitialized() { return initialized; } - private void createResourceSharingIndexIfNotExists() { + private void createResourceSharingIndexIfNotExists(Callable callable) { try (ThreadContext.StoredContext ctx = this.threadPool.getThreadContext().stashContext()) { CreateIndexRequest cir = new CreateIndexRequest(RESOURCE_SHARING_INDEX); - ActionListener cirListener = ActionListener.wrap( - response -> { log.info(RESOURCE_SHARING_INDEX + " created."); }, - (failResponse) -> { - /* Index already exists, ignore and continue */ - log.info(RESOURCE_SHARING_INDEX + " exists."); + ActionListener cirListener = ActionListener.wrap(response -> { + log.warn(RESOURCE_SHARING_INDEX + " created."); + callable.call(); + }, (failResponse) -> { + /* Index already exists, ignore and continue */ + log.warn(RESOURCE_SHARING_INDEX + " exists."); + try { + callable.call(); + } catch (Exception e) { + throw new RuntimeException(e); } - ); + }); this.client.admin().indices().create(cir, cirListener); } } - public boolean indexResourceSharing(Resource resource) { - createResourceSharingIndexIfNotExists(); + public boolean indexResourceSharing(String resourceId, Resource resource, ShareWith shareWith, ActionListener listener) + throws IOException { + createResourceSharingIndexIfNotExists(() -> { + ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, shareWith); + + IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) + .request(); + + log.warn("Index Request: " + ir.toString()); + + ActionListener irListener = ActionListener.wrap(idxResponse -> { + log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); + listener.onResponse(idxResponse); + }, (failResponse) -> { + log.error(failResponse.getMessage()); + log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); + listener.onFailure(failResponse); + }); + client.index(ir, irListener); + return null; + }); return true; } } diff --git a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java new file mode 100644 index 0000000000..c594310887 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java @@ -0,0 +1,40 @@ +package org.opensearch.security.spi; + +import java.io.IOException; +import java.util.List; + +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; + +public class ShareWith implements ToXContentFragment { + + public final static ShareWith PRIVATE = new ShareWith(List.of(), List.of(), List.of()); + public final static ShareWith PUBLIC = new ShareWith(List.of("*"), List.of("*"), List.of("*")); + + private final List users; + private final List roles; + private final List backendRoles; + + public ShareWith(List users, List roles, List backendRoles) { + this.users = users; + this.roles = roles; + this.backendRoles = backendRoles; + } + + public List getUsers() { + return users; + } + + public List getRoles() { + return roles; + } + + public List getBackendRoles() { + return backendRoles; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject().field("users", users).field("roles", roles).field("backendRoles", backendRoles).endObject(); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java index 0c7230cb9f..b445e42056 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java @@ -27,6 +27,7 @@ import org.opensearch.core.xcontent.ToXContent; import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceSharingUtils; +import org.opensearch.security.spi.ShareWith; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -76,7 +77,6 @@ protected void doExecute(Task task, CreateResourceRequest request, ActionList private void createResource(CreateResourceRequest request, ActionListener listener) { log.warn("Sample name: " + request.getResource()); Resource sample = request.getResource(); - ResourceSharingUtils.getInstance().indexResourceSharing(sample); try { IndexRequest ir = nodeClient.prepareIndex(resourceIndex) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) @@ -85,8 +85,19 @@ private void createResource(CreateResourceRequest request, ActionListener resourceSharingListener = ActionListener.wrap(resourceSharingResponse -> { + listener.onResponse(new CreateResourceResponse("Created resource: " + resourceSharingResponse.toString())); + }, listener::onFailure); + ActionListener irListener = ActionListener.wrap(idxResponse -> { - listener.onResponse(new CreateResourceResponse("Created resource: " + idxResponse.toString())); + // TODO Make sure security is an IndexOperationListener and automatically create entry in .resource-sharing + // and set to private + + // Idea, if not entry in .resource-sharing then assume private? Maybe its not necessary to be an IndexOperationListener + log.info("Created resource: " + idxResponse.toString()); + ResourceSharingUtils.getInstance() + .indexResourceSharing(idxResponse.getId(), sample, ShareWith.PUBLIC, resourceSharingListener); + // listener.onResponse(new CreateResourceResponse("Created resource: " + idxResponse.toString())); }, listener::onFailure); nodeClient.index(ir, irListener); } catch (IOException e) { From fb23e6ba9da2572619b72ecbb25f7c36f390de95 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 15 Aug 2024 22:54:18 -0400 Subject: [PATCH 17/80] Truly singleton Signed-off-by: Craig Perkins --- sample-extension-plugin/build.gradle | 20 +++++++++---------- .../plugin-metadata/plugin-security.policy | 3 +++ .../security/spi/ResourceSharingUtils.java | 12 +++++++++-- 3 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 sample-extension-plugin/src/main/plugin-metadata/plugin-security.policy diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle index 7420afb315..1920e21dff 100644 --- a/sample-extension-plugin/build.gradle +++ b/sample-extension-plugin/build.gradle @@ -176,13 +176,13 @@ run { // The security zip is added explicitly above but the sample-extension-plugin is added implicitly at some time during evaluation. // Will need to do a deep dive to find out exactly what task adds the sample-extension-plugin and add security there but a temporary hack is to // reorder the plugins list after evaluation but prior to task execution when the plugins are installed. -afterEvaluate { - testClusters.javaRestTest.nodes.each { node -> - def nodePlugins = node.plugins - def firstPlugin = nodePlugins.get(0) - if (firstPlugin.provider == project.bundlePlugin.archiveFile) { - nodePlugins.remove(0) - nodePlugins.add(firstPlugin) - } - } -} +//afterEvaluate { +// testClusters.javaRestTest.nodes.each { node -> +// def nodePlugins = node.plugins +// def firstPlugin = nodePlugins.get(0) +// if (firstPlugin.provider == project.bundlePlugin.archiveFile) { +// nodePlugins.remove(0) +// nodePlugins.add(firstPlugin) +// } +// } +//} diff --git a/sample-extension-plugin/src/main/plugin-metadata/plugin-security.policy b/sample-extension-plugin/src/main/plugin-metadata/plugin-security.policy new file mode 100644 index 0000000000..a5dfc33a87 --- /dev/null +++ b/sample-extension-plugin/src/main/plugin-metadata/plugin-security.policy @@ -0,0 +1,3 @@ +grant { + permission java.lang.RuntimePermission "getClassLoader"; +}; \ No newline at end of file diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java index 3cd81eccde..46f4e0c9ff 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java @@ -1,7 +1,11 @@ package org.opensearch.security.spi; import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Map; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -22,7 +26,7 @@ public class ResourceSharingUtils { private final static Logger log = LogManager.getLogger(ResourceSharingUtils.class); - private static final ResourceSharingUtils INSTANCE = new ResourceSharingUtils(); + private static final Map instances = new ConcurrentHashMap<>(); public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; @@ -33,7 +37,11 @@ public class ResourceSharingUtils { private ResourceSharingUtils() {} public static ResourceSharingUtils getInstance() { - return ResourceSharingUtils.INSTANCE; + ClassLoader classLoader = AccessController.doPrivileged( + (PrivilegedAction) () -> Thread.currentThread().getContextClassLoader() + ); + instances.computeIfAbsent(classLoader, cl -> new ResourceSharingUtils()); + return instances.get(classLoader); } public void initialize(ThreadPool threadPool, Client client) { From 233f3995b3651994d3fe79b447cc388241ba6a4d Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 16 Aug 2024 12:16:54 -0400 Subject: [PATCH 18/80] IndexOperationListener Signed-off-by: Craig Perkins --- sample-extension-plugin/build.gradle | 4 ++-- .../create/CreateSampleResourceRequest.java | 1 - .../CreateSampleResourceRestAction.java | 4 ++-- .../CreateSampleResourceTransportAction.java | 1 - .../create}/SampleResource.java | 14 +++++++------ ...arch.security.spi.ResourceSharingExtension | 2 +- .../security/spi/ResourceSharingUtils.java | 16 ++++++++++++++- .../security/OpenSearchSecurityPlugin.java | 20 ++++++++++++++++++- 8 files changed, 47 insertions(+), 15 deletions(-) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/{resource => actions/create}/SampleResource.java (84%) diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle index 1920e21dff..374e2978e9 100644 --- a/sample-extension-plugin/build.gradle +++ b/sample-extension-plugin/build.gradle @@ -18,7 +18,7 @@ opensearchplugin { name 'opensearch-security-sample-extension' description 'Sample plugin that extends OpenSearch Security Resource Sharing plugin' classname 'org.opensearch.security.sampleextension.SampleExtensionPlugin' - // extendedPlugins = ['opensearch-security'] + extendedPlugins = ['opensearch-security'] } ext { @@ -34,7 +34,7 @@ repositories { } dependencies { - implementation project(path: ":${rootProject.name}-spi", configuration: 'shadow') + compileOnly project(path: ":${rootProject.name}-spi", configuration: 'shadow') } def es_tmp_dir = rootProject.file('build/private/es_tmp').absoluteFile diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java index c5e1ef8166..aaeb92c640 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java @@ -14,7 +14,6 @@ import org.opensearch.action.ActionRequestValidationException; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.Resource; /** diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java index d7cdf0df1b..72b582a508 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java @@ -17,7 +17,6 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; -import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.actions.CreateResourceRequest; import static java.util.Collections.singletonList; @@ -45,7 +44,8 @@ public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client } String name = (String) source.get("name"); - SampleResource resource = new SampleResource(name); + SampleResource resource = new SampleResource(); + resource.setName(name); final CreateResourceRequest createSampleResourceRequest = new CreateResourceRequest<>(resource); return channel -> client.executeLocally( CreateSampleResourceAction.INSTANCE, diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index f4b2a90fa0..d62cb7f35a 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -14,7 +14,6 @@ import org.opensearch.action.support.ActionFilters; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; -import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.actions.CreateResourceTransportAction; import org.opensearch.transport.TransportService; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java similarity index 84% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java index 4b21953f83..7cff71bdff 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java @@ -1,4 +1,4 @@ -package org.opensearch.security.sampleextension.resource; +package org.opensearch.security.sampleextension.actions.create; import java.io.IOException; @@ -12,13 +12,11 @@ public class SampleResource extends Resource implements ResourceSharingExtension { - private final String name; + private String name; - public SampleResource(String name) { - this.name = name; - } + public SampleResource() {} - public SampleResource(StreamInput in) throws IOException { + SampleResource(StreamInput in) throws IOException { this.name = in.readString(); } @@ -46,4 +44,8 @@ public void writeTo(StreamOutput streamOutput) throws IOException { public String getWriteableName() { return "sampled_resource"; } + + public void setName(String name) { + this.name = name; + } } diff --git a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension index 904fb99e99..8be61d03af 100644 --- a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension +++ b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension @@ -3,4 +3,4 @@ # SPDX-License-Identifier: Apache-2.0 # -org.opensearch.security.sampleextension.resource.SampleResource \ No newline at end of file +org.opensearch.security.sampleextension.actions.create.SampleResource \ No newline at end of file diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java index 46f4e0c9ff..3c8ba1992e 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java @@ -18,12 +18,15 @@ import org.opensearch.client.Client; import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; +import org.opensearch.core.index.shard.ShardId; import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.index.engine.Engine; +import org.opensearch.index.shard.IndexingOperationListener; import org.opensearch.threadpool.ThreadPool; import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; -public class ResourceSharingUtils { +public class ResourceSharingUtils implements IndexingOperationListener { private final static Logger log = LogManager.getLogger(ResourceSharingUtils.class); private static final Map instances = new ConcurrentHashMap<>(); @@ -101,4 +104,15 @@ public boolean indexResourceSharing(String resourceId, Resource resource, ShareW }); return true; } + + @Override + public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult result) { + log.warn("postIndex called on " + shardId.getIndexName()); + + } + + @Override + public void postDelete(ShardId shardId, Engine.Delete delete, Engine.DeleteResult result) { + log.warn("postDelete called on " + shardId.getIndexName()); + } } diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index c5af70b99b..96ecb3cd2c 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -116,6 +116,7 @@ import org.opensearch.indices.IndicesService; import org.opensearch.indices.SystemIndexDescriptor; import org.opensearch.plugins.ClusterPlugin; +import org.opensearch.plugins.ExtensiblePlugin; import org.opensearch.plugins.ExtensionAwarePlugin; import org.opensearch.plugins.IdentityPlugin; import org.opensearch.plugins.MapperPlugin; @@ -178,6 +179,7 @@ import org.opensearch.security.securityconf.DynamicConfigFactory; import org.opensearch.security.setting.OpensearchDynamicSetting; import org.opensearch.security.setting.TransportPassiveAuthSetting; +import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.spi.ResourceSharingUtils; import org.opensearch.security.ssl.ExternalSecurityKeyStore; import org.opensearch.security.ssl.OpenSearchSecureSettingsFactory; @@ -229,6 +231,7 @@ public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin ClusterPlugin, MapperPlugin, // CS-SUPPRESS-SINGLE: RegexpSingleline get Extensions Settings + ExtensiblePlugin, ExtensionAwarePlugin, IdentityPlugin // CS-ENFORCE-SINGLE @@ -266,6 +269,7 @@ public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin private volatile Salt salt; private volatile OpensearchDynamicSetting transportPassiveAuthSetting; private volatile PasswordHasher passwordHasher; + private final Set indicesToListen = new HashSet<>(); public static boolean isActionTraceEnabled() { @@ -705,6 +709,10 @@ public void onIndexModule(IndexModule indexModule) { salt ) ); + if (this.indicesToListen.contains(indexModule.getIndex().getName())) { + indexModule.addIndexOperationListener(ResourceSharingUtils.getInstance()); + log.warn("Security started listening to operations on index {}", indexModule.getIndex().getName()); + } indexModule.forceQueryCacheProvider((indexSettings, nodeCache) -> new QueryCache() { @Override @@ -1029,7 +1037,6 @@ public Collection createComponents( IndexNameExpressionResolver indexNameExpressionResolver, Supplier repositoriesServiceSupplier ) { - SSLConfig.registerClusterSettingsChangeListener(clusterService.getClusterSettings()); if (SSLConfig.isSslOnlyMode()) { return super.createComponents( @@ -2120,6 +2127,17 @@ public Optional getSecureSettingFactory(Settings settings return Optional.of(new OpenSearchSecureSettingsFactory(threadPool, sks, sslExceptionHandler, securityRestHandler)); } + // CS-SUPPRESS-SINGLE: RegexpSingleline SPI Extensions are unrelated to OpenSearch extensions + @Override + public void loadExtensions(ExtensiblePlugin.ExtensionLoader loader) { + for (ResourceSharingExtension extension : loader.loadExtensions(ResourceSharingExtension.class)) { + String resourceIndexName = extension.getResourceIndex(); + this.indicesToListen.add(resourceIndexName); + log.warn("Loaded resource, index: {}", resourceIndexName); + } + } + // CS-ENFORCE-SINGLE + @SuppressWarnings("removal") private void tryAddSecurityProvider() { final SecurityManager sm = System.getSecurityManager(); From 7c44fac2eb66189e99d39cd54a75d9ada226a82d Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 19 Aug 2024 15:43:37 -0400 Subject: [PATCH 19/80] WIP Signed-off-by: Craig Perkins --- .../security/spi/ResourceSharingUtils.java | 16 +----- .../security/OpenSearchSecurityPlugin.java | 3 +- .../resource/ResourceSharingListener.java | 52 +++++++++++++++++++ .../security/user/UserFragment.java | 23 ++++++++ 4 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 src/main/java/org/opensearch/security/resource/ResourceSharingListener.java create mode 100644 src/main/java/org/opensearch/security/user/UserFragment.java diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java index 3c8ba1992e..46f4e0c9ff 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java @@ -18,15 +18,12 @@ import org.opensearch.client.Client; import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; -import org.opensearch.core.index.shard.ShardId; import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.index.engine.Engine; -import org.opensearch.index.shard.IndexingOperationListener; import org.opensearch.threadpool.ThreadPool; import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; -public class ResourceSharingUtils implements IndexingOperationListener { +public class ResourceSharingUtils { private final static Logger log = LogManager.getLogger(ResourceSharingUtils.class); private static final Map instances = new ConcurrentHashMap<>(); @@ -104,15 +101,4 @@ public boolean indexResourceSharing(String resourceId, Resource resource, ShareW }); return true; } - - @Override - public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult result) { - log.warn("postIndex called on " + shardId.getIndexName()); - - } - - @Override - public void postDelete(ShardId shardId, Engine.Delete delete, Engine.DeleteResult result) { - log.warn("postDelete called on " + shardId.getIndexName()); - } } diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 96ecb3cd2c..94a52b1d91 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -170,6 +170,7 @@ import org.opensearch.security.privileges.PrivilegesInterceptor; import org.opensearch.security.privileges.RestLayerPrivilegesEvaluator; import org.opensearch.security.resolver.IndexResolverReplacer; +import org.opensearch.security.resource.ResourceSharingListener; import org.opensearch.security.rest.DashboardsInfoAction; import org.opensearch.security.rest.SecurityConfigUpdateAction; import org.opensearch.security.rest.SecurityHealthAction; @@ -710,7 +711,7 @@ public void onIndexModule(IndexModule indexModule) { ) ); if (this.indicesToListen.contains(indexModule.getIndex().getName())) { - indexModule.addIndexOperationListener(ResourceSharingUtils.getInstance()); + indexModule.addIndexOperationListener(ResourceSharingListener.getInstance()); log.warn("Security started listening to operations on index {}", indexModule.getIndex().getName()); } indexModule.forceQueryCacheProvider((indexSettings, nodeCache) -> new QueryCache() { diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java new file mode 100644 index 0000000000..ca54e99310 --- /dev/null +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -0,0 +1,52 @@ +package org.opensearch.security.resource; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.client.Client; +import org.opensearch.core.index.shard.ShardId; +import org.opensearch.index.engine.Engine; +import org.opensearch.index.shard.IndexingOperationListener; +import org.opensearch.threadpool.ThreadPool; + +public class ResourceSharingListener implements IndexingOperationListener { + private final static Logger log = LogManager.getLogger(ResourceSharingListener.class); + + private static final ResourceSharingListener INSTANCE = new ResourceSharingListener(); + + private boolean initialized; + private ThreadPool threadPool; + private Client client; + + private ResourceSharingListener() {} + + public static ResourceSharingListener getInstance() { + return ResourceSharingListener.INSTANCE; + } + + public void initialize(ThreadPool threadPool, Client client) { + if (initialized) { + return; + } + initialized = true; + this.threadPool = threadPool; + this.client = client; + } + + public boolean isInitialized() { + return initialized; + } + + @Override + public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult result) { + log.warn("postIndex called on " + shardId.getIndexName()); + String resourceId = index.id(); + String resourceIndex = shardId.getIndexName(); + + } + + @Override + public void postDelete(ShardId shardId, Engine.Delete delete, Engine.DeleteResult result) { + log.warn("postDelete called on " + shardId.getIndexName()); + } +} diff --git a/src/main/java/org/opensearch/security/user/UserFragment.java b/src/main/java/org/opensearch/security/user/UserFragment.java new file mode 100644 index 0000000000..d42413e589 --- /dev/null +++ b/src/main/java/org/opensearch/security/user/UserFragment.java @@ -0,0 +1,23 @@ +package org.opensearch.security.user; + +import java.io.IOException; + +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; + +public class UserFragment implements ToXContentFragment { + private final User user; + + public UserFragment(User user) { + this.user = user; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject() + .field("username", user.getName()) + .field("roles", user.getSecurityRoles()) + .field("backend_roles", user.getRoles()) + .endObject(); + } +} From db678cc212e94f188d4c2c4d2337d51d328373cb Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 20 Sep 2024 12:04:42 -0400 Subject: [PATCH 20/80] Fix build issues Signed-off-by: Craig Perkins --- spi/build.gradle | 2 +- .../security/resource/ResourceSharingListener.java | 11 +++++++++++ .../org/opensearch/security/user/UserFragment.java | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/spi/build.gradle b/spi/build.gradle index d36704609e..a0613e5226 100644 --- a/spi/build.gradle +++ b/spi/build.gradle @@ -11,7 +11,7 @@ plugins { id 'jacoco' id 'maven-publish' id 'signing' - id "org.gradle.test-retry" version "1.5.10" + id "org.gradle.test-retry" version "1.6.0" } apply plugin: 'opensearch.java' diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java index ca54e99310..bdf333a844 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -1,3 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + package org.opensearch.security.resource; import org.apache.logging.log4j.LogManager; diff --git a/src/main/java/org/opensearch/security/user/UserFragment.java b/src/main/java/org/opensearch/security/user/UserFragment.java index d42413e589..b0c9164404 100644 --- a/src/main/java/org/opensearch/security/user/UserFragment.java +++ b/src/main/java/org/opensearch/security/user/UserFragment.java @@ -1,3 +1,14 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + package org.opensearch.security.user; import java.io.IOException; From a57d283ecb18fec5687d6769f09baf099dba5620 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 14 Oct 2024 15:16:54 -0400 Subject: [PATCH 21/80] WIP on ResourceSharingListener Signed-off-by: Craig Perkins --- checkstyle/checkstyle.xml | 12 ++++----- .../actions/create/SampleResource.java | 2 +- .../SampleExtensionPluginIT.java | 17 +++++++++++- .../security/spi/ResourceSharingUtils.java | 26 +++++++++++++++++-- .../CreateResourceTransportAction.java | 18 +++++-------- .../security/OpenSearchSecurityPlugin.java | 1 + .../resource/ResourceSharingListener.java | 13 +++++++++- 7 files changed, 66 insertions(+), 23 deletions(-) diff --git a/checkstyle/checkstyle.xml b/checkstyle/checkstyle.xml index 04a36c49c1..cca6cdfd81 100644 --- a/checkstyle/checkstyle.xml +++ b/checkstyle/checkstyle.xml @@ -198,12 +198,12 @@ - - - - - - + + + + + + diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java index 7cff71bdff..f01409af77 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java @@ -42,7 +42,7 @@ public void writeTo(StreamOutput streamOutput) throws IOException { @Override public String getWriteableName() { - return "sampled_resource"; + return "sample_resource"; } public void setName(String name) { diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 9b418eeb04..a108b67ddd 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -43,7 +43,7 @@ public void testPluginsAreInstalled() throws IOException { ); } - public void testCreateSampleResource() throws IOException { + public void testCreateSampleResource() throws IOException, InterruptedException { Request createRequest = new Request("POST", "/_plugins/resource_sharing_example/resource"); createRequest.setEntity(new StringEntity("{\"name\":\"Craig\"}")); RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder(); @@ -57,6 +57,9 @@ public void testCreateSampleResource() throws IOException { ).mapStrings(); System.out.println("createResourceResponse: " + createResourceResponse); + // Sleep to give ResourceSharingListener time to create the .resource-sharing index + Thread.sleep(1000); + Request listRequest = new Request("GET", "/_plugins/resource_sharing_example/resource"); RequestOptions.Builder listRequestOptions = RequestOptions.DEFAULT.toBuilder(); requestOptions.setWarningsHandler((warnings) -> false); @@ -68,5 +71,17 @@ public void testCreateSampleResource() throws IOException { listResponse.getEntity().getContent() ).mapStrings(); System.out.println("listResourceResponse: " + listResourceResponse); + + Request resourceSharingRequest = new Request("POST", "/.resource-sharing/_search"); + RequestOptions.Builder resourceSharingRequestOptions = RequestOptions.DEFAULT.toBuilder(); + requestOptions.setWarningsHandler((warnings) -> false); + resourceSharingRequest.setOptions(resourceSharingRequestOptions); + Response resourceSharingResponse = adminClient().performRequest(resourceSharingRequest); + Map resourceSharingResponseMap = JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + resourceSharingResponse.getEntity().getContent() + ).map(); + System.out.println("resourceSharingResponse: " + resourceSharingResponseMap); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java index 46f4e0c9ff..2a006dcfd5 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java @@ -76,7 +76,7 @@ private void createResourceSharingIndexIfNotExists(Callable callable) { } } - public boolean indexResourceSharing(String resourceId, Resource resource, ShareWith shareWith, ActionListener listener) + public void indexResourceSharing(String resourceId, Resource resource, ShareWith shareWith, ActionListener listener) throws IOException { createResourceSharingIndexIfNotExists(() -> { ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, shareWith); @@ -99,6 +99,28 @@ public boolean indexResourceSharing(String resourceId, Resource resource, ShareW client.index(ir, irListener); return null; }); - return true; + } + + public void indexResourceSharing(String resourceId, String resourceIndex, ShareWith shareWith) throws IOException { + createResourceSharingIndexIfNotExists(() -> { + ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, shareWith); + + IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) + .request(); + + log.warn("Index Request: " + ir.toString()); + + ActionListener irListener = ActionListener.wrap( + idxResponse -> { log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); }, + (failResponse) -> { + log.error(failResponse.getMessage()); + log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); + } + ); + client.index(ir, irListener); + return null; + }); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java index b445e42056..c35ebc1c2f 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java @@ -26,8 +26,6 @@ import org.opensearch.core.common.io.stream.Writeable; import org.opensearch.core.xcontent.ToXContent; import org.opensearch.security.spi.Resource; -import org.opensearch.security.spi.ResourceSharingUtils; -import org.opensearch.security.spi.ShareWith; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -85,19 +83,15 @@ private void createResource(CreateResourceRequest request, ActionListener resourceSharingListener = ActionListener.wrap(resourceSharingResponse -> { - listener.onResponse(new CreateResourceResponse("Created resource: " + resourceSharingResponse.toString())); - }, listener::onFailure); + // ActionListener resourceSharingListener = ActionListener.wrap(resourceSharingResponse -> { + // listener.onResponse(new CreateResourceResponse("Created resource: " + resourceSharingResponse.toString())); + // }, listener::onFailure); ActionListener irListener = ActionListener.wrap(idxResponse -> { - // TODO Make sure security is an IndexOperationListener and automatically create entry in .resource-sharing - // and set to private - - // Idea, if not entry in .resource-sharing then assume private? Maybe its not necessary to be an IndexOperationListener log.info("Created resource: " + idxResponse.toString()); - ResourceSharingUtils.getInstance() - .indexResourceSharing(idxResponse.getId(), sample, ShareWith.PUBLIC, resourceSharingListener); - // listener.onResponse(new CreateResourceResponse("Created resource: " + idxResponse.toString())); + // ResourceSharingUtils.getInstance() + // .indexResourceSharing(idxResponse.getId(), sample, ShareWith.PUBLIC, resourceSharingListener); + listener.onResponse(new CreateResourceResponse("Created resource: " + idxResponse.toString())); }, listener::onFailure); nodeClient.index(ir, irListener); } catch (IOException e) { diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index aa21c0c6c2..1a5a823f8e 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -2186,6 +2186,7 @@ public void loadExtensions(ExtensiblePlugin.ExtensionLoader loader) { for (ResourceSharingExtension extension : loader.loadExtensions(ResourceSharingExtension.class)) { String resourceIndexName = extension.getResourceIndex(); this.indicesToListen.add(resourceIndexName); + System.out.println("Loaded resource, index: " + resourceIndexName); log.warn("Loaded resource, index: {}", resourceIndexName); } } diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java index bdf333a844..e7c164ee4b 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -11,6 +11,8 @@ package org.opensearch.security.resource; +import java.io.IOException; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -18,6 +20,8 @@ import org.opensearch.core.index.shard.ShardId; import org.opensearch.index.engine.Engine; import org.opensearch.index.shard.IndexingOperationListener; +import org.opensearch.security.spi.ResourceSharingUtils; +import org.opensearch.security.spi.ShareWith; import org.opensearch.threadpool.ThreadPool; public class ResourceSharingListener implements IndexingOperationListener { @@ -53,7 +57,14 @@ public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult re log.warn("postIndex called on " + shardId.getIndexName()); String resourceId = index.id(); String resourceIndex = shardId.getIndexName(); - + System.out.println("postIndex called on " + shardId.getIndexName()); + System.out.println("resourceId: " + resourceId); + System.out.println("resourceIndex: " + resourceIndex); + try { + ResourceSharingUtils.getInstance().indexResourceSharing(resourceId, resourceIndex, ShareWith.PRIVATE); + } catch (IOException e) { + throw new RuntimeException(e); + } } @Override From 56b0c36850558bcbe2fa972f57a8ed4056770e8b Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 14 Oct 2024 16:20:47 -0400 Subject: [PATCH 22/80] Test create with 2 different users Signed-off-by: Craig Perkins --- .../SampleExtensionPluginIT.java | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index a108b67ddd..71b0be437f 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -9,6 +9,8 @@ package org.opensearch.security.sampleextension; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.List; import java.util.Map; @@ -24,6 +26,13 @@ public class SampleExtensionPluginIT extends ODFERestTestCase { + // @BeforeClass + // public static void createTestUsers() throws IOException { + // Request createUserRequest = new Request("POST", "/_opendistro/_security/api/internalusers/craig"); + // createUserRequest.setJsonEntity("{\"password\":\"changeme\",\"roles\":[\"all_access\"]}"); + // client().performRequest(createUserRequest); + // } + @SuppressWarnings("unchecked") public void testPluginsAreInstalled() throws IOException { Request request = new Request("GET", "/_cat/plugins?s=component&h=name,component,version,description&format=json"); @@ -44,10 +53,16 @@ public void testPluginsAreInstalled() throws IOException { } public void testCreateSampleResource() throws IOException, InterruptedException { - Request createRequest = new Request("POST", "/_plugins/resource_sharing_example/resource"); - createRequest.setEntity(new StringEntity("{\"name\":\"Craig\"}")); + String strongPassword = "myStrongPassword123!"; + Request createUserRequest = new Request("PUT", "/_opendistro/_security/api/internalusers/craig"); + createUserRequest.setJsonEntity("{\"password\":\"" + strongPassword + "\",\"opendistro_security_roles\":[\"all_access\"]}"); + client().performRequest(createUserRequest); + RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder(); requestOptions.setWarningsHandler((warnings) -> false); + + Request createRequest = new Request("POST", "/_plugins/resource_sharing_example/resource"); + createRequest.setEntity(new StringEntity("{\"name\":\"ExampleResource1\"}")); createRequest.setOptions(requestOptions); Response response = client().performRequest(createRequest); Map createResourceResponse = JsonXContent.jsonXContent.createParser( @@ -57,13 +72,25 @@ public void testCreateSampleResource() throws IOException, InterruptedException ).mapStrings(); System.out.println("createResourceResponse: " + createResourceResponse); + Request createRequest2 = new Request("POST", "/_plugins/resource_sharing_example/resource"); + createRequest2.setEntity(new StringEntity("{\"name\":\"ExampleResource2\"}")); + RequestOptions.Builder requestOptions2 = RequestOptions.DEFAULT.toBuilder(); + requestOptions2.setWarningsHandler((warnings) -> false); + requestOptions2.addHeader("Authorization", Base64.getEncoder().encodeToString(strongPassword.getBytes(StandardCharsets.UTF_8))); + createRequest2.setOptions(requestOptions2); + Response response2 = client().performRequest(createRequest); + Map createResourceResponse2 = JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + response.getEntity().getContent() + ).mapStrings(); + System.out.println("createResourceResponse2: " + createResourceResponse2); + // Sleep to give ResourceSharingListener time to create the .resource-sharing index Thread.sleep(1000); Request listRequest = new Request("GET", "/_plugins/resource_sharing_example/resource"); - RequestOptions.Builder listRequestOptions = RequestOptions.DEFAULT.toBuilder(); - requestOptions.setWarningsHandler((warnings) -> false); - listRequest.setOptions(listRequestOptions); + listRequest.setOptions(requestOptions); Response listResponse = client().performRequest(listRequest); Map listResourceResponse = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, @@ -73,9 +100,7 @@ public void testCreateSampleResource() throws IOException, InterruptedException System.out.println("listResourceResponse: " + listResourceResponse); Request resourceSharingRequest = new Request("POST", "/.resource-sharing/_search"); - RequestOptions.Builder resourceSharingRequestOptions = RequestOptions.DEFAULT.toBuilder(); - requestOptions.setWarningsHandler((warnings) -> false); - resourceSharingRequest.setOptions(resourceSharingRequestOptions); + resourceSharingRequest.setOptions(requestOptions); Response resourceSharingResponse = adminClient().performRequest(resourceSharingRequest); Map resourceSharingResponseMap = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, From 90daa1870618a93e8ebb698e931fc448d6468170 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 14 Oct 2024 16:55:16 -0400 Subject: [PATCH 23/80] Add resourceUser to ResourceSharingEntry Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 2 -- .../SampleExtensionPluginIT.java | 11 ++++--- .../org/opensearch/security/spi/Resource.java | 2 +- .../opensearch/security/spi/ShareWith.java | 2 +- .../security/OpenSearchSecurityPlugin.java | 3 +- .../security/auth/BackendRegistry.java | 10 +++++- .../resource}/ResourceSharingEntry.java | 20 ++++++++++-- .../resource/ResourceSharingListener.java | 9 ++++-- .../resource}/ResourceSharingUtils.java | 32 +++++++++++++++---- .../security/support/ConfigConstants.java | 1 + .../org/opensearch/security/user/User.java | 9 +++++- 11 files changed, 80 insertions(+), 21 deletions(-) rename {spi/src/main/java/org/opensearch/security/spi => src/main/java/org/opensearch/security/resource}/ResourceSharingEntry.java (58%) rename {spi/src/main/java/org/opensearch/security/spi => src/main/java/org/opensearch/security/resource}/ResourceSharingUtils.java (84%) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index a38cf18ab8..0c7162c0e9 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -44,7 +44,6 @@ import org.opensearch.security.sampleextension.actions.list.ListSampleResourceAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceTransportAction; -import org.opensearch.security.spi.ResourceSharingUtils; import org.opensearch.threadpool.ThreadPool; import org.opensearch.watcher.ResourceWatcherService; @@ -76,7 +75,6 @@ public Collection createComponents( Supplier repositoriesServiceSupplier ) { this.client = client; - ResourceSharingUtils.getInstance().initialize(threadPool, client); return Collections.emptyList(); } diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 71b0be437f..4177a71866 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -55,7 +55,7 @@ public void testPluginsAreInstalled() throws IOException { public void testCreateSampleResource() throws IOException, InterruptedException { String strongPassword = "myStrongPassword123!"; Request createUserRequest = new Request("PUT", "/_opendistro/_security/api/internalusers/craig"); - createUserRequest.setJsonEntity("{\"password\":\"" + strongPassword + "\",\"opendistro_security_roles\":[\"all_access\"]}"); + createUserRequest.setJsonEntity("{\"password\":\"" + strongPassword + "\",\"backend_roles\":[\"admin\"]}"); client().performRequest(createUserRequest); RequestOptions.Builder requestOptions = RequestOptions.DEFAULT.toBuilder(); @@ -76,13 +76,16 @@ public void testCreateSampleResource() throws IOException, InterruptedException createRequest2.setEntity(new StringEntity("{\"name\":\"ExampleResource2\"}")); RequestOptions.Builder requestOptions2 = RequestOptions.DEFAULT.toBuilder(); requestOptions2.setWarningsHandler((warnings) -> false); - requestOptions2.addHeader("Authorization", Base64.getEncoder().encodeToString(strongPassword.getBytes(StandardCharsets.UTF_8))); + requestOptions2.addHeader( + "Authorization", + "Basic " + Base64.getEncoder().encodeToString(("craig:" + strongPassword).getBytes(StandardCharsets.UTF_8)) + ); createRequest2.setOptions(requestOptions2); - Response response2 = client().performRequest(createRequest); + Response response2 = client().performRequest(createRequest2); Map createResourceResponse2 = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, - response.getEntity().getContent() + response2.getEntity().getContent() ).mapStrings(); System.out.println("createResourceResponse2: " + createResourceResponse2); diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java index 98d2b9958d..143117ba25 100644 --- a/spi/src/main/java/org/opensearch/security/spi/Resource.java +++ b/spi/src/main/java/org/opensearch/security/spi/Resource.java @@ -4,5 +4,5 @@ import org.opensearch.core.xcontent.ToXContentFragment; public abstract class Resource implements NamedWriteable, ToXContentFragment { - protected abstract String getResourceIndex(); + public abstract String getResourceIndex(); } diff --git a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java index c594310887..aaff1564cb 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java +++ b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java @@ -35,6 +35,6 @@ public List getBackendRoles() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject().field("users", users).field("roles", roles).field("backendRoles", backendRoles).endObject(); + return builder.startObject().field("users", users).field("roles", roles).field("backend_roles", backendRoles).endObject(); } } diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 1a5a823f8e..82124ef2ab 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -174,6 +174,7 @@ import org.opensearch.security.privileges.RestLayerPrivilegesEvaluator; import org.opensearch.security.resolver.IndexResolverReplacer; import org.opensearch.security.resource.ResourceSharingListener; +import org.opensearch.security.resource.ResourceSharingUtils; import org.opensearch.security.rest.DashboardsInfoAction; import org.opensearch.security.rest.SecurityConfigUpdateAction; import org.opensearch.security.rest.SecurityHealthAction; @@ -184,7 +185,6 @@ import org.opensearch.security.setting.OpensearchDynamicSetting; import org.opensearch.security.setting.TransportPassiveAuthSetting; import org.opensearch.security.spi.ResourceSharingExtension; -import org.opensearch.security.spi.ResourceSharingUtils; import org.opensearch.security.ssl.ExternalSecurityKeyStore; import org.opensearch.security.ssl.OpenSearchSecureSettingsFactory; import org.opensearch.security.ssl.OpenSearchSecuritySSLPlugin; @@ -1069,6 +1069,7 @@ public Collection createComponents( } ResourceSharingUtils.getInstance().initialize(threadPool, localClient); + ResourceSharingListener.getInstance().initialize(threadPool, localClient); // Register opensearch dynamic settings transportPassiveAuthSetting.registerClusterSettingsChangeListener(clusterService.getClusterSettings()); diff --git a/src/main/java/org/opensearch/security/auth/BackendRegistry.java b/src/main/java/org/opensearch/security/auth/BackendRegistry.java index 0b00bcf943..b50b6082fb 100644 --- a/src/main/java/org/opensearch/security/auth/BackendRegistry.java +++ b/src/main/java/org/opensearch/security/auth/BackendRegistry.java @@ -223,7 +223,9 @@ public boolean authenticate(final SecurityRequestChannel request) { if (adminDns.isAdminDN(sslPrincipal)) { // PKI authenticated REST call - threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, new User(sslPrincipal)); + User superuser = new User(sslPrincipal); + threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, superuser); + threadPool.getThreadContext().putPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER, superuser); auditLog.logSucceededLogin(sslPrincipal, true, null, request); return true; } @@ -389,6 +391,11 @@ public boolean authenticate(final SecurityRequestChannel request) { final User impersonatedUser = impersonate(request, authenticatedUser); threadPool.getThreadContext() .putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, impersonatedUser == null ? authenticatedUser : impersonatedUser); + threadPool.getThreadContext() + .putPersistent( + ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER, + impersonatedUser == null ? authenticatedUser : impersonatedUser + ); auditLog.logSucceededLogin( (impersonatedUser == null ? authenticatedUser : impersonatedUser).getName(), false, @@ -422,6 +429,7 @@ public boolean authenticate(final SecurityRequestChannel request) { anonymousUser.setRequestedTenant(tenant); threadPool.getThreadContext().putTransient(ConfigConstants.OPENDISTRO_SECURITY_USER, anonymousUser); + threadPool.getThreadContext().putPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER, anonymousUser); auditLog.logSucceededLogin(anonymousUser.getName(), false, null, request); if (isDebugEnabled) { log.debug("Anonymous User is authenticated"); diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingEntry.java b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java similarity index 58% rename from spi/src/main/java/org/opensearch/security/spi/ResourceSharingEntry.java rename to src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java index dc3df82c75..60cec97154 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingEntry.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java @@ -1,18 +1,33 @@ -package org.opensearch.security.spi; +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.security.resource; import java.io.IOException; import org.opensearch.core.xcontent.ToXContentFragment; import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.spi.ShareWith; +import org.opensearch.security.user.User; public class ResourceSharingEntry implements ToXContentFragment { private final String resourceIndex; private final String resourceId; + private final User resourceUser; private final ShareWith shareWith; - public ResourceSharingEntry(String resourceIndex, String resourceId, ShareWith shareWith) { + public ResourceSharingEntry(String resourceIndex, String resourceId, User resourceUser, ShareWith shareWith) { this.resourceIndex = resourceIndex; this.resourceId = resourceId; + this.resourceUser = resourceUser; this.shareWith = shareWith; } @@ -21,6 +36,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws return builder.startObject() .field("resource_index", resourceIndex) .field("resource_id", resourceId) + .field("resource_user", resourceUser) .field("share_with", shareWith) .endObject(); } diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java index e7c164ee4b..33fe4102a0 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -20,8 +20,9 @@ import org.opensearch.core.index.shard.ShardId; import org.opensearch.index.engine.Engine; import org.opensearch.index.shard.IndexingOperationListener; -import org.opensearch.security.spi.ResourceSharingUtils; import org.opensearch.security.spi.ShareWith; +import org.opensearch.security.support.ConfigConstants; +import org.opensearch.security.user.User; import org.opensearch.threadpool.ThreadPool; public class ResourceSharingListener implements IndexingOperationListener { @@ -60,8 +61,12 @@ public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult re System.out.println("postIndex called on " + shardId.getIndexName()); System.out.println("resourceId: " + resourceId); System.out.println("resourceIndex: " + resourceIndex); + User resourceUser = (User) client.threadPool() + .getThreadContext() + .getPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER); + System.out.println("resourceUser: " + resourceUser); try { - ResourceSharingUtils.getInstance().indexResourceSharing(resourceId, resourceIndex, ShareWith.PRIVATE); + ResourceSharingUtils.getInstance().indexResourceSharing(resourceId, resourceIndex, resourceUser, ShareWith.PRIVATE); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java b/src/main/java/org/opensearch/security/resource/ResourceSharingUtils.java similarity index 84% rename from spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java rename to src/main/java/org/opensearch/security/resource/ResourceSharingUtils.java index 2a006dcfd5..2e2880f46d 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingUtils.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingUtils.java @@ -1,4 +1,15 @@ -package org.opensearch.security.spi; +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.security.resource; import java.io.IOException; import java.security.AccessController; @@ -19,6 +30,9 @@ import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ShareWith; +import org.opensearch.security.user.User; import org.opensearch.threadpool.ThreadPool; import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; @@ -36,6 +50,7 @@ public class ResourceSharingUtils { private ResourceSharingUtils() {} + @SuppressWarnings("removal") public static ResourceSharingUtils getInstance() { ClassLoader classLoader = AccessController.doPrivileged( (PrivilegedAction) () -> Thread.currentThread().getContextClassLoader() @@ -76,10 +91,15 @@ private void createResourceSharingIndexIfNotExists(Callable callable) { } } - public void indexResourceSharing(String resourceId, Resource resource, ShareWith shareWith, ActionListener listener) - throws IOException { + public void indexResourceSharing( + String resourceId, + Resource resource, + User resourceUser, + ShareWith shareWith, + ActionListener listener + ) throws IOException { createResourceSharingIndexIfNotExists(() -> { - ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, shareWith); + ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, resourceUser, shareWith); IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) @@ -101,9 +121,9 @@ public void indexResourceSharing(String resourceId, Resource resource, ShareWith }); } - public void indexResourceSharing(String resourceId, String resourceIndex, ShareWith shareWith) throws IOException { + public void indexResourceSharing(String resourceId, String resourceIndex, User resourceUser, ShareWith shareWith) throws IOException { createResourceSharingIndexIfNotExists(() -> { - ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, shareWith); + ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, shareWith); IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) diff --git a/src/main/java/org/opensearch/security/support/ConfigConstants.java b/src/main/java/org/opensearch/security/support/ConfigConstants.java index f35afc6489..aa38d9becf 100644 --- a/src/main/java/org/opensearch/security/support/ConfigConstants.java +++ b/src/main/java/org/opensearch/security/support/ConfigConstants.java @@ -113,6 +113,7 @@ public class ConfigConstants { public static final String OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL = OPENDISTRO_SECURITY_CONFIG_PREFIX + "ssl_transport_principal"; public static final String OPENDISTRO_SECURITY_USER = OPENDISTRO_SECURITY_CONFIG_PREFIX + "user"; + public static final String OPENDISTRO_SECURITY_AUTHENTICATED_USER = OPENDISTRO_SECURITY_CONFIG_PREFIX + "authenticated_user"; public static final String OPENDISTRO_SECURITY_USER_HEADER = OPENDISTRO_SECURITY_CONFIG_PREFIX + "user_header"; public static final String OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT = OPENDISTRO_SECURITY_CONFIG_PREFIX + "user_info"; diff --git a/src/main/java/org/opensearch/security/user/User.java b/src/main/java/org/opensearch/security/user/User.java index 6abba3d734..d40cbe58d1 100644 --- a/src/main/java/org/opensearch/security/user/User.java +++ b/src/main/java/org/opensearch/security/user/User.java @@ -41,6 +41,8 @@ import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.common.io.stream.Writeable; +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; /** * A authenticated user and attributes associated to them (like roles, tenant, custom attributes) @@ -48,7 +50,7 @@ * Do not subclass from this class! * */ -public class User implements Serializable, Writeable, CustomAttributesAware { +public class User implements Serializable, Writeable, CustomAttributesAware, ToXContentFragment { public static final User ANONYMOUS = new User( "opendistro_security_anonymous", @@ -296,4 +298,9 @@ public boolean isServiceAccount() { Map userAttributesMap = this.getCustomAttributesMap(); return userAttributesMap != null && "true".equals(userAttributesMap.get("attr.internal.service")); } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject().field("username", name).field("backend_roles", roles).endObject(); + } } From e94cb68eaa2e74a4dca612f993468b025a419828 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 14 Oct 2024 22:52:17 -0400 Subject: [PATCH 24/80] WIP on ResourceSharingService and create default impl Signed-off-by: Craig Perkins --- sample-extension-plugin/build.gradle | 2 + .../SampleExtensionPlugin.java | 22 ++- .../CreateSampleResourceAction.java | 2 +- .../CreateSampleResourceRequest.java | 2 +- .../CreateSampleResourceResponse.java | 2 +- .../CreateSampleResourceRestAction.java | 2 +- .../CreateSampleResourceTransportAction.java | 2 +- .../{list => }/ListSampleResourceAction.java | 2 +- .../{list => }/ListSampleResourceRequest.java | 2 +- .../ListSampleResourceResponse.java | 18 ++- .../ListSampleResourceRestAction.java | 2 +- .../ListSampleResourceTransportAction.java | 17 +- .../actions/{create => }/SampleResource.java | 18 ++- .../SampleResourceSharingService.java | 42 +++++ .../plugin-metadata/plugin-security.policy | 1 + ...arch.security.spi.ResourceSharingExtension | 2 +- .../SampleExtensionPluginIT.java | 9 +- .../spi/AbstractResourceSharingService.java | 72 +++++++++ .../spi/DefaultResourceSharingService.java | 10 ++ .../org/opensearch/security/spi/Resource.java | 8 + .../spi/ResourceSharingExtension.java | 2 + .../security/spi/ResourceSharingService.java | 10 ++ .../spi/ResourceSharingServiceProvider.java | 41 +++++ .../security/OpenSearchSecurityPlugin.java | 3 +- .../resource/ResourceSharingListener.java | 88 ++++++++++- .../resource/ResourceSharingUtils.java | 146 ------------------ 26 files changed, 346 insertions(+), 181 deletions(-) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{create => }/CreateSampleResourceAction.java (92%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{create => }/CreateSampleResourceRequest.java (95%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{create => }/CreateSampleResourceResponse.java (95%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{create => }/CreateSampleResourceRestAction.java (96%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{create => }/CreateSampleResourceTransportAction.java (94%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{list => }/ListSampleResourceAction.java (92%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{list => }/ListSampleResourceRequest.java (94%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{list => }/ListSampleResourceResponse.java (70%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{list => }/ListSampleResourceRestAction.java (95%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{list => }/ListSampleResourceTransportAction.java (76%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{create => }/SampleResource.java (66%) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceSharingServiceProvider.java delete mode 100644 src/main/java/org/opensearch/security/resource/ResourceSharingUtils.java diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle index 374e2978e9..bc47f1d2a8 100644 --- a/sample-extension-plugin/build.gradle +++ b/sample-extension-plugin/build.gradle @@ -35,6 +35,8 @@ repositories { dependencies { compileOnly project(path: ":${rootProject.name}-spi", configuration: 'shadow') + testImplementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" + testImplementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}" } def es_tmp_dir = rootProject.file('build/private/es_tmp').absoluteFile diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 0c7162c0e9..bc06ce934a 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -38,12 +38,16 @@ import org.opensearch.rest.RestController; import org.opensearch.rest.RestHandler; import org.opensearch.script.ScriptService; -import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceAction; -import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceRestAction; -import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceTransportAction; -import org.opensearch.security.sampleextension.actions.list.ListSampleResourceAction; -import org.opensearch.security.sampleextension.actions.list.ListSampleResourceRestAction; -import org.opensearch.security.sampleextension.actions.list.ListSampleResourceTransportAction; +import org.opensearch.security.sampleextension.actions.CreateSampleResourceAction; +import org.opensearch.security.sampleextension.actions.CreateSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.CreateSampleResourceTransportAction; +import org.opensearch.security.sampleextension.actions.ListSampleResourceAction; +import org.opensearch.security.sampleextension.actions.ListSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.ListSampleResourceTransportAction; +import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; +import org.opensearch.security.spi.DefaultResourceSharingService; +import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.threadpool.ThreadPool; import org.opensearch.watcher.ResourceWatcherService; @@ -75,6 +79,12 @@ public Collection createComponents( Supplier repositoriesServiceSupplier ) { this.client = client; + ResourceSharingService sharingService = new DefaultResourceSharingService<>( + client, + RESOURCE_INDEX_NAME, + SampleResource.class + ); + SampleResourceSharingService.getInstance().initialize(sharingService); return Collections.emptyList(); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java similarity index 92% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java index 19c2685ec3..a3a32db1e3 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.create; +package org.opensearch.security.sampleextension.actions; import org.opensearch.action.ActionType; import org.opensearch.security.spi.actions.CreateResourceResponse; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java similarity index 95% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java index aaeb92c640..1bc859d8e9 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.create; +package org.opensearch.security.sampleextension.actions; import java.io.IOException; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java similarity index 95% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceResponse.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java index 54cc5746f2..b2b018d849 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.create; +package org.opensearch.security.sampleextension.actions; import java.io.IOException; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java similarity index 96% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java index 72b582a508..210105c878 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.create; +package org.opensearch.security.sampleextension.actions; import java.io.IOException; import java.util.List; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java similarity index 94% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java index d62cb7f35a..a67134bf4e 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.create; +package org.opensearch.security.sampleextension.actions; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceAction.java similarity index 92% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceAction.java index aac9ab10d9..b4c3f39726 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.list; +package org.opensearch.security.sampleextension.actions; import org.opensearch.action.ActionType; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRequest.java similarity index 94% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRequest.java index 3a6acb5cfb..041a5964e7 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRequest.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.list; +package org.opensearch.security.sampleextension.actions; import java.io.IOException; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java similarity index 70% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java index eb1150a379..7662051c3b 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java @@ -6,34 +6,36 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.list; +package org.opensearch.security.sampleextension.actions; import java.io.IOException; +import java.util.List; import org.opensearch.core.action.ActionResponse; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.spi.Resource; /** * Response to a ListSampleResourceRequest */ public class ListSampleResourceResponse extends ActionResponse implements ToXContentObject { - private final String message; + private final List resources; /** * Default constructor * - * @param message The message + * @param resources The resources */ - public ListSampleResourceResponse(String message) { - this.message = message; + public ListSampleResourceResponse(List resources) { + this.resources = resources; } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(message); + out.writeList(resources); } /** @@ -42,13 +44,13 @@ public void writeTo(StreamOutput out) throws IOException { * @param in the stream input */ public ListSampleResourceResponse(final StreamInput in) throws IOException { - message = in.readString(); + resources = in.readList(SampleResource::new); } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.field("message", message); + builder.array("resources", (Object[]) resources.toArray(new Resource[0])); builder.endObject(); return builder; } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRestAction.java similarity index 95% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRestAction.java index 4bab2c9ce6..97e54904e3 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRestAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.list; +package org.opensearch.security.sampleextension.actions; import java.util.List; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java similarity index 76% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java index 8160fe2854..af48be06ce 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java @@ -6,10 +6,11 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.list; +package org.opensearch.security.sampleextension.actions; + +import java.util.List; import org.opensearch.action.search.SearchRequest; -import org.opensearch.action.search.SearchResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; import org.opensearch.client.Client; @@ -18,6 +19,7 @@ import org.opensearch.core.action.ActionListener; import org.opensearch.index.query.MatchAllQueryBuilder; import org.opensearch.search.builder.SearchSourceBuilder; +import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -42,11 +44,14 @@ protected void doExecute(Task task, ListSampleResourceRequest request, ActionLis SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); matchAllQuery.query(new MatchAllQueryBuilder()); sr.source(matchAllQuery); - /* Index already exists, ignore and continue */ - ActionListener searchListener = ActionListener.wrap(response -> { - listener.onResponse(new ListSampleResourceResponse(response.toString())); + ActionListener> sampleResourceListener = ActionListener.wrap(sampleResourcesList -> { + System.out.println("sampleResourcesList: " + sampleResourcesList); + listener.onResponse(new ListSampleResourceResponse(sampleResourcesList)); }, listener::onFailure); - nodeClient.search(sr, searchListener); + SampleResourceSharingService.getInstance().getSharingService().listResources(sampleResourceListener); + // listener.onResponse(new ListSampleResourceResponse(sampleResources)); + /* Index already exists, ignore and continue */ + // nodeClient.search(sr, searchListener); } } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java similarity index 66% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java index f01409af77..8fb2a3f79a 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java @@ -1,18 +1,21 @@ -package org.opensearch.security.sampleextension.actions.create; +package org.opensearch.security.sampleextension.actions; import java.io.IOException; +import java.util.Map; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceSharingExtension; +import org.opensearch.security.spi.ResourceSharingService; import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; public class SampleResource extends Resource implements ResourceSharingExtension { private String name; + private ResourceSharingService resourceSharingService; public SampleResource() {} @@ -25,11 +28,24 @@ public String getResourceType() { return "sample_resource"; } + @Override + public SampleResource fromSource(Map sourceAsMap) { + SampleResource sample = new SampleResource(); + sample.setName((String) sourceAsMap.get("name")); + return sample; + } + @Override public String getResourceIndex() { return RESOURCE_INDEX_NAME; } + @Override + public void assignResourceSharingService(ResourceSharingService service) { + // Only called if security plugin is installed + System.out.println("assignResourceSharingService called"); + } + @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { return builder.startObject().field("name", name).endObject(); diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java new file mode 100644 index 0000000000..7924970a11 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java @@ -0,0 +1,42 @@ +package org.opensearch.security.sampleextension.resource; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.spi.ResourceSharingService; + +public class SampleResourceSharingService { + private final static Logger log = LogManager.getLogger(SampleResourceSharingService.class); + + private static final SampleResourceSharingService INSTANCE = new SampleResourceSharingService(); + + private boolean initialized; + private ResourceSharingService sharingService; + + private SampleResourceSharingService() {} + + public static SampleResourceSharingService getInstance() { + return SampleResourceSharingService.INSTANCE; + } + + public void initialize(ResourceSharingService sharingService) { + if (initialized) { + return; + } + initialized = true; + this.sharingService = sharingService; + } + + public boolean isInitialized() { + return initialized; + } + + public ResourceSharingService getSharingService() { + return sharingService; + } + + public void setSharingService(ResourceSharingService sharingService) { + this.sharingService = sharingService; + } +} diff --git a/sample-extension-plugin/src/main/plugin-metadata/plugin-security.policy b/sample-extension-plugin/src/main/plugin-metadata/plugin-security.policy index a5dfc33a87..197a86c647 100644 --- a/sample-extension-plugin/src/main/plugin-metadata/plugin-security.policy +++ b/sample-extension-plugin/src/main/plugin-metadata/plugin-security.policy @@ -1,3 +1,4 @@ grant { permission java.lang.RuntimePermission "getClassLoader"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; }; \ No newline at end of file diff --git a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension index 8be61d03af..0155e94fc4 100644 --- a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension +++ b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension @@ -3,4 +3,4 @@ # SPDX-License-Identifier: Apache-2.0 # -org.opensearch.security.sampleextension.actions.create.SampleResource \ No newline at end of file +org.opensearch.security.sampleextension.actions.SampleResource \ No newline at end of file diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 4177a71866..2322a51407 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -14,6 +14,8 @@ import java.util.List; import java.util.Map; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.hc.core5.http.io.entity.StringEntity; import org.junit.Assert; @@ -95,11 +97,14 @@ public void testCreateSampleResource() throws IOException, InterruptedException Request listRequest = new Request("GET", "/_plugins/resource_sharing_example/resource"); listRequest.setOptions(requestOptions); Response listResponse = client().performRequest(listRequest); - Map listResourceResponse = JsonXContent.jsonXContent.createParser( + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode resNode = objectMapper.readTree(listResponse.getEntity().getContent()); + System.out.println("resNode: " + resNode); + Map listResourceResponse = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, listResponse.getEntity().getContent() - ).mapStrings(); + ).map(); System.out.println("listResourceResponse: " + listResourceResponse); Request resourceSharingRequest = new Request("POST", "/.resource-sharing/_search"); diff --git a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java new file mode 100644 index 0000000000..07e9be45e6 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java @@ -0,0 +1,72 @@ +package org.opensearch.security.spi; + +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; + +import org.opensearch.OpenSearchException; +import org.opensearch.action.search.SearchRequest; +import org.opensearch.action.search.SearchResponse; +import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.action.ActionListener; +import org.opensearch.index.query.MatchAllQueryBuilder; +import org.opensearch.search.SearchHit; +import org.opensearch.search.builder.SearchSourceBuilder; + +public abstract class AbstractResourceSharingService implements ResourceSharingService { + private final Client client; + private final String resourceIndex; + private final Class resourceClass; + + public AbstractResourceSharingService(Client client, String resourceIndex, Class resourceClass) { + this.client = client; + this.resourceIndex = resourceIndex; + this.resourceClass = resourceClass; + } + + private T newResource() { + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public T run() { + try { + return resourceClass.getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + }); + } + + @SuppressWarnings("unchecked") + @Override + public void listResources(ActionListener> listResourceListener) { + T resource = newResource(); + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + SearchRequest sr = new SearchRequest(resourceIndex); + SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); + matchAllQuery.query(new MatchAllQueryBuilder()); + sr.source(matchAllQuery); + /* Index already exists, ignore and continue */ + ActionListener searchListener = new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + List resources = new ArrayList<>(); + for (SearchHit hit : searchResponse.getHits().getHits()) { + System.out.println("SearchHit: " + hit); + resources.add((T) resource.fromSource(hit.getSourceAsMap())); + } + listResourceListener.onResponse(resources); + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + client.search(sr, searchListener); + } + }; +} diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java new file mode 100644 index 0000000000..00aab97a87 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java @@ -0,0 +1,10 @@ +package org.opensearch.security.spi; + +import org.opensearch.client.Client; + +public class DefaultResourceSharingService extends AbstractResourceSharingService { + + public DefaultResourceSharingService(Client client, String resourceIndex, Class resourceClass) { + super(client, resourceIndex, resourceClass); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java index 143117ba25..fd9cbabdf8 100644 --- a/spi/src/main/java/org/opensearch/security/spi/Resource.java +++ b/spi/src/main/java/org/opensearch/security/spi/Resource.java @@ -1,8 +1,16 @@ package org.opensearch.security.spi; +import java.util.Map; + import org.opensearch.core.common.io.stream.NamedWriteable; import org.opensearch.core.xcontent.ToXContentFragment; public abstract class Resource implements NamedWriteable, ToXContentFragment { + public Resource() {} + public abstract String getResourceIndex(); + + public abstract String getResourceType(); + + public abstract Resource fromSource(Map sourceAsMap); } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java index cddc9bfc7e..18c90b6e22 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java @@ -21,4 +21,6 @@ public interface ResourceSharingExtension { * @return resource index name. */ String getResourceIndex(); + + void assignResourceSharingService(ResourceSharingService service); } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java new file mode 100644 index 0000000000..b8b0006add --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java @@ -0,0 +1,10 @@ +package org.opensearch.security.spi; + +import java.util.List; + +import org.opensearch.core.action.ActionListener; + +public interface ResourceSharingService { + + void listResources(ActionListener> listResourceListener); +} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingServiceProvider.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingServiceProvider.java new file mode 100644 index 0000000000..1e0467976a --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingServiceProvider.java @@ -0,0 +1,41 @@ +package org.opensearch.security.spi; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ResourceSharingServiceProvider { + private final static Logger log = LogManager.getLogger(ResourceSharingServiceProvider.class); + + private static final Map instances = new ConcurrentHashMap<>(); + + private boolean initialized; + private AbstractResourceSharingService resourceSharingService; + + private ResourceSharingServiceProvider() {} + + @SuppressWarnings("removal") + public static ResourceSharingServiceProvider getInstance() { + ClassLoader classLoader = AccessController.doPrivileged( + (PrivilegedAction) () -> Thread.currentThread().getContextClassLoader() + ); + instances.computeIfAbsent(classLoader, cl -> new ResourceSharingServiceProvider()); + return instances.get(classLoader); + } + + public void initialize(AbstractResourceSharingService resourceSharingService) { + if (initialized) { + return; + } + initialized = true; + this.resourceSharingService = resourceSharingService; + } + + public boolean isInitialized() { + return initialized; + } +} diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 82124ef2ab..722530a38a 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -174,7 +174,6 @@ import org.opensearch.security.privileges.RestLayerPrivilegesEvaluator; import org.opensearch.security.resolver.IndexResolverReplacer; import org.opensearch.security.resource.ResourceSharingListener; -import org.opensearch.security.resource.ResourceSharingUtils; import org.opensearch.security.rest.DashboardsInfoAction; import org.opensearch.security.rest.SecurityConfigUpdateAction; import org.opensearch.security.rest.SecurityHealthAction; @@ -1068,7 +1067,6 @@ public Collection createComponents( return components; } - ResourceSharingUtils.getInstance().initialize(threadPool, localClient); ResourceSharingListener.getInstance().initialize(threadPool, localClient); // Register opensearch dynamic settings @@ -2186,6 +2184,7 @@ public Optional getSecureSettingFactory(Settings settings public void loadExtensions(ExtensiblePlugin.ExtensionLoader loader) { for (ResourceSharingExtension extension : loader.loadExtensions(ResourceSharingExtension.class)) { String resourceIndexName = extension.getResourceIndex(); + // ResourceSharingService resourceSharingService = new ResourceSharingService(); this.indicesToListen.add(resourceIndexName); System.out.println("Loaded resource, index: " + resourceIndexName); log.warn("Loaded resource, index: {}", resourceIndexName); diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java index 33fe4102a0..2a664a4de6 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -12,24 +12,38 @@ package org.opensearch.security.resource; import java.io.IOException; +import java.util.concurrent.Callable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.opensearch.action.admin.indices.create.CreateIndexRequest; +import org.opensearch.action.admin.indices.create.CreateIndexResponse; +import org.opensearch.action.index.IndexRequest; +import org.opensearch.action.index.IndexResponse; +import org.opensearch.action.support.WriteRequest; import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.action.ActionListener; import org.opensearch.core.index.shard.ShardId; +import org.opensearch.core.xcontent.ToXContent; import org.opensearch.index.engine.Engine; import org.opensearch.index.shard.IndexingOperationListener; +import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ShareWith; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.user.User; import org.opensearch.threadpool.ThreadPool; +import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; + public class ResourceSharingListener implements IndexingOperationListener { private final static Logger log = LogManager.getLogger(ResourceSharingListener.class); private static final ResourceSharingListener INSTANCE = new ResourceSharingListener(); + public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; + private boolean initialized; private ThreadPool threadPool; private Client client; @@ -66,7 +80,7 @@ public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult re .getPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER); System.out.println("resourceUser: " + resourceUser); try { - ResourceSharingUtils.getInstance().indexResourceSharing(resourceId, resourceIndex, resourceUser, ShareWith.PRIVATE); + indexResourceSharing(resourceId, resourceIndex, resourceUser, ShareWith.PRIVATE); } catch (IOException e) { throw new RuntimeException(e); } @@ -76,4 +90,76 @@ public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult re public void postDelete(ShardId shardId, Engine.Delete delete, Engine.DeleteResult result) { log.warn("postDelete called on " + shardId.getIndexName()); } + + private void createResourceSharingIndexIfNotExists(Callable callable) { + try (ThreadContext.StoredContext ctx = this.threadPool.getThreadContext().stashContext()) { + CreateIndexRequest cir = new CreateIndexRequest(RESOURCE_SHARING_INDEX); + ActionListener cirListener = ActionListener.wrap(response -> { + log.warn(RESOURCE_SHARING_INDEX + " created."); + callable.call(); + }, (failResponse) -> { + /* Index already exists, ignore and continue */ + log.warn(RESOURCE_SHARING_INDEX + " exists."); + try { + callable.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + this.client.admin().indices().create(cir, cirListener); + } + } + + public void indexResourceSharing( + String resourceId, + Resource resource, + User resourceUser, + ShareWith shareWith, + ActionListener listener + ) throws IOException { + createResourceSharingIndexIfNotExists(() -> { + ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, resourceUser, shareWith); + + IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) + .request(); + + log.warn("Index Request: " + ir.toString()); + + ActionListener irListener = ActionListener.wrap(idxResponse -> { + log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); + listener.onResponse(idxResponse); + }, (failResponse) -> { + log.error(failResponse.getMessage()); + log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); + listener.onFailure(failResponse); + }); + client.index(ir, irListener); + return null; + }); + } + + public void indexResourceSharing(String resourceId, String resourceIndex, User resourceUser, ShareWith shareWith) throws IOException { + createResourceSharingIndexIfNotExists(() -> { + ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, shareWith); + + IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) + .request(); + + log.warn("Index Request: " + ir.toString()); + + ActionListener irListener = ActionListener.wrap( + idxResponse -> { log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); }, + (failResponse) -> { + log.error(failResponse.getMessage()); + log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); + } + ); + client.index(ir, irListener); + return null; + }); + } } diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingUtils.java b/src/main/java/org/opensearch/security/resource/ResourceSharingUtils.java deleted file mode 100644 index 2e2880f46d..0000000000 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingUtils.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -package org.opensearch.security.resource; - -import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import org.opensearch.action.admin.indices.create.CreateIndexRequest; -import org.opensearch.action.admin.indices.create.CreateIndexResponse; -import org.opensearch.action.index.IndexRequest; -import org.opensearch.action.index.IndexResponse; -import org.opensearch.action.support.WriteRequest; -import org.opensearch.client.Client; -import org.opensearch.common.util.concurrent.ThreadContext; -import org.opensearch.core.action.ActionListener; -import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.security.spi.Resource; -import org.opensearch.security.spi.ShareWith; -import org.opensearch.security.user.User; -import org.opensearch.threadpool.ThreadPool; - -import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; - -public class ResourceSharingUtils { - private final static Logger log = LogManager.getLogger(ResourceSharingUtils.class); - - private static final Map instances = new ConcurrentHashMap<>(); - - public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; - - private boolean initialized; - private ThreadPool threadPool; - private Client client; - - private ResourceSharingUtils() {} - - @SuppressWarnings("removal") - public static ResourceSharingUtils getInstance() { - ClassLoader classLoader = AccessController.doPrivileged( - (PrivilegedAction) () -> Thread.currentThread().getContextClassLoader() - ); - instances.computeIfAbsent(classLoader, cl -> new ResourceSharingUtils()); - return instances.get(classLoader); - } - - public void initialize(ThreadPool threadPool, Client client) { - if (initialized) { - return; - } - initialized = true; - this.threadPool = threadPool; - this.client = client; - } - - public boolean isInitialized() { - return initialized; - } - - private void createResourceSharingIndexIfNotExists(Callable callable) { - try (ThreadContext.StoredContext ctx = this.threadPool.getThreadContext().stashContext()) { - CreateIndexRequest cir = new CreateIndexRequest(RESOURCE_SHARING_INDEX); - ActionListener cirListener = ActionListener.wrap(response -> { - log.warn(RESOURCE_SHARING_INDEX + " created."); - callable.call(); - }, (failResponse) -> { - /* Index already exists, ignore and continue */ - log.warn(RESOURCE_SHARING_INDEX + " exists."); - try { - callable.call(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - this.client.admin().indices().create(cir, cirListener); - } - } - - public void indexResourceSharing( - String resourceId, - Resource resource, - User resourceUser, - ShareWith shareWith, - ActionListener listener - ) throws IOException { - createResourceSharingIndexIfNotExists(() -> { - ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, resourceUser, shareWith); - - IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) - .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) - .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) - .request(); - - log.warn("Index Request: " + ir.toString()); - - ActionListener irListener = ActionListener.wrap(idxResponse -> { - log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); - listener.onResponse(idxResponse); - }, (failResponse) -> { - log.error(failResponse.getMessage()); - log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); - listener.onFailure(failResponse); - }); - client.index(ir, irListener); - return null; - }); - } - - public void indexResourceSharing(String resourceId, String resourceIndex, User resourceUser, ShareWith shareWith) throws IOException { - createResourceSharingIndexIfNotExists(() -> { - ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, shareWith); - - IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) - .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) - .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) - .request(); - - log.warn("Index Request: " + ir.toString()); - - ActionListener irListener = ActionListener.wrap( - idxResponse -> { log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); }, - (failResponse) -> { - log.error(failResponse.getMessage()); - log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); - } - ); - client.index(ir, irListener); - return null; - }); - } -} From 8057cbaa037987b4861d2defeeaba176f91b556d Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 15 Oct 2024 15:03:22 -0400 Subject: [PATCH 25/80] WIP on SecurityResourceSharingService Signed-off-by: Craig Perkins --- .../actions/CreateSampleResourceRequest.java | 55 -------------- .../actions/CreateSampleResourceResponse.java | 55 -------------- .../actions/ListSampleResourceResponse.java | 4 +- .../actions/SampleResource.java | 22 ++++-- .../security/spi/AbstractResource.java | 33 +++++++++ .../spi/AbstractResourceSharingService.java | 15 ++-- .../spi/DefaultResourceSharingService.java | 2 +- .../org/opensearch/security/spi/Resource.java | 16 ---- .../spi/ResourceSharingExtension.java | 7 +- .../security/spi/ResourceSharingService.java | 2 +- .../opensearch/security/spi/ResourceUser.java | 41 ++++++++++ .../spi/actions/CreateResourceRequest.java | 6 +- .../CreateResourceTransportAction.java | 6 +- .../security/OpenSearchSecurityPlugin.java | 12 ++- .../resource/ResourceSharingEntry.java | 6 +- .../resource/ResourceSharingListener.java | 70 +++++++++--------- .../SecurityResourceSharingService.java | 74 +++++++++++++++++++ .../org/opensearch/security/user/User.java | 9 +-- 18 files changed, 236 insertions(+), 199 deletions(-) delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/AbstractResource.java delete mode 100644 spi/src/main/java/org/opensearch/security/spi/Resource.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceUser.java create mode 100644 src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java deleted file mode 100644 index 1bc859d8e9..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRequest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.sampleextension.actions; - -import java.io.IOException; - -import org.opensearch.action.ActionRequest; -import org.opensearch.action.ActionRequestValidationException; -import org.opensearch.core.common.io.stream.StreamInput; -import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.security.spi.Resource; - -/** - * Request object for CreateSampleResource transport action - */ -public class CreateSampleResourceRequest extends ActionRequest { - - private final Resource resource; - - /** - * Default constructor - */ - public CreateSampleResourceRequest(Resource resource) { - this.resource = resource; - } - - /** - * Constructor with stream input - * @param in the stream input - * @throws IOException IOException - */ - public CreateSampleResourceRequest(final StreamInput in) throws IOException { - this.resource = new SampleResource(in); - } - - @Override - public void writeTo(final StreamOutput out) throws IOException { - resource.writeTo(out); - } - - @Override - public ActionRequestValidationException validate() { - return null; - } - - public Resource getResource() { - return this.resource; - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java deleted file mode 100644 index b2b018d849..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceResponse.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.sampleextension.actions; - -import java.io.IOException; - -import org.opensearch.core.action.ActionResponse; -import org.opensearch.core.common.io.stream.StreamInput; -import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.core.xcontent.ToXContentObject; -import org.opensearch.core.xcontent.XContentBuilder; - -/** - * Response to a CreateSampleResourceRequest - */ -public class CreateSampleResourceResponse extends ActionResponse implements ToXContentObject { - private final String message; - - /** - * Default constructor - * - * @param message The message - */ - public CreateSampleResourceResponse(String message) { - this.message = message; - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(message); - } - - /** - * Constructor with StreamInput - * - * @param in the stream input - */ - public CreateSampleResourceResponse(final StreamInput in) throws IOException { - message = in.readString(); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field("message", message); - builder.endObject(); - return builder; - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java index 7662051c3b..6569510284 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java @@ -16,7 +16,7 @@ import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.AbstractResource; /** * Response to a ListSampleResourceRequest @@ -50,7 +50,7 @@ public ListSampleResourceResponse(final StreamInput in) throws IOException { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.array("resources", (Object[]) resources.toArray(new Resource[0])); + builder.array("resources", (Object[]) resources.toArray(new AbstractResource[0])); builder.endObject(); return builder; } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java index 8fb2a3f79a..fe9b953167 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java @@ -6,13 +6,14 @@ import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; +import org.opensearch.security.spi.AbstractResource; import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.spi.ResourceSharingService; import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; -public class SampleResource extends Resource implements ResourceSharingExtension { +public class SampleResource extends AbstractResource implements ResourceSharingExtension { private String name; private ResourceSharingService resourceSharingService; @@ -29,10 +30,9 @@ public String getResourceType() { } @Override - public SampleResource fromSource(Map sourceAsMap) { - SampleResource sample = new SampleResource(); - sample.setName((String) sourceAsMap.get("name")); - return sample; + public void fromSource(String resourceId, Map sourceAsMap) { + super.fromSource(resourceId, sourceAsMap); + this.name = (String) sourceAsMap.get("name"); } @Override @@ -41,9 +41,17 @@ public String getResourceIndex() { } @Override - public void assignResourceSharingService(ResourceSharingService service) { + public Class getResourceClass() { + return SampleResource.class; + } + + @SuppressWarnings("unchecked") + @Override + public void assignResourceSharingService(ResourceSharingService service) { // Only called if security plugin is installed System.out.println("assignResourceSharingService called"); + ResourceSharingService sharingService = (ResourceSharingService) service; + SampleResourceSharingService.getInstance().setSharingService(sharingService); } @Override diff --git a/spi/src/main/java/org/opensearch/security/spi/AbstractResource.java b/spi/src/main/java/org/opensearch/security/spi/AbstractResource.java new file mode 100644 index 0000000000..7fe36bb92d --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/AbstractResource.java @@ -0,0 +1,33 @@ +package org.opensearch.security.spi; + +import java.util.Map; +import java.util.Set; + +import org.opensearch.core.common.io.stream.NamedWriteable; +import org.opensearch.core.xcontent.ToXContentFragment; + +public abstract class AbstractResource implements NamedWriteable, ToXContentFragment { + protected ResourceUser resourceUser; + protected String resourceId; + + public AbstractResource() {} + + public String getResourceId() { + return resourceId; + } + + public ResourceUser getResourceUser() { + return resourceUser; + } + + @SuppressWarnings("unchecked") + public void fromSource(String resourceId, Map sourceAsMap) { + this.resourceId = resourceId; + if (sourceAsMap.containsKey("resource_user")) { + Map userMap = (Map) sourceAsMap.get("resource_user"); + String username = (String) userMap.get("name"); + Set backendRoles = (Set) userMap.get("backend_roles"); + this.resourceUser = new ResourceUser(username, backendRoles); + } + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java index 07e9be45e6..0396c6d7a5 100644 --- a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java @@ -16,10 +16,10 @@ import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; -public abstract class AbstractResourceSharingService implements ResourceSharingService { - private final Client client; - private final String resourceIndex; - private final Class resourceClass; +public abstract class AbstractResourceSharingService implements ResourceSharingService { + protected final Client client; + protected final String resourceIndex; + protected final Class resourceClass; public AbstractResourceSharingService(Client client, String resourceIndex, Class resourceClass) { this.client = client; @@ -27,7 +27,7 @@ public AbstractResourceSharingService(Client client, String resourceIndex, Class this.resourceClass = resourceClass; } - private T newResource() { + protected T newResource() { return AccessController.doPrivileged(new PrivilegedAction() { @Override public T run() { @@ -56,7 +56,8 @@ public void onResponse(SearchResponse searchResponse) { List resources = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { System.out.println("SearchHit: " + hit); - resources.add((T) resource.fromSource(hit.getSourceAsMap())); + resource.fromSource(hit.getId(), hit.getSourceAsMap()); + resources.add(resource); } listResourceListener.onResponse(resources); } @@ -68,5 +69,5 @@ public void onFailure(Exception e) { }; client.search(sr, searchListener); } - }; + } } diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java index 00aab97a87..9c17707a32 100644 --- a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java @@ -2,7 +2,7 @@ import org.opensearch.client.Client; -public class DefaultResourceSharingService extends AbstractResourceSharingService { +public class DefaultResourceSharingService extends AbstractResourceSharingService { public DefaultResourceSharingService(Client client, String resourceIndex, Class resourceClass) { super(client, resourceIndex, resourceClass); diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java deleted file mode 100644 index fd9cbabdf8..0000000000 --- a/spi/src/main/java/org/opensearch/security/spi/Resource.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.opensearch.security.spi; - -import java.util.Map; - -import org.opensearch.core.common.io.stream.NamedWriteable; -import org.opensearch.core.xcontent.ToXContentFragment; - -public abstract class Resource implements NamedWriteable, ToXContentFragment { - public Resource() {} - - public abstract String getResourceIndex(); - - public abstract String getResourceType(); - - public abstract Resource fromSource(Map sourceAsMap); -} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java index 18c90b6e22..eb95a9c236 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java @@ -22,5 +22,10 @@ public interface ResourceSharingExtension { */ String getResourceIndex(); - void assignResourceSharingService(ResourceSharingService service); + /** + * @return The class corresponding to this resource + */ + Class getResourceClass(); + + void assignResourceSharingService(ResourceSharingService service); } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java index b8b0006add..b2eb467573 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java @@ -4,7 +4,7 @@ import org.opensearch.core.action.ActionListener; -public interface ResourceSharingService { +public interface ResourceSharingService { void listResources(ActionListener> listResourceListener); } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java b/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java new file mode 100644 index 0000000000..741efd1bab --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java @@ -0,0 +1,41 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi; + +import java.io.IOException; +import java.util.Set; + +import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; + +public class ResourceUser implements ToXContentFragment { + private final String name; + + private final Set backendRoles; + + public ResourceUser(String name, Set backendRoles) { + this.name = name; + this.backendRoles = backendRoles; + } + + public String getName() { + return name; + } + + public Set getBackendRoles() { + return backendRoles; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { + return builder.startObject().field("username", name).field("backend_roles", backendRoles).endObject(); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java index e930cf1ecf..6ee2a67c3d 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java @@ -15,12 +15,12 @@ import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.common.io.stream.Writeable; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.AbstractResource; /** * Request object for CreateSampleResource transport action */ -public class CreateResourceRequest extends ActionRequest { +public class CreateResourceRequest extends ActionRequest { private final T resource; @@ -45,7 +45,7 @@ public ActionRequestValidationException validate() { return null; } - public Resource getResource() { + public AbstractResource getResource() { return this.resource; } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java index c35ebc1c2f..fe089cbab9 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java @@ -25,7 +25,7 @@ import org.opensearch.core.action.ActionListener; import org.opensearch.core.common.io.stream.Writeable; import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.AbstractResource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -34,7 +34,7 @@ /** * Transport action for CreateSampleResource. */ -public class CreateResourceTransportAction extends HandledTransportAction< +public class CreateResourceTransportAction extends HandledTransportAction< CreateResourceRequest, CreateResourceResponse> { private static final Logger log = LogManager.getLogger(CreateResourceTransportAction.class); @@ -74,7 +74,7 @@ protected void doExecute(Task task, CreateResourceRequest request, ActionList private void createResource(CreateResourceRequest request, ActionListener listener) { log.warn("Sample name: " + request.getResource()); - Resource sample = request.getResource(); + AbstractResource sample = request.getResource(); try { IndexRequest ir = nodeClient.prepareIndex(resourceIndex) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 722530a38a..101821e41c 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -174,6 +174,7 @@ import org.opensearch.security.privileges.RestLayerPrivilegesEvaluator; import org.opensearch.security.resolver.IndexResolverReplacer; import org.opensearch.security.resource.ResourceSharingListener; +import org.opensearch.security.resource.SecurityResourceSharingService; import org.opensearch.security.rest.DashboardsInfoAction; import org.opensearch.security.rest.SecurityConfigUpdateAction; import org.opensearch.security.rest.SecurityHealthAction; @@ -184,6 +185,7 @@ import org.opensearch.security.setting.OpensearchDynamicSetting; import org.opensearch.security.setting.TransportPassiveAuthSetting; import org.opensearch.security.spi.ResourceSharingExtension; +import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.security.ssl.ExternalSecurityKeyStore; import org.opensearch.security.ssl.OpenSearchSecureSettingsFactory; import org.opensearch.security.ssl.OpenSearchSecuritySSLPlugin; @@ -2184,10 +2186,14 @@ public Optional getSecureSettingFactory(Settings settings public void loadExtensions(ExtensiblePlugin.ExtensionLoader loader) { for (ResourceSharingExtension extension : loader.loadExtensions(ResourceSharingExtension.class)) { String resourceIndexName = extension.getResourceIndex(); - // ResourceSharingService resourceSharingService = new ResourceSharingService(); + ResourceSharingService resourceSharingService = new SecurityResourceSharingService<>( + localClient, + extension.getResourceIndex(), + extension.getResourceClass() + ); this.indicesToListen.add(resourceIndexName); - System.out.println("Loaded resource, index: " + resourceIndexName); - log.warn("Loaded resource, index: {}", resourceIndexName); + log.info("Loaded resource, index: {}", resourceIndexName); + extension.assignResourceSharingService(resourceSharingService); } } // CS-ENFORCE-SINGLE diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java index 60cec97154..4e28c011b7 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java @@ -15,16 +15,16 @@ import org.opensearch.core.xcontent.ToXContentFragment; import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.spi.ResourceUser; import org.opensearch.security.spi.ShareWith; -import org.opensearch.security.user.User; public class ResourceSharingEntry implements ToXContentFragment { private final String resourceIndex; private final String resourceId; - private final User resourceUser; + private final ResourceUser resourceUser; private final ShareWith shareWith; - public ResourceSharingEntry(String resourceIndex, String resourceId, User resourceUser, ShareWith shareWith) { + public ResourceSharingEntry(String resourceIndex, String resourceId, ResourceUser resourceUser, ShareWith shareWith) { this.resourceIndex = resourceIndex; this.resourceId = resourceId; this.resourceUser = resourceUser; diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java index 2a664a4de6..ba00f98860 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -29,7 +29,7 @@ import org.opensearch.core.xcontent.ToXContent; import org.opensearch.index.engine.Engine; import org.opensearch.index.shard.IndexingOperationListener; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ResourceUser; import org.opensearch.security.spi.ShareWith; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.user.User; @@ -75,10 +75,11 @@ public void postIndex(ShardId shardId, Engine.Index index, Engine.IndexResult re System.out.println("postIndex called on " + shardId.getIndexName()); System.out.println("resourceId: " + resourceId); System.out.println("resourceIndex: " + resourceIndex); - User resourceUser = (User) client.threadPool() + User authenticatedUser = (User) client.threadPool() .getThreadContext() .getPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER); - System.out.println("resourceUser: " + resourceUser); + System.out.println("resourceUser: " + authenticatedUser); + ResourceUser resourceUser = new ResourceUser(authenticatedUser.getName(), authenticatedUser.getRoles()); try { indexResourceSharing(resourceId, resourceIndex, resourceUser, ShareWith.PRIVATE); } catch (IOException e) { @@ -110,37 +111,38 @@ private void createResourceSharingIndexIfNotExists(Callable callable) { } } - public void indexResourceSharing( - String resourceId, - Resource resource, - User resourceUser, - ShareWith shareWith, - ActionListener listener - ) throws IOException { - createResourceSharingIndexIfNotExists(() -> { - ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, resourceUser, shareWith); - - IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) - .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) - .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) - .request(); - - log.warn("Index Request: " + ir.toString()); - - ActionListener irListener = ActionListener.wrap(idxResponse -> { - log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); - listener.onResponse(idxResponse); - }, (failResponse) -> { - log.error(failResponse.getMessage()); - log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); - listener.onFailure(failResponse); - }); - client.index(ir, irListener); - return null; - }); - } - - public void indexResourceSharing(String resourceId, String resourceIndex, User resourceUser, ShareWith shareWith) throws IOException { + // public void indexResourceSharing( + // String resourceId, + // Resource resource, + // ResourceUser resourceUser, + // ShareWith shareWith, + // ActionListener listener + // ) throws IOException { + // createResourceSharingIndexIfNotExists(() -> { + // ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, resourceUser, shareWith); + // + // IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) + // .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + // .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) + // .request(); + // + // log.warn("Index Request: " + ir.toString()); + // + // ActionListener irListener = ActionListener.wrap(idxResponse -> { + // log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); + // listener.onResponse(idxResponse); + // }, (failResponse) -> { + // log.error(failResponse.getMessage()); + // log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); + // listener.onFailure(failResponse); + // }); + // client.index(ir, irListener); + // return null; + // }); + // } + + public void indexResourceSharing(String resourceId, String resourceIndex, ResourceUser resourceUser, ShareWith shareWith) + throws IOException { createResourceSharingIndexIfNotExists(() -> { ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, shareWith); diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java new file mode 100644 index 0000000000..c730dedff6 --- /dev/null +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -0,0 +1,74 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.security.resource; + +import java.util.ArrayList; +import java.util.List; + +import org.opensearch.OpenSearchException; +import org.opensearch.action.search.SearchRequest; +import org.opensearch.action.search.SearchResponse; +import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.action.ActionListener; +import org.opensearch.index.query.MatchAllQueryBuilder; +import org.opensearch.search.SearchHit; +import org.opensearch.search.builder.SearchSourceBuilder; +import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.AbstractResourceSharingService; +import org.opensearch.security.support.ConfigConstants; +import org.opensearch.security.user.User; + +public class SecurityResourceSharingService extends AbstractResourceSharingService { + public SecurityResourceSharingService(Client client, String resourceIndex, Class resourceClass) { + super(client, resourceIndex, resourceClass); + } + + @SuppressWarnings("unchecked") + @Override + public void listResources(ActionListener> listResourceListener) { + T resource = newResource(); + User authenticatedUser = client.threadPool().getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + SearchRequest sr = new SearchRequest(resourceIndex); + SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); + matchAllQuery.query(new MatchAllQueryBuilder()); + sr.source(matchAllQuery); + /* Index already exists, ignore and continue */ + ActionListener searchListener = new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + List resources = new ArrayList<>(); + for (SearchHit hit : searchResponse.getHits().getHits()) { + // TODO Combine with an MGET request to get resourceUser and sharedWith data + System.out.println("SearchHit: " + hit); + resource.fromSource(hit.getId(), hit.getSourceAsMap()); + // TODO check what resources have been shared with the authenticatedUser + System.out.println("authenticatedUser: " + authenticatedUser); + System.out.println("resource.getResourceUser(): " + resource.getResourceUser()); + if (resource.getResourceUser() != null + && authenticatedUser.getName().equals(resource.getResourceUser().getName())) { + resources.add(resource); + } + } + listResourceListener.onResponse(resources); + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + client.search(sr, searchListener); + } + } +} diff --git a/src/main/java/org/opensearch/security/user/User.java b/src/main/java/org/opensearch/security/user/User.java index d40cbe58d1..6abba3d734 100644 --- a/src/main/java/org/opensearch/security/user/User.java +++ b/src/main/java/org/opensearch/security/user/User.java @@ -41,8 +41,6 @@ import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.common.io.stream.Writeable; -import org.opensearch.core.xcontent.ToXContentFragment; -import org.opensearch.core.xcontent.XContentBuilder; /** * A authenticated user and attributes associated to them (like roles, tenant, custom attributes) @@ -50,7 +48,7 @@ * Do not subclass from this class! * */ -public class User implements Serializable, Writeable, CustomAttributesAware, ToXContentFragment { +public class User implements Serializable, Writeable, CustomAttributesAware { public static final User ANONYMOUS = new User( "opendistro_security_anonymous", @@ -298,9 +296,4 @@ public boolean isServiceAccount() { Map userAttributesMap = this.getCustomAttributesMap(); return userAttributesMap != null && "true".equals(userAttributesMap.get("attr.internal.service")); } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject().field("username", name).field("backend_roles", roles).endObject(); - } } From 9577c32befa6d72b5f4977cd3f2777df8d99e9c3 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 15 Oct 2024 15:47:52 -0400 Subject: [PATCH 26/80] WIP on list shared with resources Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 4 +- .../ListSampleResourceTransportAction.java | 32 +++---- .../actions/SampleResource.java | 5 +- .../SampleResourceSharingService.java | 4 - .../opensearch/security/spi/ResourceUser.java | 2 +- .../security/OpenSearchSecurityPlugin.java | 22 +++-- .../SecurityResourceSharingService.java | 86 +++++++++++++++---- 7 files changed, 108 insertions(+), 47 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index bc06ce934a..226d9340d7 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -84,7 +84,9 @@ public Collection createComponents( RESOURCE_INDEX_NAME, SampleResource.class ); - SampleResourceSharingService.getInstance().initialize(sharingService); + if (!SampleResourceSharingService.getInstance().isInitialized()) { + SampleResourceSharingService.getInstance().initialize(sharingService); + } return Collections.emptyList(); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java index af48be06ce..e2785f9d1c 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java @@ -10,15 +10,11 @@ import java.util.List; -import org.opensearch.action.search.SearchRequest; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; -import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; -import org.opensearch.index.query.MatchAllQueryBuilder; -import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -39,19 +35,19 @@ public ListSampleResourceTransportAction(TransportService transportService, Acti @Override protected void doExecute(Task task, ListSampleResourceRequest request, ActionListener listener) { - try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { - SearchRequest sr = new SearchRequest(".resource-sharing"); - SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); - matchAllQuery.query(new MatchAllQueryBuilder()); - sr.source(matchAllQuery); - ActionListener> sampleResourceListener = ActionListener.wrap(sampleResourcesList -> { - System.out.println("sampleResourcesList: " + sampleResourcesList); - listener.onResponse(new ListSampleResourceResponse(sampleResourcesList)); - }, listener::onFailure); - SampleResourceSharingService.getInstance().getSharingService().listResources(sampleResourceListener); - // listener.onResponse(new ListSampleResourceResponse(sampleResources)); - /* Index already exists, ignore and continue */ - // nodeClient.search(sr, searchListener); - } + ActionListener> sampleResourceListener = ActionListener.wrap(sampleResourcesList -> { + System.out.println("sampleResourcesList: " + sampleResourcesList); + listener.onResponse(new ListSampleResourceResponse(sampleResourcesList)); + }, listener::onFailure); + SampleResourceSharingService.getInstance().getSharingService().listResources(sampleResourceListener); + // try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { + // SearchRequest sr = new SearchRequest(".resource-sharing"); + // SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); + // matchAllQuery.query(new MatchAllQueryBuilder()); + // sr.source(matchAllQuery); + // listener.onResponse(new ListSampleResourceResponse(sampleResources)); + /* Index already exists, ignore and continue */ + // nodeClient.search(sr, searchListener); + // } } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java index fe9b953167..ba6d1c97d2 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java @@ -51,7 +51,10 @@ public void assignResourceSharingService(ResourceSharingService sharingService = (ResourceSharingService) service; - SampleResourceSharingService.getInstance().setSharingService(sharingService); + if (SampleResourceSharingService.getInstance().isInitialized()) { + throw new IllegalStateException("Resource sharing service already initialized"); + } + SampleResourceSharingService.getInstance().initialize(sharingService); } @Override diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java index 7924970a11..f328034b22 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java @@ -35,8 +35,4 @@ public boolean isInitialized() { public ResourceSharingService getSharingService() { return sharingService; } - - public void setSharingService(ResourceSharingService sharingService) { - this.sharingService = sharingService; - } } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java b/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java index 741efd1bab..3b8093eef3 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java @@ -36,6 +36,6 @@ public Set getBackendRoles() { @Override public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { - return builder.startObject().field("username", name).field("backend_roles", backendRoles).endObject(); + return builder.startObject().field("name", name).field("backend_roles", backendRoles).endObject(); } } diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 101821e41c..c01a68d35a 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -275,6 +275,9 @@ public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin private volatile OpensearchDynamicSetting transportPassiveAuthSetting; private volatile PasswordHasher passwordHasher; private final Set indicesToListen = new HashSet<>(); + // CS-SUPPRESS-SINGLE: RegexpSingleline SPI Extensions are unrelated to OpenSearch extensions + private final List resourceSharingExtensions = new ArrayList<>(); + // CS-ENFORCE-SINGLE public static boolean isActionTraceEnabled() { @@ -1070,6 +1073,16 @@ public Collection createComponents( } ResourceSharingListener.getInstance().initialize(threadPool, localClient); + // CS-SUPPRESS-SINGLE: RegexpSingleline SPI Extensions are unrelated to OpenSearch extensions + for (ResourceSharingExtension extension : resourceSharingExtensions) { + ResourceSharingService resourceSharingService = new SecurityResourceSharingService<>( + localClient, + extension.getResourceIndex(), + extension.getResourceClass() + ); + extension.assignResourceSharingService(resourceSharingService); + } + // CS-ENFORCE-SINGLE // Register opensearch dynamic settings transportPassiveAuthSetting.registerClusterSettingsChangeListener(clusterService.getClusterSettings()); @@ -2186,14 +2199,11 @@ public Optional getSecureSettingFactory(Settings settings public void loadExtensions(ExtensiblePlugin.ExtensionLoader loader) { for (ResourceSharingExtension extension : loader.loadExtensions(ResourceSharingExtension.class)) { String resourceIndexName = extension.getResourceIndex(); - ResourceSharingService resourceSharingService = new SecurityResourceSharingService<>( - localClient, - extension.getResourceIndex(), - extension.getResourceClass() - ); + System.out.println("loadExtensions"); + System.out.println("localClient: " + localClient); this.indicesToListen.add(resourceIndexName); + resourceSharingExtensions.add(extension); log.info("Loaded resource, index: {}", resourceIndexName); - extension.assignResourceSharingService(resourceSharingService); } } // CS-ENFORCE-SINGLE diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index c730dedff6..89292b1649 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -20,7 +20,8 @@ import org.opensearch.client.Client; import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.core.action.ActionListener; -import org.opensearch.index.query.MatchAllQueryBuilder; +import org.opensearch.index.query.BoolQueryBuilder; +import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.security.spi.AbstractResource; @@ -28,6 +29,8 @@ import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.user.User; +import static org.opensearch.security.resource.ResourceSharingListener.RESOURCE_SHARING_INDEX; + public class SecurityResourceSharingService extends AbstractResourceSharingService { public SecurityResourceSharingService(Client client, String resourceIndex, Class resourceClass) { super(client, resourceIndex, resourceClass); @@ -36,29 +39,50 @@ public SecurityResourceSharingService(Client client, String resourceIndex, Class @SuppressWarnings("unchecked") @Override public void listResources(ActionListener> listResourceListener) { + System.out.println("SecurityResourceSharingService.listResources"); + // TODO Flip this around. First query .resource-sharing and then use MGet to get all resources T resource = newResource(); User authenticatedUser = client.threadPool().getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { - SearchRequest sr = new SearchRequest(resourceIndex); - SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); - matchAllQuery.query(new MatchAllQueryBuilder()); - sr.source(matchAllQuery); - /* Index already exists, ignore and continue */ + SearchRequest rsr = new SearchRequest(RESOURCE_SHARING_INDEX); + BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); + + // 1. The resource_user is the currently authenticated user + boolQuery.should(QueryBuilders.termQuery("resource_user.name", authenticatedUser.getName())); + + // 2. The resource has been shared with the authenticated user + boolQuery.should(QueryBuilders.termQuery("share_with.users", authenticatedUser.getName())); + + // 3. The resource has been shared with a backend role that the authenticated user has + if (!authenticatedUser.getRoles().isEmpty()) { + BoolQueryBuilder roleQuery = QueryBuilders.boolQuery(); + for (String role : authenticatedUser.getRoles()) { + roleQuery.should(QueryBuilders.termQuery("share_with.backend_roles", role)); + } + boolQuery.should(roleQuery); + } + + // Set minimum should match to 1 to ensure at least one of the conditions is met + boolQuery.minimumShouldMatch(1); + + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(boolQuery); + rsr.source(searchSourceBuilder); + ActionListener searchListener = new ActionListener() { @Override public void onResponse(SearchResponse searchResponse) { List resources = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { - // TODO Combine with an MGET request to get resourceUser and sharedWith data System.out.println("SearchHit: " + hit); - resource.fromSource(hit.getId(), hit.getSourceAsMap()); - // TODO check what resources have been shared with the authenticatedUser - System.out.println("authenticatedUser: " + authenticatedUser); - System.out.println("resource.getResourceUser(): " + resource.getResourceUser()); - if (resource.getResourceUser() != null - && authenticatedUser.getName().equals(resource.getResourceUser().getName())) { - resources.add(resource); - } + // resource.fromSource(hit.getId(), hit.getSourceAsMap()); + // // TODO check what resources have been shared with the authenticatedUser + // System.out.println("authenticatedUser: " + authenticatedUser); + // System.out.println("resource.getResourceUser(): " + resource.getResourceUser()); + // if (resource.getResourceUser() != null + // && authenticatedUser.getName().equals(resource.getResourceUser().getName())) { + // resources.add(resource); + // } } listResourceListener.onResponse(resources); } @@ -68,7 +92,37 @@ public void onFailure(Exception e) { throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); } }; - client.search(sr, searchListener); + client.search(rsr, searchListener); + + // SearchRequest sr = new SearchRequest(resourceIndex); + // SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); + // matchAllQuery.query(new MatchAllQueryBuilder()); + // sr.source(matchAllQuery); + // /* Index already exists, ignore and continue */ + // ActionListener searchListener = new ActionListener() { + // @Override + // public void onResponse(SearchResponse searchResponse) { + // List resources = new ArrayList<>(); + // for (SearchHit hit : searchResponse.getHits().getHits()) { + // System.out.println("SearchHit: " + hit); + // resource.fromSource(hit.getId(), hit.getSourceAsMap()); + // // TODO check what resources have been shared with the authenticatedUser + // System.out.println("authenticatedUser: " + authenticatedUser); + // System.out.println("resource.getResourceUser(): " + resource.getResourceUser()); + // if (resource.getResourceUser() != null + // && authenticatedUser.getName().equals(resource.getResourceUser().getName())) { + // resources.add(resource); + // } + // } + // listResourceListener.onResponse(resources); + // } + // + // @Override + // public void onFailure(Exception e) { + // throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + // } + // }; + // client.search(sr, searchListener); } } } From 9dde4a65acfc3f43eec2ed5d46b4204257c8fff1 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 15 Oct 2024 16:02:15 -0400 Subject: [PATCH 27/80] Use mget in SecurityResourceSharingService to list all resources shared with the authenticated user Signed-off-by: Craig Perkins --- .../SecurityResourceSharingService.java | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index 89292b1649..f2f9c8520d 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -15,6 +15,10 @@ import java.util.List; import org.opensearch.OpenSearchException; +import org.opensearch.action.get.GetResponse; +import org.opensearch.action.get.MultiGetItemResponse; +import org.opensearch.action.get.MultiGetRequest; +import org.opensearch.action.get.MultiGetResponse; import org.opensearch.action.search.SearchRequest; import org.opensearch.action.search.SearchResponse; import org.opensearch.client.Client; @@ -39,8 +43,6 @@ public SecurityResourceSharingService(Client client, String resourceIndex, Class @SuppressWarnings("unchecked") @Override public void listResources(ActionListener> listResourceListener) { - System.out.println("SecurityResourceSharingService.listResources"); - // TODO Flip this around. First query .resource-sharing and then use MGet to get all resources T resource = newResource(); User authenticatedUser = client.threadPool().getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { @@ -73,18 +75,51 @@ public void listResources(ActionListener> listResourceListener) { @Override public void onResponse(SearchResponse searchResponse) { List resources = new ArrayList<>(); + List resourceIds = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { - System.out.println("SearchHit: " + hit); - // resource.fromSource(hit.getId(), hit.getSourceAsMap()); - // // TODO check what resources have been shared with the authenticatedUser - // System.out.println("authenticatedUser: " + authenticatedUser); - // System.out.println("resource.getResourceUser(): " + resource.getResourceUser()); - // if (resource.getResourceUser() != null - // && authenticatedUser.getName().equals(resource.getResourceUser().getName())) { - // resources.add(resource); - // } + resourceIds.add((String) hit.getSourceAsMap().get("resource_id")); } - listResourceListener.onResponse(resources); + if (resourceIds.isEmpty()) { + listResourceListener.onResponse(resources); + } + + final MultiGetRequest mget = new MultiGetRequest(); + + for (String resourceId : resourceIds) { + mget.add(resourceIndex, resourceId); + } + + mget.refresh(true); + mget.realtime(true); + + client.multiGet(mget, new ActionListener() { + @Override + public void onResponse(MultiGetResponse response) { + MultiGetItemResponse[] responses = response.getResponses(); + for (MultiGetItemResponse singleResponse : responses) { + if (singleResponse != null && !singleResponse.isFailed()) { + GetResponse singleGetResponse = singleResponse.getResponse(); + if (singleGetResponse.isExists() && !singleGetResponse.isSourceEmpty()) { + resource.fromSource(singleGetResponse.getId(), singleGetResponse.getSourceAsMap()); + resources.add(resource); + } else { + // does not exist or empty source + continue; + } + } else { + // failure + continue; + } + } + listResourceListener.onResponse(resources); + } + + @Override + public void onFailure(Exception e) { + listResourceListener.onFailure(e); + } + }); + } @Override From ff38103dfe59f38304b719e6b8bd9a2438efd231 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 15 Oct 2024 20:42:47 -0400 Subject: [PATCH 28/80] WIP on update sharing endpoint Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 12 ++- .../UpdateSampleResourceSharingAction.java | 30 ++++++ ...UpdateSampleResourceSharingRestAction.java | 65 ++++++++++++ ...eSampleResourceSharingTransportAction.java | 33 +++++++ .../SampleExtensionPluginIT.java | 74 +++++++++++++- .../opensearch/security/spi/ShareWith.java | 35 ++++--- .../actions/UpdateResourceSharingRequest.java | 59 +++++++++++ .../UpdateResourceSharingResponse.java | 55 +++++++++++ .../UpdateResourceSharingTransportAction.java | 98 +++++++++++++++++++ .../security/OpenSearchSecurityPlugin.java | 7 +- 10 files changed, 453 insertions(+), 15 deletions(-) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingTransportAction.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingResponse.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 226d9340d7..fd2029f50b 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -45,6 +45,9 @@ import org.opensearch.security.sampleextension.actions.ListSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.ListSampleResourceTransportAction; import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingAction; +import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingRestAction; +import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingTransportAction; import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; import org.opensearch.security.spi.DefaultResourceSharingService; import org.opensearch.security.spi.ResourceSharingService; @@ -100,14 +103,19 @@ public List getRestHandlers( IndexNameExpressionResolver indexNameExpressionResolver, Supplier nodesInCluster ) { - return List.of(new CreateSampleResourceRestAction(), new ListSampleResourceRestAction()); + return List.of( + new CreateSampleResourceRestAction(), + new ListSampleResourceRestAction(), + new UpdateSampleResourceSharingRestAction() + ); } @Override public List> getActions() { return List.of( new ActionHandler<>(CreateSampleResourceAction.INSTANCE, CreateSampleResourceTransportAction.class), - new ActionHandler<>(ListSampleResourceAction.INSTANCE, ListSampleResourceTransportAction.class) + new ActionHandler<>(ListSampleResourceAction.INSTANCE, ListSampleResourceTransportAction.class), + new ActionHandler<>(UpdateSampleResourceSharingAction.INSTANCE, UpdateSampleResourceSharingTransportAction.class) ); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingAction.java new file mode 100644 index 0000000000..4a70d8ff04 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingAction.java @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import org.opensearch.action.ActionType; +import org.opensearch.security.spi.actions.UpdateResourceSharingResponse; + +/** + * Action to create a sample resource + */ +public class UpdateSampleResourceSharingAction extends ActionType { + /** + * Create sample resource action instance + */ + public static final UpdateSampleResourceSharingAction INSTANCE = new UpdateSampleResourceSharingAction(); + /** + * Create sample resource action name + */ + public static final String NAME = "cluster:admin/sampleresource/updatesharing"; + + private UpdateSampleResourceSharingAction() { + super(NAME, UpdateResourceSharingResponse::new); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java new file mode 100644 index 0000000000..1b6ae279fc --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.opensearch.client.node.NodeClient; +import org.opensearch.core.xcontent.XContentParser; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.RestRequest; +import org.opensearch.rest.action.RestToXContentListener; +import org.opensearch.security.spi.ShareWith; +import org.opensearch.security.spi.actions.UpdateResourceSharingRequest; + +import static java.util.Collections.singletonList; +import static org.opensearch.rest.RestRequest.Method.PUT; + +public class UpdateSampleResourceSharingRestAction extends BaseRestHandler { + + public UpdateSampleResourceSharingRestAction() {} + + @Override + public List routes() { + return singletonList(new Route(PUT, "/_plugins/resource_sharing_example/resource/update_sharing/{id}")); + } + + @Override + public String getName() { + return "update_sample_resource_sharing"; + } + + @SuppressWarnings("unchecked") + @Override + public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + String resourceId = request.param("id"); + + System.out.println("update sharing endpoint"); + System.out.println("resourceId: " + resourceId); + Map source; + try (XContentParser parser = request.contentParser()) { + source = parser.map(); + } + + Map shareWithMap = (Map) source.get("share_with"); + ShareWith shareWith = new ShareWith((List) shareWithMap.get("users"), (List) shareWithMap.get("backend_roles")); + + final UpdateResourceSharingRequest updateSampleResourceSharingRequest = new UpdateResourceSharingRequest<>( + resourceId, + shareWith + ); + return channel -> client.executeLocally( + UpdateSampleResourceSharingAction.INSTANCE, + updateSampleResourceSharingRequest, + new RestToXContentListener<>(channel) + ); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingTransportAction.java new file mode 100644 index 0000000000..4c54465467 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingTransportAction.java @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.action.support.ActionFilters; +import org.opensearch.client.Client; +import org.opensearch.common.inject.Inject; +import org.opensearch.security.spi.ShareWith; +import org.opensearch.security.spi.actions.UpdateResourceSharingTransportAction; +import org.opensearch.transport.TransportService; + +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; + +/** + * Transport action for UpdateSampleResourceSharing. + */ +public class UpdateSampleResourceSharingTransportAction extends UpdateResourceSharingTransportAction { + private static final Logger log = LogManager.getLogger(UpdateSampleResourceSharingTransportAction.class); + + @Inject + public UpdateSampleResourceSharingTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { + super(transportService, actionFilters, nodeClient, UpdateSampleResourceSharingAction.NAME, RESOURCE_INDEX_NAME, ShareWith::new); + } +} diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 2322a51407..9e43a239f4 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -13,6 +13,8 @@ import java.util.Base64; import java.util.List; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -84,6 +86,20 @@ public void testCreateSampleResource() throws IOException, InterruptedException ); createRequest2.setOptions(requestOptions2); Response response2 = client().performRequest(createRequest2); + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode indexResponseNode = objectMapper.readTree(response2.getEntity().getContent()); + // Regular expression to capture the value of "id" + Pattern pattern = Pattern.compile("id=([a-zA-Z0-9]+)"); + Matcher matcher = pattern.matcher(indexResponseNode.get("message").asText()); + + String resourceId = ""; + if (matcher.find()) { + resourceId = matcher.group(1); // Extract the ID + System.out.println("Extracted ID: " + resourceId); + } else { + System.out.println("ID not found."); + } + System.out.println("indexResponseNode: " + indexResponseNode); Map createResourceResponse2 = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, @@ -94,10 +110,54 @@ public void testCreateSampleResource() throws IOException, InterruptedException // Sleep to give ResourceSharingListener time to create the .resource-sharing index Thread.sleep(1000); + // TODO Expose this via API to update sharing + // try { + // // Create the request + // Request request = new Request("POST", "/.resource-sharing/_update_by_query"); + // + // // Build the request body using XContentBuilder + // XContentBuilder builder = XContentFactory.jsonBuilder(); + // builder.startObject(); + // { + // builder.startObject("query"); + // { + // builder.startObject("term"); + // { + // builder.field("resource_user", "craig"); + // } + // builder.endObject(); + // } + // builder.endObject(); + // + // builder.startObject("script"); + // { + // builder.field("source", "ctx._source.share_with.users = ['admin']"); + // builder.field("lang", "painless"); + // } + // builder.endObject(); + // } + // builder.endObject(); + // + // // Set the request body + // request.setJsonEntity(builder.toString()); + // + // System.out.println("updateByQueryRequest: " + request); + // + // // Execute the request using the admin client + // Response updateByQueryResponse = adminClient().performRequest(request); + // + // // Handle the response + // System.out.println("Update request executed successfully. Status: " + response.getStatusLine().getStatusCode()); + // System.out.println("updateByQueryResponse: " + updateByQueryResponse.toString()); + // + // } catch (IOException e) { + // // Handle the exception (e.g., log it or throw a custom exception) + // System.err.println("Error executing update request: " + e.getMessage()); + // } + Request listRequest = new Request("GET", "/_plugins/resource_sharing_example/resource"); listRequest.setOptions(requestOptions); Response listResponse = client().performRequest(listRequest); - ObjectMapper objectMapper = new ObjectMapper(); JsonNode resNode = objectMapper.readTree(listResponse.getEntity().getContent()); System.out.println("resNode: " + resNode); Map listResourceResponse = JsonXContent.jsonXContent.createParser( @@ -116,5 +176,17 @@ public void testCreateSampleResource() throws IOException, InterruptedException resourceSharingResponse.getEntity().getContent() ).map(); System.out.println("resourceSharingResponse: " + resourceSharingResponseMap); + + Request updateSharingRequest = new Request("PUT", "/_plugins/resource_sharing_example/resource/update_sharing/" + resourceId); + updateSharingRequest.setEntity(new StringEntity("{\"share_with\":{\"users\": [\"admin\"], \"backend_roles\": []}}")); + requestOptions.addHeader("Content-Type", "application/json"); + updateSharingRequest.setOptions(requestOptions); + Response updateResponse = client().performRequest(updateSharingRequest); + Map updateSharingResponse = JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + updateResponse.getEntity().getContent() + ).mapStrings(); + System.out.println("updateSharingResponse: " + updateSharingResponse); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java index aaff1564cb..359d8145d6 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java +++ b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java @@ -3,30 +3,32 @@ import java.io.IOException; import java.util.List; +import org.opensearch.core.common.io.stream.NamedWriteable; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.ToXContentFragment; import org.opensearch.core.xcontent.XContentBuilder; -public class ShareWith implements ToXContentFragment { +public class ShareWith implements NamedWriteable, ToXContentFragment { - public final static ShareWith PRIVATE = new ShareWith(List.of(), List.of(), List.of()); - public final static ShareWith PUBLIC = new ShareWith(List.of("*"), List.of("*"), List.of("*")); + public final static ShareWith PRIVATE = new ShareWith(List.of(), List.of()); + public final static ShareWith PUBLIC = new ShareWith(List.of("*"), List.of("*")); private final List users; - private final List roles; private final List backendRoles; - public ShareWith(List users, List roles, List backendRoles) { + public ShareWith(List users, List backendRoles) { this.users = users; - this.roles = roles; this.backendRoles = backendRoles; } - public List getUsers() { - return users; + public ShareWith(StreamInput in) throws IOException { + this.users = in.readStringList(); + this.backendRoles = in.readStringList(); } - public List getRoles() { - return roles; + public List getUsers() { + return users; } public List getBackendRoles() { @@ -35,6 +37,17 @@ public List getBackendRoles() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject().field("users", users).field("roles", roles).field("backend_roles", backendRoles).endObject(); + return builder.startObject().field("users", users).field("backend_roles", backendRoles).endObject(); + } + + @Override + public String getWriteableName() { + return "share_with"; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeStringCollection(users); + out.writeStringCollection(backendRoles); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java new file mode 100644 index 0000000000..e0cfca44fd --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java @@ -0,0 +1,59 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.ShareWith; + +/** + * Request object for CreateSampleResource transport action + */ +public class UpdateResourceSharingRequest extends ActionRequest { + + private final String resourceId; + private final ShareWith shareWith; + + /** + * Default constructor + */ + public UpdateResourceSharingRequest(String resourceId, ShareWith shareWith) { + this.resourceId = resourceId; + this.shareWith = shareWith; + } + + public UpdateResourceSharingRequest(StreamInput in, Reader shareWithReader) throws IOException { + this.resourceId = in.readString(); + this.shareWith = shareWithReader.read(in); + } + + @Override + public void writeTo(final StreamOutput out) throws IOException { + out.writeString(resourceId); + shareWith.writeTo(out); + } + + @Override + public ActionRequestValidationException validate() { + return null; + } + + public String getResourceId() { + return this.resourceId; + } + + public ShareWith getShareWith() { + return this.shareWith; + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingResponse.java new file mode 100644 index 0000000000..3fd4887f9c --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingResponse.java @@ -0,0 +1,55 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.opensearch.core.action.ActionResponse; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; + +/** + * Response to a CreateSampleResourceRequest + */ +public class UpdateResourceSharingResponse extends ActionResponse implements ToXContentObject { + private final String message; + + /** + * Default constructor + * + * @param message The message + */ + public UpdateResourceSharingResponse(String message) { + this.message = message; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeString(message); + } + + /** + * Constructor with StreamInput + * + * @param in the stream input + */ + public UpdateResourceSharingResponse(final StreamInput in) throws IOException { + message = in.readString(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field("message", message); + builder.endObject(); + return builder; + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java new file mode 100644 index 0000000000..871293166b --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java @@ -0,0 +1,98 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.action.index.IndexRequest; +import org.opensearch.action.index.IndexResponse; +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.action.support.WriteRequest; +import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.action.ActionListener; +import org.opensearch.core.common.io.stream.Writeable; +import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.ShareWith; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; + +/** + * Transport action for CreateSampleResource. + */ +public class UpdateResourceSharingTransportAction extends HandledTransportAction< + UpdateResourceSharingRequest, + UpdateResourceSharingResponse> { + private static final Logger log = LogManager.getLogger(UpdateResourceSharingTransportAction.class); + + private final TransportService transportService; + private final Client nodeClient; + private final String resourceIndex; + + public UpdateResourceSharingTransportAction( + TransportService transportService, + ActionFilters actionFilters, + Client nodeClient, + String actionName, + String resourceIndex, + Writeable.Reader shareWithReader + ) { + super(actionName, transportService, actionFilters, (in) -> new UpdateResourceSharingRequest(in, shareWithReader)); + this.transportService = transportService; + this.nodeClient = nodeClient; + this.resourceIndex = resourceIndex; + } + + @Override + protected void doExecute(Task task, UpdateResourceSharingRequest request, ActionListener listener) { + try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { + System.out.println("resourceId: " + request.getResourceId()); + System.out.println("shareWith: " + request.getShareWith()); + IndexRequest ir = new IndexRequest(resourceIndex); + ActionListener indexListener = ActionListener.wrap(response -> { + listener.onResponse(new UpdateResourceSharingResponse("success")); + }, listener::onFailure); + nodeClient.index(ir, indexListener); + } + } + + private void indexResource(CreateResourceRequest request, ActionListener listener) { + log.warn("Sample name: " + request.getResource()); + AbstractResource sample = request.getResource(); + try { + IndexRequest ir = nodeClient.prepareIndex(resourceIndex) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .setSource(sample.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) + .request(); + + log.warn("Index Request: " + ir.toString()); + + // ActionListener resourceSharingListener = ActionListener.wrap(resourceSharingResponse -> { + // listener.onResponse(new CreateResourceResponse("Created resource: " + resourceSharingResponse.toString())); + // }, listener::onFailure); + + ActionListener irListener = ActionListener.wrap(idxResponse -> { + log.info("Created resource: " + idxResponse.toString()); + // ResourceSharingUtils.getInstance() + // .indexResourceSharing(idxResponse.getId(), sample, ShareWith.PUBLIC, resourceSharingListener); + listener.onResponse(new CreateResourceResponse("Created resource: " + idxResponse.toString())); + }, listener::onFailure); + nodeClient.index(ir, irListener); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index c01a68d35a..1b19d68617 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -225,6 +225,7 @@ import static org.opensearch.security.dlic.rest.api.RestApiAdminPrivilegesEvaluator.ENDPOINTS_WITH_PERMISSIONS; import static org.opensearch.security.dlic.rest.api.RestApiAdminPrivilegesEvaluator.SECURITY_CONFIG_UPDATE; +import static org.opensearch.security.resource.ResourceSharingListener.RESOURCE_SHARING_INDEX; import static org.opensearch.security.setting.DeprecatedSettings.checkForDeprecatedSetting; import static org.opensearch.security.support.ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX; import static org.opensearch.security.support.ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_USE_CLUSTER_STATE; @@ -2163,7 +2164,11 @@ public Collection getSystemIndexDescriptors(Settings sett ConfigConstants.OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX ); final SystemIndexDescriptor systemIndexDescriptor = new SystemIndexDescriptor(indexPattern, "Security index"); - return Collections.singletonList(systemIndexDescriptor); + final SystemIndexDescriptor resourceSharingIndexDescriptor = new SystemIndexDescriptor( + RESOURCE_SHARING_INDEX, + "Resource sharing index" + ); + return List.of(systemIndexDescriptor, resourceSharingIndexDescriptor); } private static String handleKeyword(final String field) { From 8779c8a0cf00344b6d60d8dd634e0ad96635ee18 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 15 Oct 2024 21:13:16 -0400 Subject: [PATCH 29/80] WIP on update sharing endpoint Signed-off-by: Craig Perkins --- .../SampleExtensionPluginIT.java | 2 +- .../UpdateResourceSharingTransportAction.java | 81 +++++++++++++++++-- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 9e43a239f4..9e54633a86 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -89,7 +89,7 @@ public void testCreateSampleResource() throws IOException, InterruptedException ObjectMapper objectMapper = new ObjectMapper(); JsonNode indexResponseNode = objectMapper.readTree(response2.getEntity().getContent()); // Regular expression to capture the value of "id" - Pattern pattern = Pattern.compile("id=([a-zA-Z0-9]+)"); + Pattern pattern = Pattern.compile("id=([a-zA-Z0-9_-]+)"); Matcher matcher = pattern.matcher(indexResponseNode.get("message").asText()); String resourceId = ""; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java index 871293166b..1a260b4e9b 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java @@ -9,20 +9,32 @@ package org.opensearch.security.spi.actions; import java.io.IOException; +import java.util.Arrays; +import java.util.Objects; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.opensearch.action.index.IndexRequest; import org.opensearch.action.index.IndexResponse; +import org.opensearch.action.search.SearchRequest; +import org.opensearch.action.search.SearchResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; import org.opensearch.action.support.WriteRequest; +import org.opensearch.action.update.UpdateRequest; +import org.opensearch.action.update.UpdateResponse; import org.opensearch.client.Client; import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.common.xcontent.XContentFactory; import org.opensearch.core.action.ActionListener; import org.opensearch.core.common.io.stream.Writeable; import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.index.query.BoolQueryBuilder; +import org.opensearch.index.query.QueryBuilders; +import org.opensearch.search.SearchHit; +import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.security.spi.AbstractResource; import org.opensearch.security.spi.ShareWith; import org.opensearch.tasks.Task; @@ -38,6 +50,8 @@ public class UpdateResourceSharingTransportAction ex UpdateResourceSharingResponse> { private static final Logger log = LogManager.getLogger(UpdateResourceSharingTransportAction.class); + public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; + private final TransportService transportService; private final Client nodeClient; private final String resourceIndex; @@ -59,13 +73,66 @@ public UpdateResourceSharingTransportAction( @Override protected void doExecute(Task task, UpdateResourceSharingRequest request, ActionListener listener) { try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { - System.out.println("resourceId: " + request.getResourceId()); - System.out.println("shareWith: " + request.getShareWith()); - IndexRequest ir = new IndexRequest(resourceIndex); - ActionListener indexListener = ActionListener.wrap(response -> { - listener.onResponse(new UpdateResourceSharingResponse("success")); - }, listener::onFailure); - nodeClient.index(ir, indexListener); + // TODO write a request to find the record in .resource-sharing matching this resource_id and resource_index + SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() + .must(QueryBuilders.termQuery("resource_id", request.getResourceId())) + .must(QueryBuilders.termQuery("resource_index", resourceIndex)); + searchSourceBuilder.query(boolQuery); + searchRequest.source(searchSourceBuilder); + + System.out.println("SearchRequest: " + searchRequest.toString()); + + // Execute the search request + nodeClient.search(searchRequest, new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + System.out.println("searchResponse.getHits(): " + Arrays.toString(searchResponse.getHits().getHits())); + if (Objects.requireNonNull(searchResponse.getHits().getTotalHits()).value == 1) { + // Record found, update it + SearchHit hit = searchResponse.getHits().getAt(0); + UpdateRequest updateRequest = new UpdateRequest(RESOURCE_SHARING_INDEX, hit.getId()); + try { + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject(); + { + builder.startObject("share_with"); + { + builder.field("users", request.getShareWith().getUsers()); + builder.field("backend_roles", request.getShareWith().getBackendRoles()); + } + builder.endObject(); + } + builder.endObject(); + updateRequest.doc(builder); + + nodeClient.update(updateRequest, new ActionListener() { + @Override + public void onResponse(UpdateResponse updateResponse) { + listener.onResponse(new UpdateResourceSharingResponse("success")); + } + + @Override + public void onFailure(Exception e) { + listener.onFailure(e); + } + }); + } catch (IOException e) { + listener.onFailure(e); + } + } else { + // Record not found, create a new one + // createNewRecord(request, listener); + listener.onFailure(new IllegalStateException(".resource-sharing entry not found")); + } + } + + @Override + public void onFailure(Exception e) { + listener.onFailure(e); + } + }); } } From c7dcef620e88329b2ab96b4442a6a7bd3016e708 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 15 Oct 2024 21:21:42 -0400 Subject: [PATCH 30/80] Demonstrate update sharing and re-run list after sharing info was updated Signed-off-by: Craig Perkins --- .../SampleExtensionPluginIT.java | 18 ++++++++++++++++++ .../UpdateResourceSharingTransportAction.java | 7 ++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 9e54633a86..a8ae480353 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -188,5 +188,23 @@ public void testCreateSampleResource() throws IOException, InterruptedException updateResponse.getEntity().getContent() ).mapStrings(); System.out.println("updateSharingResponse: " + updateSharingResponse); + + Thread.sleep(1000); + + resourceSharingResponse = adminClient().performRequest(resourceSharingRequest); + resourceSharingResponseMap = JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + resourceSharingResponse.getEntity().getContent() + ).map(); + System.out.println("resourceSharingResponse after update: " + resourceSharingResponseMap); + + listResponse = client().performRequest(listRequest); + listResourceResponse = JsonXContent.jsonXContent.createParser( + NamedXContentRegistry.EMPTY, + LoggingDeprecationHandler.INSTANCE, + listResponse.getEntity().getContent() + ).map(); + System.out.println("listResourceResponse after update: " + listResourceResponse); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java index 1a260b4e9b..50cc72343a 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java @@ -73,17 +73,14 @@ public UpdateResourceSharingTransportAction( @Override protected void doExecute(Task task, UpdateResourceSharingRequest request, ActionListener listener) { try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { - // TODO write a request to find the record in .resource-sharing matching this resource_id and resource_index SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() - .must(QueryBuilders.termQuery("resource_id", request.getResourceId())) - .must(QueryBuilders.termQuery("resource_index", resourceIndex)); + .must(QueryBuilders.matchQuery("resource_id", request.getResourceId())) + .must(QueryBuilders.matchQuery("resource_index", resourceIndex)); searchSourceBuilder.query(boolQuery); searchRequest.source(searchSourceBuilder); - System.out.println("SearchRequest: " + searchRequest.toString()); - // Execute the search request nodeClient.search(searchRequest, new ActionListener() { @Override From 37b197c82d758ab9a5cfcca9d2fa5144d793d74b Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 18 Oct 2024 09:23:47 -0400 Subject: [PATCH 31/80] WIP on integ test Signed-off-by: Craig Perkins --- build.gradle | 56 ++++++++++------- sample-extension-plugin/build.gradle | 29 +++++++++ .../SampleExtensionPluginTests.java | 63 +++++++++++++++++++ 3 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java diff --git a/build.gradle b/build.gradle index 64989fe453..38b89dbf46 100644 --- a/build.gradle +++ b/build.gradle @@ -713,36 +713,44 @@ dependencies { compileOnly "org.opensearch:opensearch:${opensearch_version}" - //integration test framework: - integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { - exclude(group: 'junit', module: 'junit') - } - integrationTestImplementation 'junit:junit:4.13.2' - integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" - integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" - integrationTestImplementation 'commons-io:commons-io:2.17.0' - integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" - integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" - integrationTestImplementation 'org.hamcrest:hamcrest:2.2' - integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" - integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" - integrationTestImplementation('org.awaitility:awaitility:4.2.2') { - exclude(group: 'org.hamcrest', module: 'hamcrest') - } - integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' - integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" - integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" - integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" - //spotless implementation('com.google.googlejavaformat:google-java-format:1.24.0') { exclude group: 'com.google.guava' } } +allprojects { + configurations { + integrationTestImplementation.extendsFrom implementation + integrationTestRuntimeOnly.extendsFrom runtimeOnly + } + dependencies { + //integration test framework: + integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { + exclude(group: 'junit', module: 'junit') + } + integrationTestImplementation 'junit:junit:4.13.2' + integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" + integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" + integrationTestImplementation 'commons-io:commons-io:2.17.0' + integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" + integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" + integrationTestImplementation 'org.hamcrest:hamcrest:2.2' + integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" + integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" + integrationTestImplementation('org.awaitility:awaitility:4.2.2') { + exclude(group: 'org.hamcrest', module: 'hamcrest') + } + integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' + integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" + integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" + integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" + } +} + jar { libsDirName = '.' into '', { diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle index bc47f1d2a8..a03896b81e 100644 --- a/sample-extension-plugin/build.gradle +++ b/sample-extension-plugin/build.gradle @@ -35,6 +35,8 @@ repositories { dependencies { compileOnly project(path: ":${rootProject.name}-spi", configuration: 'shadow') +// integrationTestImplementation project(path: ":") +// integrationTestImplementation sourceSets.integrationTest.output testImplementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" testImplementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}" } @@ -65,6 +67,33 @@ task integTest(type: RestIntegTestTask) { } tasks.named("check").configure { dependsOn(integTest) } +//create source set 'integrationTest' +//add classes from the main source set to the compilation and runtime classpaths of the integrationTest +sourceSets { + integrationTest { + java { + srcDir file ('src/integrationTest/java') + compileClasspath += sourceSets.main.output + runtimeClasspath += sourceSets.main.output + } + resources { + srcDir file('src/integrationTest/resources') + } + processIntegrationTestResources { + duplicatesStrategy(DuplicatesStrategy.INCLUDE) + } + } +} + +task integrationTest(type: Test) { + testClassesDirs = sourceSets.integrationTest.output.classesDirs + classpath = sourceSets.integrationTest.runtimeClasspath +} + +configurations { + integrationTestImplementation.extendsFrom(rootProject.configurations.integrationTestImplementation) +} + integTest { if (project.hasProperty('excludeTests')) { project.properties['excludeTests']?.replaceAll('\\s', '')?.split('[,;]')?.each { diff --git a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java new file mode 100644 index 0000000000..8a58e8c9d5 --- /dev/null +++ b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.security.sampleextension; + +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; +import org.apache.http.HttpStatus; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.opensearch.test.framework.TestSecurityConfig; +import org.opensearch.test.framework.TestSecurityConfig.Role; +import org.opensearch.test.framework.cluster.ClusterManager; +import org.opensearch.test.framework.cluster.LocalCluster; +import org.opensearch.test.framework.cluster.TestRestClient; +import org.opensearch.test.framework.cluster.TestRestClient.HttpResponse; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL; + +@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class) +@ThreadLeakScope(ThreadLeakScope.Scope.NONE) +public class SampleExtensionPluginTests { + + protected final static TestSecurityConfig.User USER_SR = new TestSecurityConfig.User("sr_user").roles( + new Role("abc_ber").indexPermissions("*").on("*").clusterPermissions("*"), + new Role("def_efg").indexPermissions("*").on("*").clusterPermissions("*") + ); + + @ClassRule + public static LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.THREE_CLUSTER_MANAGERS) + .anonymousAuth(true) + .authc(AUTHC_HTTPBASIC_INTERNAL) + .users(USER_SR) + .build(); + + @Test + public void testSecurityRoles() throws Exception { + try (TestRestClient client = cluster.getRestClient(USER_SR)) { + HttpResponse response = client.getAuthInfo(); + response.assertStatusCode(HttpStatus.SC_OK); + + // Check username + assertThat(response.getTextFromJsonBody("/user_name"), equalTo("sr_user")); + + // Check security roles + assertThat(response.getTextFromJsonBody("/roles/0"), equalTo("user_sr_user__abc_ber")); + assertThat(response.getTextFromJsonBody("/roles/1"), equalTo("user_sr_user__def_efg")); + + } + } + +} From 37ad3aad6f32fb19c22cab468cc97532059127ee Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 21 Oct 2024 22:46:33 -0400 Subject: [PATCH 32/80] Get integrationTest to run for sample plugin Signed-off-by: Craig Perkins --- sample-extension-plugin/build.gradle | 91 +++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle index a03896b81e..89316763ea 100644 --- a/sample-extension-plugin/build.gradle +++ b/sample-extension-plugin/build.gradle @@ -33,12 +33,97 @@ repositories { maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } +configurations { + all { + resolutionStrategy { + force 'commons-codec:commons-codec:1.17.1' + force "org.apache.httpcomponents:httpclient:4.5.14" + force "org.apache.httpcomponents:httpcore:4.4.16" + force "com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1" + force "org.hamcrest:hamcrest:2.2" + } + } +} + +// TODO Make this plugin have an integration test dependency on integrationTest from root project dependencies { compileOnly project(path: ":${rootProject.name}-spi", configuration: 'shadow') -// integrationTestImplementation project(path: ":") -// integrationTestImplementation sourceSets.integrationTest.output + // integrationTestImplementation project(":") + integrationTestImplementation rootProject.sourceSets.main.output + integrationTestImplementation rootProject.sourceSets.integrationTest.output testImplementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" testImplementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}" + + implementation "org.opensearch.plugin:transport-netty4-client:${opensearch_version}" + implementation "org.opensearch.client:opensearch-rest-high-level-client:${opensearch_version}" + implementation "org.apache.httpcomponents.client5:httpclient5-cache:${versions.httpclient5}" + implementation "org.apache.httpcomponents:httpclient:${versions.httpclient}" + implementation "org.apache.httpcomponents:httpcore:${versions.httpcore}" + implementation "org.apache.httpcomponents:httpasyncclient:${versions.httpasyncclient}" + implementation "com.google.guava:guava:${guava_version}" + implementation 'org.greenrobot:eventbus-java:3.3.1' + implementation 'commons-cli:commons-cli:1.9.0' + implementation "org.bouncycastle:bcprov-jdk18on:${versions.bouncycastle}" + implementation 'org.ldaptive:ldaptive:1.2.3' + implementation 'com.nimbusds:nimbus-jose-jwt:9.41.2' + implementation 'com.rfksystems:blake2b:2.0.0' + implementation 'com.password4j:password4j:1.8.2' + //JWT + implementation "io.jsonwebtoken:jjwt-api:${jjwt_version}" + implementation "io.jsonwebtoken:jjwt-impl:${jjwt_version}" + implementation "io.jsonwebtoken:jjwt-jackson:${jjwt_version}" + // JSON patch + implementation 'com.flipkart.zjsonpatch:zjsonpatch:0.4.16' + implementation 'org.apache.commons:commons-collections4:4.4' + + //Password generation + implementation 'org.passay:passay:1.6.5' + + implementation "org.apache.kafka:kafka-clients:${kafka_version}" + + runtimeOnly 'net.minidev:accessors-smart:2.5.1' + + runtimeOnly 'com.sun.activation:jakarta.activation:1.2.2' + runtimeOnly 'com.eclipsesource.minimal-json:minimal-json:0.9.5' + runtimeOnly 'commons-codec:commons-codec:1.17.1' + runtimeOnly 'org.cryptacular:cryptacular:1.2.7' + compileOnly 'com.google.errorprone:error_prone_annotations:2.33.0' + runtimeOnly 'com.sun.istack:istack-commons-runtime:4.2.0' + runtimeOnly 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.2' + runtimeOnly 'org.ow2.asm:asm:9.7.1' + + implementation "com.nulab-inc:zxcvbn:1.9.0" + + runtimeOnly 'com.google.guava:failureaccess:1.0.2' + runtimeOnly 'org.apache.commons:commons-text:1.12.0' + runtimeOnly "org.glassfish.jaxb:jaxb-runtime:${jaxb_version}" + runtimeOnly 'com.google.j2objc:j2objc-annotations:2.8' + compileOnly 'com.google.code.findbugs:jsr305:3.0.2' + runtimeOnly 'org.lz4:lz4-java:1.8.0' + runtimeOnly 'org.slf4j:slf4j-api:1.7.36' + runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" + runtimeOnly 'org.xerial.snappy:snappy-java:1.1.10.7' + runtimeOnly 'org.codehaus.woodstox:stax2-api:4.2.2' + runtimeOnly "org.glassfish.jaxb:txw2:${jaxb_version}" + runtimeOnly 'com.fasterxml.woodstox:woodstox-core:6.7.0' + runtimeOnly 'org.apache.ws.xmlschema:xmlschema-core:2.3.1' + runtimeOnly 'org.apache.santuario:xmlsec:2.3.4' + runtimeOnly "com.github.luben:zstd-jni:${versions.zstd}" + runtimeOnly 'org.checkerframework:checker-qual:3.47.0' + runtimeOnly "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" + runtimeOnly 'org.scala-lang.modules:scala-java8-compat_3:1.0.2' + + implementation "org.apache.commons:commons-lang3:${versions.commonslang}" + + implementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" + implementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}" + + compileOnly "org.opensearch:opensearch:${opensearch_version}" + + //spotless + implementation('com.google.googlejavaformat:google-java-format:1.24.0') { + exclude group: 'com.google.guava' + } } def es_tmp_dir = rootProject.file('build/private/es_tmp').absoluteFile @@ -91,6 +176,8 @@ task integrationTest(type: Test) { } configurations { + integrationTestImplementation.extendsFrom(rootProject.configurations.implementation) + integrationTestImplementation.extendsFrom(rootProject.configurations.testImplementation) integrationTestImplementation.extendsFrom(rootProject.configurations.integrationTestImplementation) } From c141a6fd6dfc238a56807c08e052e2efa6183368 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 21 Oct 2024 22:55:18 -0400 Subject: [PATCH 33/80] Add integration test to verify plugin installed Signed-off-by: Craig Perkins --- .../SampleExtensionPluginTests.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java index 8a58e8c9d5..7528ffb8df 100644 --- a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java +++ b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java @@ -17,46 +17,41 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.opensearch.test.framework.TestSecurityConfig; -import org.opensearch.test.framework.TestSecurityConfig.Role; import org.opensearch.test.framework.cluster.ClusterManager; import org.opensearch.test.framework.cluster.LocalCluster; import org.opensearch.test.framework.cluster.TestRestClient; import org.opensearch.test.framework.cluster.TestRestClient.HttpResponse; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.opensearch.test.framework.TestSecurityConfig.AuthcDomain.AUTHC_HTTPBASIC_INTERNAL; +import static org.opensearch.test.framework.TestSecurityConfig.User.USER_ADMIN; @RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class) @ThreadLeakScope(ThreadLeakScope.Scope.NONE) public class SampleExtensionPluginTests { - protected final static TestSecurityConfig.User USER_SR = new TestSecurityConfig.User("sr_user").roles( - new Role("abc_ber").indexPermissions("*").on("*").clusterPermissions("*"), - new Role("def_efg").indexPermissions("*").on("*").clusterPermissions("*") - ); - @ClassRule public static LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.THREE_CLUSTER_MANAGERS) + .plugin(SampleExtensionPlugin.class) .anonymousAuth(true) .authc(AUTHC_HTTPBASIC_INTERNAL) - .users(USER_SR) + .users(USER_ADMIN) .build(); @Test public void testSecurityRoles() throws Exception { - try (TestRestClient client = cluster.getRestClient(USER_SR)) { + try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) { HttpResponse response = client.getAuthInfo(); response.assertStatusCode(HttpStatus.SC_OK); // Check username - assertThat(response.getTextFromJsonBody("/user_name"), equalTo("sr_user")); - - // Check security roles - assertThat(response.getTextFromJsonBody("/roles/0"), equalTo("user_sr_user__abc_ber")); - assertThat(response.getTextFromJsonBody("/roles/1"), equalTo("user_sr_user__def_efg")); - + assertThat(response.getTextFromJsonBody("/user_name"), equalTo("admin")); + System.out.println("Response: " + response.getBody()); + HttpResponse pluginsResponse = client.get("_cat/plugins?s=component&h=name,component,version,description"); + assertThat(pluginsResponse.getBody(), containsString("org.opensearch.security.OpenSearchSecurityPlugin")); + assertThat(pluginsResponse.getBody(), containsString("org.opensearch.security.sampleextension.SampleExtensionPlugin")); } } From 87d94720592286229d3b5602f6e336ec0016632a Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 15 Nov 2024 09:16:51 -0500 Subject: [PATCH 34/80] Simplify for merge Signed-off-by: Craig Perkins --- build.gradle | 110 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index 38b89dbf46..3e98803f02 100644 --- a/build.gradle +++ b/build.gradle @@ -637,7 +637,29 @@ dependencies { runtimeOnly 'org.apache.commons:commons-text:1.12.0' runtimeOnly "org.glassfish.jaxb:jaxb-runtime:${jaxb_version}" runtimeOnly 'com.google.j2objc:j2objc-annotations:2.8' - compileOnly 'com.google.code.findbugs:jsr305:3.0.2' + compileOnly 'com.google.code.f//integration test framework:\n' + + ' integrationTestImplementation(\'com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1\') {\n' + + ' exclude(group: \'junit\', module: \'junit\')\n' + + ' }\n' + + ' integrationTestImplementation \'junit:junit:4.13.2\'\n' + + ' integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}"\n' + + ' integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}"\n' + + ' integrationTestImplementation \'commons-io:commons-io:2.17.0\'\n' + + ' integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}"\n' + + ' integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}"\n' + + ' integrationTestImplementation \'org.hamcrest:hamcrest:2.2\'\n' + + ' integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}"\n' + + ' integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}"\n' + + ' integrationTestImplementation(\'org.awaitility:awaitility:4.2.2\') {\n' + + ' exclude(group: \'org.hamcrest\', module: \'hamcrest\')\n' + + ' }\n' + + ' integrationTestImplementation \'com.unboundid:unboundid-ldapsdk:4.0.14\'\n' + + ' integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}"\n' + + ' integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14"\n' + + ' integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14"\n' + + ' integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14"\n' + + ' integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16"\n' + + ' integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5"indbugs:jsr305:3.0.2' runtimeOnly 'org.lz4:lz4-java:1.8.0' runtimeOnly 'org.slf4j:slf4j-api:1.7.36' runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" @@ -713,43 +735,67 @@ dependencies { compileOnly "org.opensearch:opensearch:${opensearch_version}" + //integration test framework: + integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { + exclude(group: 'junit', module: 'junit') + } + integrationTestImplementation 'junit:junit:4.13.2' + integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" + integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" + integrationTestImplementation 'commons-io:commons-io:2.17.0' + integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" + integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" + integrationTestImplementation 'org.hamcrest:hamcrest:2.2' + integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" + integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" + integrationTestImplementation('org.awaitility:awaitility:4.2.2') { + exclude(group: 'org.hamcrest', module: 'hamcrest') + } + integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' + integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" + integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" + integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" + //spotless implementation('com.google.googlejavaformat:google-java-format:1.24.0') { exclude group: 'com.google.guava' } } -allprojects { - configurations { - integrationTestImplementation.extendsFrom implementation - integrationTestRuntimeOnly.extendsFrom runtimeOnly - } - dependencies { - //integration test framework: - integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { - exclude(group: 'junit', module: 'junit') - } - integrationTestImplementation 'junit:junit:4.13.2' - integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" - integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" - integrationTestImplementation 'commons-io:commons-io:2.17.0' - integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" - integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" - integrationTestImplementation 'org.hamcrest:hamcrest:2.2' - integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" - integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" - integrationTestImplementation('org.awaitility:awaitility:4.2.2') { - exclude(group: 'org.hamcrest', module: 'hamcrest') - } - integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' - integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" - integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" - integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" - } -} +//allprojects { +// configurations { +// integrationTestImplementation.extendsFrom implementation +// integrationTestRuntimeOnly.extendsFrom runtimeOnly +// } +// dependencies { +// //integration test framework: +// integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { +// exclude(group: 'junit', module: 'junit') +// } +// integrationTestImplementation 'junit:junit:4.13.2' +// integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" +// integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" +// integrationTestImplementation 'commons-io:commons-io:2.17.0' +// integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" +// integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" +// integrationTestImplementation 'org.hamcrest:hamcrest:2.2' +// integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" +// integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" +// integrationTestImplementation('org.awaitility:awaitility:4.2.2') { +// exclude(group: 'org.hamcrest', module: 'hamcrest') +// } +// integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' +// integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" +// integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" +// integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" +// } +//} jar { libsDirName = '.' From 879afa7487d56c5711a0909231a1ff89c14e417d Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 15 Nov 2024 09:54:23 -0500 Subject: [PATCH 35/80] Rebase with latest from main Signed-off-by: Craig Perkins --- build.gradle | 133 ++++++++---------- sample-extension-plugin/build.gradle | 4 + .../security/OpenSearchSecurityPlugin.java | 1 + 3 files changed, 61 insertions(+), 77 deletions(-) diff --git a/build.gradle b/build.gradle index 87469dff38..7c5ab01546 100644 --- a/build.gradle +++ b/build.gradle @@ -645,29 +645,7 @@ dependencies { runtimeOnly 'org.apache.commons:commons-text:1.12.0' runtimeOnly "org.glassfish.jaxb:jaxb-runtime:${jaxb_version}" runtimeOnly 'com.google.j2objc:j2objc-annotations:2.8' - compileOnly 'com.google.code.f//integration test framework:\n' + - ' integrationTestImplementation(\'com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1\') {\n' + - ' exclude(group: \'junit\', module: \'junit\')\n' + - ' }\n' + - ' integrationTestImplementation \'junit:junit:4.13.2\'\n' + - ' integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}"\n' + - ' integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}"\n' + - ' integrationTestImplementation \'commons-io:commons-io:2.17.0\'\n' + - ' integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}"\n' + - ' integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}"\n' + - ' integrationTestImplementation \'org.hamcrest:hamcrest:2.2\'\n' + - ' integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}"\n' + - ' integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}"\n' + - ' integrationTestImplementation(\'org.awaitility:awaitility:4.2.2\') {\n' + - ' exclude(group: \'org.hamcrest\', module: \'hamcrest\')\n' + - ' }\n' + - ' integrationTestImplementation \'com.unboundid:unboundid-ldapsdk:4.0.14\'\n' + - ' integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}"\n' + - ' integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14"\n' + - ' integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14"\n' + - ' integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14"\n' + - ' integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16"\n' + - ' integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5"indbugs:jsr305:3.0.2' + compileOnly 'com.google.code.findbugs:jsr305:3.0.2' runtimeOnly 'org.lz4:lz4-java:1.8.0' runtimeOnly 'org.slf4j:slf4j-api:1.7.36' runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" @@ -747,29 +725,29 @@ dependencies { compileOnly "org.opensearch:opensearch:${opensearch_version}" //integration test framework: - integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { - exclude(group: 'junit', module: 'junit') - } - integrationTestImplementation 'junit:junit:4.13.2' - integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" - integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" - integrationTestImplementation 'commons-io:commons-io:2.17.0' - integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" - integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" - integrationTestImplementation 'org.hamcrest:hamcrest:2.2' - integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" - integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" - integrationTestImplementation('org.awaitility:awaitility:4.2.2') { - exclude(group: 'org.hamcrest', module: 'hamcrest') - } - integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' - integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" - integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" - integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" - integrationTestImplementation "org.mockito:mockito-core:5.14.2" +// integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { +// exclude(group: 'junit', module: 'junit') +// } +// integrationTestImplementation 'junit:junit:4.13.2' +// integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" +// integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" +// integrationTestImplementation 'commons-io:commons-io:2.17.0' +// integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" +// integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" +// integrationTestImplementation 'org.hamcrest:hamcrest:2.2' +// integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" +// integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" +// integrationTestImplementation('org.awaitility:awaitility:4.2.2') { +// exclude(group: 'org.hamcrest', module: 'hamcrest') +// } +// integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' +// integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" +// integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" +// integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" +// integrationTestImplementation "org.mockito:mockito-core:5.14.2" //spotless implementation('com.google.googlejavaformat:google-java-format:1.24.0') { @@ -777,37 +755,38 @@ dependencies { } } -//allprojects { -// configurations { -// integrationTestImplementation.extendsFrom implementation -// integrationTestRuntimeOnly.extendsFrom runtimeOnly -// } -// dependencies { -// //integration test framework: -// integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { -// exclude(group: 'junit', module: 'junit') -// } -// integrationTestImplementation 'junit:junit:4.13.2' -// integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" -// integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" -// integrationTestImplementation 'commons-io:commons-io:2.17.0' -// integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" -// integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" -// integrationTestImplementation 'org.hamcrest:hamcrest:2.2' -// integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" -// integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" -// integrationTestImplementation('org.awaitility:awaitility:4.2.2') { -// exclude(group: 'org.hamcrest', module: 'hamcrest') -// } -// integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' -// integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" -// integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" -// integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" -// } -//} +allprojects { + configurations { + integrationTestImplementation.extendsFrom implementation + integrationTestRuntimeOnly.extendsFrom runtimeOnly + } + dependencies { + //integration test framework: + integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { + exclude(group: 'junit', module: 'junit') + } + integrationTestImplementation 'junit:junit:4.13.2' + integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" + integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" + integrationTestImplementation 'commons-io:commons-io:2.17.0' + integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" + integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" + integrationTestImplementation 'org.hamcrest:hamcrest:2.2' + integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" + integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" + integrationTestImplementation('org.awaitility:awaitility:4.2.2') { + exclude(group: 'org.hamcrest', module: 'hamcrest') + } + integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' + integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" + integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" + integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" + integrationTestImplementation "org.mockito:mockito-core:5.14.2" + } +} jar { libsDirName = '.' diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle index 89316763ea..518113e56f 100644 --- a/sample-extension-plugin/build.gradle +++ b/sample-extension-plugin/build.gradle @@ -68,6 +68,10 @@ dependencies { implementation 'com.nimbusds:nimbus-jose-jwt:9.41.2' implementation 'com.rfksystems:blake2b:2.0.0' implementation 'com.password4j:password4j:1.8.2' + + // Action privileges: check tables and compact collections + implementation 'com.selectivem.collections:special-collections-complete:1.4.0' + //JWT implementation "io.jsonwebtoken:jjwt-api:${jjwt_version}" implementation "io.jsonwebtoken:jjwt-impl:${jjwt_version}" diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 09a5a1f024..b24680d1be 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -43,6 +43,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; From 631c0317c083f128abacf5853f7fbbcd62fe6a31 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 15 Nov 2024 12:28:31 -0500 Subject: [PATCH 36/80] Exclude bytebuddy Signed-off-by: Craig Perkins --- build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7c5ab01546..1ac834d424 100644 --- a/build.gradle +++ b/build.gradle @@ -784,7 +784,10 @@ allprojects { integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" - integrationTestImplementation "org.mockito:mockito-core:5.14.2" + integrationTestImplementation("org.mockito:mockito-core:5.14.2") { + exclude(group: 'net.bytebuddy', module: 'byte-buddy') + } + integrationTestImplementation "net.bytebuddy:byte-buddy:${versions.bytebuddy}" } } From e36109175bf0dead895b575aa7fc3bc76db2b615 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 15 Nov 2024 12:52:39 -0500 Subject: [PATCH 37/80] Limit dependencies Signed-off-by: Craig Perkins --- sample-extension-plugin/build.gradle | 96 ++++++++-------------------- 1 file changed, 27 insertions(+), 69 deletions(-) diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle index 518113e56f..8e1e69c498 100644 --- a/sample-extension-plugin/build.gradle +++ b/sample-extension-plugin/build.gradle @@ -33,14 +33,27 @@ repositories { maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } +//buildscript { +// ext { +// dependencies { +// classpath "org.opensearch.gradle:build-tools:${opensearch_version}" +// } +// } +//} + configurations { all { resolutionStrategy { + force 'org.slf4j:slf4j-api:1.7.36' force 'commons-codec:commons-codec:1.17.1' force "org.apache.httpcomponents:httpclient:4.5.14" force "org.apache.httpcomponents:httpcore:4.4.16" force "com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1" force "org.hamcrest:hamcrest:2.2" + force "com.fasterxml.jackson:jackson-bom:${versions.jackson}" + force "com.fasterxml.jackson.core:jackson-core:${versions.jackson}" + force "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${versions.jackson}" + force "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}" } } } @@ -54,80 +67,25 @@ dependencies { testImplementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" testImplementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}" - implementation "org.opensearch.plugin:transport-netty4-client:${opensearch_version}" - implementation "org.opensearch.client:opensearch-rest-high-level-client:${opensearch_version}" - implementation "org.apache.httpcomponents.client5:httpclient5-cache:${versions.httpclient5}" - implementation "org.apache.httpcomponents:httpclient:${versions.httpclient}" - implementation "org.apache.httpcomponents:httpcore:${versions.httpcore}" - implementation "org.apache.httpcomponents:httpasyncclient:${versions.httpasyncclient}" - implementation "com.google.guava:guava:${guava_version}" - implementation 'org.greenrobot:eventbus-java:3.3.1' - implementation 'commons-cli:commons-cli:1.9.0' - implementation "org.bouncycastle:bcprov-jdk18on:${versions.bouncycastle}" - implementation 'org.ldaptive:ldaptive:1.2.3' - implementation 'com.nimbusds:nimbus-jose-jwt:9.41.2' - implementation 'com.rfksystems:blake2b:2.0.0' - implementation 'com.password4j:password4j:1.8.2' - + integrationTestImplementation "org.opensearch.plugin:transport-netty4-client:${opensearch_version}" + integrationTestImplementation "org.opensearch.client:opensearch-rest-high-level-client:${opensearch_version}" + integrationTestImplementation "com.google.guava:guava:${guava_version}" + integrationTestImplementation 'org.greenrobot:eventbus-java:3.3.1' + integrationTestImplementation 'org.ldaptive:ldaptive:1.2.3' + integrationTestImplementation 'com.password4j:password4j:1.8.2' // Action privileges: check tables and compact collections - implementation 'com.selectivem.collections:special-collections-complete:1.4.0' - - //JWT - implementation "io.jsonwebtoken:jjwt-api:${jjwt_version}" - implementation "io.jsonwebtoken:jjwt-impl:${jjwt_version}" - implementation "io.jsonwebtoken:jjwt-jackson:${jjwt_version}" + integrationTestImplementation 'com.selectivem.collections:special-collections-complete:1.4.0' // JSON patch - implementation 'com.flipkart.zjsonpatch:zjsonpatch:0.4.16' - implementation 'org.apache.commons:commons-collections4:4.4' - + integrationTestImplementation 'com.flipkart.zjsonpatch:zjsonpatch:0.4.16' //Password generation - implementation 'org.passay:passay:1.6.5' - - implementation "org.apache.kafka:kafka-clients:${kafka_version}" + integrationTestImplementation 'org.passay:passay:1.6.5' + integrationTestImplementation 'org.slf4j:slf4j-api:1.7.36' + integrationTestImplementation "org.apache.commons:commons-lang3:${versions.commonslang}" - runtimeOnly 'net.minidev:accessors-smart:2.5.1' + integrationTestImplementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" + integrationTestImplementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}" - runtimeOnly 'com.sun.activation:jakarta.activation:1.2.2' - runtimeOnly 'com.eclipsesource.minimal-json:minimal-json:0.9.5' - runtimeOnly 'commons-codec:commons-codec:1.17.1' - runtimeOnly 'org.cryptacular:cryptacular:1.2.7' - compileOnly 'com.google.errorprone:error_prone_annotations:2.33.0' - runtimeOnly 'com.sun.istack:istack-commons-runtime:4.2.0' - runtimeOnly 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.2' - runtimeOnly 'org.ow2.asm:asm:9.7.1' - - implementation "com.nulab-inc:zxcvbn:1.9.0" - - runtimeOnly 'com.google.guava:failureaccess:1.0.2' - runtimeOnly 'org.apache.commons:commons-text:1.12.0' - runtimeOnly "org.glassfish.jaxb:jaxb-runtime:${jaxb_version}" - runtimeOnly 'com.google.j2objc:j2objc-annotations:2.8' - compileOnly 'com.google.code.findbugs:jsr305:3.0.2' - runtimeOnly 'org.lz4:lz4-java:1.8.0' - runtimeOnly 'org.slf4j:slf4j-api:1.7.36' - runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" - runtimeOnly 'org.xerial.snappy:snappy-java:1.1.10.7' - runtimeOnly 'org.codehaus.woodstox:stax2-api:4.2.2' - runtimeOnly "org.glassfish.jaxb:txw2:${jaxb_version}" - runtimeOnly 'com.fasterxml.woodstox:woodstox-core:6.7.0' - runtimeOnly 'org.apache.ws.xmlschema:xmlschema-core:2.3.1' - runtimeOnly 'org.apache.santuario:xmlsec:2.3.4' - runtimeOnly "com.github.luben:zstd-jni:${versions.zstd}" - runtimeOnly 'org.checkerframework:checker-qual:3.47.0' - runtimeOnly "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" - runtimeOnly 'org.scala-lang.modules:scala-java8-compat_3:1.0.2' - - implementation "org.apache.commons:commons-lang3:${versions.commonslang}" - - implementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" - implementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}" - - compileOnly "org.opensearch:opensearch:${opensearch_version}" - - //spotless - implementation('com.google.googlejavaformat:google-java-format:1.24.0') { - exclude group: 'com.google.guava' - } + integrationTestImplementation "org.opensearch:opensearch:${opensearch_version}" } def es_tmp_dir = rootProject.file('build/private/es_tmp').absoluteFile From 3cf01d98cd2fc8767697b23875729fe8c3efb2f2 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 15 Nov 2024 14:32:08 -0500 Subject: [PATCH 38/80] Only assemble root project Signed-off-by: Craig Perkins --- .github/workflows/plugin_install.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/plugin_install.yml b/.github/workflows/plugin_install.yml index 3f8d61795c..c427b160c4 100644 --- a/.github/workflows/plugin_install.yml +++ b/.github/workflows/plugin_install.yml @@ -32,7 +32,7 @@ jobs: uses: gradle/gradle-build-action@v3 with: cache-disabled: true - arguments: assemble + arguments: :assemble # Move and rename the plugin for installation - name: Move and rename the plugin for installation From ebeb92a27d40b630b765e46b8dab62738f875af9 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 15 Nov 2024 15:06:14 -0500 Subject: [PATCH 39/80] root project assemble Signed-off-by: Craig Perkins --- .github/actions/create-bwc-build/action.yaml | 2 +- .github/workflows/ci.yml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/create-bwc-build/action.yaml b/.github/actions/create-bwc-build/action.yaml index 8960849333..0f9e373b16 100644 --- a/.github/actions/create-bwc-build/action.yaml +++ b/.github/actions/create-bwc-build/action.yaml @@ -42,7 +42,7 @@ runs: uses: gradle/gradle-build-action@v2 with: cache-disabled: true - arguments: assemble + arguments: :assemble build-root-directory: ${{ inputs.plugin-branch }} - id: get-opensearch-version diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12c24861f2..46460167c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -208,7 +208,7 @@ jobs: - uses: github/codeql-action/init@v3 with: languages: java - - run: ./gradlew clean assemble + - run: ./gradlew clean :assemble - uses: github/codeql-action/analyze@v3 build-artifact-names: @@ -238,13 +238,13 @@ jobs: echo ${{ env.SECURITY_PLUGIN_VERSION_ONLY_NUMBER }} echo ${{ env.TEST_QUALIFIER }} - - run: ./gradlew clean assemble && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION }}.zip + - run: ./gradlew clean :assemble && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION }}.zip - - run: ./gradlew clean assemble -Dbuild.snapshot=false && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION_NO_SNAPSHOT }}.zip + - run: ./gradlew clean :assemble -Dbuild.snapshot=false && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION_NO_SNAPSHOT }}.zip - - run: ./gradlew clean assemble -Dbuild.snapshot=false -Dbuild.version_qualifier=${{ env.TEST_QUALIFIER }} && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION_ONLY_NUMBER }}-${{ env.TEST_QUALIFIER }}.zip + - run: ./gradlew clean :assemble -Dbuild.snapshot=false -Dbuild.version_qualifier=${{ env.TEST_QUALIFIER }} && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION_ONLY_NUMBER }}-${{ env.TEST_QUALIFIER }}.zip - - run: ./gradlew clean assemble -Dbuild.version_qualifier=${{ env.TEST_QUALIFIER }} && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION_ONLY_NUMBER }}-${{ env.TEST_QUALIFIER }}-SNAPSHOT.zip + - run: ./gradlew clean :assemble -Dbuild.version_qualifier=${{ env.TEST_QUALIFIER }} && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION_ONLY_NUMBER }}-${{ env.TEST_QUALIFIER }}-SNAPSHOT.zip - run: ./gradlew clean publishPluginZipPublicationToZipStagingRepository && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION }}.zip && test -s ./build/distributions/opensearch-security-${{ env.SECURITY_PLUGIN_VERSION }}.pom From 328b749f776a7d14bf228e0997f40d8b9b6635aa Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 15 Nov 2024 15:21:24 -0500 Subject: [PATCH 40/80] Only on root project Signed-off-by: Craig Perkins --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46460167c4..fae88ecad2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -151,7 +151,7 @@ jobs: with: cache-disabled: true arguments: | - integrationTest -Dbuild.snapshot=false --tests org.opensearch.security.ResourceFocusedTests + :integrationTest -Dbuild.snapshot=false --tests org.opensearch.security.ResourceFocusedTests backward-compatibility-build: runs-on: ubuntu-latest From 65190a1f20a8c5e5f1bd2a9cd9ca2e509b959ce6 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 2 Dec 2024 13:22:31 -0500 Subject: [PATCH 41/80] uncomment Signed-off-by: Craig Perkins --- build.gradle | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/build.gradle b/build.gradle index 1ac834d424..0bd0decacb 100644 --- a/build.gradle +++ b/build.gradle @@ -725,29 +725,29 @@ dependencies { compileOnly "org.opensearch:opensearch:${opensearch_version}" //integration test framework: -// integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { -// exclude(group: 'junit', module: 'junit') -// } -// integrationTestImplementation 'junit:junit:4.13.2' -// integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" -// integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" -// integrationTestImplementation 'commons-io:commons-io:2.17.0' -// integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" -// integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" -// integrationTestImplementation 'org.hamcrest:hamcrest:2.2' -// integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" -// integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" -// integrationTestImplementation('org.awaitility:awaitility:4.2.2') { -// exclude(group: 'org.hamcrest', module: 'hamcrest') -// } -// integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' -// integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" -// integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" -// integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" -// integrationTestImplementation "org.mockito:mockito-core:5.14.2" + integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { + exclude(group: 'junit', module: 'junit') + } + integrationTestImplementation 'junit:junit:4.13.2' + integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" + integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" + integrationTestImplementation 'commons-io:commons-io:2.17.0' + integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" + integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" + integrationTestImplementation 'org.hamcrest:hamcrest:2.2' + integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" + integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" + integrationTestImplementation('org.awaitility:awaitility:4.2.2') { + exclude(group: 'org.hamcrest', module: 'hamcrest') + } + integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' + integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" + integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" + integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" + integrationTestImplementation "org.mockito:mockito-core:5.14.2" //spotless implementation('com.google.googlejavaformat:google-java-format:1.24.0') { From c01157d873c4849cafe0a7d07167a52746877a3c Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 2 Dec 2024 13:25:13 -0500 Subject: [PATCH 42/80] Merge with main Signed-off-by: Craig Perkins --- build.gradle | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index 5242f203a2..d6b746da41 100644 --- a/build.gradle +++ b/build.gradle @@ -725,29 +725,29 @@ dependencies { compileOnly "org.opensearch:opensearch:${opensearch_version}" //integration test framework: - integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { - exclude(group: 'junit', module: 'junit') - } - integrationTestImplementation 'junit:junit:4.13.2' - integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" - integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" - integrationTestImplementation 'commons-io:commons-io:2.18.0' - integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" - integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" - integrationTestImplementation 'org.hamcrest:hamcrest:2.2' - integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" - integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" - integrationTestImplementation('org.awaitility:awaitility:4.2.2') { - exclude(group: 'org.hamcrest', module: 'hamcrest') - } - integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' - integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" - integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" - integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" - integrationTestImplementation "org.mockito:mockito-core:5.14.2" +// integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { +// exclude(group: 'junit', module: 'junit') +// } +// integrationTestImplementation 'junit:junit:4.13.2' +// integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" +// integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" +// integrationTestImplementation 'commons-io:commons-io:2.18.0' +// integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" +// integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" +// integrationTestImplementation 'org.hamcrest:hamcrest:2.2' +// integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" +// integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" +// integrationTestImplementation('org.awaitility:awaitility:4.2.2') { +// exclude(group: 'org.hamcrest', module: 'hamcrest') +// } +// integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' +// integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" +// integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" +// integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" +// integrationTestImplementation "org.mockito:mockito-core:5.14.2" //spotless implementation('com.google.googlejavaformat:google-java-format:1.25.0') { @@ -768,7 +768,7 @@ allprojects { integrationTestImplementation 'junit:junit:4.13.2' integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" - integrationTestImplementation 'commons-io:commons-io:2.17.0' + integrationTestImplementation 'commons-io:commons-io:2.18.0' integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" integrationTestImplementation 'org.hamcrest:hamcrest:2.2' From 25e946dc893a2d20e9b0535a0c6385491f0ba4d8 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 10 Dec 2024 20:54:15 -0500 Subject: [PATCH 43/80] Add allowed_actions to share with entry Signed-off-by: Craig Perkins --- ...UpdateSampleResourceSharingRestAction.java | 6 +++- .../SampleExtensionPluginIT.java | 4 ++- .../opensearch/security/spi/ShareWith.java | 20 ++++++++--- .../UpdateResourceSharingTransportAction.java | 1 + .../resource/ResourceSharingEntry.java | 5 +-- .../resource/ResourceSharingListener.java | 33 ++----------------- 6 files changed, 30 insertions(+), 39 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java index 1b6ae279fc..0b55ff83da 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java @@ -50,7 +50,11 @@ public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client } Map shareWithMap = (Map) source.get("share_with"); - ShareWith shareWith = new ShareWith((List) shareWithMap.get("users"), (List) shareWithMap.get("backend_roles")); + ShareWith shareWith = new ShareWith( + (List) shareWithMap.get("users"), + (List) shareWithMap.get("backend_roles"), + (List) shareWithMap.get("allowed_actions") + ); final UpdateResourceSharingRequest updateSampleResourceSharingRequest = new UpdateResourceSharingRequest<>( resourceId, diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index a8ae480353..d28dffbe7e 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -178,7 +178,9 @@ public void testCreateSampleResource() throws IOException, InterruptedException System.out.println("resourceSharingResponse: " + resourceSharingResponseMap); Request updateSharingRequest = new Request("PUT", "/_plugins/resource_sharing_example/resource/update_sharing/" + resourceId); - updateSharingRequest.setEntity(new StringEntity("{\"share_with\":{\"users\": [\"admin\"], \"backend_roles\": []}}")); + updateSharingRequest.setEntity( + new StringEntity("{\"share_with\":{\"users\": [\"admin\"], \"backend_roles\": [], \"allowed_actions\": [\"*\"]}}") + ); requestOptions.addHeader("Content-Type", "application/json"); updateSharingRequest.setOptions(requestOptions); Response updateResponse = client().performRequest(updateSharingRequest); diff --git a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java index 359d8145d6..6ed2ae1739 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java +++ b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java @@ -11,20 +11,23 @@ public class ShareWith implements NamedWriteable, ToXContentFragment { - public final static ShareWith PRIVATE = new ShareWith(List.of(), List.of()); - public final static ShareWith PUBLIC = new ShareWith(List.of("*"), List.of("*")); + public final static ShareWith PRIVATE = new ShareWith(List.of(), List.of(), List.of("*")); + public final static ShareWith PUBLIC = new ShareWith(List.of("*"), List.of("*"), List.of("*")); + private final List allowedActions; private final List users; private final List backendRoles; - public ShareWith(List users, List backendRoles) { + public ShareWith(List users, List backendRoles, List allowedActions) { this.users = users; this.backendRoles = backendRoles; + this.allowedActions = allowedActions; } public ShareWith(StreamInput in) throws IOException { this.users = in.readStringList(); this.backendRoles = in.readStringList(); + this.allowedActions = in.readStringList(); } public List getUsers() { @@ -35,9 +38,17 @@ public List getBackendRoles() { return backendRoles; } + public List getAllowedActions() { + return allowedActions; + } + @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject().field("users", users).field("backend_roles", backendRoles).endObject(); + return builder.startObject() + .field("users", users) + .field("backend_roles", backendRoles) + .field("allowed_actions", allowedActions) + .endObject(); } @Override @@ -49,5 +60,6 @@ public String getWriteableName() { public void writeTo(StreamOutput out) throws IOException { out.writeStringCollection(users); out.writeStringCollection(backendRoles); + out.writeStringCollection(allowedActions); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java index 50cc72343a..78d9c1a827 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java @@ -98,6 +98,7 @@ public void onResponse(SearchResponse searchResponse) { { builder.field("users", request.getShareWith().getUsers()); builder.field("backend_roles", request.getShareWith().getBackendRoles()); + builder.field("allowed_actions", request.getShareWith().getAllowedActions()); } builder.endObject(); } diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java index 4e28c011b7..0e1f729b08 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java @@ -12,6 +12,7 @@ package org.opensearch.security.resource; import java.io.IOException; +import java.util.List; import org.opensearch.core.xcontent.ToXContentFragment; import org.opensearch.core.xcontent.XContentBuilder; @@ -22,9 +23,9 @@ public class ResourceSharingEntry implements ToXContentFragment { private final String resourceIndex; private final String resourceId; private final ResourceUser resourceUser; - private final ShareWith shareWith; + private final List shareWith; - public ResourceSharingEntry(String resourceIndex, String resourceId, ResourceUser resourceUser, ShareWith shareWith) { + public ResourceSharingEntry(String resourceIndex, String resourceId, ResourceUser resourceUser, List shareWith) { this.resourceIndex = resourceIndex; this.resourceId = resourceId; this.resourceUser = resourceUser; diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java index ba00f98860..c6fb4b18b4 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -12,6 +12,7 @@ package org.opensearch.security.resource; import java.io.IOException; +import java.util.List; import java.util.concurrent.Callable; import org.apache.logging.log4j.LogManager; @@ -111,40 +112,10 @@ private void createResourceSharingIndexIfNotExists(Callable callable) { } } - // public void indexResourceSharing( - // String resourceId, - // Resource resource, - // ResourceUser resourceUser, - // ShareWith shareWith, - // ActionListener listener - // ) throws IOException { - // createResourceSharingIndexIfNotExists(() -> { - // ResourceSharingEntry entry = new ResourceSharingEntry(resource.getResourceIndex(), resourceId, resourceUser, shareWith); - // - // IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) - // .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) - // .setSource(entry.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) - // .request(); - // - // log.warn("Index Request: " + ir.toString()); - // - // ActionListener irListener = ActionListener.wrap(idxResponse -> { - // log.warn("Created " + RESOURCE_SHARING_INDEX + " entry."); - // listener.onResponse(idxResponse); - // }, (failResponse) -> { - // log.error(failResponse.getMessage()); - // log.error("Failed to create " + RESOURCE_SHARING_INDEX + " entry."); - // listener.onFailure(failResponse); - // }); - // client.index(ir, irListener); - // return null; - // }); - // } - public void indexResourceSharing(String resourceId, String resourceIndex, ResourceUser resourceUser, ShareWith shareWith) throws IOException { createResourceSharingIndexIfNotExists(() -> { - ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, shareWith); + ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, List.of(shareWith)); IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) From 586d26c9891bcbe5edf727784abe73ee0eeb4304 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 12 Dec 2024 15:18:32 -0500 Subject: [PATCH 44/80] Create UpdateResourceAction Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 5 +- .../actions/UpdateSampleResourceAction.java | 29 +++++++ .../actions/UpdateSampleResourceRequest.java | 53 ++++++++++++ .../actions/UpdateSampleResourceResponse.java | 57 +++++++++++++ .../UpdateSampleResourceRestAction.java | 57 +++++++++++++ .../UpdateSampleResourceTransportAction.java | 80 +++++++++++++++++++ .../UpdateResourceSharingTransportAction.java | 33 -------- 7 files changed, 280 insertions(+), 34 deletions(-) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRequest.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceResponse.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRestAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index fd2029f50b..b2d6c85f1f 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -45,9 +45,11 @@ import org.opensearch.security.sampleextension.actions.ListSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.ListSampleResourceTransportAction; import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.actions.UpdateSampleResourceAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingRestAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingTransportAction; +import org.opensearch.security.sampleextension.actions.UpdateSampleResourceTransportAction; import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; import org.opensearch.security.spi.DefaultResourceSharingService; import org.opensearch.security.spi.ResourceSharingService; @@ -115,7 +117,8 @@ public List getRestHandlers( return List.of( new ActionHandler<>(CreateSampleResourceAction.INSTANCE, CreateSampleResourceTransportAction.class), new ActionHandler<>(ListSampleResourceAction.INSTANCE, ListSampleResourceTransportAction.class), - new ActionHandler<>(UpdateSampleResourceSharingAction.INSTANCE, UpdateSampleResourceSharingTransportAction.class) + new ActionHandler<>(UpdateSampleResourceSharingAction.INSTANCE, UpdateSampleResourceSharingTransportAction.class), + new ActionHandler<>(UpdateSampleResourceAction.INSTANCE, UpdateSampleResourceTransportAction.class) ); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceAction.java new file mode 100644 index 0000000000..c3037a03cf --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceAction.java @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import org.opensearch.action.ActionType; + +/** + * Action to create a sample resource + */ +public class UpdateSampleResourceAction extends ActionType { + /** + * Create sample resource action instance + */ + public static final UpdateSampleResourceAction INSTANCE = new UpdateSampleResourceAction(); + /** + * Create sample resource action name + */ + public static final String NAME = "cluster:admin/sampleresource/update"; + + private UpdateSampleResourceAction() { + super(NAME, UpdateSampleResourceResponse::new); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRequest.java new file mode 100644 index 0000000000..8dd86933a4 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRequest.java @@ -0,0 +1,53 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import java.io.IOException; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; + +/** + * Request object for ListSampleResource transport action + */ +public class UpdateSampleResourceRequest extends ActionRequest { + + private String resourceId; + private String name; + + public UpdateSampleResourceRequest(String resourceId, String name) { + this.resourceId = resourceId; + this.name = name; + } + + public String getResourceId() { + return resourceId; + } + + public String getName() { + return name; + } + + /** + * Constructor with stream input + * @param in the stream input + * @throws IOException IOException + */ + public UpdateSampleResourceRequest(final StreamInput in) throws IOException {} + + @Override + public void writeTo(final StreamOutput out) throws IOException {} + + @Override + public ActionRequestValidationException validate() { + return null; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceResponse.java new file mode 100644 index 0000000000..aa103d1440 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceResponse.java @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import java.io.IOException; +import java.util.List; + +import org.opensearch.core.action.ActionResponse; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.spi.AbstractResource; + +/** + * Response to a ListSampleResourceRequest + */ +public class UpdateSampleResourceResponse extends ActionResponse implements ToXContentObject { + private final List resources; + + /** + * Default constructor + * + * @param resources The resources + */ + public UpdateSampleResourceResponse(List resources) { + this.resources = resources; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeList(resources); + } + + /** + * Constructor with StreamInput + * + * @param in the stream input + */ + public UpdateSampleResourceResponse(final StreamInput in) throws IOException { + resources = in.readList(SampleResource::new); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.array("resources", (Object[]) resources.toArray(new AbstractResource[0])); + builder.endObject(); + return builder; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRestAction.java new file mode 100644 index 0000000000..01c0dc3aa7 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRestAction.java @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.opensearch.client.node.NodeClient; +import org.opensearch.core.xcontent.XContentParser; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.RestRequest; +import org.opensearch.rest.action.RestToXContentListener; + +import static java.util.Collections.singletonList; +import static org.opensearch.rest.RestRequest.Method.PUT; + +public class UpdateSampleResourceRestAction extends BaseRestHandler { + + public UpdateSampleResourceRestAction() {} + + @Override + public List routes() { + return singletonList(new Route(PUT, "/_plugins/resource_sharing_example/resource/update/{id}")); + } + + @Override + public String getName() { + return "update_sample_resource"; + } + + @SuppressWarnings("unchecked") + @Override + public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + String resourceId = request.param("id"); + Map source; + try (XContentParser parser = request.contentParser()) { + source = parser.map(); + } + + String name = (String) source.get("name"); + + // TODO Update the request obj + final UpdateSampleResourceRequest updateSampleResourceRequest = new UpdateSampleResourceRequest(resourceId, name); + return channel -> client.executeLocally( + UpdateSampleResourceAction.INSTANCE, + updateSampleResourceRequest, + new RestToXContentListener<>(channel) + ); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java new file mode 100644 index 0000000000..76c0a7e2c1 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java @@ -0,0 +1,80 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions; + +import java.io.IOException; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.action.index.IndexRequest; +import org.opensearch.action.index.IndexResponse; +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.action.support.WriteRequest; +import org.opensearch.client.Client; +import org.opensearch.common.inject.Inject; +import org.opensearch.core.action.ActionListener; +import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; + +/** + * Transport action for UpdateSampleResource. + */ +public class UpdateSampleResourceTransportAction extends HandledTransportAction { + private static final Logger log = LogManager.getLogger(UpdateSampleResourceTransportAction.class); + + private final Client nodeClient; + private final String resourceIndex; + + @Inject + public UpdateSampleResourceTransportAction( + TransportService transportService, + ActionFilters actionFilters, + Client nodeClient, + String resourceIndex + ) { + super(UpdateSampleResourceAction.NAME, transportService, actionFilters, UpdateSampleResourceRequest::new); + this.nodeClient = nodeClient; + this.resourceIndex = resourceIndex; + } + + @Override + protected void doExecute(Task task, UpdateSampleResourceRequest request, ActionListener actionListener) { + indexResource(request, actionListener); + } + + private void indexResource(UpdateSampleResourceRequest request, ActionListener listener) { + log.warn("resourceId: " + request.getResourceId()); + String name = request.getName(); + SampleResource updatedResource = new SampleResource(); + updatedResource.setName(name); + try { + IndexRequest ir = nodeClient.prepareIndex(resourceIndex) + .setId(request.getResourceId()) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .setSource(updatedResource.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) + .request(); + + log.warn("Index Request: " + ir.toString()); + + ActionListener irListener = ActionListener.wrap(idxResponse -> { + log.info("Updated resource: " + idxResponse.toString()); + listener.onResponse(new UpdateSampleResourceResponse(List.of(updatedResource))); + }, listener::onFailure); + nodeClient.index(ir, irListener); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java index 78d9c1a827..a4b15bdf81 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java @@ -15,13 +15,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.opensearch.action.index.IndexRequest; -import org.opensearch.action.index.IndexResponse; import org.opensearch.action.search.SearchRequest; import org.opensearch.action.search.SearchResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; -import org.opensearch.action.support.WriteRequest; import org.opensearch.action.update.UpdateRequest; import org.opensearch.action.update.UpdateResponse; import org.opensearch.client.Client; @@ -29,7 +26,6 @@ import org.opensearch.common.xcontent.XContentFactory; import org.opensearch.core.action.ActionListener; import org.opensearch.core.common.io.stream.Writeable; -import org.opensearch.core.xcontent.ToXContent; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.index.query.BoolQueryBuilder; import org.opensearch.index.query.QueryBuilders; @@ -40,8 +36,6 @@ import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; -import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; - /** * Transport action for CreateSampleResource. */ @@ -133,31 +127,4 @@ public void onFailure(Exception e) { }); } } - - private void indexResource(CreateResourceRequest request, ActionListener listener) { - log.warn("Sample name: " + request.getResource()); - AbstractResource sample = request.getResource(); - try { - IndexRequest ir = nodeClient.prepareIndex(resourceIndex) - .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) - .setSource(sample.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)) - .request(); - - log.warn("Index Request: " + ir.toString()); - - // ActionListener resourceSharingListener = ActionListener.wrap(resourceSharingResponse -> { - // listener.onResponse(new CreateResourceResponse("Created resource: " + resourceSharingResponse.toString())); - // }, listener::onFailure); - - ActionListener irListener = ActionListener.wrap(idxResponse -> { - log.info("Created resource: " + idxResponse.toString()); - // ResourceSharingUtils.getInstance() - // .indexResourceSharing(idxResponse.getId(), sample, ShareWith.PUBLIC, resourceSharingListener); - listener.onResponse(new CreateResourceResponse("Created resource: " + idxResponse.toString())); - }, listener::onFailure); - nodeClient.index(ir, irListener); - } catch (IOException e) { - throw new RuntimeException(e); - } - } } From fd491572357b276c17acab55c068f6c2f4a65b96 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 12 Dec 2024 16:08:17 -0500 Subject: [PATCH 45/80] Return resourceId in created response Signed-off-by: Craig Perkins --- .../SampleExtensionPluginTests.java | 10 +++ .../SampleExtensionPluginIT.java | 61 +------------------ .../spi/actions/CreateResourceResponse.java | 14 ++--- .../CreateResourceTransportAction.java | 2 +- 4 files changed, 20 insertions(+), 67 deletions(-) diff --git a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java index 7528ffb8df..7ccdc0b755 100644 --- a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java +++ b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java @@ -55,4 +55,14 @@ public void testSecurityRoles() throws Exception { } } + @Test + public void testCreateAndUpdateOwnSampleResource() throws Exception { + try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) { + String sampleResource = "{\"name\":\"sample\"}"; + HttpResponse response = client.postJson("_plugins/resource_sharing_example/resource", sampleResource); + response.assertStatusCode(HttpStatus.SC_OK); + System.out.println("Response: " + response.getBody()); + } + } + } diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index d28dffbe7e..3fec88b4bd 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -13,8 +13,6 @@ import java.util.Base64; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -88,18 +86,8 @@ public void testCreateSampleResource() throws IOException, InterruptedException Response response2 = client().performRequest(createRequest2); ObjectMapper objectMapper = new ObjectMapper(); JsonNode indexResponseNode = objectMapper.readTree(response2.getEntity().getContent()); - // Regular expression to capture the value of "id" - Pattern pattern = Pattern.compile("id=([a-zA-Z0-9_-]+)"); - Matcher matcher = pattern.matcher(indexResponseNode.get("message").asText()); - - String resourceId = ""; - if (matcher.find()) { - resourceId = matcher.group(1); // Extract the ID - System.out.println("Extracted ID: " + resourceId); - } else { - System.out.println("ID not found."); - } - System.out.println("indexResponseNode: " + indexResponseNode); + + String resourceId = indexResponseNode.get("resourceId").asText(); Map createResourceResponse2 = JsonXContent.jsonXContent.createParser( NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, @@ -110,51 +98,6 @@ public void testCreateSampleResource() throws IOException, InterruptedException // Sleep to give ResourceSharingListener time to create the .resource-sharing index Thread.sleep(1000); - // TODO Expose this via API to update sharing - // try { - // // Create the request - // Request request = new Request("POST", "/.resource-sharing/_update_by_query"); - // - // // Build the request body using XContentBuilder - // XContentBuilder builder = XContentFactory.jsonBuilder(); - // builder.startObject(); - // { - // builder.startObject("query"); - // { - // builder.startObject("term"); - // { - // builder.field("resource_user", "craig"); - // } - // builder.endObject(); - // } - // builder.endObject(); - // - // builder.startObject("script"); - // { - // builder.field("source", "ctx._source.share_with.users = ['admin']"); - // builder.field("lang", "painless"); - // } - // builder.endObject(); - // } - // builder.endObject(); - // - // // Set the request body - // request.setJsonEntity(builder.toString()); - // - // System.out.println("updateByQueryRequest: " + request); - // - // // Execute the request using the admin client - // Response updateByQueryResponse = adminClient().performRequest(request); - // - // // Handle the response - // System.out.println("Update request executed successfully. Status: " + response.getStatusLine().getStatusCode()); - // System.out.println("updateByQueryResponse: " + updateByQueryResponse.toString()); - // - // } catch (IOException e) { - // // Handle the exception (e.g., log it or throw a custom exception) - // System.err.println("Error executing update request: " + e.getMessage()); - // } - Request listRequest = new Request("GET", "/_plugins/resource_sharing_example/resource"); listRequest.setOptions(requestOptions); Response listResponse = client().performRequest(listRequest); diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java index 958ca9fbbf..8e13c78c4e 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java @@ -20,20 +20,20 @@ * Response to a CreateSampleResourceRequest */ public class CreateResourceResponse extends ActionResponse implements ToXContentObject { - private final String message; + private final String resourceId; /** * Default constructor * - * @param message The message + * @param resourceId The resourceId */ - public CreateResourceResponse(String message) { - this.message = message; + public CreateResourceResponse(String resourceId) { + this.resourceId = resourceId; } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(message); + out.writeString(resourceId); } /** @@ -42,13 +42,13 @@ public void writeTo(StreamOutput out) throws IOException { * @param in the stream input */ public CreateResourceResponse(final StreamInput in) throws IOException { - message = in.readString(); + resourceId = in.readString(); } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.field("message", message); + builder.field("resourceId", resourceId); builder.endObject(); return builder; } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java index fe089cbab9..4df474019a 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java @@ -91,7 +91,7 @@ private void createResource(CreateResourceRequest request, ActionListener Date: Thu, 12 Dec 2024 16:18:27 -0500 Subject: [PATCH 46/80] Add integ tests where user creates a sample resource and updates it Signed-off-by: Craig Perkins --- .../sampleextension/SampleExtensionPluginTests.java | 9 +++++++++ .../security/sampleextension/SampleExtensionPlugin.java | 2 ++ .../actions/UpdateSampleResourceTransportAction.java | 8 +++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java index 7ccdc0b755..22bc4d1973 100644 --- a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java +++ b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java @@ -62,6 +62,15 @@ public void testCreateAndUpdateOwnSampleResource() throws Exception { HttpResponse response = client.postJson("_plugins/resource_sharing_example/resource", sampleResource); response.assertStatusCode(HttpStatus.SC_OK); System.out.println("Response: " + response.getBody()); + + String resourceId = response.getTextFromJsonBody("/resourceId"); + + System.out.println("resourceId: " + resourceId); + + String sampleResourceUpdated = "{\"name\":\"sampleUpdated\"}"; + HttpResponse updateResponse = client.putJson("_plugins/resource_sharing_example/resource/update/" + resourceId, sampleResourceUpdated); + updateResponse.assertStatusCode(HttpStatus.SC_OK); + System.out.println("Update Response: " + updateResponse.getBody()); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index b2d6c85f1f..e028be9a01 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -46,6 +46,7 @@ import org.opensearch.security.sampleextension.actions.ListSampleResourceTransportAction; import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceAction; +import org.opensearch.security.sampleextension.actions.UpdateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingRestAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingTransportAction; @@ -108,6 +109,7 @@ public List getRestHandlers( return List.of( new CreateSampleResourceRestAction(), new ListSampleResourceRestAction(), + new UpdateSampleResourceRestAction(), new UpdateSampleResourceSharingRestAction() ); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java index 76c0a7e2c1..dd00625bc5 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java @@ -27,6 +27,7 @@ import org.opensearch.transport.TransportService; import static org.opensearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; /** * Transport action for UpdateSampleResource. @@ -35,18 +36,15 @@ public class UpdateSampleResourceTransportAction extends HandledTransportAction< private static final Logger log = LogManager.getLogger(UpdateSampleResourceTransportAction.class); private final Client nodeClient; - private final String resourceIndex; @Inject public UpdateSampleResourceTransportAction( TransportService transportService, ActionFilters actionFilters, - Client nodeClient, - String resourceIndex + Client nodeClient ) { super(UpdateSampleResourceAction.NAME, transportService, actionFilters, UpdateSampleResourceRequest::new); this.nodeClient = nodeClient; - this.resourceIndex = resourceIndex; } @Override @@ -60,7 +58,7 @@ private void indexResource(UpdateSampleResourceRequest request, ActionListener Date: Thu, 12 Dec 2024 16:30:54 -0500 Subject: [PATCH 47/80] Separate package Signed-off-by: Craig Perkins --- .../SampleExtensionPluginTests.java | 5 ++++- .../sampleextension/SampleExtensionPlugin.java | 6 +++--- .../UpdateSampleResourceAction.java | 2 +- .../UpdateSampleResourceRequest.java | 2 +- .../UpdateSampleResourceResponse.java | 18 ++++++++---------- .../UpdateSampleResourceRestAction.java | 2 +- .../UpdateSampleResourceTransportAction.java | 12 ++++-------- 7 files changed, 22 insertions(+), 25 deletions(-) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => update}/UpdateSampleResourceAction.java (92%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => update}/UpdateSampleResourceRequest.java (95%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => update}/UpdateSampleResourceResponse.java (69%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => update}/UpdateSampleResourceRestAction.java (96%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => update}/UpdateSampleResourceTransportAction.java (90%) diff --git a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java index 22bc4d1973..8a7b106a1c 100644 --- a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java +++ b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java @@ -68,7 +68,10 @@ public void testCreateAndUpdateOwnSampleResource() throws Exception { System.out.println("resourceId: " + resourceId); String sampleResourceUpdated = "{\"name\":\"sampleUpdated\"}"; - HttpResponse updateResponse = client.putJson("_plugins/resource_sharing_example/resource/update/" + resourceId, sampleResourceUpdated); + HttpResponse updateResponse = client.putJson( + "_plugins/resource_sharing_example/resource/update/" + resourceId, + sampleResourceUpdated + ); updateResponse.assertStatusCode(HttpStatus.SC_OK); System.out.println("Update Response: " + updateResponse.getBody()); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index e028be9a01..f014e39980 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -45,12 +45,12 @@ import org.opensearch.security.sampleextension.actions.ListSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.ListSampleResourceTransportAction; import org.opensearch.security.sampleextension.actions.SampleResource; -import org.opensearch.security.sampleextension.actions.UpdateSampleResourceAction; -import org.opensearch.security.sampleextension.actions.UpdateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingRestAction; import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingTransportAction; -import org.opensearch.security.sampleextension.actions.UpdateSampleResourceTransportAction; +import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceAction; +import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceTransportAction; import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; import org.opensearch.security.spi.DefaultResourceSharingService; import org.opensearch.security.spi.ResourceSharingService; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceAction.java similarity index 92% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceAction.java index c3037a03cf..18f8f1d3fe 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.update; import org.opensearch.action.ActionType; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRequest.java similarity index 95% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRequest.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRequest.java index 8dd86933a4..ad3118e577 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRequest.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.update; import java.io.IOException; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceResponse.java similarity index 69% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceResponse.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceResponse.java index aa103d1440..dcd996db9b 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceResponse.java @@ -6,36 +6,34 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.update; import java.io.IOException; -import java.util.List; import org.opensearch.core.action.ActionResponse; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.spi.AbstractResource; /** * Response to a ListSampleResourceRequest */ public class UpdateSampleResourceResponse extends ActionResponse implements ToXContentObject { - private final List resources; + private final String resourceId; /** * Default constructor * - * @param resources The resources + * @param resourceId The resourceId */ - public UpdateSampleResourceResponse(List resources) { - this.resources = resources; + public UpdateSampleResourceResponse(String resourceId) { + this.resourceId = resourceId; } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeList(resources); + out.writeString(resourceId); } /** @@ -44,13 +42,13 @@ public void writeTo(StreamOutput out) throws IOException { * @param in the stream input */ public UpdateSampleResourceResponse(final StreamInput in) throws IOException { - resources = in.readList(SampleResource::new); + resourceId = in.readString(); } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.array("resources", (Object[]) resources.toArray(new AbstractResource[0])); + builder.field("resourceId", resourceId); builder.endObject(); return builder; } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRestAction.java similarity index 96% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRestAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRestAction.java index 01c0dc3aa7..8658193c9b 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRestAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.update; import java.io.IOException; import java.util.List; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceTransportAction.java similarity index 90% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceTransportAction.java index dd00625bc5..443fa01728 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceTransportAction.java @@ -6,10 +6,9 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.update; import java.io.IOException; -import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -23,6 +22,7 @@ import org.opensearch.common.inject.Inject; import org.opensearch.core.action.ActionListener; import org.opensearch.core.xcontent.ToXContent; +import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -38,11 +38,7 @@ public class UpdateSampleResourceTransportAction extends HandledTransportAction< private final Client nodeClient; @Inject - public UpdateSampleResourceTransportAction( - TransportService transportService, - ActionFilters actionFilters, - Client nodeClient - ) { + public UpdateSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { super(UpdateSampleResourceAction.NAME, transportService, actionFilters, UpdateSampleResourceRequest::new); this.nodeClient = nodeClient; } @@ -68,7 +64,7 @@ private void indexResource(UpdateSampleResourceRequest request, ActionListener irListener = ActionListener.wrap(idxResponse -> { log.info("Updated resource: " + idxResponse.toString()); - listener.onResponse(new UpdateSampleResourceResponse(List.of(updatedResource))); + listener.onResponse(new UpdateSampleResourceResponse(updatedResource.getResourceId())); }, listener::onFailure); nodeClient.index(ir, irListener); } catch (IOException e) { From 285dbbf3a04fae274d1e77565a31b5a74a6c67ae Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 12 Dec 2024 16:32:11 -0500 Subject: [PATCH 48/80] reorg Signed-off-by: Craig Perkins --- .../security/sampleextension/SampleExtensionPlugin.java | 6 +++--- .../{ => sharing}/UpdateSampleResourceSharingAction.java | 2 +- .../UpdateSampleResourceSharingRestAction.java | 3 ++- .../UpdateSampleResourceSharingTransportAction.java | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => sharing}/UpdateSampleResourceSharingAction.java (93%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => sharing}/UpdateSampleResourceSharingRestAction.java (94%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => sharing}/UpdateSampleResourceSharingTransportAction.java (90%) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index f014e39980..c6d541f7f0 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -45,9 +45,9 @@ import org.opensearch.security.sampleextension.actions.ListSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.ListSampleResourceTransportAction; import org.opensearch.security.sampleextension.actions.SampleResource; -import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingAction; -import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingRestAction; -import org.opensearch.security.sampleextension.actions.UpdateSampleResourceSharingTransportAction; +import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingAction; +import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingRestAction; +import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingTransportAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceTransportAction; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java similarity index 93% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java index 4a70d8ff04..4fcd311d3c 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.sharing; import org.opensearch.action.ActionType; import org.opensearch.security.spi.actions.UpdateResourceSharingResponse; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java similarity index 94% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java index 0b55ff83da..efb68b134d 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.sharing; import java.io.IOException; import java.util.List; @@ -17,6 +17,7 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; +import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.security.spi.ShareWith; import org.opensearch.security.spi.actions.UpdateResourceSharingRequest; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java similarity index 90% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingTransportAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java index 4c54465467..26803dcd02 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/UpdateSampleResourceSharingTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.sharing; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -14,6 +14,7 @@ import org.opensearch.action.support.ActionFilters; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; +import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.security.spi.ShareWith; import org.opensearch.security.spi.actions.UpdateResourceSharingTransportAction; import org.opensearch.transport.TransportService; From d015aa057365b82076daa449dbc990bf7ae75fa0 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 12 Dec 2024 16:37:22 -0500 Subject: [PATCH 49/80] reorg Signed-off-by: Craig Perkins --- .../sampleextension/SampleExtensionPlugin.java | 12 ++++++------ .../sampleextension/actions/SampleResource.java | 4 ++++ .../{ => create}/CreateSampleResourceAction.java | 2 +- .../{ => create}/CreateSampleResourceRestAction.java | 3 ++- .../CreateSampleResourceTransportAction.java | 5 +++-- .../actions/{ => list}/ListSampleResourceAction.java | 2 +- .../{ => list}/ListSampleResourceRequest.java | 2 +- .../{ => list}/ListSampleResourceResponse.java | 5 +++-- .../{ => list}/ListSampleResourceRestAction.java | 2 +- .../ListSampleResourceTransportAction.java | 3 ++- 10 files changed, 24 insertions(+), 16 deletions(-) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => create}/CreateSampleResourceAction.java (92%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => create}/CreateSampleResourceRestAction.java (92%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => create}/CreateSampleResourceTransportAction.java (89%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => list}/ListSampleResourceAction.java (92%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => list}/ListSampleResourceRequest.java (94%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => list}/ListSampleResourceResponse.java (89%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => list}/ListSampleResourceRestAction.java (95%) rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/{ => list}/ListSampleResourceTransportAction.java (94%) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index c6d541f7f0..a8cb3f084a 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -38,13 +38,13 @@ import org.opensearch.rest.RestController; import org.opensearch.rest.RestHandler; import org.opensearch.script.ScriptService; -import org.opensearch.security.sampleextension.actions.CreateSampleResourceAction; -import org.opensearch.security.sampleextension.actions.CreateSampleResourceRestAction; -import org.opensearch.security.sampleextension.actions.CreateSampleResourceTransportAction; -import org.opensearch.security.sampleextension.actions.ListSampleResourceAction; -import org.opensearch.security.sampleextension.actions.ListSampleResourceRestAction; -import org.opensearch.security.sampleextension.actions.ListSampleResourceTransportAction; import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceAction; +import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceTransportAction; +import org.opensearch.security.sampleextension.actions.list.ListSampleResourceAction; +import org.opensearch.security.sampleextension.actions.list.ListSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.list.ListSampleResourceTransportAction; import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingAction; import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingRestAction; import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingTransportAction; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java index ba6d1c97d2..af2b51cdcc 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java @@ -24,6 +24,10 @@ public SampleResource() {} this.name = in.readString(); } + public static SampleResource from(StreamInput in) throws IOException { + return new SampleResource(in); + } + @Override public String getResourceType() { return "sample_resource"; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java similarity index 92% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java index a3a32db1e3..19c2685ec3 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.create; import org.opensearch.action.ActionType; import org.opensearch.security.spi.actions.CreateResourceResponse; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java similarity index 92% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java index 210105c878..07d8a0f68a 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.create; import java.io.IOException; import java.util.List; @@ -17,6 +17,7 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; +import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.security.spi.actions.CreateResourceRequest; import static java.util.Collections.singletonList; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java similarity index 89% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index a67134bf4e..92d498a8c3 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.create; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -14,6 +14,7 @@ import org.opensearch.action.support.ActionFilters; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; +import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.security.spi.actions.CreateResourceTransportAction; import org.opensearch.transport.TransportService; @@ -27,6 +28,6 @@ public class CreateSampleResourceTransportAction extends CreateResourceTransport @Inject public CreateSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { - super(transportService, actionFilters, nodeClient, CreateSampleResourceAction.NAME, RESOURCE_INDEX_NAME, SampleResource::new); + super(transportService, actionFilters, nodeClient, CreateSampleResourceAction.NAME, RESOURCE_INDEX_NAME, SampleResource::from); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java similarity index 92% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java index b4c3f39726..aac9ab10d9 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.list; import org.opensearch.action.ActionType; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java similarity index 94% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRequest.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java index 041a5964e7..3a6acb5cfb 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.list; import java.io.IOException; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java similarity index 89% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java index 6569510284..9eb14cac61 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.list; import java.io.IOException; import java.util.List; @@ -16,6 +16,7 @@ import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.security.spi.AbstractResource; /** @@ -44,7 +45,7 @@ public void writeTo(StreamOutput out) throws IOException { * @param in the stream input */ public ListSampleResourceResponse(final StreamInput in) throws IOException { - resources = in.readList(SampleResource::new); + resources = in.readList(SampleResource::from); } @Override diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java similarity index 95% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRestAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java index 97e54904e3..4bab2c9ce6 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.list; import java.util.List; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java similarity index 94% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java rename to sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java index e2785f9d1c..864f7c6bdf 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/ListSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions; +package org.opensearch.security.sampleextension.actions.list; import java.util.List; @@ -15,6 +15,7 @@ import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; import org.opensearch.core.action.ActionListener; +import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; From 0d8eeed39b1cda1913fe1d847172cc8f2c8fc1e1 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 12 Dec 2024 16:48:29 -0500 Subject: [PATCH 50/80] Add Get action Signed-off-by: Craig Perkins --- .../SampleExtensionPluginTests.java | 4 ++ .../SampleExtensionPlugin.java | 5 ++ .../actions/get/GetSampleResourceAction.java | 29 +++++++++ .../actions/get/GetSampleResourceRequest.java | 47 ++++++++++++++ .../get/GetSampleResourceResponse.java | 56 +++++++++++++++++ .../get/GetSampleResourceRestAction.java | 48 +++++++++++++++ .../get/GetSampleResourceTransportAction.java | 61 +++++++++++++++++++ 7 files changed, 250 insertions(+) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRequest.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java diff --git a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java index 8a7b106a1c..c18e000a12 100644 --- a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java +++ b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java @@ -67,6 +67,10 @@ public void testCreateAndUpdateOwnSampleResource() throws Exception { System.out.println("resourceId: " + resourceId); + HttpResponse getResponse = client.get("_plugins/resource_sharing_example/resource/" + resourceId); + getResponse.assertStatusCode(HttpStatus.SC_OK); + System.out.println("Get Response: " + getResponse.getBody()); + String sampleResourceUpdated = "{\"name\":\"sampleUpdated\"}"; HttpResponse updateResponse = client.putJson( "_plugins/resource_sharing_example/resource/update/" + resourceId, diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index a8cb3f084a..bd8c409689 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -42,6 +42,9 @@ import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceAction; import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceTransportAction; +import org.opensearch.security.sampleextension.actions.get.GetSampleResourceAction; +import org.opensearch.security.sampleextension.actions.get.GetSampleResourceRestAction; +import org.opensearch.security.sampleextension.actions.get.GetSampleResourceTransportAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceTransportAction; @@ -108,6 +111,7 @@ public List getRestHandlers( ) { return List.of( new CreateSampleResourceRestAction(), + new GetSampleResourceRestAction(), new ListSampleResourceRestAction(), new UpdateSampleResourceRestAction(), new UpdateSampleResourceSharingRestAction() @@ -118,6 +122,7 @@ public List getRestHandlers( public List> getActions() { return List.of( new ActionHandler<>(CreateSampleResourceAction.INSTANCE, CreateSampleResourceTransportAction.class), + new ActionHandler<>(GetSampleResourceAction.INSTANCE, GetSampleResourceTransportAction.class), new ActionHandler<>(ListSampleResourceAction.INSTANCE, ListSampleResourceTransportAction.class), new ActionHandler<>(UpdateSampleResourceSharingAction.INSTANCE, UpdateSampleResourceSharingTransportAction.class), new ActionHandler<>(UpdateSampleResourceAction.INSTANCE, UpdateSampleResourceTransportAction.class) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java new file mode 100644 index 0000000000..a58bc0b4bd --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.get; + +import org.opensearch.action.ActionType; + +/** + * Action to get a sample resource + */ +public class GetSampleResourceAction extends ActionType { + /** + * Get sample resource action instance + */ + public static final GetSampleResourceAction INSTANCE = new GetSampleResourceAction(); + /** + * Get sample resource action name + */ + public static final String NAME = "cluster:admin/sampleresource/get"; + + private GetSampleResourceAction() { + super(NAME, GetSampleResourceResponse::new); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRequest.java new file mode 100644 index 0000000000..3dbc2e861d --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRequest.java @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.get; + +import java.io.IOException; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; + +/** + * Request object for GetSampleResource transport action + */ +public class GetSampleResourceRequest extends ActionRequest { + + private String resourceId; + + public GetSampleResourceRequest(String resourceId) { + this.resourceId = resourceId; + } + + public String getResourceId() { + return resourceId; + } + + /** + * Constructor with stream input + * @param in the stream input + * @throws IOException IOException + */ + public GetSampleResourceRequest(final StreamInput in) throws IOException {} + + @Override + public void writeTo(final StreamOutput out) throws IOException {} + + @Override + public ActionRequestValidationException validate() { + return null; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java new file mode 100644 index 0000000000..35c9b247a0 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java @@ -0,0 +1,56 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.get; + +import java.io.IOException; + +import org.opensearch.core.action.ActionResponse; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.sampleextension.actions.SampleResource; + +/** + * Response to a ListSampleResourceRequest + */ +public class GetSampleResourceResponse extends ActionResponse implements ToXContentObject { + private final SampleResource resource; + + /** + * Default constructor + * + * @param resource The resource + */ + public GetSampleResourceResponse(SampleResource resource) { + this.resource = resource; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + resource.writeTo(out); + } + + /** + * Constructor with StreamInput + * + * @param in the stream input + */ + public GetSampleResourceResponse(final StreamInput in) throws IOException { + resource = SampleResource.from(in); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field("resource", resource); + builder.endObject(); + return builder; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java new file mode 100644 index 0000000000..3db09de2e1 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java @@ -0,0 +1,48 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.get; + +import java.io.IOException; +import java.util.List; + +import org.opensearch.client.node.NodeClient; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.RestRequest; +import org.opensearch.rest.action.RestToXContentListener; + +import static java.util.Collections.singletonList; +import static org.opensearch.rest.RestRequest.Method.GET; + +public class GetSampleResourceRestAction extends BaseRestHandler { + + public GetSampleResourceRestAction() {} + + @Override + public List routes() { + return singletonList(new Route(GET, "/_plugins/resource_sharing_example/resource/{id}")); + } + + @Override + public String getName() { + return "get_sample_resource"; + } + + @SuppressWarnings("unchecked") + @Override + public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + String resourceId = request.param("id"); + + final GetSampleResourceRequest getSampleResourceRequest = new GetSampleResourceRequest(resourceId); + return channel -> client.executeLocally( + GetSampleResourceAction.INSTANCE, + getSampleResourceRequest, + new RestToXContentListener<>(channel) + ); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java new file mode 100644 index 0000000000..c3b109146b --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java @@ -0,0 +1,61 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.sampleextension.actions.get; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.action.get.GetRequest; +import org.opensearch.action.get.GetResponse; +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.client.Client; +import org.opensearch.common.inject.Inject; +import org.opensearch.core.action.ActionListener; +import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; + +/** + * Transport action for UpdateSampleResource. + */ +public class GetSampleResourceTransportAction extends HandledTransportAction { + private static final Logger log = LogManager.getLogger(GetSampleResourceTransportAction.class); + + private final Client nodeClient; + + @Inject + public GetSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { + super(GetSampleResourceAction.NAME, transportService, actionFilters, GetSampleResourceRequest::new); + this.nodeClient = nodeClient; + } + + @Override + protected void doExecute(Task task, GetSampleResourceRequest request, ActionListener actionListener) { + getResource(request, actionListener); + } + + private void getResource(GetSampleResourceRequest request, ActionListener listener) { + log.warn("resourceId: " + request.getResourceId()); + GetRequest gr = nodeClient.prepareGet().setIndex(RESOURCE_INDEX_NAME).setId(request.getResourceId()).request(); + + log.warn("GET Request: " + gr.toString()); + + ActionListener grListener = ActionListener.wrap(getResponse -> { + log.info("Updated resource: " + getResponse.toString()); + getResponse.getSource(); + SampleResource resource = new SampleResource(); + resource.setName(getResponse.getSource().get("name").toString()); + listener.onResponse(new GetSampleResourceResponse(resource)); + }, listener::onFailure); + nodeClient.get(gr, grListener); + } +} From d062a98e065450af886238cfd1b78b1029d3f4ea Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 12 Dec 2024 17:07:48 -0500 Subject: [PATCH 51/80] only instantiate if needed Signed-off-by: Craig Perkins --- .../sampleextension/SampleExtensionPlugin.java | 10 +++++----- .../sampleextension/actions/SampleResource.java | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index bd8c409689..2af85c0f43 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -88,12 +88,12 @@ public Collection createComponents( Supplier repositoriesServiceSupplier ) { this.client = client; - ResourceSharingService sharingService = new DefaultResourceSharingService<>( - client, - RESOURCE_INDEX_NAME, - SampleResource.class - ); if (!SampleResourceSharingService.getInstance().isInitialized()) { + ResourceSharingService sharingService = new DefaultResourceSharingService<>( + client, + RESOURCE_INDEX_NAME, + SampleResource.class + ); SampleResourceSharingService.getInstance().initialize(sharingService); } return Collections.emptyList(); diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java index af2b51cdcc..34d9caa5d2 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java @@ -53,7 +53,6 @@ public Class getResourceClass() { @Override public void assignResourceSharingService(ResourceSharingService service) { // Only called if security plugin is installed - System.out.println("assignResourceSharingService called"); ResourceSharingService sharingService = (ResourceSharingService) service; if (SampleResourceSharingService.getInstance().isInitialized()) { throw new IllegalStateException("Resource sharing service already initialized"); From 99348d72a4394719c618f7e9908e34c0b66b6128 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 12 Dec 2024 17:17:02 -0500 Subject: [PATCH 52/80] Implement get resource Signed-off-by: Craig Perkins --- .../get/GetSampleResourceTransportAction.java | 21 ++++----------- .../spi/AbstractResourceSharingService.java | 26 +++++++++++++++++++ .../security/spi/ResourceSharingService.java | 2 ++ .../SecurityResourceSharingService.java | 25 ++++++++++++++++++ 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java index c3b109146b..714c5956af 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java @@ -11,19 +11,16 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.opensearch.action.get.GetRequest; -import org.opensearch.action.get.GetResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; import org.opensearch.core.action.ActionListener; import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; -import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; - /** * Transport action for UpdateSampleResource. */ @@ -44,18 +41,10 @@ protected void doExecute(Task task, GetSampleResourceRequest request, ActionList } private void getResource(GetSampleResourceRequest request, ActionListener listener) { - log.warn("resourceId: " + request.getResourceId()); - GetRequest gr = nodeClient.prepareGet().setIndex(RESOURCE_INDEX_NAME).setId(request.getResourceId()).request(); - - log.warn("GET Request: " + gr.toString()); - - ActionListener grListener = ActionListener.wrap(getResponse -> { - log.info("Updated resource: " + getResponse.toString()); - getResponse.getSource(); - SampleResource resource = new SampleResource(); - resource.setName(getResponse.getSource().get("name").toString()); - listener.onResponse(new GetSampleResourceResponse(resource)); + ActionListener getResourceListener = ActionListener.wrap(sampleResource -> { + System.out.println("sampleResource: " + sampleResource); + listener.onResponse(new GetSampleResourceResponse(sampleResource)); }, listener::onFailure); - nodeClient.get(gr, grListener); + SampleResourceSharingService.getInstance().getSharingService().getResource(request.getResourceId(), getResourceListener); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java index 0396c6d7a5..c05b901b70 100644 --- a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java @@ -7,6 +7,8 @@ import java.util.List; import org.opensearch.OpenSearchException; +import org.opensearch.action.get.GetRequest; +import org.opensearch.action.get.GetResponse; import org.opensearch.action.search.SearchRequest; import org.opensearch.action.search.SearchResponse; import org.opensearch.client.Client; @@ -70,4 +72,28 @@ public void onFailure(Exception e) { client.search(sr, searchListener); } } + + @SuppressWarnings("unchecked") + @Override + public void getResource(String resourceId, ActionListener getResourceListener) { + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + GetRequest gr = new GetRequest(resourceIndex); + gr.id(resourceId); + /* Index already exists, ignore and continue */ + ActionListener getListener = new ActionListener() { + @Override + public void onResponse(GetResponse getResponse) { + T resource = newResource(); + resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); + getResourceListener.onResponse(resource); + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + client.get(gr, getListener); + } + } } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java index b2eb467573..c73e47a4c7 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java @@ -7,4 +7,6 @@ public interface ResourceSharingService { void listResources(ActionListener> listResourceListener); + + void getResource(String resourceId, ActionListener getResourceListener); } diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index f2f9c8520d..b0e29ad12b 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -15,6 +15,7 @@ import java.util.List; import org.opensearch.OpenSearchException; +import org.opensearch.action.get.GetRequest; import org.opensearch.action.get.GetResponse; import org.opensearch.action.get.MultiGetItemResponse; import org.opensearch.action.get.MultiGetRequest; @@ -160,4 +161,28 @@ public void onFailure(Exception e) { // client.search(sr, searchListener); } } + + @SuppressWarnings("unchecked") + @Override + public void getResource(String resourceId, ActionListener getResourceListener) { + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + GetRequest gr = new GetRequest(resourceIndex); + gr.id(resourceId); + /* Index already exists, ignore and continue */ + ActionListener getListener = new ActionListener() { + @Override + public void onResponse(GetResponse getResponse) { + T resource = newResource(); + resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); + getResourceListener.onResponse(resource); + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + client.get(gr, getListener); + } + } } From d8f0f8a9a0544be9c6177314d4a7662a6ae6bbbb Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 12 Dec 2024 23:53:57 -0500 Subject: [PATCH 53/80] Use provider pattern Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 43 +++++++--- .../actions/SampleResource.java | 81 ------------------- .../CreateSampleResourceRestAction.java | 2 +- .../CreateSampleResourceTransportAction.java | 2 +- .../get/GetSampleResourceResponse.java | 2 +- .../get/GetSampleResourceTransportAction.java | 15 +++- .../list/ListSampleResourceResponse.java | 2 +- .../ListSampleResourceTransportAction.java | 25 +++--- ...UpdateSampleResourceSharingRestAction.java | 2 +- ...eSampleResourceSharingTransportAction.java | 2 +- .../UpdateSampleResourceTransportAction.java | 4 +- .../resource/SampleResource.java | 49 +++++++++++ .../SampleResourceSharingService.java | 38 --------- .../SampleResourceSharingServiceProvider.java | 44 ++++++++++ ...arch.security.spi.ResourceSharingExtension | 2 +- 15 files changed, 157 insertions(+), 156 deletions(-) delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 2af85c0f43..3b1e410ee3 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -38,7 +38,6 @@ import org.opensearch.rest.RestController; import org.opensearch.rest.RestHandler; import org.opensearch.script.ScriptService; -import org.opensearch.security.sampleextension.actions.SampleResource; import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceAction; import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.create.CreateSampleResourceTransportAction; @@ -54,8 +53,11 @@ import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceTransportAction; -import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; +import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; +import org.opensearch.security.spi.AbstractResource; import org.opensearch.security.spi.DefaultResourceSharingService; +import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.threadpool.ThreadPool; import org.opensearch.watcher.ResourceWatcherService; @@ -66,13 +68,15 @@ * It use ".sample_extension_resources" index to manage its resources, and exposes a REST API * */ -public class SampleExtensionPlugin extends Plugin implements ActionPlugin, SystemIndexPlugin { +public class SampleExtensionPlugin extends Plugin implements ActionPlugin, SystemIndexPlugin, ResourceSharingExtension { private static final Logger log = LogManager.getLogger(SampleExtensionPlugin.class); public static final String RESOURCE_INDEX_NAME = ".sample_extension_resources"; private Client client; + private final SampleResourceSharingServiceProvider provider = new SampleResourceSharingServiceProvider(); + @Override public Collection createComponents( Client client, @@ -88,15 +92,11 @@ public Collection createComponents( Supplier repositoriesServiceSupplier ) { this.client = client; - if (!SampleResourceSharingService.getInstance().isInitialized()) { - ResourceSharingService sharingService = new DefaultResourceSharingService<>( - client, - RESOURCE_INDEX_NAME, - SampleResource.class - ); - SampleResourceSharingService.getInstance().initialize(sharingService); + if (provider.get() == null) { + provider.set(new DefaultResourceSharingService<>(client, RESOURCE_INDEX_NAME, SampleResource.class)); } - return Collections.emptyList(); + System.out.println("provider: " + provider); + return List.of(provider); } @Override @@ -134,4 +134,25 @@ public Collection getSystemIndexDescriptors(Settings sett final SystemIndexDescriptor systemIndexDescriptor = new SystemIndexDescriptor(RESOURCE_INDEX_NAME, "Example index with resources"); return Collections.singletonList(systemIndexDescriptor); } + + @Override + public String getResourceType() { + return "sample_resource"; + } + + @Override + public String getResourceIndex() { + return RESOURCE_INDEX_NAME; + } + + @Override + public Class getResourceClass() { + return SampleResource.class; + } + + @SuppressWarnings("unchecked") + @Override + public void assignResourceSharingService(ResourceSharingService service) { + provider.set((ResourceSharingService) service); + } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java deleted file mode 100644 index 34d9caa5d2..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/SampleResource.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.opensearch.security.sampleextension.actions; - -import java.io.IOException; -import java.util.Map; - -import org.opensearch.core.common.io.stream.StreamInput; -import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; -import org.opensearch.security.spi.AbstractResource; -import org.opensearch.security.spi.ResourceSharingExtension; -import org.opensearch.security.spi.ResourceSharingService; - -import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; - -public class SampleResource extends AbstractResource implements ResourceSharingExtension { - - private String name; - private ResourceSharingService resourceSharingService; - - public SampleResource() {} - - SampleResource(StreamInput in) throws IOException { - this.name = in.readString(); - } - - public static SampleResource from(StreamInput in) throws IOException { - return new SampleResource(in); - } - - @Override - public String getResourceType() { - return "sample_resource"; - } - - @Override - public void fromSource(String resourceId, Map sourceAsMap) { - super.fromSource(resourceId, sourceAsMap); - this.name = (String) sourceAsMap.get("name"); - } - - @Override - public String getResourceIndex() { - return RESOURCE_INDEX_NAME; - } - - @Override - public Class getResourceClass() { - return SampleResource.class; - } - - @SuppressWarnings("unchecked") - @Override - public void assignResourceSharingService(ResourceSharingService service) { - // Only called if security plugin is installed - ResourceSharingService sharingService = (ResourceSharingService) service; - if (SampleResourceSharingService.getInstance().isInitialized()) { - throw new IllegalStateException("Resource sharing service already initialized"); - } - SampleResourceSharingService.getInstance().initialize(sharingService); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject().field("name", name).endObject(); - } - - @Override - public void writeTo(StreamOutput streamOutput) throws IOException { - streamOutput.writeString(name); - } - - @Override - public String getWriteableName() { - return "sample_resource"; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java index 07d8a0f68a..e0be740991 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java @@ -17,7 +17,7 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; -import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.actions.CreateResourceRequest; import static java.util.Collections.singletonList; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index 92d498a8c3..181947ba8b 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -14,7 +14,7 @@ import org.opensearch.action.support.ActionFilters; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; -import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.actions.CreateResourceTransportAction; import org.opensearch.transport.TransportService; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java index 35c9b247a0..77e926d916 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java @@ -15,7 +15,7 @@ import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResource; /** * Response to a ListSampleResourceRequest diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java index 714c5956af..9ccbf732b6 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java @@ -16,8 +16,8 @@ import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; import org.opensearch.core.action.ActionListener; -import org.opensearch.security.sampleextension.actions.SampleResource; -import org.opensearch.security.sampleextension.resource.SampleResourceSharingService; +import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -28,11 +28,18 @@ public class GetSampleResourceTransportAction extends HandledTransportAction { private final TransportService transportService; private final Client nodeClient; + private final SampleResourceSharingServiceProvider resourceSharingService; + // TODO How can this inject work if either a DefaultResourceSharingService or SecurityResourceSharingService is binded? @Inject - public ListSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { + public ListSampleResourceTransportAction( + TransportService transportService, + ActionFilters actionFilters, + Client nodeClient, + SampleResourceSharingServiceProvider resourceSharingService + ) { super(ListSampleResourceAction.NAME, transportService, actionFilters, ListSampleResourceRequest::new); this.transportService = transportService; this.nodeClient = nodeClient; + this.resourceSharingService = resourceSharingService; } @Override @@ -40,15 +48,6 @@ protected void doExecute(Task task, ListSampleResourceRequest request, ActionLis System.out.println("sampleResourcesList: " + sampleResourcesList); listener.onResponse(new ListSampleResourceResponse(sampleResourcesList)); }, listener::onFailure); - SampleResourceSharingService.getInstance().getSharingService().listResources(sampleResourceListener); - // try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { - // SearchRequest sr = new SearchRequest(".resource-sharing"); - // SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); - // matchAllQuery.query(new MatchAllQueryBuilder()); - // sr.source(matchAllQuery); - // listener.onResponse(new ListSampleResourceResponse(sampleResources)); - /* Index already exists, ignore and continue */ - // nodeClient.search(sr, searchListener); - // } + resourceSharingService.get().listResources(sampleResourceListener); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java index efb68b134d..94213787e0 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java @@ -17,7 +17,7 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; -import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.ShareWith; import org.opensearch.security.spi.actions.UpdateResourceSharingRequest; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java index 26803dcd02..7e5981cf90 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java @@ -14,7 +14,7 @@ import org.opensearch.action.support.ActionFilters; import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; -import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.ShareWith; import org.opensearch.security.spi.actions.UpdateResourceSharingTransportAction; import org.opensearch.transport.TransportService; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceTransportAction.java index 443fa01728..9070622371 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceTransportAction.java @@ -22,7 +22,7 @@ import org.opensearch.common.inject.Inject; import org.opensearch.core.action.ActionListener; import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.security.sampleextension.actions.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -64,7 +64,7 @@ private void indexResource(UpdateSampleResourceRequest request, ActionListener irListener = ActionListener.wrap(idxResponse -> { log.info("Updated resource: " + idxResponse.toString()); - listener.onResponse(new UpdateSampleResourceResponse(updatedResource.getResourceId())); + listener.onResponse(new UpdateSampleResourceResponse(idxResponse.getId())); }, listener::onFailure); nodeClient.index(ir, irListener); } catch (IOException e) { diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java new file mode 100644 index 0000000000..97038e5037 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java @@ -0,0 +1,49 @@ +package org.opensearch.security.sampleextension.resource; + +import java.io.IOException; +import java.util.Map; + +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.spi.AbstractResource; + +public class SampleResource extends AbstractResource { + + private String name; + + public SampleResource() {} + + SampleResource(StreamInput in) throws IOException { + this.name = in.readString(); + } + + public static SampleResource from(StreamInput in) throws IOException { + return new SampleResource(in); + } + + @Override + public void fromSource(String resourceId, Map sourceAsMap) { + super.fromSource(resourceId, sourceAsMap); + this.name = (String) sourceAsMap.get("name"); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder.startObject().field("name", name).endObject(); + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + streamOutput.writeString(name); + } + + @Override + public String getWriteableName() { + return "sample_resource"; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java deleted file mode 100644 index f328034b22..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingService.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.opensearch.security.sampleextension.resource; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import org.opensearch.security.sampleextension.actions.SampleResource; -import org.opensearch.security.spi.ResourceSharingService; - -public class SampleResourceSharingService { - private final static Logger log = LogManager.getLogger(SampleResourceSharingService.class); - - private static final SampleResourceSharingService INSTANCE = new SampleResourceSharingService(); - - private boolean initialized; - private ResourceSharingService sharingService; - - private SampleResourceSharingService() {} - - public static SampleResourceSharingService getInstance() { - return SampleResourceSharingService.INSTANCE; - } - - public void initialize(ResourceSharingService sharingService) { - if (initialized) { - return; - } - initialized = true; - this.sharingService = sharingService; - } - - public boolean isInitialized() { - return initialized; - } - - public ResourceSharingService getSharingService() { - return sharingService; - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java new file mode 100644 index 0000000000..d375e9bc12 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java @@ -0,0 +1,44 @@ +package org.opensearch.security.sampleextension.resource; + +import org.opensearch.common.inject.Provider; +import org.opensearch.security.spi.ResourceSharingService; + +/** + * Provider for ResourceSharingService that handles SampleResource instances. + * This provider allows for flexible injection of different ResourceSharingService + * implementations based on runtime conditions. + */ +public final class SampleResourceSharingServiceProvider implements Provider> { + + private volatile ResourceSharingService resourceSharingService; + + /** + * Sets the resource sharing service implementation. + * This method is thread-safe and ensures the service is only set once. + * + * @param resourceSharingService the service implementation to use + * @throws IllegalStateException if the service has already been set + * @throws IllegalArgumentException if the provided service is null + */ + public void set(ResourceSharingService resourceSharingService) { + if (resourceSharingService == null) { + throw new IllegalArgumentException("ResourceSharingService cannot be null"); + } + + if (this.resourceSharingService != null) { + throw new IllegalStateException("ResourceSharingService has already been set"); + } + + this.resourceSharingService = resourceSharingService; + } + + /** + * {@inheritDoc} + * + * @return the configured ResourceSharingService + */ + @Override + public ResourceSharingService get() { + return resourceSharingService; + } +} diff --git a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension index 0155e94fc4..e32f06ee56 100644 --- a/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension +++ b/sample-extension-plugin/src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension @@ -3,4 +3,4 @@ # SPDX-License-Identifier: Apache-2.0 # -org.opensearch.security.sampleextension.actions.SampleResource \ No newline at end of file +org.opensearch.security.sampleextension.SampleExtensionPlugin \ No newline at end of file From c266a17cfaf9b1afb4731ed5b31d23366884a7b7 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 13 Dec 2024 10:35:59 -0500 Subject: [PATCH 54/80] Use ResourceFactory pattern Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 12 +++--- .../list/ListSampleResourceResponse.java | 4 +- .../resource/SampleResource.java | 4 +- .../resource/SampleResourceFactory.java | 10 +++++ .../spi/AbstractResourceSharingService.java | 40 +++++++++---------- .../spi/DefaultResourceSharingService.java | 6 +-- .../{AbstractResource.java => Resource.java} | 4 +- .../security/spi/ResourceFactory.java | 5 +++ .../spi/ResourceSharingExtension.java | 4 +- .../security/spi/ResourceSharingService.java | 2 +- .../spi/actions/CreateResourceRequest.java | 6 +-- .../CreateResourceTransportAction.java | 6 +-- .../actions/UpdateResourceSharingRequest.java | 4 +- .../UpdateResourceSharingTransportAction.java | 4 +- .../security/OpenSearchSecurityPlugin.java | 2 +- .../SecurityResourceSharingService.java | 14 ++++--- 16 files changed, 72 insertions(+), 55 deletions(-) create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceFactory.java rename spi/src/main/java/org/opensearch/security/spi/{AbstractResource.java => Resource.java} (88%) create mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceFactory.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 3b1e410ee3..5067708bc6 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -54,9 +54,11 @@ import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceTransportAction; import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResourceFactory; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; -import org.opensearch.security.spi.AbstractResource; import org.opensearch.security.spi.DefaultResourceSharingService; +import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ResourceFactory; import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.threadpool.ThreadPool; @@ -93,7 +95,7 @@ public Collection createComponents( ) { this.client = client; if (provider.get() == null) { - provider.set(new DefaultResourceSharingService<>(client, RESOURCE_INDEX_NAME, SampleResource.class)); + provider.set(new DefaultResourceSharingService<>(client, RESOURCE_INDEX_NAME, new SampleResourceFactory())); } System.out.println("provider: " + provider); return List.of(provider); @@ -146,13 +148,13 @@ public String getResourceIndex() { } @Override - public Class getResourceClass() { - return SampleResource.class; + public ResourceFactory getResourceFactory() { + return new SampleResourceFactory(); } @SuppressWarnings("unchecked") @Override - public void assignResourceSharingService(ResourceSharingService service) { + public void assignResourceSharingService(ResourceSharingService service) { provider.set((ResourceSharingService) service); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java index c908970f67..7225ed835d 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java @@ -17,7 +17,7 @@ import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.security.sampleextension.resource.SampleResource; -import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.Resource; /** * Response to a ListSampleResourceRequest @@ -51,7 +51,7 @@ public ListSampleResourceResponse(final StreamInput in) throws IOException { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.array("resources", (Object[]) resources.toArray(new AbstractResource[0])); + builder.array("resources", (Object[]) resources.toArray(new Resource[0])); builder.endObject(); return builder; } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java index 97038e5037..942449c8bb 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java @@ -6,9 +6,9 @@ import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.Resource; -public class SampleResource extends AbstractResource { +public class SampleResource extends Resource { private String name; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceFactory.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceFactory.java new file mode 100644 index 0000000000..b902f38fb3 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceFactory.java @@ -0,0 +1,10 @@ +package org.opensearch.security.sampleextension.resource; + +import org.opensearch.security.spi.ResourceFactory; + +public class SampleResourceFactory implements ResourceFactory { + @Override + public SampleResource createResource() { + return new SampleResource(); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java index c05b901b70..53e529936e 100644 --- a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java @@ -1,8 +1,5 @@ package org.opensearch.security.spi; -import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; @@ -18,34 +15,34 @@ import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; -public abstract class AbstractResourceSharingService implements ResourceSharingService { +public abstract class AbstractResourceSharingService implements ResourceSharingService { protected final Client client; protected final String resourceIndex; - protected final Class resourceClass; + protected final ResourceFactory resourceFactory; + // protected final Class resourceClass; - public AbstractResourceSharingService(Client client, String resourceIndex, Class resourceClass) { + public AbstractResourceSharingService(Client client, String resourceIndex, ResourceFactory resourceFactory) { this.client = client; this.resourceIndex = resourceIndex; - this.resourceClass = resourceClass; + this.resourceFactory = resourceFactory; } - protected T newResource() { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public T run() { - try { - return resourceClass.getDeclaredConstructor().newInstance(); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - }); - } + // protected T newResource() { + // return AccessController.doPrivileged(new PrivilegedAction() { + // @Override + // public T run() { + // try { + // return resourceClass.getDeclaredConstructor().newInstance(); + // } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + // throw new RuntimeException(e); + // } + // } + // }); + // } @SuppressWarnings("unchecked") @Override public void listResources(ActionListener> listResourceListener) { - T resource = newResource(); try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { SearchRequest sr = new SearchRequest(resourceIndex); SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); @@ -58,6 +55,7 @@ public void onResponse(SearchResponse searchResponse) { List resources = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { System.out.println("SearchHit: " + hit); + T resource = resourceFactory.createResource(); resource.fromSource(hit.getId(), hit.getSourceAsMap()); resources.add(resource); } @@ -83,7 +81,7 @@ public void getResource(String resourceId, ActionListener getResourceListener ActionListener getListener = new ActionListener() { @Override public void onResponse(GetResponse getResponse) { - T resource = newResource(); + T resource = resourceFactory.createResource(); resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); getResourceListener.onResponse(resource); } diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java index 9c17707a32..faade29b3b 100644 --- a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java @@ -2,9 +2,9 @@ import org.opensearch.client.Client; -public class DefaultResourceSharingService extends AbstractResourceSharingService { +public class DefaultResourceSharingService extends AbstractResourceSharingService { - public DefaultResourceSharingService(Client client, String resourceIndex, Class resourceClass) { - super(client, resourceIndex, resourceClass); + public DefaultResourceSharingService(Client client, String resourceIndex, ResourceFactory resourceFactory) { + super(client, resourceIndex, resourceFactory); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/AbstractResource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java similarity index 88% rename from spi/src/main/java/org/opensearch/security/spi/AbstractResource.java rename to spi/src/main/java/org/opensearch/security/spi/Resource.java index 7fe36bb92d..8104ecc418 100644 --- a/spi/src/main/java/org/opensearch/security/spi/AbstractResource.java +++ b/spi/src/main/java/org/opensearch/security/spi/Resource.java @@ -6,11 +6,11 @@ import org.opensearch.core.common.io.stream.NamedWriteable; import org.opensearch.core.xcontent.ToXContentFragment; -public abstract class AbstractResource implements NamedWriteable, ToXContentFragment { +public abstract class Resource implements NamedWriteable, ToXContentFragment { protected ResourceUser resourceUser; protected String resourceId; - public AbstractResource() {} + public Resource() {} public String getResourceId() { return resourceId; diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceFactory.java b/spi/src/main/java/org/opensearch/security/spi/ResourceFactory.java new file mode 100644 index 0000000000..ab86c7a819 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceFactory.java @@ -0,0 +1,5 @@ +package org.opensearch.security.spi; + +public interface ResourceFactory { + T createResource(); +} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java index eb95a9c236..85cb73dcb5 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java @@ -25,7 +25,7 @@ public interface ResourceSharingExtension { /** * @return The class corresponding to this resource */ - Class getResourceClass(); + ResourceFactory getResourceFactory(); - void assignResourceSharingService(ResourceSharingService service); + void assignResourceSharingService(ResourceSharingService service); } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java index c73e47a4c7..6faabaeee7 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java @@ -4,7 +4,7 @@ import org.opensearch.core.action.ActionListener; -public interface ResourceSharingService { +public interface ResourceSharingService { void listResources(ActionListener> listResourceListener); diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java index 6ee2a67c3d..e930cf1ecf 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java @@ -15,12 +15,12 @@ import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.common.io.stream.Writeable; -import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.Resource; /** * Request object for CreateSampleResource transport action */ -public class CreateResourceRequest extends ActionRequest { +public class CreateResourceRequest extends ActionRequest { private final T resource; @@ -45,7 +45,7 @@ public ActionRequestValidationException validate() { return null; } - public AbstractResource getResource() { + public Resource getResource() { return this.resource; } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java index 4df474019a..ede88c5326 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java @@ -25,7 +25,7 @@ import org.opensearch.core.action.ActionListener; import org.opensearch.core.common.io.stream.Writeable; import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.Resource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -34,7 +34,7 @@ /** * Transport action for CreateSampleResource. */ -public class CreateResourceTransportAction extends HandledTransportAction< +public class CreateResourceTransportAction extends HandledTransportAction< CreateResourceRequest, CreateResourceResponse> { private static final Logger log = LogManager.getLogger(CreateResourceTransportAction.class); @@ -74,7 +74,7 @@ protected void doExecute(Task task, CreateResourceRequest request, ActionList private void createResource(CreateResourceRequest request, ActionListener listener) { log.warn("Sample name: " + request.getResource()); - AbstractResource sample = request.getResource(); + Resource sample = request.getResource(); try { IndexRequest ir = nodeClient.prepareIndex(resourceIndex) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java index e0cfca44fd..c658b34430 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java @@ -14,13 +14,13 @@ import org.opensearch.action.ActionRequestValidationException; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ShareWith; /** * Request object for CreateSampleResource transport action */ -public class UpdateResourceSharingRequest extends ActionRequest { +public class UpdateResourceSharingRequest extends ActionRequest { private final String resourceId; private final ShareWith shareWith; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java index a4b15bdf81..35cd9105e4 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java @@ -31,7 +31,7 @@ import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; -import org.opensearch.security.spi.AbstractResource; +import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ShareWith; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -39,7 +39,7 @@ /** * Transport action for CreateSampleResource. */ -public class UpdateResourceSharingTransportAction extends HandledTransportAction< +public class UpdateResourceSharingTransportAction extends HandledTransportAction< UpdateResourceSharingRequest, UpdateResourceSharingResponse> { private static final Logger log = LogManager.getLogger(UpdateResourceSharingTransportAction.class); diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 7d07a7f377..f0b9bab4c0 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -1077,7 +1077,7 @@ public Collection createComponents( ResourceSharingService resourceSharingService = new SecurityResourceSharingService<>( localClient, extension.getResourceIndex(), - extension.getResourceClass() + extension.getResourceFactory() ); extension.assignResourceSharingService(resourceSharingService); } diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index b0e29ad12b..f649e92e0e 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -29,22 +29,22 @@ import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; -import org.opensearch.security.spi.AbstractResource; import org.opensearch.security.spi.AbstractResourceSharingService; +import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ResourceFactory; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.user.User; import static org.opensearch.security.resource.ResourceSharingListener.RESOURCE_SHARING_INDEX; -public class SecurityResourceSharingService extends AbstractResourceSharingService { - public SecurityResourceSharingService(Client client, String resourceIndex, Class resourceClass) { - super(client, resourceIndex, resourceClass); +public class SecurityResourceSharingService extends AbstractResourceSharingService { + public SecurityResourceSharingService(Client client, String resourceIndex, ResourceFactory resourceFactory) { + super(client, resourceIndex, resourceFactory); } @SuppressWarnings("unchecked") @Override public void listResources(ActionListener> listResourceListener) { - T resource = newResource(); User authenticatedUser = client.threadPool().getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { SearchRequest rsr = new SearchRequest(RESOURCE_SHARING_INDEX); @@ -101,6 +101,8 @@ public void onResponse(MultiGetResponse response) { if (singleResponse != null && !singleResponse.isFailed()) { GetResponse singleGetResponse = singleResponse.getResponse(); if (singleGetResponse.isExists() && !singleGetResponse.isSourceEmpty()) { + // TODO Is there a better way to create this instance of a generic w/o using reflection + T resource = resourceFactory.createResource(); resource.fromSource(singleGetResponse.getId(), singleGetResponse.getSourceAsMap()); resources.add(resource); } else { @@ -172,7 +174,7 @@ public void getResource(String resourceId, ActionListener getResourceListener ActionListener getListener = new ActionListener() { @Override public void onResponse(GetResponse getResponse) { - T resource = newResource(); + T resource = resourceFactory.createResource(); resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); getResourceListener.onResponse(resource); } From a1e80b8c7102da3d6e83c7e35b7aea8d06fbaccb Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 13 Dec 2024 11:51:23 -0500 Subject: [PATCH 55/80] Use default constructor Signed-off-by: Craig Perkins --- spi/src/main/java/org/opensearch/security/spi/Resource.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java index 8104ecc418..f5c9cc7a4b 100644 --- a/spi/src/main/java/org/opensearch/security/spi/Resource.java +++ b/spi/src/main/java/org/opensearch/security/spi/Resource.java @@ -10,8 +10,6 @@ public abstract class Resource implements NamedWriteable, ToXContentFragment { protected ResourceUser resourceUser; protected String resourceId; - public Resource() {} - public String getResourceId() { return resourceId; } From b4aa89288b53fddbfa76586de5787746577ecba5 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 13 Dec 2024 12:37:17 -0500 Subject: [PATCH 56/80] Remove abstract sharing service Signed-off-by: Craig Perkins --- .../spi/AbstractResourceSharingService.java | 97 ------------------- .../spi/DefaultResourceSharingService.java | 77 ++++++++++++++- .../spi/ResourceSharingServiceProvider.java | 41 -------- .../SecurityResourceSharingService.java | 12 ++- 4 files changed, 84 insertions(+), 143 deletions(-) delete mode 100644 spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java delete mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceSharingServiceProvider.java diff --git a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java deleted file mode 100644 index 53e529936e..0000000000 --- a/spi/src/main/java/org/opensearch/security/spi/AbstractResourceSharingService.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.opensearch.security.spi; - -import java.util.ArrayList; -import java.util.List; - -import org.opensearch.OpenSearchException; -import org.opensearch.action.get.GetRequest; -import org.opensearch.action.get.GetResponse; -import org.opensearch.action.search.SearchRequest; -import org.opensearch.action.search.SearchResponse; -import org.opensearch.client.Client; -import org.opensearch.common.util.concurrent.ThreadContext; -import org.opensearch.core.action.ActionListener; -import org.opensearch.index.query.MatchAllQueryBuilder; -import org.opensearch.search.SearchHit; -import org.opensearch.search.builder.SearchSourceBuilder; - -public abstract class AbstractResourceSharingService implements ResourceSharingService { - protected final Client client; - protected final String resourceIndex; - protected final ResourceFactory resourceFactory; - // protected final Class resourceClass; - - public AbstractResourceSharingService(Client client, String resourceIndex, ResourceFactory resourceFactory) { - this.client = client; - this.resourceIndex = resourceIndex; - this.resourceFactory = resourceFactory; - } - - // protected T newResource() { - // return AccessController.doPrivileged(new PrivilegedAction() { - // @Override - // public T run() { - // try { - // return resourceClass.getDeclaredConstructor().newInstance(); - // } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - // throw new RuntimeException(e); - // } - // } - // }); - // } - - @SuppressWarnings("unchecked") - @Override - public void listResources(ActionListener> listResourceListener) { - try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { - SearchRequest sr = new SearchRequest(resourceIndex); - SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); - matchAllQuery.query(new MatchAllQueryBuilder()); - sr.source(matchAllQuery); - /* Index already exists, ignore and continue */ - ActionListener searchListener = new ActionListener() { - @Override - public void onResponse(SearchResponse searchResponse) { - List resources = new ArrayList<>(); - for (SearchHit hit : searchResponse.getHits().getHits()) { - System.out.println("SearchHit: " + hit); - T resource = resourceFactory.createResource(); - resource.fromSource(hit.getId(), hit.getSourceAsMap()); - resources.add(resource); - } - listResourceListener.onResponse(resources); - } - - @Override - public void onFailure(Exception e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - }; - client.search(sr, searchListener); - } - } - - @SuppressWarnings("unchecked") - @Override - public void getResource(String resourceId, ActionListener getResourceListener) { - try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { - GetRequest gr = new GetRequest(resourceIndex); - gr.id(resourceId); - /* Index already exists, ignore and continue */ - ActionListener getListener = new ActionListener() { - @Override - public void onResponse(GetResponse getResponse) { - T resource = resourceFactory.createResource(); - resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); - getResourceListener.onResponse(resource); - } - - @Override - public void onFailure(Exception e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - }; - client.get(gr, getListener); - } - } -} diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java index faade29b3b..ab5c041e90 100644 --- a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java @@ -1,10 +1,83 @@ package org.opensearch.security.spi; +import java.util.ArrayList; +import java.util.List; + +import org.opensearch.OpenSearchException; +import org.opensearch.action.get.GetRequest; +import org.opensearch.action.get.GetResponse; +import org.opensearch.action.search.SearchRequest; +import org.opensearch.action.search.SearchResponse; import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.core.action.ActionListener; +import org.opensearch.index.query.MatchAllQueryBuilder; +import org.opensearch.search.SearchHit; +import org.opensearch.search.builder.SearchSourceBuilder; -public class DefaultResourceSharingService extends AbstractResourceSharingService { +public class DefaultResourceSharingService implements ResourceSharingService { + private final Client client; + private final String resourceIndex; + private final ResourceFactory resourceFactory; public DefaultResourceSharingService(Client client, String resourceIndex, ResourceFactory resourceFactory) { - super(client, resourceIndex, resourceFactory); + this.client = client; + this.resourceIndex = resourceIndex; + this.resourceFactory = resourceFactory; + } + + @SuppressWarnings("unchecked") + @Override + public void listResources(ActionListener> listResourceListener) { + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + SearchRequest sr = new SearchRequest(resourceIndex); + SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); + matchAllQuery.query(new MatchAllQueryBuilder()); + sr.source(matchAllQuery); + /* Index already exists, ignore and continue */ + ActionListener searchListener = new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + List resources = new ArrayList<>(); + for (SearchHit hit : searchResponse.getHits().getHits()) { + System.out.println("SearchHit: " + hit); + T resource = resourceFactory.createResource(); + resource.fromSource(hit.getId(), hit.getSourceAsMap()); + resources.add(resource); + } + listResourceListener.onResponse(resources); + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + client.search(sr, searchListener); + } + } + + @SuppressWarnings("unchecked") + @Override + public void getResource(String resourceId, ActionListener getResourceListener) { + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + GetRequest gr = new GetRequest(resourceIndex); + gr.id(resourceId); + /* Index already exists, ignore and continue */ + ActionListener getListener = new ActionListener() { + @Override + public void onResponse(GetResponse getResponse) { + T resource = resourceFactory.createResource(); + resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); + getResourceListener.onResponse(resource); + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + client.get(gr, getListener); + } } } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingServiceProvider.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingServiceProvider.java deleted file mode 100644 index 1e0467976a..0000000000 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingServiceProvider.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.opensearch.security.spi; - -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class ResourceSharingServiceProvider { - private final static Logger log = LogManager.getLogger(ResourceSharingServiceProvider.class); - - private static final Map instances = new ConcurrentHashMap<>(); - - private boolean initialized; - private AbstractResourceSharingService resourceSharingService; - - private ResourceSharingServiceProvider() {} - - @SuppressWarnings("removal") - public static ResourceSharingServiceProvider getInstance() { - ClassLoader classLoader = AccessController.doPrivileged( - (PrivilegedAction) () -> Thread.currentThread().getContextClassLoader() - ); - instances.computeIfAbsent(classLoader, cl -> new ResourceSharingServiceProvider()); - return instances.get(classLoader); - } - - public void initialize(AbstractResourceSharingService resourceSharingService) { - if (initialized) { - return; - } - initialized = true; - this.resourceSharingService = resourceSharingService; - } - - public boolean isInitialized() { - return initialized; - } -} diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index f649e92e0e..f69d6a3f11 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -29,17 +29,23 @@ import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; -import org.opensearch.security.spi.AbstractResourceSharingService; import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceFactory; +import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.user.User; import static org.opensearch.security.resource.ResourceSharingListener.RESOURCE_SHARING_INDEX; -public class SecurityResourceSharingService extends AbstractResourceSharingService { +public class SecurityResourceSharingService implements ResourceSharingService { + private final Client client; + private final String resourceIndex; + private final ResourceFactory resourceFactory; + public SecurityResourceSharingService(Client client, String resourceIndex, ResourceFactory resourceFactory) { - super(client, resourceIndex, resourceFactory); + this.client = client; + this.resourceIndex = resourceIndex; + this.resourceFactory = resourceFactory; } @SuppressWarnings("unchecked") From a3bd41dcb30367a8ae7ceb3753c7070a290739da Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 13 Dec 2024 15:48:04 -0500 Subject: [PATCH 57/80] WIP on secure get resource Signed-off-by: Craig Perkins --- .../spi/DefaultResourceSharingService.java | 1 - .../opensearch/security/spi/ShareWith.java | 9 ++ .../SecurityResourceSharingService.java | 117 +++++++++++++----- 3 files changed, 94 insertions(+), 33 deletions(-) diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java index ab5c041e90..f2c7ed2ed1 100644 --- a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java @@ -40,7 +40,6 @@ public void listResources(ActionListener> listResourceListener) { public void onResponse(SearchResponse searchResponse) { List resources = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { - System.out.println("SearchHit: " + hit); T resource = resourceFactory.createResource(); resource.fromSource(hit.getId(), hit.getSourceAsMap()); resources.add(resource); diff --git a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java index 6ed2ae1739..08fcd99d38 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java +++ b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.util.List; +import java.util.Map; import org.opensearch.core.common.io.stream.NamedWriteable; import org.opensearch.core.common.io.stream.StreamInput; @@ -30,6 +31,14 @@ public ShareWith(StreamInput in) throws IOException { this.allowedActions = in.readStringList(); } + @SuppressWarnings("unchecked") + public static ShareWith fromSource(Map sourceAsMap) { + List users = (List) sourceAsMap.get("users"); + List backendRoles = (List) sourceAsMap.get("backend_roles"); + List allowedActions = (List) sourceAsMap.get("allowed_actions"); + return new ShareWith(users, backendRoles, allowedActions); + } + public List getUsers() { return users; } diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index f69d6a3f11..31fe30727c 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -15,6 +15,7 @@ import java.util.List; import org.opensearch.OpenSearchException; +import org.opensearch.ResourceNotFoundException; import org.opensearch.action.get.GetRequest; import org.opensearch.action.get.GetResponse; import org.opensearch.action.get.MultiGetItemResponse; @@ -32,6 +33,7 @@ import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceFactory; import org.opensearch.security.spi.ResourceSharingService; +import org.opensearch.security.spi.ShareWith; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.user.User; @@ -48,6 +50,51 @@ public SecurityResourceSharingService(Client client, String resourceIndex, Resou this.resourceFactory = resourceFactory; } +// private boolean hasPermissionsFor(User authenticatedUser, Resource resource) { +// // TODO Complete this function. The user has permissions if either of the conditions are true: +// +// // 1. The resource_user is the currently authenticated user +// // 2. The resource has been shared with the authenticated user +// // 3. The resource has been shared with a backend role that the authenticated user has +// if (authenticatedUser.getName().equals(resource.getResourceUser().getName())) { +// return true; +// } +// try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { +// SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); +// SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); +// BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() +// .must(QueryBuilders.termQuery("resource_index", resourceIndex)) +// .must(QueryBuilders.termQuery("resource_id", resource.getResourceId())); +// +// searchSourceBuilder.query(boolQuery); +// searchSourceBuilder.size(1); // Limit to 1 result +// searchRequest.source(searchSourceBuilder); +// +// ActionListener searchListener = new ActionListener() { +// @Override +// public void onResponse(SearchResponse searchResponse) { +// SearchHit[] hits = searchResponse.getHits().getHits(); +// if (hits.length > 0) { +// SearchHit hit = hits[0]; +// T resource = resourceFactory.createResource(); +// resource.fromSource(hit.getId(), hit.getSourceAsMap()); +// getResourceListener.onResponse(resource); +// } else { +// getResourceListener.onFailure(new ResourceNotFoundException("Resource not found")); +// } +// } +// +// @Override +// public void onFailure(Exception e) { +// throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); +// } +// }; +// +// client.search(searchRequest, searchListener); +// } +// return false; +// } + @SuppressWarnings("unchecked") @Override public void listResources(ActionListener> listResourceListener) { @@ -137,42 +184,13 @@ public void onFailure(Exception e) { } }; client.search(rsr, searchListener); - - // SearchRequest sr = new SearchRequest(resourceIndex); - // SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); - // matchAllQuery.query(new MatchAllQueryBuilder()); - // sr.source(matchAllQuery); - // /* Index already exists, ignore and continue */ - // ActionListener searchListener = new ActionListener() { - // @Override - // public void onResponse(SearchResponse searchResponse) { - // List resources = new ArrayList<>(); - // for (SearchHit hit : searchResponse.getHits().getHits()) { - // System.out.println("SearchHit: " + hit); - // resource.fromSource(hit.getId(), hit.getSourceAsMap()); - // // TODO check what resources have been shared with the authenticatedUser - // System.out.println("authenticatedUser: " + authenticatedUser); - // System.out.println("resource.getResourceUser(): " + resource.getResourceUser()); - // if (resource.getResourceUser() != null - // && authenticatedUser.getName().equals(resource.getResourceUser().getName())) { - // resources.add(resource); - // } - // } - // listResourceListener.onResponse(resources); - // } - // - // @Override - // public void onFailure(Exception e) { - // throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - // } - // }; - // client.search(sr, searchListener); } } @SuppressWarnings("unchecked") @Override public void getResource(String resourceId, ActionListener getResourceListener) { + User authenticatedUser = client.threadPool().getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { GetRequest gr = new GetRequest(resourceIndex); gr.id(resourceId); @@ -182,15 +200,50 @@ public void getResource(String resourceId, ActionListener getResourceListener public void onResponse(GetResponse getResponse) { T resource = resourceFactory.createResource(); resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); - getResourceListener.onResponse(resource); + finishGetResourceIfUserIsAllowed(resource, authenticatedUser, getResourceListener); } @Override public void onFailure(Exception e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + getResourceListener.onFailure(new OpenSearchException("Caught exception while loading resources: " + e.getMessage())); } }; client.get(gr, getListener); } } + + private void finishGetResourceIfUserIsAllowed(T resource, User authenticatedUser, ActionListener getResourceListener) { + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() + .must(QueryBuilders.termQuery("resource_index", resourceIndex)) + .must(QueryBuilders.termQuery("resource_id", resource.getResourceId())); + + searchSourceBuilder.query(boolQuery); + searchSourceBuilder.size(1); // Limit to 1 result + searchRequest.source(searchSourceBuilder); + + ActionListener searchListener = new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + SearchHit[] hits = searchResponse.getHits().getHits(); + if (hits.length > 0) { + SearchHit hit = hits[0]; + ShareWith sharedWith = ShareWith.fromSource(hit.getSourceAsMap()); + getResourceListener.onResponse(resource); + } else { + getResourceListener.onFailure(new ResourceNotFoundException("Resource not found")); + } + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + + client.search(searchRequest, searchListener); + } + } } From 20c24d004dd28166289cdbb1b7d233c5ef15b353 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 13 Dec 2024 17:44:38 -0500 Subject: [PATCH 58/80] WIP on securing get resource, integrationTest not using correct resource service Signed-off-by: Craig Perkins --- sample-extension-plugin/build.gradle | 2 +- .../SampleExtensionPluginTests.java | 3 +- .../SampleExtensionPlugin.java | 16 ++-- .../SampleResourceSharingServiceProvider.java | 18 +++++ .../SecurityResourceSharingService.java | 74 +++++++------------ 5 files changed, 57 insertions(+), 56 deletions(-) diff --git a/sample-extension-plugin/build.gradle b/sample-extension-plugin/build.gradle index 8e1e69c498..d601890483 100644 --- a/sample-extension-plugin/build.gradle +++ b/sample-extension-plugin/build.gradle @@ -16,7 +16,7 @@ import java.util.concurrent.Callable opensearchplugin { name 'opensearch-security-sample-extension' - description 'Sample plugin that extends OpenSearch Security Resource Sharing plugin' + description 'Sample plugin that extends OpenSearch Security Resource Sharing Extension' classname 'org.opensearch.security.sampleextension.SampleExtensionPlugin' extendedPlugins = ['opensearch-security'] } diff --git a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java index c18e000a12..3c3f8c281c 100644 --- a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java +++ b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java @@ -33,7 +33,7 @@ public class SampleExtensionPluginTests { @ClassRule - public static LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.THREE_CLUSTER_MANAGERS) + public static LocalCluster cluster = new LocalCluster.Builder().clusterManager(ClusterManager.SINGLENODE) .plugin(SampleExtensionPlugin.class) .anonymousAuth(true) .authc(AUTHC_HTTPBASIC_INTERNAL) @@ -50,6 +50,7 @@ public void testSecurityRoles() throws Exception { assertThat(response.getTextFromJsonBody("/user_name"), equalTo("admin")); System.out.println("Response: " + response.getBody()); HttpResponse pluginsResponse = client.get("_cat/plugins?s=component&h=name,component,version,description"); + System.out.println("pluginsResponse: " + pluginsResponse.getBody()); assertThat(pluginsResponse.getBody(), containsString("org.opensearch.security.OpenSearchSecurityPlugin")); assertThat(pluginsResponse.getBody(), containsString("org.opensearch.security.sampleextension.SampleExtensionPlugin")); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 5067708bc6..aa48c54d7f 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -77,8 +77,6 @@ public class SampleExtensionPlugin extends Plugin implements ActionPlugin, Syste private Client client; - private final SampleResourceSharingServiceProvider provider = new SampleResourceSharingServiceProvider(); - @Override public Collection createComponents( Client client, @@ -94,11 +92,15 @@ public Collection createComponents( Supplier repositoriesServiceSupplier ) { this.client = client; - if (provider.get() == null) { - provider.set(new DefaultResourceSharingService<>(client, RESOURCE_INDEX_NAME, new SampleResourceFactory())); + if (SampleResourceSharingServiceProvider.getInstance().get() == null) { + System.out.println("Using DefaultResourceSharingService"); + SampleResourceSharingServiceProvider.getInstance() + .set(new DefaultResourceSharingService<>(client, RESOURCE_INDEX_NAME, new SampleResourceFactory())); } - System.out.println("provider: " + provider); - return List.of(provider); + System.out.println( + "SampleResourceSharingServiceProvider.getInstance(): " + SampleResourceSharingServiceProvider.getInstance().get() + ); + return List.of(SampleResourceSharingServiceProvider.getInstance()); } @Override @@ -155,6 +157,6 @@ public ResourceFactory getResourceFactory() { @SuppressWarnings("unchecked") @Override public void assignResourceSharingService(ResourceSharingService service) { - provider.set((ResourceSharingService) service); + SampleResourceSharingServiceProvider.getInstance().set((ResourceSharingService) service); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java index d375e9bc12..7540c07977 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java @@ -1,5 +1,10 @@ package org.opensearch.security.sampleextension.resource; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + import org.opensearch.common.inject.Provider; import org.opensearch.security.spi.ResourceSharingService; @@ -12,6 +17,19 @@ public final class SampleResourceSharingServiceProvider implements Provider resourceSharingService; + private static final Map instances = new ConcurrentHashMap<>(); + + private SampleResourceSharingServiceProvider() {} + + @SuppressWarnings("removal") + public static SampleResourceSharingServiceProvider getInstance() { + ClassLoader classLoader = AccessController.doPrivileged( + (PrivilegedAction) () -> Thread.currentThread().getContextClassLoader() + ); + instances.computeIfAbsent(classLoader, cl -> new SampleResourceSharingServiceProvider()); + return instances.get(classLoader); + } + /** * Sets the resource sharing service implementation. * This method is thread-safe and ensures the service is only set once. diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index 31fe30727c..967f023754 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -35,6 +35,7 @@ import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.security.spi.ShareWith; import org.opensearch.security.support.ConfigConstants; +import org.opensearch.security.support.WildcardMatcher; import org.opensearch.security.user.User; import static org.opensearch.security.resource.ResourceSharingListener.RESOURCE_SHARING_INDEX; @@ -50,50 +51,24 @@ public SecurityResourceSharingService(Client client, String resourceIndex, Resou this.resourceFactory = resourceFactory; } -// private boolean hasPermissionsFor(User authenticatedUser, Resource resource) { -// // TODO Complete this function. The user has permissions if either of the conditions are true: -// -// // 1. The resource_user is the currently authenticated user -// // 2. The resource has been shared with the authenticated user -// // 3. The resource has been shared with a backend role that the authenticated user has -// if (authenticatedUser.getName().equals(resource.getResourceUser().getName())) { -// return true; -// } -// try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { -// SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); -// SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); -// BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() -// .must(QueryBuilders.termQuery("resource_index", resourceIndex)) -// .must(QueryBuilders.termQuery("resource_id", resource.getResourceId())); -// -// searchSourceBuilder.query(boolQuery); -// searchSourceBuilder.size(1); // Limit to 1 result -// searchRequest.source(searchSourceBuilder); -// -// ActionListener searchListener = new ActionListener() { -// @Override -// public void onResponse(SearchResponse searchResponse) { -// SearchHit[] hits = searchResponse.getHits().getHits(); -// if (hits.length > 0) { -// SearchHit hit = hits[0]; -// T resource = resourceFactory.createResource(); -// resource.fromSource(hit.getId(), hit.getSourceAsMap()); -// getResourceListener.onResponse(resource); -// } else { -// getResourceListener.onFailure(new ResourceNotFoundException("Resource not found")); -// } -// } -// -// @Override -// public void onFailure(Exception e) { -// throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); -// } -// }; -// -// client.search(searchRequest, searchListener); -// } -// return false; -// } + private boolean hasPermissionsFor(User authenticatedUser, Resource resource, ShareWith sharedWith) { + System.out.println("hasPermissionsFor: " + authenticatedUser + " " + resource + " " + sharedWith); + // 1. The resource_user is the currently authenticated user + // 2. The resource has been shared with the authenticated user + // 3. The resource has been shared with a backend role that the authenticated user has + if (authenticatedUser.getName().equals(resource.getResourceUser().getName())) { + return true; + } + WildcardMatcher userMatcher = WildcardMatcher.from(sharedWith.getUsers()); + if (userMatcher.test(authenticatedUser.getName())) { + return true; + } + WildcardMatcher backendRoleMatcher = WildcardMatcher.from(sharedWith.getBackendRoles()); + if (authenticatedUser.getRoles().stream().anyMatch(backendRoleMatcher::test)) { + return true; + } + return false; + } @SuppressWarnings("unchecked") @Override @@ -200,6 +175,7 @@ public void getResource(String resourceId, ActionListener getResourceListener public void onResponse(GetResponse getResponse) { T resource = resourceFactory.createResource(); resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); + System.out.println("finishGetResourceIfUserIsAllowed"); finishGetResourceIfUserIsAllowed(resource, authenticatedUser, getResourceListener); } @@ -217,8 +193,8 @@ private void finishGetResourceIfUserIsAllowed(T resource, User authenticatedUser SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() - .must(QueryBuilders.termQuery("resource_index", resourceIndex)) - .must(QueryBuilders.termQuery("resource_id", resource.getResourceId())); + .must(QueryBuilders.termQuery("resource_index", resourceIndex)) + .must(QueryBuilders.termQuery("resource_id", resource.getResourceId())); searchSourceBuilder.query(boolQuery); searchSourceBuilder.size(1); // Limit to 1 result @@ -231,7 +207,11 @@ public void onResponse(SearchResponse searchResponse) { if (hits.length > 0) { SearchHit hit = hits[0]; ShareWith sharedWith = ShareWith.fromSource(hit.getSourceAsMap()); - getResourceListener.onResponse(resource); + if (hasPermissionsFor(authenticatedUser, resource, sharedWith)) { + getResourceListener.onResponse(resource); + } else { + getResourceListener.onFailure(new OpenSearchException("User is not authorized to access this resource")); + } } else { getResourceListener.onFailure(new ResourceNotFoundException("Resource not found")); } From e676819743d7a548653312d2e8b3f2c4ccb8e25d Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 16 Dec 2024 17:11:49 -0500 Subject: [PATCH 59/80] Enforce security on get resource Signed-off-by: Craig Perkins --- .../SampleExtensionPluginTests.java | 12 ++++++- .../opensearch/security/spi/ResourceUser.java | 10 ++++++ .../resource/ResourceSharingEntry.java | 23 +++++++++++++ .../SecurityResourceSharingService.java | 32 +++++++++++-------- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java index 3c3f8c281c..8d22e01410 100644 --- a/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java +++ b/sample-extension-plugin/src/integrationTest/java/org/opensearch/security/sampleextension/SampleExtensionPluginTests.java @@ -58,15 +58,25 @@ public void testSecurityRoles() throws Exception { @Test public void testCreateAndUpdateOwnSampleResource() throws Exception { + String resourceId; try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) { String sampleResource = "{\"name\":\"sample\"}"; HttpResponse response = client.postJson("_plugins/resource_sharing_example/resource", sampleResource); response.assertStatusCode(HttpStatus.SC_OK); System.out.println("Response: " + response.getBody()); - String resourceId = response.getTextFromJsonBody("/resourceId"); + resourceId = response.getTextFromJsonBody("/resourceId"); System.out.println("resourceId: " + resourceId); + Thread.sleep(2000); + } + try (TestRestClient client = cluster.getRestClient(cluster.getAdminCertificate())) { + HttpResponse response = client.postJson(".resource-sharing/_search", "{\"query\" : {\"match_all\" : {}}}"); + System.out.println("Resource sharing entries: " + response.getBody()); + } + + try (TestRestClient client = cluster.getRestClient(USER_ADMIN)) { + Thread.sleep(1000); HttpResponse getResponse = client.get("_plugins/resource_sharing_example/resource/" + resourceId); getResponse.assertStatusCode(HttpStatus.SC_OK); diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java b/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java index 3b8093eef3..a1599c578d 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java @@ -10,6 +10,9 @@ package org.opensearch.security.spi; import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; import org.opensearch.core.xcontent.ToXContent; @@ -34,6 +37,13 @@ public Set getBackendRoles() { return backendRoles; } + @SuppressWarnings("unchecked") + public static ResourceUser fromSource(Map sourceAsMap) { + String name = (String) sourceAsMap.get("name"); + Set backendRoles = new HashSet<>((List) sourceAsMap.get("backend_roles")); + return new ResourceUser(name, backendRoles); + } + @Override public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { return builder.startObject().field("name", name).field("backend_roles", backendRoles).endObject(); diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java index 0e1f729b08..2cc74b4849 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java @@ -12,7 +12,9 @@ package org.opensearch.security.resource; import java.io.IOException; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.opensearch.core.xcontent.ToXContentFragment; import org.opensearch.core.xcontent.XContentBuilder; @@ -32,6 +34,27 @@ public ResourceSharingEntry(String resourceIndex, String resourceId, ResourceUse this.shareWith = shareWith; } + @SuppressWarnings("unchecked") + public static ResourceSharingEntry fromSource(Map sourceAsMap) { + String resourceIndex = (String) sourceAsMap.get("resource_index"); + String resourceId = (String) sourceAsMap.get("resource_id"); + ResourceUser resourceUser = ResourceUser.fromSource((Map) sourceAsMap.get("resource_user")); + List> sharedWithList = (List>) sourceAsMap.get("share_with"); + List sharedWith = new ArrayList<>(); + for (Map sharedWithMap : sharedWithList) { + sharedWith.add(ShareWith.fromSource(sharedWithMap)); + } + return new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, sharedWith); + } + + public ResourceUser getResourceUser() { + return resourceUser; + } + + public List getShareWith() { + return shareWith; + } + @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { return builder.startObject() diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index 967f023754..59fe12d858 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -51,21 +51,23 @@ public SecurityResourceSharingService(Client client, String resourceIndex, Resou this.resourceFactory = resourceFactory; } - private boolean hasPermissionsFor(User authenticatedUser, Resource resource, ShareWith sharedWith) { - System.out.println("hasPermissionsFor: " + authenticatedUser + " " + resource + " " + sharedWith); + private boolean hasPermissionsFor(User authenticatedUser, ResourceSharingEntry sharedWith) { // 1. The resource_user is the currently authenticated user // 2. The resource has been shared with the authenticated user // 3. The resource has been shared with a backend role that the authenticated user has - if (authenticatedUser.getName().equals(resource.getResourceUser().getName())) { + if (authenticatedUser.getName().equals(sharedWith.getResourceUser().getName())) { return true; } - WildcardMatcher userMatcher = WildcardMatcher.from(sharedWith.getUsers()); - if (userMatcher.test(authenticatedUser.getName())) { - return true; - } - WildcardMatcher backendRoleMatcher = WildcardMatcher.from(sharedWith.getBackendRoles()); - if (authenticatedUser.getRoles().stream().anyMatch(backendRoleMatcher::test)) { - return true; + + for (ShareWith shareWith : sharedWith.getShareWith()) { + WildcardMatcher userMatcher = WildcardMatcher.from(shareWith.getUsers()); + if (userMatcher.test(authenticatedUser.getName())) { + return true; + } + WildcardMatcher backendRoleMatcher = WildcardMatcher.from(shareWith.getBackendRoles()); + if (authenticatedUser.getRoles().stream().anyMatch(backendRoleMatcher::test)) { + return true; + } } return false; } @@ -192,9 +194,11 @@ private void finishGetResourceIfUserIsAllowed(T resource, User authenticatedUser try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + System.out.println("resourceIndex: " + resourceIndex); + System.out.println("resource.getResourceId(): " + resource.getResourceId()); BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() - .must(QueryBuilders.termQuery("resource_index", resourceIndex)) - .must(QueryBuilders.termQuery("resource_id", resource.getResourceId())); + .must(QueryBuilders.matchQuery("resource_index", resourceIndex)) + .must(QueryBuilders.matchQuery("resource_id", resource.getResourceId())); searchSourceBuilder.query(boolQuery); searchSourceBuilder.size(1); // Limit to 1 result @@ -206,8 +210,8 @@ public void onResponse(SearchResponse searchResponse) { SearchHit[] hits = searchResponse.getHits().getHits(); if (hits.length > 0) { SearchHit hit = hits[0]; - ShareWith sharedWith = ShareWith.fromSource(hit.getSourceAsMap()); - if (hasPermissionsFor(authenticatedUser, resource, sharedWith)) { + ResourceSharingEntry sharedWith = ResourceSharingEntry.fromSource(hit.getSourceAsMap()); + if (hasPermissionsFor(authenticatedUser, sharedWith)) { getResourceListener.onResponse(resource); } else { getResourceListener.onFailure(new OpenSearchException("User is not authorized to access this resource")); From c33d42a88c54e112e4e2fe843b1c265843e27e68 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 16 Dec 2024 17:24:54 -0500 Subject: [PATCH 60/80] Reverse the order Signed-off-by: Craig Perkins --- .../SecurityResourceSharingService.java | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index 59fe12d858..515fbba468 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -168,37 +168,12 @@ public void onFailure(Exception e) { @Override public void getResource(String resourceId, ActionListener getResourceListener) { User authenticatedUser = client.threadPool().getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); - try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { - GetRequest gr = new GetRequest(resourceIndex); - gr.id(resourceId); - /* Index already exists, ignore and continue */ - ActionListener getListener = new ActionListener() { - @Override - public void onResponse(GetResponse getResponse) { - T resource = resourceFactory.createResource(); - resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); - System.out.println("finishGetResourceIfUserIsAllowed"); - finishGetResourceIfUserIsAllowed(resource, authenticatedUser, getResourceListener); - } - - @Override - public void onFailure(Exception e) { - getResourceListener.onFailure(new OpenSearchException("Caught exception while loading resources: " + e.getMessage())); - } - }; - client.get(gr, getListener); - } - } - - private void finishGetResourceIfUserIsAllowed(T resource, User authenticatedUser, ActionListener getResourceListener) { try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - System.out.println("resourceIndex: " + resourceIndex); - System.out.println("resource.getResourceId(): " + resource.getResourceId()); BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("resource_index", resourceIndex)) - .must(QueryBuilders.matchQuery("resource_id", resource.getResourceId())); + .must(QueryBuilders.matchQuery("resource_id", resourceId)); searchSourceBuilder.query(boolQuery); searchSourceBuilder.size(1); // Limit to 1 result @@ -212,7 +187,7 @@ public void onResponse(SearchResponse searchResponse) { SearchHit hit = hits[0]; ResourceSharingEntry sharedWith = ResourceSharingEntry.fromSource(hit.getSourceAsMap()); if (hasPermissionsFor(authenticatedUser, sharedWith)) { - getResourceListener.onResponse(resource); + finishGetResourceIfUserIsAllowed(resourceId, getResourceListener); } else { getResourceListener.onFailure(new OpenSearchException("User is not authorized to access this resource")); } @@ -230,4 +205,26 @@ public void onFailure(Exception e) { client.search(searchRequest, searchListener); } } + + private void finishGetResourceIfUserIsAllowed(String resourceId, ActionListener getResourceListener) { + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + GetRequest gr = new GetRequest(resourceIndex); + gr.id(resourceId); + /* Index already exists, ignore and continue */ + ActionListener getListener = new ActionListener() { + @Override + public void onResponse(GetResponse getResponse) { + T resource = resourceFactory.createResource(); + resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); + getResourceListener.onResponse(resource); + } + + @Override + public void onFailure(Exception e) { + getResourceListener.onFailure(new OpenSearchException("Caught exception while loading resources: " + e.getMessage())); + } + }; + client.get(gr, getListener); + } + } } From 4a0a8c39e0c28115dabcfacbfe83c713192403a9 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 17 Dec 2024 14:40:00 -0500 Subject: [PATCH 61/80] Use action group Signed-off-by: Craig Perkins --- .../resource/ResourceSharingEntry.java | 18 +++++++++--------- .../resource/ResourceSharingListener.java | 6 ++++-- .../SecurityResourceSharingService.java | 2 +- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java index 2cc74b4849..082dc59f3b 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java @@ -12,8 +12,7 @@ package org.opensearch.security.resource; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; import java.util.Map; import org.opensearch.core.xcontent.ToXContentFragment; @@ -25,9 +24,9 @@ public class ResourceSharingEntry implements ToXContentFragment { private final String resourceIndex; private final String resourceId; private final ResourceUser resourceUser; - private final List shareWith; + private final Map shareWith; - public ResourceSharingEntry(String resourceIndex, String resourceId, ResourceUser resourceUser, List shareWith) { + public ResourceSharingEntry(String resourceIndex, String resourceId, ResourceUser resourceUser, Map shareWith) { this.resourceIndex = resourceIndex; this.resourceId = resourceId; this.resourceUser = resourceUser; @@ -39,10 +38,11 @@ public static ResourceSharingEntry fromSource(Map sourceAsMap) { String resourceIndex = (String) sourceAsMap.get("resource_index"); String resourceId = (String) sourceAsMap.get("resource_id"); ResourceUser resourceUser = ResourceUser.fromSource((Map) sourceAsMap.get("resource_user")); - List> sharedWithList = (List>) sourceAsMap.get("share_with"); - List sharedWith = new ArrayList<>(); - for (Map sharedWithMap : sharedWithList) { - sharedWith.add(ShareWith.fromSource(sharedWithMap)); + Map sharedWithMap = (Map) sourceAsMap.get("share_with"); + Map sharedWith = new HashMap<>(); + for (Map.Entry entry : sharedWithMap.entrySet()) { + ShareWith shareWith = ShareWith.fromSource((Map) entry.getValue()); + sharedWith.put(entry.getKey(), shareWith); } return new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, sharedWith); } @@ -51,7 +51,7 @@ public ResourceUser getResourceUser() { return resourceUser; } - public List getShareWith() { + public Map getShareWith() { return shareWith; } diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java index c6fb4b18b4..f8f46d7fb4 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -12,7 +12,7 @@ package org.opensearch.security.resource; import java.io.IOException; -import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; import org.apache.logging.log4j.LogManager; @@ -45,6 +45,8 @@ public class ResourceSharingListener implements IndexingOperationListener { public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; + private static final String UNLIMITED = "unlimited"; + private boolean initialized; private ThreadPool threadPool; private Client client; @@ -115,7 +117,7 @@ private void createResourceSharingIndexIfNotExists(Callable callable) { public void indexResourceSharing(String resourceId, String resourceIndex, ResourceUser resourceUser, ShareWith shareWith) throws IOException { createResourceSharingIndexIfNotExists(() -> { - ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, List.of(shareWith)); + ResourceSharingEntry entry = new ResourceSharingEntry(resourceIndex, resourceId, resourceUser, Map.of(UNLIMITED, shareWith)); IndexRequest ir = client.prepareIndex(RESOURCE_SHARING_INDEX) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index 515fbba468..e75da07899 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -59,7 +59,7 @@ private boolean hasPermissionsFor(User authenticatedUser, ResourceSharingEntry s return true; } - for (ShareWith shareWith : sharedWith.getShareWith()) { + for (ShareWith shareWith : sharedWith.getShareWith().values()) { WildcardMatcher userMatcher = WildcardMatcher.from(shareWith.getUsers()); if (userMatcher.test(authenticatedUser.getName())) { return true; From ff030cbed6236747fda8ac2956efaed6d314d754 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 17 Dec 2024 15:25:13 -0500 Subject: [PATCH 62/80] Create re-usable ActionRequest for ResourceRequests and create re-usable GetResourceTransportAction Signed-off-by: Craig Perkins --- .../actions/get/GetSampleResourceAction.java | 6 +- .../get/GetSampleResourceRestAction.java | 4 +- .../get/GetSampleResourceTransportAction.java | 28 +-------- .../spi/actions/GetResourceRequest.java | 30 ++++++++++ .../spi/actions/GetResourceResponse.java | 57 +++++++++++++++++++ .../actions/GetResourceTransportAction.java | 52 +++++++++++++++++ .../security/spi/actions/ResourceRequest.java | 46 +++++++++++++++ .../resource/ResourceSharingEntry.java | 1 + 8 files changed, 196 insertions(+), 28 deletions(-) create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/GetResourceRequest.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/GetResourceResponse.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/GetResourceTransportAction.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/ResourceRequest.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java index a58bc0b4bd..fde94b365e 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java @@ -9,11 +9,13 @@ package org.opensearch.security.sampleextension.actions.get; import org.opensearch.action.ActionType; +import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.spi.actions.GetResourceResponse; /** * Action to get a sample resource */ -public class GetSampleResourceAction extends ActionType { +public class GetSampleResourceAction extends ActionType> { /** * Get sample resource action instance */ @@ -24,6 +26,6 @@ public class GetSampleResourceAction extends ActionType new GetResourceResponse<>(in, SampleResource::from)); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java index 3db09de2e1..1ee29cf3e0 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java @@ -15,9 +15,11 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; +import org.opensearch.security.spi.actions.GetResourceRequest; import static java.util.Collections.singletonList; import static org.opensearch.rest.RestRequest.Method.GET; +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; public class GetSampleResourceRestAction extends BaseRestHandler { @@ -38,7 +40,7 @@ public String getName() { public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { String resourceId = request.param("id"); - final GetSampleResourceRequest getSampleResourceRequest = new GetSampleResourceRequest(resourceId); + final GetResourceRequest getSampleResourceRequest = new GetResourceRequest(resourceId, RESOURCE_INDEX_NAME); return channel -> client.executeLocally( GetSampleResourceAction.INSTANCE, getSampleResourceRequest, diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java index 9ccbf732b6..55046c5664 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java @@ -12,46 +12,24 @@ import org.apache.logging.log4j.Logger; import org.opensearch.action.support.ActionFilters; -import org.opensearch.action.support.HandledTransportAction; -import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; -import org.opensearch.core.action.ActionListener; import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; -import org.opensearch.tasks.Task; +import org.opensearch.security.spi.actions.GetResourceTransportAction; import org.opensearch.transport.TransportService; /** * Transport action for UpdateSampleResource. */ -public class GetSampleResourceTransportAction extends HandledTransportAction { +public class GetSampleResourceTransportAction extends GetResourceTransportAction { private static final Logger log = LogManager.getLogger(GetSampleResourceTransportAction.class); - private final Client nodeClient; - private final SampleResourceSharingServiceProvider resourceSharingService; - @Inject public GetSampleResourceTransportAction( TransportService transportService, ActionFilters actionFilters, - Client nodeClient, SampleResourceSharingServiceProvider resourceSharingService ) { - super(GetSampleResourceAction.NAME, transportService, actionFilters, GetSampleResourceRequest::new); - this.nodeClient = nodeClient; - this.resourceSharingService = resourceSharingService; - } - - @Override - protected void doExecute(Task task, GetSampleResourceRequest request, ActionListener actionListener) { - getResource(request, actionListener); - } - - private void getResource(GetSampleResourceRequest request, ActionListener listener) { - ActionListener getResourceListener = ActionListener.wrap(sampleResource -> { - System.out.println("sampleResource: " + sampleResource); - listener.onResponse(new GetSampleResourceResponse(sampleResource)); - }, listener::onFailure); - resourceSharingService.get().getResource(request.getResourceId(), getResourceListener); + super(transportService, actionFilters, GetSampleResourceAction.NAME, resourceSharingService.get()); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceRequest.java new file mode 100644 index 0000000000..546cf1be36 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceRequest.java @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.opensearch.core.common.io.stream.StreamInput; + +/** + * Request object for GetSampleResource transport action + */ +public class GetResourceRequest extends ResourceRequest { + + /** + * Default constructor + */ + public GetResourceRequest(String resourceId, String resourceIndex) { + super(resourceId, resourceIndex); + } + + public GetResourceRequest(StreamInput in) throws IOException { + super(in); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceResponse.java new file mode 100644 index 0000000000..0b90f90221 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceResponse.java @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.opensearch.core.action.ActionResponse; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.common.io.stream.Writeable; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.security.spi.Resource; + +/** + * Response to a GetSampleResourceRequest + */ +public class GetResourceResponse extends ActionResponse implements ToXContentObject { + private final T resource; + + /** + * Default constructor + * + * @param resource The resource + */ + public GetResourceResponse(T resource) { + this.resource = resource; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + resource.writeTo(out); + } + + /** + * Constructor with StreamInput + * + * @param in the stream input + */ + public GetResourceResponse(final StreamInput in, Writeable.Reader resourceReader) throws IOException { + resource = resourceReader.read(in); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field("resource", resource); + builder.endObject(); + return builder; + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceTransportAction.java new file mode 100644 index 0000000000..3ada340ef8 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceTransportAction.java @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.core.action.ActionListener; +import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ResourceSharingService; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +/** + * Transport action for GetResource. + */ +public class GetResourceTransportAction extends HandledTransportAction> { + private static final Logger log = LogManager.getLogger(GetResourceTransportAction.class); + + private final ResourceSharingService resourceSharingService; + + public GetResourceTransportAction( + TransportService transportService, + ActionFilters actionFilters, + String actionName, + ResourceSharingService resourceSharingService + ) { + super(actionName, transportService, actionFilters, GetResourceRequest::new); + this.resourceSharingService = resourceSharingService; + } + + @Override + protected void doExecute(Task task, GetResourceRequest request, ActionListener> actionListener) { + getResource(request, actionListener); + } + + private void getResource(GetResourceRequest request, ActionListener> listener) { + ActionListener getResourceListener = ActionListener.wrap(sampleResource -> { + System.out.println("sampleResource: " + sampleResource); + listener.onResponse(new GetResourceResponse(sampleResource)); + }, listener::onFailure); + resourceSharingService.getResource(request.getResourceId(), getResourceListener); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/ResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/ResourceRequest.java new file mode 100644 index 0000000000..ae748e89a5 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/ResourceRequest.java @@ -0,0 +1,46 @@ +package org.opensearch.security.spi.actions; + +import java.io.IOException; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; + +public class ResourceRequest extends ActionRequest { + protected final String resourceId; + + protected final String resourceIndex; + + /** + * Default constructor + */ + public ResourceRequest(String resourceId, String resourceIndex) { + this.resourceId = resourceId; + this.resourceIndex = resourceIndex; + } + + public ResourceRequest(StreamInput in) throws IOException { + this.resourceId = in.readString(); + this.resourceIndex = in.readString(); + } + + @Override + public void writeTo(final StreamOutput out) throws IOException { + out.writeString(resourceId); + out.writeString(resourceIndex); + } + + @Override + public ActionRequestValidationException validate() { + return null; + } + + public String getResourceId() { + return this.resourceId; + } + + public String getResourceIndex() { + return this.resourceIndex; + } +} diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java index 082dc59f3b..ad454547df 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java @@ -24,6 +24,7 @@ public class ResourceSharingEntry implements ToXContentFragment { private final String resourceIndex; private final String resourceId; private final ResourceUser resourceUser; + // Key to this map is an action group private final Map shareWith; public ResourceSharingEntry(String resourceIndex, String resourceId, ResourceUser resourceUser, Map shareWith) { From 003b257153c1c4386d37275809e5f3ccc53982c0 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 17 Dec 2024 16:39:02 -0500 Subject: [PATCH 63/80] Remove now redundant classes Signed-off-by: Craig Perkins --- .../actions/get/GetSampleResourceRequest.java | 47 ---------------- .../get/GetSampleResourceResponse.java | 56 ------------------- 2 files changed, 103 deletions(-) delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRequest.java delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRequest.java deleted file mode 100644 index 3dbc2e861d..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRequest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.sampleextension.actions.get; - -import java.io.IOException; - -import org.opensearch.action.ActionRequest; -import org.opensearch.action.ActionRequestValidationException; -import org.opensearch.core.common.io.stream.StreamInput; -import org.opensearch.core.common.io.stream.StreamOutput; - -/** - * Request object for GetSampleResource transport action - */ -public class GetSampleResourceRequest extends ActionRequest { - - private String resourceId; - - public GetSampleResourceRequest(String resourceId) { - this.resourceId = resourceId; - } - - public String getResourceId() { - return resourceId; - } - - /** - * Constructor with stream input - * @param in the stream input - * @throws IOException IOException - */ - public GetSampleResourceRequest(final StreamInput in) throws IOException {} - - @Override - public void writeTo(final StreamOutput out) throws IOException {} - - @Override - public ActionRequestValidationException validate() { - return null; - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java deleted file mode 100644 index 77e926d916..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceResponse.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.sampleextension.actions.get; - -import java.io.IOException; - -import org.opensearch.core.action.ActionResponse; -import org.opensearch.core.common.io.stream.StreamInput; -import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.core.xcontent.ToXContentObject; -import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.sampleextension.resource.SampleResource; - -/** - * Response to a ListSampleResourceRequest - */ -public class GetSampleResourceResponse extends ActionResponse implements ToXContentObject { - private final SampleResource resource; - - /** - * Default constructor - * - * @param resource The resource - */ - public GetSampleResourceResponse(SampleResource resource) { - this.resource = resource; - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - resource.writeTo(out); - } - - /** - * Constructor with StreamInput - * - * @param in the stream input - */ - public GetSampleResourceResponse(final StreamInput in) throws IOException { - resource = SampleResource.from(in); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field("resource", resource); - builder.endObject(); - return builder; - } -} From e25d28fa6244cf9ee75818a244c5d564d88b2ca4 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 17 Dec 2024 16:54:16 -0500 Subject: [PATCH 64/80] Reorganize Signed-off-by: Craig Perkins --- .../create/CreateSampleResourceAction.java | 2 +- .../CreateSampleResourceRestAction.java | 2 +- .../CreateSampleResourceTransportAction.java | 2 +- .../actions/get/GetSampleResourceAction.java | 2 +- .../get/GetSampleResourceRestAction.java | 2 +- .../get/GetSampleResourceTransportAction.java | 4 +- .../list/ListSampleResourceAction.java | 6 ++- .../list/ListSampleResourceRequest.java | 39 ---------------- .../list/ListSampleResourceRestAction.java | 4 +- .../ListSampleResourceTransportAction.java | 30 +++---------- .../UpdateSampleResourceSharingAction.java | 2 +- ...UpdateSampleResourceSharingRestAction.java | 2 +- ...eSampleResourceSharingTransportAction.java | 2 +- .../security/spi/actions/ResourceRequest.java | 11 +---- .../create}/CreateResourceRequest.java | 2 +- .../create}/CreateResourceResponse.java | 2 +- .../CreateResourceTransportAction.java | 2 +- .../get}/GetResourceRequest.java | 12 ++++- .../get}/GetResourceResponse.java | 2 +- .../get}/GetResourceTransportAction.java | 2 +- .../resource/list/ListResourceRequest.java | 33 ++++++++++++++ .../resource/list/ListResourceResponse.java | 17 ++++--- .../list/ListResourceTransportAction.java | 45 +++++++++++++++++++ .../update}/UpdateResourceSharingRequest.java | 2 +- .../UpdateResourceSharingResponse.java | 2 +- .../UpdateResourceSharingTransportAction.java | 2 +- 26 files changed, 128 insertions(+), 105 deletions(-) delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java rename spi/src/main/java/org/opensearch/security/spi/actions/{ => resource/create}/CreateResourceRequest.java (95%) rename spi/src/main/java/org/opensearch/security/spi/actions/{ => resource/create}/CreateResourceResponse.java (96%) rename spi/src/main/java/org/opensearch/security/spi/actions/{ => resource/create}/CreateResourceTransportAction.java (98%) rename spi/src/main/java/org/opensearch/security/spi/actions/{ => resource/get}/GetResourceRequest.java (65%) rename spi/src/main/java/org/opensearch/security/spi/actions/{ => resource/get}/GetResourceResponse.java (96%) rename spi/src/main/java/org/opensearch/security/spi/actions/{ => resource/get}/GetResourceTransportAction.java (97%) create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceRequest.java rename sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java => spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java (65%) create mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java rename spi/src/main/java/org/opensearch/security/spi/actions/{ => sharing/update}/UpdateResourceSharingRequest.java (96%) rename spi/src/main/java/org/opensearch/security/spi/actions/{ => sharing/update}/UpdateResourceSharingResponse.java (96%) rename spi/src/main/java/org/opensearch/security/spi/actions/{ => sharing/update}/UpdateResourceSharingTransportAction.java (99%) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java index 19c2685ec3..618c31f24c 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceAction.java @@ -9,7 +9,7 @@ package org.opensearch.security.sampleextension.actions.create; import org.opensearch.action.ActionType; -import org.opensearch.security.spi.actions.CreateResourceResponse; +import org.opensearch.security.spi.actions.resource.create.CreateResourceResponse; /** * Action to create a sample resource diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java index e0be740991..315619b1d3 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceRestAction.java @@ -18,7 +18,7 @@ import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; import org.opensearch.security.sampleextension.resource.SampleResource; -import org.opensearch.security.spi.actions.CreateResourceRequest; +import org.opensearch.security.spi.actions.resource.create.CreateResourceRequest; import static java.util.Collections.singletonList; import static org.opensearch.rest.RestRequest.Method.POST; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index 181947ba8b..05f4c986de 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -15,7 +15,7 @@ import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; import org.opensearch.security.sampleextension.resource.SampleResource; -import org.opensearch.security.spi.actions.CreateResourceTransportAction; +import org.opensearch.security.spi.actions.resource.create.CreateResourceTransportAction; import org.opensearch.transport.TransportService; import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java index fde94b365e..4ea3e20486 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java @@ -10,7 +10,7 @@ import org.opensearch.action.ActionType; import org.opensearch.security.sampleextension.resource.SampleResource; -import org.opensearch.security.spi.actions.GetResourceResponse; +import org.opensearch.security.spi.actions.resource.get.GetResourceResponse; /** * Action to get a sample resource diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java index 1ee29cf3e0..bb517d7668 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceRestAction.java @@ -15,7 +15,7 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; -import org.opensearch.security.spi.actions.GetResourceRequest; +import org.opensearch.security.spi.actions.resource.get.GetResourceRequest; import static java.util.Collections.singletonList; import static org.opensearch.rest.RestRequest.Method.GET; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java index 55046c5664..5ea29634e7 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java @@ -15,11 +15,11 @@ import org.opensearch.common.inject.Inject; import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; -import org.opensearch.security.spi.actions.GetResourceTransportAction; +import org.opensearch.security.spi.actions.resource.get.GetResourceTransportAction; import org.opensearch.transport.TransportService; /** - * Transport action for UpdateSampleResource. + * Transport action for GetSampleResource. */ public class GetSampleResourceTransportAction extends GetResourceTransportAction { private static final Logger log = LogManager.getLogger(GetSampleResourceTransportAction.class); diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java index aac9ab10d9..e91bb7e111 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java @@ -9,11 +9,13 @@ package org.opensearch.security.sampleextension.actions.list; import org.opensearch.action.ActionType; +import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.spi.actions.resource.list.ListResourceResponse; /** * Action to list sample resources */ -public class ListSampleResourceAction extends ActionType { +public class ListSampleResourceAction extends ActionType> { /** * List sample resource action instance */ @@ -24,6 +26,6 @@ public class ListSampleResourceAction extends ActionType new ListResourceResponse<>(in, SampleResource::from)); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java deleted file mode 100644 index 3a6acb5cfb..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRequest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.sampleextension.actions.list; - -import java.io.IOException; - -import org.opensearch.action.ActionRequest; -import org.opensearch.action.ActionRequestValidationException; -import org.opensearch.core.common.io.stream.StreamInput; -import org.opensearch.core.common.io.stream.StreamOutput; - -/** - * Request object for ListSampleResource transport action - */ -public class ListSampleResourceRequest extends ActionRequest { - - public ListSampleResourceRequest() {} - - /** - * Constructor with stream input - * @param in the stream input - * @throws IOException IOException - */ - public ListSampleResourceRequest(final StreamInput in) throws IOException {} - - @Override - public void writeTo(final StreamOutput out) throws IOException {} - - @Override - public ActionRequestValidationException validate() { - return null; - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java index 4bab2c9ce6..da30b498f5 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceRestAction.java @@ -14,9 +14,11 @@ import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; +import org.opensearch.security.spi.actions.resource.list.ListResourceRequest; import static java.util.Collections.singletonList; import static org.opensearch.rest.RestRequest.Method.GET; +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; public class ListSampleResourceRestAction extends BaseRestHandler { @@ -34,7 +36,7 @@ public String getName() { @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) { - final ListSampleResourceRequest listSampleResourceRequest = new ListSampleResourceRequest(); + final ListResourceRequest listSampleResourceRequest = new ListResourceRequest(RESOURCE_INDEX_NAME); return channel -> client.executeLocally( ListSampleResourceAction.INSTANCE, listSampleResourceRequest, diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java index e7cda7e480..c8004f48e2 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java @@ -8,46 +8,28 @@ package org.opensearch.security.sampleextension.actions.list; -import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.opensearch.action.support.ActionFilters; -import org.opensearch.action.support.HandledTransportAction; -import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; -import org.opensearch.core.action.ActionListener; import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; -import org.opensearch.tasks.Task; +import org.opensearch.security.spi.actions.resource.list.ListResourceTransportAction; import org.opensearch.transport.TransportService; /** * Transport action for ListSampleResource. */ -public class ListSampleResourceTransportAction extends HandledTransportAction { - private final TransportService transportService; - private final Client nodeClient; - private final SampleResourceSharingServiceProvider resourceSharingService; +public class ListSampleResourceTransportAction extends ListResourceTransportAction { + private static final Logger log = LogManager.getLogger(ListSampleResourceTransportAction.class); - // TODO How can this inject work if either a DefaultResourceSharingService or SecurityResourceSharingService is binded? @Inject public ListSampleResourceTransportAction( TransportService transportService, ActionFilters actionFilters, - Client nodeClient, SampleResourceSharingServiceProvider resourceSharingService ) { - super(ListSampleResourceAction.NAME, transportService, actionFilters, ListSampleResourceRequest::new); - this.transportService = transportService; - this.nodeClient = nodeClient; - this.resourceSharingService = resourceSharingService; - } - - @Override - protected void doExecute(Task task, ListSampleResourceRequest request, ActionListener listener) { - ActionListener> sampleResourceListener = ActionListener.wrap(sampleResourcesList -> { - System.out.println("sampleResourcesList: " + sampleResourcesList); - listener.onResponse(new ListSampleResourceResponse(sampleResourcesList)); - }, listener::onFailure); - resourceSharingService.get().listResources(sampleResourceListener); + super(transportService, actionFilters, ListSampleResourceAction.NAME, resourceSharingService.get()); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java index 4fcd311d3c..3df1e73f6d 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java @@ -9,7 +9,7 @@ package org.opensearch.security.sampleextension.actions.sharing; import org.opensearch.action.ActionType; -import org.opensearch.security.spi.actions.UpdateResourceSharingResponse; +import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingResponse; /** * Action to create a sample resource diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java index 94213787e0..42915299b9 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java @@ -19,7 +19,7 @@ import org.opensearch.rest.action.RestToXContentListener; import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.ShareWith; -import org.opensearch.security.spi.actions.UpdateResourceSharingRequest; +import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingRequest; import static java.util.Collections.singletonList; import static org.opensearch.rest.RestRequest.Method.PUT; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java index 7e5981cf90..d21cd43f28 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java @@ -16,7 +16,7 @@ import org.opensearch.common.inject.Inject; import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.ShareWith; -import org.opensearch.security.spi.actions.UpdateResourceSharingTransportAction; +import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingTransportAction; import org.opensearch.transport.TransportService; import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/ResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/ResourceRequest.java index ae748e89a5..798bcce874 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/ResourceRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/ResourceRequest.java @@ -8,26 +8,21 @@ import org.opensearch.core.common.io.stream.StreamOutput; public class ResourceRequest extends ActionRequest { - protected final String resourceId; - protected final String resourceIndex; /** * Default constructor */ - public ResourceRequest(String resourceId, String resourceIndex) { - this.resourceId = resourceId; + public ResourceRequest(String resourceIndex) { this.resourceIndex = resourceIndex; } public ResourceRequest(StreamInput in) throws IOException { - this.resourceId = in.readString(); this.resourceIndex = in.readString(); } @Override public void writeTo(final StreamOutput out) throws IOException { - out.writeString(resourceId); out.writeString(resourceIndex); } @@ -36,10 +31,6 @@ public ActionRequestValidationException validate() { return null; } - public String getResourceId() { - return this.resourceId; - } - public String getResourceIndex() { return this.resourceIndex; } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceRequest.java similarity index 95% rename from spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java rename to spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceRequest.java index e930cf1ecf..69576bc040 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceRequest.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.resource.create; import java.io.IOException; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceResponse.java similarity index 96% rename from spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java rename to spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceResponse.java index 8e13c78c4e..5cbf28c7c9 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceResponse.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.resource.create; import java.io.IOException; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceTransportAction.java similarity index 98% rename from spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java rename to spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceTransportAction.java index ede88c5326..5c62a0b5e9 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/CreateResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceTransportAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.resource.create; import java.io.IOException; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceRequest.java similarity index 65% rename from spi/src/main/java/org/opensearch/security/spi/actions/GetResourceRequest.java rename to spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceRequest.java index 546cf1be36..d7df10e4e8 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceRequest.java @@ -6,25 +6,33 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.resource.get; import java.io.IOException; import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.security.spi.actions.ResourceRequest; /** * Request object for GetSampleResource transport action */ public class GetResourceRequest extends ResourceRequest { + private final String resourceId; /** * Default constructor */ public GetResourceRequest(String resourceId, String resourceIndex) { - super(resourceId, resourceIndex); + super(resourceIndex); + this.resourceId = resourceId; } public GetResourceRequest(StreamInput in) throws IOException { super(in); + this.resourceId = in.readString(); + } + + public String getResourceId() { + return this.resourceId; } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java similarity index 96% rename from spi/src/main/java/org/opensearch/security/spi/actions/GetResourceResponse.java rename to spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java index 0b90f90221..6f57097861 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.resource.get; import java.io.IOException; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java similarity index 97% rename from spi/src/main/java/org/opensearch/security/spi/actions/GetResourceTransportAction.java rename to spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java index 3ada340ef8..bb5e5ba934 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/GetResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.resource.get; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceRequest.java new file mode 100644 index 0000000000..b0c1f199ca --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceRequest.java @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions.resource.list; + +import java.io.IOException; + +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.security.spi.actions.ResourceRequest; + +/** + * Request object for ListSampleResource transport action + */ +public class ListResourceRequest extends ResourceRequest { + + // TODO Change this into Search instead of List + + /** + * Default constructor + */ + public ListResourceRequest(String resourceIndex) { + super(resourceIndex); + } + + public ListResourceRequest(StreamInput in) throws IOException { + super(in); + } +} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java similarity index 65% rename from sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java rename to spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java index 7225ed835d..1d2812a768 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.sampleextension.actions.list; +package org.opensearch.security.spi.actions.resource.list; import java.io.IOException; import java.util.List; @@ -16,21 +16,20 @@ import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.spi.Resource; /** - * Response to a ListSampleResourceRequest + * Response to a GetSampleResourceRequest */ -public class ListSampleResourceResponse extends ActionResponse implements ToXContentObject { - private final List resources; +public class ListResourceResponse extends ActionResponse implements ToXContentObject { + private final List resources; /** * Default constructor * * @param resources The resources */ - public ListSampleResourceResponse(List resources) { + public ListResourceResponse(List resources) { this.resources = resources; } @@ -44,14 +43,14 @@ public void writeTo(StreamOutput out) throws IOException { * * @param in the stream input */ - public ListSampleResourceResponse(final StreamInput in) throws IOException { - resources = in.readList(SampleResource::from); + public ListResourceResponse(final StreamInput in, Reader resourceReader) throws IOException { + resources = in.readList(resourceReader); } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.array("resources", (Object[]) resources.toArray(new Resource[0])); + builder.field("resources", resources); builder.endObject(); return builder; } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java new file mode 100644 index 0000000000..29b405b160 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi.actions.resource.list; + +import java.util.List; + +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.core.action.ActionListener; +import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ResourceSharingService; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +/** + * Transport action for GetResource. + */ +public class ListResourceTransportAction extends HandledTransportAction> { + private final ResourceSharingService resourceSharingService; + + public ListResourceTransportAction( + TransportService transportService, + ActionFilters actionFilters, + String actionName, + ResourceSharingService resourceSharingService + ) { + super(actionName, transportService, actionFilters, ListResourceRequest::new); + this.resourceSharingService = resourceSharingService; + } + + @Override + protected void doExecute(Task task, ListResourceRequest request, ActionListener> listener) { + ActionListener> sampleResourceListener = ActionListener.wrap(sampleResourcesList -> { + System.out.println("sampleResourcesList: " + sampleResourcesList); + listener.onResponse(new ListResourceResponse(sampleResourcesList)); + }, listener::onFailure); + resourceSharingService.listResources(sampleResourceListener); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java similarity index 96% rename from spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java rename to spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java index c658b34430..eda3b533b1 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.sharing.update; import java.io.IOException; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java similarity index 96% rename from spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingResponse.java rename to spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java index 3fd4887f9c..7bf8fe2f32 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.sharing.update; import java.io.IOException; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java similarity index 99% rename from spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java rename to spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java index 35cd9105e4..3157e98255 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/UpdateResourceSharingTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.security.spi.actions; +package org.opensearch.security.spi.actions.sharing.update; import java.io.IOException; import java.util.Arrays; From 291d33d6b6447e8bfae5829fe30033aac9225b03 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 17 Dec 2024 17:43:14 -0500 Subject: [PATCH 65/80] WIP on general resource sharing rest action Signed-off-by: Craig Perkins --- .../UpdateSampleResourceSharingAction.java | 6 +- .../update/UpdateSampleResourceAction.java | 6 +- .../update/UpdateSampleResourceRequest.java | 2 +- .../update/UpdateSampleResourceResponse.java | 2 +- .../org/opensearch/security/spi/Resource.java | 13 -- .../resource/get/GetResourceRequest.java | 2 +- .../resource/get/GetResourceResponse.java | 2 +- .../resource/list/ListResourceRequest.java | 2 +- .../resource/list/ListResourceResponse.java | 2 +- .../list/ListResourceTransportAction.java | 2 +- .../update/UpdateResourceSharingRequest.java | 2 +- .../update/UpdateResourceSharingResponse.java | 2 +- .../UpdateResourceSharingTransportAction.java | 4 +- .../security/OpenSearchSecurityPlugin.java | 3 +- .../rest/api/SecurityApiDependencies.java | 12 +- .../dlic/rest/api/SecurityRestApiActions.java | 7 +- .../rest/resource/ShareWithAction.java | 30 +++++ .../rest/resource/ShareWithRequest.java | 66 ++++++++++ .../rest/resource/ShareWithResponse.java | 55 ++++++++ .../rest/resource/ShareWithRestAction.java | 83 ++++++++++++ .../resource/ShareWithTransportAction.java | 124 ++++++++++++++++++ .../api/AbstractApiActionValidationTest.java | 3 +- ...SecurityConfigApiActionValidationTest.java | 19 ++- 23 files changed, 410 insertions(+), 39 deletions(-) create mode 100644 src/main/java/org/opensearch/security/rest/resource/ShareWithAction.java create mode 100644 src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java create mode 100644 src/main/java/org/opensearch/security/rest/resource/ShareWithResponse.java create mode 100644 src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java create mode 100644 src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java index 3df1e73f6d..439c0db520 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java @@ -12,15 +12,15 @@ import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingResponse; /** - * Action to create a sample resource + * Action to update sharing configuration for a sample resource */ public class UpdateSampleResourceSharingAction extends ActionType { /** - * Create sample resource action instance + * Update sharing configuratino for sample resource action instance */ public static final UpdateSampleResourceSharingAction INSTANCE = new UpdateSampleResourceSharingAction(); /** - * Create sample resource action name + * Update sharing configuration for sample resource action name */ public static final String NAME = "cluster:admin/sampleresource/updatesharing"; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceAction.java index 18f8f1d3fe..cb1a6a394c 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceAction.java @@ -11,15 +11,15 @@ import org.opensearch.action.ActionType; /** - * Action to create a sample resource + * Action to update a sample resource */ public class UpdateSampleResourceAction extends ActionType { /** - * Create sample resource action instance + * Update sample resource action instance */ public static final UpdateSampleResourceAction INSTANCE = new UpdateSampleResourceAction(); /** - * Create sample resource action name + * Update sample resource action name */ public static final String NAME = "cluster:admin/sampleresource/update"; diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRequest.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRequest.java index ad3118e577..1f35dcffd6 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRequest.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceRequest.java @@ -16,7 +16,7 @@ import org.opensearch.core.common.io.stream.StreamOutput; /** - * Request object for ListSampleResource transport action + * Request object for UpdateSampleResource transport action */ public class UpdateSampleResourceRequest extends ActionRequest { diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceResponse.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceResponse.java index dcd996db9b..83babbc847 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceResponse.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/update/UpdateSampleResourceResponse.java @@ -17,7 +17,7 @@ import org.opensearch.core.xcontent.XContentBuilder; /** - * Response to a ListSampleResourceRequest + * Response to a UpdateSampleResourceRequest */ public class UpdateSampleResourceResponse extends ActionResponse implements ToXContentObject { private final String resourceId; diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java index f5c9cc7a4b..2ef8795874 100644 --- a/spi/src/main/java/org/opensearch/security/spi/Resource.java +++ b/spi/src/main/java/org/opensearch/security/spi/Resource.java @@ -1,31 +1,18 @@ package org.opensearch.security.spi; import java.util.Map; -import java.util.Set; import org.opensearch.core.common.io.stream.NamedWriteable; import org.opensearch.core.xcontent.ToXContentFragment; public abstract class Resource implements NamedWriteable, ToXContentFragment { - protected ResourceUser resourceUser; protected String resourceId; public String getResourceId() { return resourceId; } - public ResourceUser getResourceUser() { - return resourceUser; - } - - @SuppressWarnings("unchecked") public void fromSource(String resourceId, Map sourceAsMap) { this.resourceId = resourceId; - if (sourceAsMap.containsKey("resource_user")) { - Map userMap = (Map) sourceAsMap.get("resource_user"); - String username = (String) userMap.get("name"); - Set backendRoles = (Set) userMap.get("backend_roles"); - this.resourceUser = new ResourceUser(username, backendRoles); - } } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceRequest.java index d7df10e4e8..a5b97b89b3 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceRequest.java @@ -14,7 +14,7 @@ import org.opensearch.security.spi.actions.ResourceRequest; /** - * Request object for GetSampleResource transport action + * Request object for GetResource transport action */ public class GetResourceRequest extends ResourceRequest { private final String resourceId; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java index 6f57097861..30b00e7aca 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java @@ -19,7 +19,7 @@ import org.opensearch.security.spi.Resource; /** - * Response to a GetSampleResourceRequest + * Response to a GetResourceRequest */ public class GetResourceResponse extends ActionResponse implements ToXContentObject { private final T resource; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceRequest.java index b0c1f199ca..09013d226b 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceRequest.java @@ -14,7 +14,7 @@ import org.opensearch.security.spi.actions.ResourceRequest; /** - * Request object for ListSampleResource transport action + * Request object for ListResource transport action */ public class ListResourceRequest extends ResourceRequest { diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java index 1d2812a768..b0d7ccf81f 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java @@ -19,7 +19,7 @@ import org.opensearch.security.spi.Resource; /** - * Response to a GetSampleResourceRequest + * Response to a ListResourceRequest */ public class ListResourceResponse extends ActionResponse implements ToXContentObject { private final List resources; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java index 29b405b160..c843678598 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java @@ -19,7 +19,7 @@ import org.opensearch.transport.TransportService; /** - * Transport action for GetResource. + * Transport action for ListResource. */ public class ListResourceTransportAction extends HandledTransportAction> { private final ResourceSharingService resourceSharingService; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java index eda3b533b1..af201a6e45 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java @@ -18,7 +18,7 @@ import org.opensearch.security.spi.ShareWith; /** - * Request object for CreateSampleResource transport action + * Request object for UpdateResourceSharing transport action */ public class UpdateResourceSharingRequest extends ActionRequest { diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java index 7bf8fe2f32..2e04572543 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java @@ -17,7 +17,7 @@ import org.opensearch.core.xcontent.XContentBuilder; /** - * Response to a CreateSampleResourceRequest + * Response to a UpdateResourceSharingRequest */ public class UpdateResourceSharingResponse extends ActionResponse implements ToXContentObject { private final String message; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java index 3157e98255..07892dd0e0 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java @@ -9,7 +9,6 @@ package org.opensearch.security.spi.actions.sharing.update; import java.io.IOException; -import java.util.Arrays; import java.util.Objects; import org.apache.logging.log4j.LogManager; @@ -37,7 +36,7 @@ import org.opensearch.transport.TransportService; /** - * Transport action for CreateSampleResource. + * Transport action for UpdateResourceSharing. */ public class UpdateResourceSharingTransportAction extends HandledTransportAction< UpdateResourceSharingRequest, @@ -79,7 +78,6 @@ protected void doExecute(Task task, UpdateResourceSharingRequest request, Act nodeClient.search(searchRequest, new ActionListener() { @Override public void onResponse(SearchResponse searchResponse) { - System.out.println("searchResponse.getHits(): " + Arrays.toString(searchResponse.getHits().getHits())); if (Objects.requireNonNull(searchResponse.getHits().getTotalHits()).value == 1) { // Record found, update it SearchHit hit = searchResponse.getHits().getAt(0); diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index f0b9bab4c0..ab81ca5a77 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -670,7 +670,8 @@ public List getRestHandlers( sslSettingsManager, Objects.requireNonNull(userService), sslCertReloadEnabled, - passwordHasher + passwordHasher, + resourceSharingExtensions ) ); log.debug("Added {} rest handler(s)", handlers.size()); diff --git a/src/main/java/org/opensearch/security/dlic/rest/api/SecurityApiDependencies.java b/src/main/java/org/opensearch/security/dlic/rest/api/SecurityApiDependencies.java index 498230423f..7d3be960b3 100644 --- a/src/main/java/org/opensearch/security/dlic/rest/api/SecurityApiDependencies.java +++ b/src/main/java/org/opensearch/security/dlic/rest/api/SecurityApiDependencies.java @@ -11,11 +11,14 @@ package org.opensearch.security.dlic.rest.api; +import java.util.List; + import org.opensearch.common.settings.Settings; import org.opensearch.security.auditlog.AuditLog; import org.opensearch.security.configuration.AdminDNs; import org.opensearch.security.configuration.ConfigurationRepository; import org.opensearch.security.privileges.PrivilegesEvaluator; +import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.support.ConfigConstants; public class SecurityApiDependencies { @@ -25,6 +28,7 @@ public class SecurityApiDependencies { private final RestApiAdminPrivilegesEvaluator restApiAdminPrivilegesEvaluator; private final AuditLog auditLog; private final Settings settings; + private final List resourceSharingExtensions; private final PrivilegesEvaluator privilegesEvaluator; @@ -35,7 +39,8 @@ public SecurityApiDependencies( final RestApiPrivilegesEvaluator restApiPrivilegesEvaluator, final RestApiAdminPrivilegesEvaluator restApiAdminPrivilegesEvaluator, final AuditLog auditLog, - final Settings settings + final Settings settings, + final List resourceSharingExtensions ) { this.adminDNs = adminDNs; this.configurationRepository = configurationRepository; @@ -44,6 +49,7 @@ public SecurityApiDependencies( this.restApiAdminPrivilegesEvaluator = restApiAdminPrivilegesEvaluator; this.auditLog = auditLog; this.settings = settings; + this.resourceSharingExtensions = resourceSharingExtensions; } public AdminDNs adminDNs() { @@ -66,6 +72,10 @@ public RestApiAdminPrivilegesEvaluator restApiAdminPrivilegesEvaluator() { return restApiAdminPrivilegesEvaluator; } + public List resourceSharingExtensions() { + return resourceSharingExtensions; + } + public AuditLog auditLog() { return auditLog; } diff --git a/src/main/java/org/opensearch/security/dlic/rest/api/SecurityRestApiActions.java b/src/main/java/org/opensearch/security/dlic/rest/api/SecurityRestApiActions.java index c28a1bdc1d..926b091c91 100644 --- a/src/main/java/org/opensearch/security/dlic/rest/api/SecurityRestApiActions.java +++ b/src/main/java/org/opensearch/security/dlic/rest/api/SecurityRestApiActions.java @@ -25,6 +25,7 @@ import org.opensearch.security.configuration.ConfigurationRepository; import org.opensearch.security.hasher.PasswordHasher; import org.opensearch.security.privileges.PrivilegesEvaluator; +import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.ssl.SslSettingsManager; import org.opensearch.security.ssl.transport.PrincipalExtractor; import org.opensearch.security.user.UserService; @@ -49,7 +50,8 @@ public static Collection getHandler( final SslSettingsManager sslSettingsManager, final UserService userService, final boolean certificatesReloadEnabled, - final PasswordHasher passwordHasher + final PasswordHasher passwordHasher, + final List resourceSharingExtensions ) { final var securityApiDependencies = new SecurityApiDependencies( adminDns, @@ -63,7 +65,8 @@ public static Collection getHandler( settings.getAsBoolean(SECURITY_RESTAPI_ADMIN_ENABLED, false) ), auditLog, - settings + settings, + resourceSharingExtensions ); return List.of( new InternalUsersApiAction(clusterService, threadPool, userService, securityApiDependencies, passwordHasher), diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithAction.java new file mode 100644 index 0000000000..a97989270e --- /dev/null +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithAction.java @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.rest.resource; + +import org.opensearch.action.ActionType; +import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingResponse; + +/** + * Action to update sharing configuration for a sample resource + */ +public class ShareWithAction extends ActionType { + /** + * Update sharing configuratino for sample resource action instance + */ + public static final ShareWithAction INSTANCE = new ShareWithAction(); + /** + * Update sharing configuration for sample resource action name + */ + public static final String NAME = "cluster:admin/opendistro_security/resource/share_with"; + + private ShareWithAction() { + super(NAME, UpdateResourceSharingResponse::new); + } +} diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java new file mode 100644 index 0000000000..1204b7e061 --- /dev/null +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.rest.resource; + +import java.io.IOException; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.ActionRequestValidationException; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.security.spi.ShareWith; + +/** + * Request object for UpdateResourceSharing transport action + */ +public class ShareWithRequest extends ActionRequest { + + private final String resourceId; + private final String resourceIndex; + private final ShareWith shareWith; + + /** + * Default constructor + */ + public ShareWithRequest(String resourceId, String resourceIndex, ShareWith shareWith) { + this.resourceId = resourceId; + this.resourceIndex = resourceIndex; + this.shareWith = shareWith; + } + + public ShareWithRequest(StreamInput in, Reader shareWithReader) throws IOException { + this.resourceId = in.readString(); + this.resourceIndex = in.readString(); + this.shareWith = shareWithReader.read(in); + } + + @Override + public void writeTo(final StreamOutput out) throws IOException { + out.writeString(resourceId); + out.writeString(resourceIndex); + shareWith.writeTo(out); + } + + @Override + public ActionRequestValidationException validate() { + return null; + } + + public String getResourceId() { + return this.resourceId; + } + + public String getResourceIndex() { + return this.resourceIndex; + } + + public ShareWith getShareWith() { + return this.shareWith; + } +} diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithResponse.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithResponse.java new file mode 100644 index 0000000000..a33529091e --- /dev/null +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithResponse.java @@ -0,0 +1,55 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.rest.resource; + +import java.io.IOException; + +import org.opensearch.core.action.ActionResponse; +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.xcontent.ToXContentObject; +import org.opensearch.core.xcontent.XContentBuilder; + +/** + * Response to a UpdateResourceSharingRequest + */ +public class ShareWithResponse extends ActionResponse implements ToXContentObject { + private final String message; + + /** + * Default constructor + * + * @param message The message + */ + public ShareWithResponse(String message) { + this.message = message; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeString(message); + } + + /** + * Constructor with StreamInput + * + * @param in the stream input + */ + public ShareWithResponse(final StreamInput in) throws IOException { + message = in.readString(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field("message", message); + builder.endObject(); + return builder; + } +} diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java new file mode 100644 index 0000000000..1d50c497be --- /dev/null +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java @@ -0,0 +1,83 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.rest.resource; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableList; + +import org.opensearch.client.node.NodeClient; +import org.opensearch.core.xcontent.XContentParser; +import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.RestRequest; +import org.opensearch.rest.action.RestToXContentListener; +import org.opensearch.security.spi.ResourceSharingExtension; +import org.opensearch.security.spi.ShareWith; + +import static org.opensearch.rest.RestRequest.Method.PUT; +import static org.opensearch.security.dlic.rest.support.Utils.addRoutesPrefix; + +public class ShareWithRestAction extends BaseRestHandler { + + private final Map resourceTypeToIndexMap = new HashMap<>(); + + public ShareWithRestAction(final List resourceSharingExtensions) { + if (resourceSharingExtensions != null) { + for (ResourceSharingExtension resourceSharingExtension : resourceSharingExtensions) { + resourceTypeToIndexMap.put(resourceSharingExtension.getResourceType(), resourceSharingExtension.getResourceIndex()); + } + } + } + + private static final List routes = addRoutesPrefix( + ImmutableList.of(new Route(PUT, "/resource/{resource_type}/{id}/share_with")), + "/_plugins/_security" + ); + + @Override + public List routes() { + return routes; + } + + @Override + public String getName() { + return "update_resource_sharing"; + } + + @SuppressWarnings("unchecked") + @Override + public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + String resourceId = request.param("id"); + String resourceType = request.param("resource_type"); + + if (!resourceTypeToIndexMap.containsKey(resourceType)) { + throw new IllegalArgumentException("Resource type " + resourceType + " is not supported"); + } + + System.out.println("share with endpoint"); + System.out.println("resourceId: " + resourceId); + Map source; + try (XContentParser parser = request.contentParser()) { + source = parser.map(); + } + + Map shareWithMap = (Map) source.get("share_with"); + ShareWith shareWith = new ShareWith( + (List) shareWithMap.get("users"), + (List) shareWithMap.get("backend_roles"), + (List) shareWithMap.get("allowed_actions") + ); + + final ShareWithRequest shareWithRequest = new ShareWithRequest(resourceId, resourceTypeToIndexMap.get(resourceType), shareWith); + return channel -> client.executeLocally(ShareWithAction.INSTANCE, shareWithRequest, new RestToXContentListener<>(channel)); + } +} diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java new file mode 100644 index 0000000000..06d2241600 --- /dev/null +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java @@ -0,0 +1,124 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.rest.resource; + +import java.io.IOException; +import java.util.Objects; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.opensearch.action.search.SearchRequest; +import org.opensearch.action.search.SearchResponse; +import org.opensearch.action.support.ActionFilters; +import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.action.update.UpdateRequest; +import org.opensearch.action.update.UpdateResponse; +import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.common.xcontent.XContentFactory; +import org.opensearch.core.action.ActionListener; +import org.opensearch.core.common.io.stream.Writeable; +import org.opensearch.core.xcontent.XContentBuilder; +import org.opensearch.index.query.BoolQueryBuilder; +import org.opensearch.index.query.QueryBuilders; +import org.opensearch.search.SearchHit; +import org.opensearch.search.builder.SearchSourceBuilder; +import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ShareWith; +import org.opensearch.tasks.Task; +import org.opensearch.transport.TransportService; + +/** + * Transport action for UpdateResourceSharing. + */ +public class ShareWithTransportAction extends HandledTransportAction { + private static final Logger log = LogManager.getLogger(ShareWithTransportAction.class); + + public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; + + private final TransportService transportService; + private final Client nodeClient; + + public ShareWithTransportAction( + TransportService transportService, + ActionFilters actionFilters, + Client nodeClient, + String actionName, + String resourceIndex, + Writeable.Reader shareWithReader + ) { + super(actionName, transportService, actionFilters, (in) -> new ShareWithRequest(in, shareWithReader)); + this.transportService = transportService; + this.nodeClient = nodeClient; + } + + @Override + protected void doExecute(Task task, ShareWithRequest request, ActionListener listener) { + try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { + SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() + .must(QueryBuilders.matchQuery("resource_id", request.getResourceId())) + .must(QueryBuilders.matchQuery("resource_index", request.getResourceIndex())); + searchSourceBuilder.query(boolQuery); + searchRequest.source(searchSourceBuilder); + + // Execute the search request + nodeClient.search(searchRequest, new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + if (Objects.requireNonNull(searchResponse.getHits().getTotalHits()).value == 1) { + // Record found, update it + SearchHit hit = searchResponse.getHits().getAt(0); + UpdateRequest updateRequest = new UpdateRequest(RESOURCE_SHARING_INDEX, hit.getId()); + try { + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject(); + { + builder.startObject("share_with"); + { + builder.field("users", request.getShareWith().getUsers()); + builder.field("backend_roles", request.getShareWith().getBackendRoles()); + builder.field("allowed_actions", request.getShareWith().getAllowedActions()); + } + builder.endObject(); + } + builder.endObject(); + updateRequest.doc(builder); + + nodeClient.update(updateRequest, new ActionListener() { + @Override + public void onResponse(UpdateResponse updateResponse) { + listener.onResponse(new ShareWithResponse("success")); + } + + @Override + public void onFailure(Exception e) { + listener.onFailure(e); + } + }); + } catch (IOException e) { + listener.onFailure(e); + } + } else { + // Record not found, create a new one + // createNewRecord(request, listener); + listener.onFailure(new IllegalStateException(".resource-sharing entry not found")); + } + } + + @Override + public void onFailure(Exception e) { + listener.onFailure(e); + } + }); + } + } +} diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/AbstractApiActionValidationTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/AbstractApiActionValidationTest.java index 9278551efa..f5237115d1 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/AbstractApiActionValidationTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/AbstractApiActionValidationTest.java @@ -78,7 +78,8 @@ public void setup() { null, restApiAdminPrivilegesEvaluator, null, - Settings.EMPTY + Settings.EMPTY, + List.of() ); passwordHasher = PasswordHasherFactory.createPasswordHasher( diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityConfigApiActionValidationTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityConfigApiActionValidationTest.java index a6832457b3..b164d9a245 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityConfigApiActionValidationTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityConfigApiActionValidationTest.java @@ -11,6 +11,8 @@ package org.opensearch.security.dlic.rest.api; +import java.util.List; + import org.junit.Test; import org.opensearch.common.settings.Settings; @@ -30,7 +32,16 @@ public void accessHandlerForDefaultSettings() { final var securityConfigApiAction = new SecurityConfigApiAction( clusterService, threadPool, - new SecurityApiDependencies(null, configurationRepository, null, null, restApiAdminPrivilegesEvaluator, null, Settings.EMPTY) + new SecurityApiDependencies( + null, + configurationRepository, + null, + null, + restApiAdminPrivilegesEvaluator, + null, + Settings.EMPTY, + List.of() + ) ); assertTrue(securityConfigApiAction.accessHandler(FakeRestRequest.builder().withMethod(RestRequest.Method.GET).build())); assertFalse(securityConfigApiAction.accessHandler(FakeRestRequest.builder().withMethod(RestRequest.Method.PUT).build())); @@ -49,7 +60,8 @@ public void accessHandlerForUnsupportedSetting() { null, restApiAdminPrivilegesEvaluator, null, - Settings.builder().put(SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build() + Settings.builder().put(SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build(), + List.of() ) ); assertTrue(securityConfigApiAction.accessHandler(FakeRestRequest.builder().withMethod(RestRequest.Method.GET).build())); @@ -70,7 +82,8 @@ public void accessHandlerForRestAdmin() { null, restApiAdminPrivilegesEvaluator, null, - Settings.builder().put(SECURITY_RESTAPI_ADMIN_ENABLED, true).build() + Settings.builder().put(SECURITY_RESTAPI_ADMIN_ENABLED, true).build(), + List.of() ) ); assertTrue(securityConfigApiAction.accessHandler(FakeRestRequest.builder().withMethod(RestRequest.Method.GET).build())); From 259366306ebf2a54fcbc1bf1b9906f6a551c5c79 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 17 Dec 2024 17:49:46 -0500 Subject: [PATCH 66/80] WIP on share with rest action from security plugin Signed-off-by: Craig Perkins --- .../security/OpenSearchSecurityPlugin.java | 3 +++ .../dlic/rest/api/SecurityRestApiActions.java | 4 +++- .../security/rest/resource/ShareWithAction.java | 7 +++---- .../rest/resource/ShareWithTransportAction.java | 17 +++++------------ 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index ab81ca5a77..8aa1eb0e02 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -183,6 +183,8 @@ import org.opensearch.security.rest.SecurityInfoAction; import org.opensearch.security.rest.SecurityWhoAmIAction; import org.opensearch.security.rest.TenantInfoAction; +import org.opensearch.security.rest.resource.ShareWithAction; +import org.opensearch.security.rest.resource.ShareWithTransportAction; import org.opensearch.security.securityconf.DynamicConfigFactory; import org.opensearch.security.securityconf.impl.CType; import org.opensearch.security.setting.OpensearchDynamicSetting; @@ -701,6 +703,7 @@ public UnaryOperator getRestHandlerWrapper(final ThreadContext thre actions.add(new ActionHandler<>(CertificatesActionType.INSTANCE, TransportCertificatesInfoNodesAction.class)); } actions.add(new ActionHandler<>(WhoAmIAction.INSTANCE, TransportWhoAmIAction.class)); + actions.add(new ActionHandler<>(ShareWithAction.INSTANCE, ShareWithTransportAction.class)); } return actions; } diff --git a/src/main/java/org/opensearch/security/dlic/rest/api/SecurityRestApiActions.java b/src/main/java/org/opensearch/security/dlic/rest/api/SecurityRestApiActions.java index 926b091c91..d8c5402f81 100644 --- a/src/main/java/org/opensearch/security/dlic/rest/api/SecurityRestApiActions.java +++ b/src/main/java/org/opensearch/security/dlic/rest/api/SecurityRestApiActions.java @@ -25,6 +25,7 @@ import org.opensearch.security.configuration.ConfigurationRepository; import org.opensearch.security.hasher.PasswordHasher; import org.opensearch.security.privileges.PrivilegesEvaluator; +import org.opensearch.security.rest.resource.ShareWithRestAction; import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.ssl.SslSettingsManager; import org.opensearch.security.ssl.transport.PrincipalExtractor; @@ -107,7 +108,8 @@ public static Collection getHandler( certificatesReloadEnabled, securityApiDependencies ), - new CertificatesApiAction(clusterService, threadPool, securityApiDependencies) + new CertificatesApiAction(clusterService, threadPool, securityApiDependencies), + new ShareWithRestAction(resourceSharingExtensions) ); } diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithAction.java index a97989270e..7e0f52ce4e 100644 --- a/src/main/java/org/opensearch/security/rest/resource/ShareWithAction.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithAction.java @@ -9,14 +9,13 @@ package org.opensearch.security.rest.resource; import org.opensearch.action.ActionType; -import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingResponse; /** * Action to update sharing configuration for a sample resource */ -public class ShareWithAction extends ActionType { +public class ShareWithAction extends ActionType { /** - * Update sharing configuratino for sample resource action instance + * Update sharing configuration for sample resource action instance */ public static final ShareWithAction INSTANCE = new ShareWithAction(); /** @@ -25,6 +24,6 @@ public class ShareWithAction extends ActionType { public static final String NAME = "cluster:admin/opendistro_security/resource/share_with"; private ShareWithAction() { - super(NAME, UpdateResourceSharingResponse::new); + super(NAME, ShareWithResponse::new); } } diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java index 06d2241600..014b08d5f0 100644 --- a/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java @@ -21,16 +21,15 @@ import org.opensearch.action.update.UpdateRequest; import org.opensearch.action.update.UpdateResponse; import org.opensearch.client.Client; +import org.opensearch.common.inject.Inject; import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.common.xcontent.XContentFactory; import org.opensearch.core.action.ActionListener; -import org.opensearch.core.common.io.stream.Writeable; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.index.query.BoolQueryBuilder; import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; -import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ShareWith; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -38,7 +37,7 @@ /** * Transport action for UpdateResourceSharing. */ -public class ShareWithTransportAction extends HandledTransportAction { +public class ShareWithTransportAction extends HandledTransportAction { private static final Logger log = LogManager.getLogger(ShareWithTransportAction.class); public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; @@ -46,15 +45,9 @@ public class ShareWithTransportAction extends HandledTranspo private final TransportService transportService; private final Client nodeClient; - public ShareWithTransportAction( - TransportService transportService, - ActionFilters actionFilters, - Client nodeClient, - String actionName, - String resourceIndex, - Writeable.Reader shareWithReader - ) { - super(actionName, transportService, actionFilters, (in) -> new ShareWithRequest(in, shareWithReader)); + @Inject + public ShareWithTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { + super(ShareWithAction.NAME, transportService, actionFilters, (in) -> new ShareWithRequest(in, ShareWith::new)); this.transportService = transportService; this.nodeClient = nodeClient; } From 981446ab1421f990fd3c40a29b460a8fde275a0b Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 17 Dec 2024 17:54:05 -0500 Subject: [PATCH 67/80] Use constructor directly Signed-off-by: Craig Perkins --- .../opensearch/security/rest/resource/ShareWithRequest.java | 4 ++-- .../security/rest/resource/ShareWithTransportAction.java | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java index 1204b7e061..6e64ef6997 100644 --- a/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java @@ -34,10 +34,10 @@ public ShareWithRequest(String resourceId, String resourceIndex, ShareWith share this.shareWith = shareWith; } - public ShareWithRequest(StreamInput in, Reader shareWithReader) throws IOException { + public ShareWithRequest(StreamInput in) throws IOException { this.resourceId = in.readString(); this.resourceIndex = in.readString(); - this.shareWith = shareWithReader.read(in); + this.shareWith = new ShareWith(in); } @Override diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java index 014b08d5f0..d2427698a9 100644 --- a/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java @@ -30,7 +30,6 @@ import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; -import org.opensearch.security.spi.ShareWith; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -47,7 +46,7 @@ public class ShareWithTransportAction extends HandledTransportAction new ShareWithRequest(in, ShareWith::new)); + super(ShareWithAction.NAME, transportService, actionFilters, ShareWithRequest::new); this.transportService = transportService; this.nodeClient = nodeClient; } From c9cf55f8843f43137e599c62b2c8e1ee0d5217f4 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 17 Dec 2024 18:04:42 -0500 Subject: [PATCH 68/80] Add ShareWithAction to security plugin Signed-off-by: Craig Perkins --- checkstyle/checkstyle.xml | 12 +- .../SampleExtensionPlugin.java | 7 +- .../UpdateSampleResourceSharingAction.java | 30 ---- ...UpdateSampleResourceSharingRestAction.java | 70 ---------- ...eSampleResourceSharingTransportAction.java | 34 ----- .../SampleExtensionPluginIT.java | 2 +- .../update/UpdateResourceSharingRequest.java | 59 -------- .../update/UpdateResourceSharingResponse.java | 55 -------- .../UpdateResourceSharingTransportAction.java | 128 ------------------ 9 files changed, 8 insertions(+), 389 deletions(-) delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java delete mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java delete mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java delete mode 100644 spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java diff --git a/checkstyle/checkstyle.xml b/checkstyle/checkstyle.xml index 7571101556..7fe4a703de 100644 --- a/checkstyle/checkstyle.xml +++ b/checkstyle/checkstyle.xml @@ -228,12 +228,12 @@ - - - - - - + + + + + + diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index aa48c54d7f..7925377f5c 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -47,9 +47,6 @@ import org.opensearch.security.sampleextension.actions.list.ListSampleResourceAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.list.ListSampleResourceTransportAction; -import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingAction; -import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingRestAction; -import org.opensearch.security.sampleextension.actions.sharing.UpdateSampleResourceSharingTransportAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceTransportAction; @@ -117,8 +114,7 @@ public List getRestHandlers( new CreateSampleResourceRestAction(), new GetSampleResourceRestAction(), new ListSampleResourceRestAction(), - new UpdateSampleResourceRestAction(), - new UpdateSampleResourceSharingRestAction() + new UpdateSampleResourceRestAction() ); } @@ -128,7 +124,6 @@ public List getRestHandlers( new ActionHandler<>(CreateSampleResourceAction.INSTANCE, CreateSampleResourceTransportAction.class), new ActionHandler<>(GetSampleResourceAction.INSTANCE, GetSampleResourceTransportAction.class), new ActionHandler<>(ListSampleResourceAction.INSTANCE, ListSampleResourceTransportAction.class), - new ActionHandler<>(UpdateSampleResourceSharingAction.INSTANCE, UpdateSampleResourceSharingTransportAction.class), new ActionHandler<>(UpdateSampleResourceAction.INSTANCE, UpdateSampleResourceTransportAction.class) ); } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java deleted file mode 100644 index 439c0db520..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingAction.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.sampleextension.actions.sharing; - -import org.opensearch.action.ActionType; -import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingResponse; - -/** - * Action to update sharing configuration for a sample resource - */ -public class UpdateSampleResourceSharingAction extends ActionType { - /** - * Update sharing configuratino for sample resource action instance - */ - public static final UpdateSampleResourceSharingAction INSTANCE = new UpdateSampleResourceSharingAction(); - /** - * Update sharing configuration for sample resource action name - */ - public static final String NAME = "cluster:admin/sampleresource/updatesharing"; - - private UpdateSampleResourceSharingAction() { - super(NAME, UpdateResourceSharingResponse::new); - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java deleted file mode 100644 index 42915299b9..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingRestAction.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.sampleextension.actions.sharing; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import org.opensearch.client.node.NodeClient; -import org.opensearch.core.xcontent.XContentParser; -import org.opensearch.rest.BaseRestHandler; -import org.opensearch.rest.RestRequest; -import org.opensearch.rest.action.RestToXContentListener; -import org.opensearch.security.sampleextension.resource.SampleResource; -import org.opensearch.security.spi.ShareWith; -import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingRequest; - -import static java.util.Collections.singletonList; -import static org.opensearch.rest.RestRequest.Method.PUT; - -public class UpdateSampleResourceSharingRestAction extends BaseRestHandler { - - public UpdateSampleResourceSharingRestAction() {} - - @Override - public List routes() { - return singletonList(new Route(PUT, "/_plugins/resource_sharing_example/resource/update_sharing/{id}")); - } - - @Override - public String getName() { - return "update_sample_resource_sharing"; - } - - @SuppressWarnings("unchecked") - @Override - public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { - String resourceId = request.param("id"); - - System.out.println("update sharing endpoint"); - System.out.println("resourceId: " + resourceId); - Map source; - try (XContentParser parser = request.contentParser()) { - source = parser.map(); - } - - Map shareWithMap = (Map) source.get("share_with"); - ShareWith shareWith = new ShareWith( - (List) shareWithMap.get("users"), - (List) shareWithMap.get("backend_roles"), - (List) shareWithMap.get("allowed_actions") - ); - - final UpdateResourceSharingRequest updateSampleResourceSharingRequest = new UpdateResourceSharingRequest<>( - resourceId, - shareWith - ); - return channel -> client.executeLocally( - UpdateSampleResourceSharingAction.INSTANCE, - updateSampleResourceSharingRequest, - new RestToXContentListener<>(channel) - ); - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java deleted file mode 100644 index d21cd43f28..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/sharing/UpdateSampleResourceSharingTransportAction.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.sampleextension.actions.sharing; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import org.opensearch.action.support.ActionFilters; -import org.opensearch.client.Client; -import org.opensearch.common.inject.Inject; -import org.opensearch.security.sampleextension.resource.SampleResource; -import org.opensearch.security.spi.ShareWith; -import org.opensearch.security.spi.actions.sharing.update.UpdateResourceSharingTransportAction; -import org.opensearch.transport.TransportService; - -import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; - -/** - * Transport action for UpdateSampleResourceSharing. - */ -public class UpdateSampleResourceSharingTransportAction extends UpdateResourceSharingTransportAction { - private static final Logger log = LogManager.getLogger(UpdateSampleResourceSharingTransportAction.class); - - @Inject - public UpdateSampleResourceSharingTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { - super(transportService, actionFilters, nodeClient, UpdateSampleResourceSharingAction.NAME, RESOURCE_INDEX_NAME, ShareWith::new); - } -} diff --git a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java index 3fec88b4bd..6bb3a88e56 100644 --- a/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java +++ b/sample-extension-plugin/src/test/java/org/opensearch/security/sampleextension/SampleExtensionPluginIT.java @@ -120,7 +120,7 @@ public void testCreateSampleResource() throws IOException, InterruptedException ).map(); System.out.println("resourceSharingResponse: " + resourceSharingResponseMap); - Request updateSharingRequest = new Request("PUT", "/_plugins/resource_sharing_example/resource/update_sharing/" + resourceId); + Request updateSharingRequest = new Request("PUT", "/_plugins/_security/resource/sample_resource/" + resourceId + "/share_with"); updateSharingRequest.setEntity( new StringEntity("{\"share_with\":{\"users\": [\"admin\"], \"backend_roles\": [], \"allowed_actions\": [\"*\"]}}") ); diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java deleted file mode 100644 index af201a6e45..0000000000 --- a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingRequest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.spi.actions.sharing.update; - -import java.io.IOException; - -import org.opensearch.action.ActionRequest; -import org.opensearch.action.ActionRequestValidationException; -import org.opensearch.core.common.io.stream.StreamInput; -import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.security.spi.Resource; -import org.opensearch.security.spi.ShareWith; - -/** - * Request object for UpdateResourceSharing transport action - */ -public class UpdateResourceSharingRequest extends ActionRequest { - - private final String resourceId; - private final ShareWith shareWith; - - /** - * Default constructor - */ - public UpdateResourceSharingRequest(String resourceId, ShareWith shareWith) { - this.resourceId = resourceId; - this.shareWith = shareWith; - } - - public UpdateResourceSharingRequest(StreamInput in, Reader shareWithReader) throws IOException { - this.resourceId = in.readString(); - this.shareWith = shareWithReader.read(in); - } - - @Override - public void writeTo(final StreamOutput out) throws IOException { - out.writeString(resourceId); - shareWith.writeTo(out); - } - - @Override - public ActionRequestValidationException validate() { - return null; - } - - public String getResourceId() { - return this.resourceId; - } - - public ShareWith getShareWith() { - return this.shareWith; - } -} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java deleted file mode 100644 index 2e04572543..0000000000 --- a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingResponse.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.spi.actions.sharing.update; - -import java.io.IOException; - -import org.opensearch.core.action.ActionResponse; -import org.opensearch.core.common.io.stream.StreamInput; -import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.core.xcontent.ToXContentObject; -import org.opensearch.core.xcontent.XContentBuilder; - -/** - * Response to a UpdateResourceSharingRequest - */ -public class UpdateResourceSharingResponse extends ActionResponse implements ToXContentObject { - private final String message; - - /** - * Default constructor - * - * @param message The message - */ - public UpdateResourceSharingResponse(String message) { - this.message = message; - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(message); - } - - /** - * Constructor with StreamInput - * - * @param in the stream input - */ - public UpdateResourceSharingResponse(final StreamInput in) throws IOException { - message = in.readString(); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field("message", message); - builder.endObject(); - return builder; - } -} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java deleted file mode 100644 index 07892dd0e0..0000000000 --- a/spi/src/main/java/org/opensearch/security/spi/actions/sharing/update/UpdateResourceSharingTransportAction.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -package org.opensearch.security.spi.actions.sharing.update; - -import java.io.IOException; -import java.util.Objects; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import org.opensearch.action.search.SearchRequest; -import org.opensearch.action.search.SearchResponse; -import org.opensearch.action.support.ActionFilters; -import org.opensearch.action.support.HandledTransportAction; -import org.opensearch.action.update.UpdateRequest; -import org.opensearch.action.update.UpdateResponse; -import org.opensearch.client.Client; -import org.opensearch.common.util.concurrent.ThreadContext; -import org.opensearch.common.xcontent.XContentFactory; -import org.opensearch.core.action.ActionListener; -import org.opensearch.core.common.io.stream.Writeable; -import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.index.query.BoolQueryBuilder; -import org.opensearch.index.query.QueryBuilders; -import org.opensearch.search.SearchHit; -import org.opensearch.search.builder.SearchSourceBuilder; -import org.opensearch.security.spi.Resource; -import org.opensearch.security.spi.ShareWith; -import org.opensearch.tasks.Task; -import org.opensearch.transport.TransportService; - -/** - * Transport action for UpdateResourceSharing. - */ -public class UpdateResourceSharingTransportAction extends HandledTransportAction< - UpdateResourceSharingRequest, - UpdateResourceSharingResponse> { - private static final Logger log = LogManager.getLogger(UpdateResourceSharingTransportAction.class); - - public static final String RESOURCE_SHARING_INDEX = ".resource-sharing"; - - private final TransportService transportService; - private final Client nodeClient; - private final String resourceIndex; - - public UpdateResourceSharingTransportAction( - TransportService transportService, - ActionFilters actionFilters, - Client nodeClient, - String actionName, - String resourceIndex, - Writeable.Reader shareWithReader - ) { - super(actionName, transportService, actionFilters, (in) -> new UpdateResourceSharingRequest(in, shareWithReader)); - this.transportService = transportService; - this.nodeClient = nodeClient; - this.resourceIndex = resourceIndex; - } - - @Override - protected void doExecute(Task task, UpdateResourceSharingRequest request, ActionListener listener) { - try (ThreadContext.StoredContext ignore = transportService.getThreadPool().getThreadContext().stashContext()) { - SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() - .must(QueryBuilders.matchQuery("resource_id", request.getResourceId())) - .must(QueryBuilders.matchQuery("resource_index", resourceIndex)); - searchSourceBuilder.query(boolQuery); - searchRequest.source(searchSourceBuilder); - - // Execute the search request - nodeClient.search(searchRequest, new ActionListener() { - @Override - public void onResponse(SearchResponse searchResponse) { - if (Objects.requireNonNull(searchResponse.getHits().getTotalHits()).value == 1) { - // Record found, update it - SearchHit hit = searchResponse.getHits().getAt(0); - UpdateRequest updateRequest = new UpdateRequest(RESOURCE_SHARING_INDEX, hit.getId()); - try { - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject(); - { - builder.startObject("share_with"); - { - builder.field("users", request.getShareWith().getUsers()); - builder.field("backend_roles", request.getShareWith().getBackendRoles()); - builder.field("allowed_actions", request.getShareWith().getAllowedActions()); - } - builder.endObject(); - } - builder.endObject(); - updateRequest.doc(builder); - - nodeClient.update(updateRequest, new ActionListener() { - @Override - public void onResponse(UpdateResponse updateResponse) { - listener.onResponse(new UpdateResourceSharingResponse("success")); - } - - @Override - public void onFailure(Exception e) { - listener.onFailure(e); - } - }); - } catch (IOException e) { - listener.onFailure(e); - } - } else { - // Record not found, create a new one - // createNewRecord(request, listener); - listener.onFailure(new IllegalStateException(".resource-sharing entry not found")); - } - } - - @Override - public void onFailure(Exception e) { - listener.onFailure(e); - } - }); - } - } -} From c00e1d01d332b570f913ead6f42b5a3461997eb4 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 20 Dec 2024 09:38:32 -0500 Subject: [PATCH 69/80] Remove allowed_actions Signed-off-by: Craig Perkins --- .../opensearch/security/spi/ShareWith.java | 23 ++++--------------- .../rest/resource/ShareWithRestAction.java | 6 +---- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java index 08fcd99d38..dfb0ba0272 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java +++ b/spi/src/main/java/org/opensearch/security/spi/ShareWith.java @@ -12,31 +12,27 @@ public class ShareWith implements NamedWriteable, ToXContentFragment { - public final static ShareWith PRIVATE = new ShareWith(List.of(), List.of(), List.of("*")); - public final static ShareWith PUBLIC = new ShareWith(List.of("*"), List.of("*"), List.of("*")); + public final static ShareWith PRIVATE = new ShareWith(List.of(), List.of()); + public final static ShareWith PUBLIC = new ShareWith(List.of("*"), List.of("*")); - private final List allowedActions; private final List users; private final List backendRoles; - public ShareWith(List users, List backendRoles, List allowedActions) { + public ShareWith(List users, List backendRoles) { this.users = users; this.backendRoles = backendRoles; - this.allowedActions = allowedActions; } public ShareWith(StreamInput in) throws IOException { this.users = in.readStringList(); this.backendRoles = in.readStringList(); - this.allowedActions = in.readStringList(); } @SuppressWarnings("unchecked") public static ShareWith fromSource(Map sourceAsMap) { List users = (List) sourceAsMap.get("users"); List backendRoles = (List) sourceAsMap.get("backend_roles"); - List allowedActions = (List) sourceAsMap.get("allowed_actions"); - return new ShareWith(users, backendRoles, allowedActions); + return new ShareWith(users, backendRoles); } public List getUsers() { @@ -47,17 +43,9 @@ public List getBackendRoles() { return backendRoles; } - public List getAllowedActions() { - return allowedActions; - } - @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject() - .field("users", users) - .field("backend_roles", backendRoles) - .field("allowed_actions", allowedActions) - .endObject(); + return builder.startObject().field("users", users).field("backend_roles", backendRoles).endObject(); } @Override @@ -69,6 +57,5 @@ public String getWriteableName() { public void writeTo(StreamOutput out) throws IOException { out.writeStringCollection(users); out.writeStringCollection(backendRoles); - out.writeStringCollection(allowedActions); } } diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java index 1d50c497be..556fa16ff5 100644 --- a/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java @@ -71,11 +71,7 @@ public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client } Map shareWithMap = (Map) source.get("share_with"); - ShareWith shareWith = new ShareWith( - (List) shareWithMap.get("users"), - (List) shareWithMap.get("backend_roles"), - (List) shareWithMap.get("allowed_actions") - ); + ShareWith shareWith = new ShareWith((List) shareWithMap.get("users"), (List) shareWithMap.get("backend_roles")); final ShareWithRequest shareWithRequest = new ShareWithRequest(resourceId, resourceTypeToIndexMap.get(resourceType), shareWith); return channel -> client.executeLocally(ShareWithAction.INSTANCE, shareWithRequest, new RestToXContentListener<>(channel)); From 7c90e88bb6432e81a318889b83a67248f9d95cf3 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Sun, 22 Dec 2024 11:42:59 -0500 Subject: [PATCH 70/80] Remove allowed_actions from sharing endpoint Signed-off-by: Craig Perkins --- .../security/rest/resource/ShareWithTransportAction.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java index d2427698a9..8da088ab13 100644 --- a/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithTransportAction.java @@ -62,12 +62,10 @@ protected void doExecute(Task task, ShareWithRequest request, ActionListener() { + nodeClient.search(searchRequest, new ActionListener<>() { @Override public void onResponse(SearchResponse searchResponse) { if (Objects.requireNonNull(searchResponse.getHits().getTotalHits()).value == 1) { - // Record found, update it SearchHit hit = searchResponse.getHits().getAt(0); UpdateRequest updateRequest = new UpdateRequest(RESOURCE_SHARING_INDEX, hit.getId()); try { @@ -78,14 +76,13 @@ public void onResponse(SearchResponse searchResponse) { { builder.field("users", request.getShareWith().getUsers()); builder.field("backend_roles", request.getShareWith().getBackendRoles()); - builder.field("allowed_actions", request.getShareWith().getAllowedActions()); } builder.endObject(); } builder.endObject(); updateRequest.doc(builder); - nodeClient.update(updateRequest, new ActionListener() { + nodeClient.update(updateRequest, new ActionListener<>() { @Override public void onResponse(UpdateResponse updateResponse) { listener.onResponse(new ShareWithResponse("success")); @@ -100,8 +97,6 @@ public void onFailure(Exception e) { listener.onFailure(e); } } else { - // Record not found, create a new one - // createNewRecord(request, listener); listener.onFailure(new IllegalStateException(".resource-sharing entry not found")); } } From 0d7c1c545f14baf6a0171df4cd52b7a17d3b6811 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Sun, 22 Dec 2024 20:20:18 -0500 Subject: [PATCH 71/80] Move security specific classes out of spi Signed-off-by: Craig Perkins --- .../security/resource/ResourceSharingEntry.java | 3 +-- .../security/resource/ResourceSharingListener.java | 3 +-- .../opensearch/security/resource}/ResourceUser.java | 2 +- .../resource/SecurityResourceSharingService.java | 2 +- .../opensearch/security/rest/resource}/ShareWith.java | 10 +++++++++- .../security/rest/resource/ShareWithRequest.java | 1 - .../security/rest/resource/ShareWithRestAction.java | 1 - 7 files changed, 13 insertions(+), 9 deletions(-) rename {spi/src/main/java/org/opensearch/security/spi => src/main/java/org/opensearch/security/resource}/ResourceUser.java (97%) rename {spi/src/main/java/org/opensearch/security/spi => src/main/java/org/opensearch/security/rest/resource}/ShareWith.java (88%) diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java index ad454547df..d7ecfac33c 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingEntry.java @@ -17,8 +17,7 @@ import org.opensearch.core.xcontent.ToXContentFragment; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.spi.ResourceUser; -import org.opensearch.security.spi.ShareWith; +import org.opensearch.security.rest.resource.ShareWith; public class ResourceSharingEntry implements ToXContentFragment { private final String resourceIndex; diff --git a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java index f8f46d7fb4..236efea7cb 100644 --- a/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java +++ b/src/main/java/org/opensearch/security/resource/ResourceSharingListener.java @@ -30,8 +30,7 @@ import org.opensearch.core.xcontent.ToXContent; import org.opensearch.index.engine.Engine; import org.opensearch.index.shard.IndexingOperationListener; -import org.opensearch.security.spi.ResourceUser; -import org.opensearch.security.spi.ShareWith; +import org.opensearch.security.rest.resource.ShareWith; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.user.User; import org.opensearch.threadpool.ThreadPool; diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java b/src/main/java/org/opensearch/security/resource/ResourceUser.java similarity index 97% rename from spi/src/main/java/org/opensearch/security/spi/ResourceUser.java rename to src/main/java/org/opensearch/security/resource/ResourceUser.java index a1599c578d..1c135f6f01 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceUser.java +++ b/src/main/java/org/opensearch/security/resource/ResourceUser.java @@ -7,7 +7,7 @@ * compatible open source license. */ -package org.opensearch.security.spi; +package org.opensearch.security.resource; import java.io.IOException; import java.util.HashSet; diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index e75da07899..990360c0f9 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -30,10 +30,10 @@ import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; +import org.opensearch.security.rest.resource.ShareWith; import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceFactory; import org.opensearch.security.spi.ResourceSharingService; -import org.opensearch.security.spi.ShareWith; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.support.WildcardMatcher; import org.opensearch.security.user.User; diff --git a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java b/src/main/java/org/opensearch/security/rest/resource/ShareWith.java similarity index 88% rename from spi/src/main/java/org/opensearch/security/spi/ShareWith.java rename to src/main/java/org/opensearch/security/rest/resource/ShareWith.java index dfb0ba0272..341fde9153 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ShareWith.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWith.java @@ -1,4 +1,12 @@ -package org.opensearch.security.spi; +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.rest.resource; import java.io.IOException; import java.util.List; diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java index 6e64ef6997..e7404e8b9e 100644 --- a/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithRequest.java @@ -14,7 +14,6 @@ import org.opensearch.action.ActionRequestValidationException; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; -import org.opensearch.security.spi.ShareWith; /** * Request object for UpdateResourceSharing transport action diff --git a/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java b/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java index 556fa16ff5..d114b8a576 100644 --- a/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java +++ b/src/main/java/org/opensearch/security/rest/resource/ShareWithRestAction.java @@ -21,7 +21,6 @@ import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestToXContentListener; import org.opensearch.security.spi.ResourceSharingExtension; -import org.opensearch.security.spi.ShareWith; import static org.opensearch.rest.RestRequest.Method.PUT; import static org.opensearch.security.dlic.rest.support.Utils.addRoutesPrefix; From d7cf362700c3ef6aee1ab8987bf6440d6c543c4e Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Sun, 22 Dec 2024 20:52:19 -0500 Subject: [PATCH 72/80] Add ResourceParser Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 10 +- .../resource/SampleResource.java | 9 +- .../resource/SampleResourceFactory.java | 10 -- .../resource/SampleResourceParser.java | 29 ++++++ .../spi/DefaultResourceSharingService.java | 49 ++++++++-- .../org/opensearch/security/spi/Resource.java | 16 +--- .../security/spi/ResourceDocVersion.java | 94 +++++++++++++++++++ .../security/spi/ResourceFactory.java | 5 - .../security/spi/ResourceParser.java | 9 ++ .../spi/ResourceSharingExtension.java | 4 +- .../security/OpenSearchSecurityPlugin.java | 3 +- .../SecurityResourceSharingService.java | 52 +++++++--- 12 files changed, 225 insertions(+), 65 deletions(-) delete mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceFactory.java create mode 100644 sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceParser.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceDocVersion.java delete mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceFactory.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/ResourceParser.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 7925377f5c..37530e0f2c 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -51,11 +51,11 @@ import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceTransportAction; import org.opensearch.security.sampleextension.resource.SampleResource; -import org.opensearch.security.sampleextension.resource.SampleResourceFactory; +import org.opensearch.security.sampleextension.resource.SampleResourceParser; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; import org.opensearch.security.spi.DefaultResourceSharingService; import org.opensearch.security.spi.Resource; -import org.opensearch.security.spi.ResourceFactory; +import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.threadpool.ThreadPool; @@ -92,7 +92,7 @@ public Collection createComponents( if (SampleResourceSharingServiceProvider.getInstance().get() == null) { System.out.println("Using DefaultResourceSharingService"); SampleResourceSharingServiceProvider.getInstance() - .set(new DefaultResourceSharingService<>(client, RESOURCE_INDEX_NAME, new SampleResourceFactory())); + .set(new DefaultResourceSharingService<>(client, RESOURCE_INDEX_NAME, new SampleResourceParser(), xContentRegistry)); } System.out.println( "SampleResourceSharingServiceProvider.getInstance(): " + SampleResourceSharingServiceProvider.getInstance().get() @@ -145,8 +145,8 @@ public String getResourceIndex() { } @Override - public ResourceFactory getResourceFactory() { - return new SampleResourceFactory(); + public ResourceParser getResourceParser() { + return new SampleResourceParser(); } @SuppressWarnings("unchecked") diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java index 942449c8bb..3a8e04629e 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java @@ -1,14 +1,13 @@ package org.opensearch.security.sampleextension.resource; import java.io.IOException; -import java.util.Map; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.security.spi.Resource; -public class SampleResource extends Resource { +public class SampleResource implements Resource { private String name; @@ -22,12 +21,6 @@ public static SampleResource from(StreamInput in) throws IOException { return new SampleResource(in); } - @Override - public void fromSource(String resourceId, Map sourceAsMap) { - super.fromSource(resourceId, sourceAsMap); - this.name = (String) sourceAsMap.get("name"); - } - @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { return builder.startObject().field("name", name).endObject(); diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceFactory.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceFactory.java deleted file mode 100644 index b902f38fb3..0000000000 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceFactory.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.opensearch.security.sampleextension.resource; - -import org.opensearch.security.spi.ResourceFactory; - -public class SampleResourceFactory implements ResourceFactory { - @Override - public SampleResource createResource() { - return new SampleResource(); - } -} diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceParser.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceParser.java new file mode 100644 index 0000000000..6ecd4e2e73 --- /dev/null +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceParser.java @@ -0,0 +1,29 @@ +package org.opensearch.security.sampleextension.resource; + +import java.io.IOException; + +import org.opensearch.core.xcontent.XContentParser; +import org.opensearch.core.xcontent.XContentParserUtils; +import org.opensearch.security.spi.ResourceParser; + +public class SampleResourceParser implements ResourceParser { + + @Override + public SampleResource parse(XContentParser parser, String id) throws IOException { + SampleResource resource = new SampleResource(); + XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser); + + while (!parser.nextToken().equals(XContentParser.Token.END_OBJECT)) { + String fieldName = parser.currentName(); + parser.nextToken(); + switch (fieldName) { + case "name": + resource.setName(parser.text()); + break; + default: + XContentParserUtils.throwUnknownToken(parser.currentToken(), parser.getTokenLocation()); + } + } + return resource; + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java index f2c7ed2ed1..34167d3b69 100644 --- a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java @@ -1,5 +1,6 @@ package org.opensearch.security.spi; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -10,7 +11,12 @@ import org.opensearch.action.search.SearchResponse; import org.opensearch.client.Client; import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.common.xcontent.LoggingDeprecationHandler; +import org.opensearch.common.xcontent.XContentHelper; +import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.action.ActionListener; +import org.opensearch.core.xcontent.NamedXContentRegistry; +import org.opensearch.core.xcontent.XContentParser; import org.opensearch.index.query.MatchAllQueryBuilder; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; @@ -18,12 +24,19 @@ public class DefaultResourceSharingService implements ResourceSharingService { private final Client client; private final String resourceIndex; - private final ResourceFactory resourceFactory; + private final ResourceParser resourceParser; + private final NamedXContentRegistry xContentRegistry; - public DefaultResourceSharingService(Client client, String resourceIndex, ResourceFactory resourceFactory) { + public DefaultResourceSharingService( + Client client, + String resourceIndex, + ResourceParser resourceParser, + NamedXContentRegistry xContentRegistry + ) { this.client = client; this.resourceIndex = resourceIndex; - this.resourceFactory = resourceFactory; + this.resourceParser = resourceParser; + this.xContentRegistry = xContentRegistry; } @SuppressWarnings("unchecked") @@ -40,9 +53,18 @@ public void listResources(ActionListener> listResourceListener) { public void onResponse(SearchResponse searchResponse) { List resources = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { - T resource = resourceFactory.createResource(); - resource.fromSource(hit.getId(), hit.getSourceAsMap()); - resources.add(resource); + try { + XContentParser parser = XContentHelper.createParser( + xContentRegistry, + LoggingDeprecationHandler.INSTANCE, + hit.getSourceRef(), + XContentType.JSON + ); + T resource = resourceParser.parse(parser, hit.getId()); + resources.add(resource); + } catch (IOException e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } } listResourceListener.onResponse(resources); } @@ -66,9 +88,18 @@ public void getResource(String resourceId, ActionListener getResourceListener ActionListener getListener = new ActionListener() { @Override public void onResponse(GetResponse getResponse) { - T resource = resourceFactory.createResource(); - resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); - getResourceListener.onResponse(resource); + try { + XContentParser parser = XContentHelper.createParser( + xContentRegistry, + LoggingDeprecationHandler.INSTANCE, + getResponse.getSourceAsBytesRef(), + XContentType.JSON + ); + T resource = resourceParser.parse(parser, getResponse.getId()); + getResourceListener.onResponse(resource); + } catch (IOException e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } } @Override diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java index 2ef8795874..b7df3ae131 100644 --- a/spi/src/main/java/org/opensearch/security/spi/Resource.java +++ b/spi/src/main/java/org/opensearch/security/spi/Resource.java @@ -1,18 +1,6 @@ package org.opensearch.security.spi; -import java.util.Map; - import org.opensearch.core.common.io.stream.NamedWriteable; -import org.opensearch.core.xcontent.ToXContentFragment; - -public abstract class Resource implements NamedWriteable, ToXContentFragment { - protected String resourceId; - - public String getResourceId() { - return resourceId; - } +import org.opensearch.core.xcontent.ToXContentObject; - public void fromSource(String resourceId, Map sourceAsMap) { - this.resourceId = resourceId; - } -} +public interface Resource extends NamedWriteable, ToXContentObject {} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceDocVersion.java b/spi/src/main/java/org/opensearch/security/spi/ResourceDocVersion.java new file mode 100644 index 0000000000..80aabd8011 --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceDocVersion.java @@ -0,0 +1,94 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.security.spi; + +import java.io.IOException; +import java.util.Locale; + +import org.opensearch.core.common.io.stream.StreamInput; +import org.opensearch.core.common.io.stream.StreamOutput; +import org.opensearch.core.common.io.stream.Writeable; + +/** + * Structure to represent resource document version. + */ +public class ResourceDocVersion implements Comparable, Writeable { + private final long primaryTerm; + private final long seqNo; + private final long version; + + public ResourceDocVersion(long primaryTerm, long seqNo, long version) { + this.primaryTerm = primaryTerm; + this.seqNo = seqNo; + this.version = version; + } + + public ResourceDocVersion(StreamInput in) throws IOException { + this.primaryTerm = in.readLong(); + this.seqNo = in.readLong(); + this.version = in.readLong(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeLong(this.primaryTerm); + out.writeLong(this.seqNo); + out.writeLong(this.version); + } + + public long getPrimaryTerm() { + return primaryTerm; + } + + public long getSeqNo() { + return seqNo; + } + + public long getVersion() { + return version; + } + + /** + * Compare two doc versions. Refer to https://github.com/elastic/elasticsearch/issues/10708 + * + * @param v the doc version to compare. + * @return -1 if this < v, 0 if this == v, otherwise 1; + */ + @Override + public int compareTo(ResourceDocVersion v) { + if (v == null) { + return 1; + } + if (this.seqNo < v.seqNo) { + return -1; + } + if (this.seqNo > v.seqNo) { + return 1; + } + if (this.primaryTerm < v.primaryTerm) { + return -1; + } + if (this.primaryTerm > v.primaryTerm) { + return 1; + } + return 0; + } + + @Override + public String toString() { + return String.format( + Locale.getDefault(), + "{_version: %s, _primary_term: %s, _seq_no: %s}", + this.version, + this.primaryTerm, + this.seqNo + ); + } +} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceFactory.java b/spi/src/main/java/org/opensearch/security/spi/ResourceFactory.java deleted file mode 100644 index ab86c7a819..0000000000 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceFactory.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.opensearch.security.spi; - -public interface ResourceFactory { - T createResource(); -} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceParser.java b/spi/src/main/java/org/opensearch/security/spi/ResourceParser.java new file mode 100644 index 0000000000..0e4a3ac0bd --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceParser.java @@ -0,0 +1,9 @@ +package org.opensearch.security.spi; + +import java.io.IOException; + +import org.opensearch.core.xcontent.XContentParser; + +public interface ResourceParser { + T parse(XContentParser xContentParser, String id) throws IOException; +} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java index 85cb73dcb5..1b92843d3e 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java @@ -23,9 +23,9 @@ public interface ResourceSharingExtension { String getResourceIndex(); /** - * @return The class corresponding to this resource + * @return returns a parser for this resource */ - ResourceFactory getResourceFactory(); + ResourceParser getResourceParser(); void assignResourceSharingService(ResourceSharingService service); } diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 8aa1eb0e02..47f83c2a7f 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -1081,7 +1081,8 @@ public Collection createComponents( ResourceSharingService resourceSharingService = new SecurityResourceSharingService<>( localClient, extension.getResourceIndex(), - extension.getResourceFactory() + extension.getResourceParser(), + xContentRegistry ); extension.assignResourceSharingService(resourceSharingService); } diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index 990360c0f9..c44ea872ba 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -11,6 +11,7 @@ package org.opensearch.security.resource; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -25,14 +26,19 @@ import org.opensearch.action.search.SearchResponse; import org.opensearch.client.Client; import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.common.xcontent.LoggingDeprecationHandler; +import org.opensearch.common.xcontent.XContentHelper; +import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.action.ActionListener; +import org.opensearch.core.xcontent.NamedXContentRegistry; +import org.opensearch.core.xcontent.XContentParser; import org.opensearch.index.query.BoolQueryBuilder; import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.security.rest.resource.ShareWith; import org.opensearch.security.spi.Resource; -import org.opensearch.security.spi.ResourceFactory; +import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.support.WildcardMatcher; @@ -43,12 +49,19 @@ public class SecurityResourceSharingService implements ResourceSharingService { private final Client client; private final String resourceIndex; - private final ResourceFactory resourceFactory; + private final ResourceParser resourceParser; + private final NamedXContentRegistry xContentRegistry; - public SecurityResourceSharingService(Client client, String resourceIndex, ResourceFactory resourceFactory) { + public SecurityResourceSharingService( + Client client, + String resourceIndex, + ResourceParser resourceParser, + NamedXContentRegistry xContentRegistry + ) { this.client = client; this.resourceIndex = resourceIndex; - this.resourceFactory = resourceFactory; + this.resourceParser = resourceParser; + this.xContentRegistry = xContentRegistry; } private boolean hasPermissionsFor(User authenticatedUser, ResourceSharingEntry sharedWith) { @@ -131,10 +144,18 @@ public void onResponse(MultiGetResponse response) { if (singleResponse != null && !singleResponse.isFailed()) { GetResponse singleGetResponse = singleResponse.getResponse(); if (singleGetResponse.isExists() && !singleGetResponse.isSourceEmpty()) { - // TODO Is there a better way to create this instance of a generic w/o using reflection - T resource = resourceFactory.createResource(); - resource.fromSource(singleGetResponse.getId(), singleGetResponse.getSourceAsMap()); - resources.add(resource); + try { + XContentParser parser = XContentHelper.createParser( + xContentRegistry, + LoggingDeprecationHandler.INSTANCE, + singleGetResponse.getSourceAsBytesRef(), + XContentType.JSON + ); + T resource = resourceParser.parse(parser, singleGetResponse.getId()); + resources.add(resource); + } catch (IOException e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } } else { // does not exist or empty source continue; @@ -214,9 +235,18 @@ private void finishGetResourceIfUserIsAllowed(String resourceId, ActionListener< ActionListener getListener = new ActionListener() { @Override public void onResponse(GetResponse getResponse) { - T resource = resourceFactory.createResource(); - resource.fromSource(getResponse.getId(), getResponse.getSourceAsMap()); - getResourceListener.onResponse(resource); + try { + XContentParser parser = XContentHelper.createParser( + xContentRegistry, + LoggingDeprecationHandler.INSTANCE, + getResponse.getSourceAsBytesRef(), + XContentType.JSON + ); + T resource = resourceParser.parse(parser, getResponse.getId()); + getResourceListener.onResponse(resource); + } catch (IOException e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } } @Override From e280cf2d80d49b1662866ef1e9e5605ec2f0b998 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 23 Dec 2024 15:34:53 -0500 Subject: [PATCH 73/80] Simplify ResourceSharingService Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 3 +- .../get/GetSampleResourceTransportAction.java | 20 ++- .../ListSampleResourceTransportAction.java | 20 ++- .../spi/DefaultResourceSharingService.java | 106 +-------------- .../security/spi/ResourceDocVersion.java | 2 + .../security/spi/ResourceSharingService.java | 7 +- .../get/GetResourceTransportAction.java | 87 ++++++++++++- .../list/ListResourceTransportAction.java | 111 +++++++++++++++- .../SecurityResourceSharingService.java | 123 ++---------------- 9 files changed, 239 insertions(+), 240 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 37530e0f2c..10bcbed1fa 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -91,8 +91,7 @@ public Collection createComponents( this.client = client; if (SampleResourceSharingServiceProvider.getInstance().get() == null) { System.out.println("Using DefaultResourceSharingService"); - SampleResourceSharingServiceProvider.getInstance() - .set(new DefaultResourceSharingService<>(client, RESOURCE_INDEX_NAME, new SampleResourceParser(), xContentRegistry)); + SampleResourceSharingServiceProvider.getInstance().set(new DefaultResourceSharingService<>()); } System.out.println( "SampleResourceSharingServiceProvider.getInstance(): " + SampleResourceSharingServiceProvider.getInstance().get() diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java index 5ea29634e7..12d470abf5 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceTransportAction.java @@ -12,12 +12,17 @@ import org.apache.logging.log4j.Logger; import org.opensearch.action.support.ActionFilters; +import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; +import org.opensearch.core.xcontent.NamedXContentRegistry; import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResourceParser; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; import org.opensearch.security.spi.actions.resource.get.GetResourceTransportAction; import org.opensearch.transport.TransportService; +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; + /** * Transport action for GetSampleResource. */ @@ -28,8 +33,19 @@ public class GetSampleResourceTransportAction extends GetResourceTransportAction public GetSampleResourceTransportAction( TransportService transportService, ActionFilters actionFilters, - SampleResourceSharingServiceProvider resourceSharingService + SampleResourceSharingServiceProvider resourceSharingService, + Client client, + NamedXContentRegistry xContentRegistry ) { - super(transportService, actionFilters, GetSampleResourceAction.NAME, resourceSharingService.get()); + super( + transportService, + actionFilters, + GetSampleResourceAction.NAME, + RESOURCE_INDEX_NAME, + resourceSharingService.get(), + new SampleResourceParser(), + client, + xContentRegistry + ); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java index c8004f48e2..821a26a2b7 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceTransportAction.java @@ -12,12 +12,17 @@ import org.apache.logging.log4j.Logger; import org.opensearch.action.support.ActionFilters; +import org.opensearch.client.Client; import org.opensearch.common.inject.Inject; +import org.opensearch.core.xcontent.NamedXContentRegistry; import org.opensearch.security.sampleextension.resource.SampleResource; +import org.opensearch.security.sampleextension.resource.SampleResourceParser; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; import org.opensearch.security.spi.actions.resource.list.ListResourceTransportAction; import org.opensearch.transport.TransportService; +import static org.opensearch.security.sampleextension.SampleExtensionPlugin.RESOURCE_INDEX_NAME; + /** * Transport action for ListSampleResource. */ @@ -28,8 +33,19 @@ public class ListSampleResourceTransportAction extends ListResourceTransportActi public ListSampleResourceTransportAction( TransportService transportService, ActionFilters actionFilters, - SampleResourceSharingServiceProvider resourceSharingService + SampleResourceSharingServiceProvider resourceSharingService, + NamedXContentRegistry xContentRegistry, + Client client ) { - super(transportService, actionFilters, ListSampleResourceAction.NAME, resourceSharingService.get()); + super( + transportService, + actionFilters, + ListSampleResourceAction.NAME, + RESOURCE_INDEX_NAME, + resourceSharingService.get(), + new SampleResourceParser(), + client, + xContentRegistry + ); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java index 34167d3b69..ef40b0ae56 100644 --- a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java @@ -1,113 +1,11 @@ package org.opensearch.security.spi; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.opensearch.OpenSearchException; -import org.opensearch.action.get.GetRequest; -import org.opensearch.action.get.GetResponse; -import org.opensearch.action.search.SearchRequest; -import org.opensearch.action.search.SearchResponse; -import org.opensearch.client.Client; -import org.opensearch.common.util.concurrent.ThreadContext; -import org.opensearch.common.xcontent.LoggingDeprecationHandler; -import org.opensearch.common.xcontent.XContentHelper; -import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.action.ActionListener; -import org.opensearch.core.xcontent.NamedXContentRegistry; -import org.opensearch.core.xcontent.XContentParser; -import org.opensearch.index.query.MatchAllQueryBuilder; -import org.opensearch.search.SearchHit; -import org.opensearch.search.builder.SearchSourceBuilder; public class DefaultResourceSharingService implements ResourceSharingService { - private final Client client; - private final String resourceIndex; - private final ResourceParser resourceParser; - private final NamedXContentRegistry xContentRegistry; - - public DefaultResourceSharingService( - Client client, - String resourceIndex, - ResourceParser resourceParser, - NamedXContentRegistry xContentRegistry - ) { - this.client = client; - this.resourceIndex = resourceIndex; - this.resourceParser = resourceParser; - this.xContentRegistry = xContentRegistry; - } - - @SuppressWarnings("unchecked") - @Override - public void listResources(ActionListener> listResourceListener) { - try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { - SearchRequest sr = new SearchRequest(resourceIndex); - SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); - matchAllQuery.query(new MatchAllQueryBuilder()); - sr.source(matchAllQuery); - /* Index already exists, ignore and continue */ - ActionListener searchListener = new ActionListener() { - @Override - public void onResponse(SearchResponse searchResponse) { - List resources = new ArrayList<>(); - for (SearchHit hit : searchResponse.getHits().getHits()) { - try { - XContentParser parser = XContentHelper.createParser( - xContentRegistry, - LoggingDeprecationHandler.INSTANCE, - hit.getSourceRef(), - XContentType.JSON - ); - T resource = resourceParser.parse(parser, hit.getId()); - resources.add(resource); - } catch (IOException e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - } - listResourceListener.onResponse(resources); - } - - @Override - public void onFailure(Exception e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - }; - client.search(sr, searchListener); - } - } - @SuppressWarnings("unchecked") @Override - public void getResource(String resourceId, ActionListener getResourceListener) { - try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { - GetRequest gr = new GetRequest(resourceIndex); - gr.id(resourceId); - /* Index already exists, ignore and continue */ - ActionListener getListener = new ActionListener() { - @Override - public void onResponse(GetResponse getResponse) { - try { - XContentParser parser = XContentHelper.createParser( - xContentRegistry, - LoggingDeprecationHandler.INSTANCE, - getResponse.getSourceAsBytesRef(), - XContentType.JSON - ); - T resource = resourceParser.parse(parser, getResponse.getId()); - getResourceListener.onResponse(resource); - } catch (IOException e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - } - - @Override - public void onFailure(Exception e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - }; - client.get(gr, getListener); - } + public void hasResourceBeenSharedWith(String resourceId, ActionListener resourceSharingListener) { + resourceSharingListener.onResponse(Boolean.TRUE); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceDocVersion.java b/spi/src/main/java/org/opensearch/security/spi/ResourceDocVersion.java index 80aabd8011..f321c2de0b 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceDocVersion.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceDocVersion.java @@ -16,6 +16,8 @@ import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.common.io.stream.Writeable; +// TODO Job Scheduler keeps track of doc version. Should this keep track of version similarly? + /** * Structure to represent resource document version. */ diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java index 6faabaeee7..d2452a58bc 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java @@ -1,12 +1,7 @@ package org.opensearch.security.spi; -import java.util.List; - import org.opensearch.core.action.ActionListener; public interface ResourceSharingService { - - void listResources(ActionListener> listResourceListener); - - void getResource(String resourceId, ActionListener getResourceListener); + void hasResourceBeenSharedWith(String resourceId, ActionListener resourceSharingListener); } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java index bb5e5ba934..2dc97f946a 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java @@ -8,13 +8,26 @@ package org.opensearch.security.spi.actions.resource.get; +import java.io.IOException; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.opensearch.OpenSearchException; +import org.opensearch.action.get.GetRequest; +import org.opensearch.action.get.GetResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.common.xcontent.LoggingDeprecationHandler; +import org.opensearch.common.xcontent.XContentHelper; +import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.action.ActionListener; +import org.opensearch.core.xcontent.NamedXContentRegistry; +import org.opensearch.core.xcontent.XContentParser; import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -27,14 +40,30 @@ public class GetResourceTransportAction extends HandledTrans private final ResourceSharingService resourceSharingService; + private final ResourceParser resourceParser; + + private final String resourceIndex; + + private final Client client; + + private final NamedXContentRegistry xContentRegistry; + public GetResourceTransportAction( TransportService transportService, ActionFilters actionFilters, String actionName, - ResourceSharingService resourceSharingService + String resourceIndex, + ResourceSharingService resourceSharingService, + ResourceParser resourceParser, + Client client, + NamedXContentRegistry xContentRegistry ) { super(actionName, transportService, actionFilters, GetResourceRequest::new); this.resourceSharingService = resourceSharingService; + this.resourceParser = resourceParser; + this.resourceIndex = resourceIndex; + this.client = client; + this.xContentRegistry = xContentRegistry; } @Override @@ -43,10 +72,58 @@ protected void doExecute(Task task, GetResourceRequest request, ActionListener> listener) { - ActionListener getResourceListener = ActionListener.wrap(sampleResource -> { - System.out.println("sampleResource: " + sampleResource); - listener.onResponse(new GetResourceResponse(sampleResource)); + ActionListener getResourceListener = ActionListener.wrap(resource -> { + System.out.println("resource: " + resource); + listener.onResponse(new GetResourceResponse(resource)); }, listener::onFailure); - resourceSharingService.getResource(request.getResourceId(), getResourceListener); + + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + GetRequest gr = new GetRequest(resourceIndex); + gr.id(request.getResourceId()); + ActionListener getListener = new ActionListener<>() { + @Override + public void onResponse(GetResponse getResponse) { + try { + XContentParser parser = XContentHelper.createParser( + xContentRegistry, + LoggingDeprecationHandler.INSTANCE, + getResponse.getSourceAsBytesRef(), + XContentType.JSON + ); + T resource = resourceParser.parse(parser, getResponse.getId()); + ActionListener shareListener = new ActionListener<>() { + @Override + public void onResponse(Boolean isShared) { + if (isShared) { + getResourceListener.onResponse(resource); + } else { + getResourceListener.onFailure( + new OpenSearchException("User is not authorized to access this resource") + ); + } + } + + @Override + public void onFailure(Exception e) { + getResourceListener.onFailure( + new OpenSearchException("Failed to check sharing status: " + e.getMessage(), e) + ); + } + }; + + resourceSharingService.hasResourceBeenSharedWith(request.getResourceId(), shareListener); + } catch (IOException e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + client.get(gr, getListener); + } + // resourceSharingService.getResource(request.getResourceId(), getResourceListener); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java index c843678598..77c4027d4a 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java @@ -8,12 +8,29 @@ package org.opensearch.security.spi.actions.resource.list; +import java.io.IOException; +import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import org.opensearch.OpenSearchException; +import org.opensearch.action.search.SearchRequest; +import org.opensearch.action.search.SearchResponse; import org.opensearch.action.support.ActionFilters; import org.opensearch.action.support.HandledTransportAction; +import org.opensearch.client.Client; +import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.common.xcontent.LoggingDeprecationHandler; +import org.opensearch.common.xcontent.XContentHelper; +import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.action.ActionListener; +import org.opensearch.core.xcontent.NamedXContentRegistry; +import org.opensearch.core.xcontent.XContentParser; +import org.opensearch.index.query.MatchAllQueryBuilder; +import org.opensearch.search.SearchHit; +import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -24,22 +41,106 @@ public class ListResourceTransportAction extends HandledTransportAction> { private final ResourceSharingService resourceSharingService; + private final ResourceParser resourceParser; + + private final Client client; + + private final String resourceIndex; + + private final NamedXContentRegistry xContentRegistry; + public ListResourceTransportAction( TransportService transportService, ActionFilters actionFilters, String actionName, - ResourceSharingService resourceSharingService + String resourceIndex, + ResourceSharingService resourceSharingService, + ResourceParser resourceParser, + Client client, + NamedXContentRegistry xContentRegistry ) { super(actionName, transportService, actionFilters, ListResourceRequest::new); + this.client = client; this.resourceSharingService = resourceSharingService; + this.resourceIndex = resourceIndex; + this.xContentRegistry = xContentRegistry; + this.resourceParser = resourceParser; } @Override protected void doExecute(Task task, ListResourceRequest request, ActionListener> listener) { - ActionListener> sampleResourceListener = ActionListener.wrap(sampleResourcesList -> { - System.out.println("sampleResourcesList: " + sampleResourcesList); - listener.onResponse(new ListResourceResponse(sampleResourcesList)); + ActionListener> listResourceListener = ActionListener.wrap(resourcesList -> { + System.out.println("resourcesList: " + resourcesList); + listener.onResponse(new ListResourceResponse<>(resourcesList)); }, listener::onFailure); - resourceSharingService.listResources(sampleResourceListener); + try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { + SearchRequest sr = new SearchRequest(resourceIndex); + SearchSourceBuilder matchAllQuery = new SearchSourceBuilder(); + matchAllQuery.query(new MatchAllQueryBuilder()); + sr.source(matchAllQuery); + ActionListener searchListener = new ActionListener<>() { + @Override + public void onResponse(SearchResponse searchResponse) { + List resources = new ArrayList<>(); + + SearchHit[] hits = searchResponse.getHits().getHits(); + + if (hits.length == 0) { + listResourceListener.onResponse(resources); + return; + } + + AtomicInteger remainingChecks = new AtomicInteger(hits.length); + + for (SearchHit hit : hits) { + try { + XContentParser parser = XContentHelper.createParser( + xContentRegistry, + LoggingDeprecationHandler.INSTANCE, + hit.getSourceRef(), + XContentType.JSON + ); + T resource = resourceParser.parse(parser, hit.getId()); + + ActionListener shareListener = new ActionListener<>() { + @Override + public void onResponse(Boolean isShared) { + if (isShared) { + synchronized (resources) { + resources.add(resource); + } + } + if (remainingChecks.decrementAndGet() == 0) { + listResourceListener.onResponse(resources); + } + } + + @Override + public void onFailure(Exception e) { + listResourceListener.onFailure( + new OpenSearchException("Failed to check sharing status: " + e.getMessage(), e) + ); + } + }; + + resourceSharingService.hasResourceBeenSharedWith(hit.getId(), shareListener); + + } catch (IOException e) { + listResourceListener.onFailure( + new OpenSearchException("Caught exception while loading resources: " + e.getMessage(), e) + ); + return; + } + } + listResourceListener.onResponse(resources); + } + + @Override + public void onFailure(Exception e) { + throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); + } + }; + client.search(sr, searchListener); + } } } diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index c44ea872ba..46b1ebc730 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -12,16 +12,11 @@ package org.opensearch.security.resource; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import org.opensearch.OpenSearchException; import org.opensearch.ResourceNotFoundException; import org.opensearch.action.get.GetRequest; import org.opensearch.action.get.GetResponse; -import org.opensearch.action.get.MultiGetItemResponse; -import org.opensearch.action.get.MultiGetRequest; -import org.opensearch.action.get.MultiGetResponse; import org.opensearch.action.search.SearchRequest; import org.opensearch.action.search.SearchResponse; import org.opensearch.client.Client; @@ -85,110 +80,11 @@ private boolean hasPermissionsFor(User authenticatedUser, ResourceSharingEntry s return false; } - @SuppressWarnings("unchecked") @Override - public void listResources(ActionListener> listResourceListener) { - User authenticatedUser = client.threadPool().getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); - try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { - SearchRequest rsr = new SearchRequest(RESOURCE_SHARING_INDEX); - BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); - - // 1. The resource_user is the currently authenticated user - boolQuery.should(QueryBuilders.termQuery("resource_user.name", authenticatedUser.getName())); - - // 2. The resource has been shared with the authenticated user - boolQuery.should(QueryBuilders.termQuery("share_with.users", authenticatedUser.getName())); - - // 3. The resource has been shared with a backend role that the authenticated user has - if (!authenticatedUser.getRoles().isEmpty()) { - BoolQueryBuilder roleQuery = QueryBuilders.boolQuery(); - for (String role : authenticatedUser.getRoles()) { - roleQuery.should(QueryBuilders.termQuery("share_with.backend_roles", role)); - } - boolQuery.should(roleQuery); - } - - // Set minimum should match to 1 to ensure at least one of the conditions is met - boolQuery.minimumShouldMatch(1); - - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(boolQuery); - rsr.source(searchSourceBuilder); - - ActionListener searchListener = new ActionListener() { - @Override - public void onResponse(SearchResponse searchResponse) { - List resources = new ArrayList<>(); - List resourceIds = new ArrayList<>(); - for (SearchHit hit : searchResponse.getHits().getHits()) { - resourceIds.add((String) hit.getSourceAsMap().get("resource_id")); - } - if (resourceIds.isEmpty()) { - listResourceListener.onResponse(resources); - } - - final MultiGetRequest mget = new MultiGetRequest(); - - for (String resourceId : resourceIds) { - mget.add(resourceIndex, resourceId); - } - - mget.refresh(true); - mget.realtime(true); - - client.multiGet(mget, new ActionListener() { - @Override - public void onResponse(MultiGetResponse response) { - MultiGetItemResponse[] responses = response.getResponses(); - for (MultiGetItemResponse singleResponse : responses) { - if (singleResponse != null && !singleResponse.isFailed()) { - GetResponse singleGetResponse = singleResponse.getResponse(); - if (singleGetResponse.isExists() && !singleGetResponse.isSourceEmpty()) { - try { - XContentParser parser = XContentHelper.createParser( - xContentRegistry, - LoggingDeprecationHandler.INSTANCE, - singleGetResponse.getSourceAsBytesRef(), - XContentType.JSON - ); - T resource = resourceParser.parse(parser, singleGetResponse.getId()); - resources.add(resource); - } catch (IOException e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - } else { - // does not exist or empty source - continue; - } - } else { - // failure - continue; - } - } - listResourceListener.onResponse(resources); - } - - @Override - public void onFailure(Exception e) { - listResourceListener.onFailure(e); - } - }); - - } - - @Override - public void onFailure(Exception e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - }; - client.search(rsr, searchListener); - } - } - - @SuppressWarnings("unchecked") - @Override - public void getResource(String resourceId, ActionListener getResourceListener) { - User authenticatedUser = client.threadPool().getThreadContext().getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); + public void hasResourceBeenSharedWith(String resourceId, ActionListener resourceSharingListener) { + User authenticatedUser = (User) client.threadPool() + .getThreadContext() + .getPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER); try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { SearchRequest searchRequest = new SearchRequest(RESOURCE_SHARING_INDEX); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); @@ -200,7 +96,7 @@ public void getResource(String resourceId, ActionListener getResourceListener searchSourceBuilder.size(1); // Limit to 1 result searchRequest.source(searchSourceBuilder); - ActionListener searchListener = new ActionListener() { + ActionListener searchListener = new ActionListener<>() { @Override public void onResponse(SearchResponse searchResponse) { SearchHit[] hits = searchResponse.getHits().getHits(); @@ -208,12 +104,12 @@ public void onResponse(SearchResponse searchResponse) { SearchHit hit = hits[0]; ResourceSharingEntry sharedWith = ResourceSharingEntry.fromSource(hit.getSourceAsMap()); if (hasPermissionsFor(authenticatedUser, sharedWith)) { - finishGetResourceIfUserIsAllowed(resourceId, getResourceListener); + resourceSharingListener.onResponse(Boolean.TRUE); } else { - getResourceListener.onFailure(new OpenSearchException("User is not authorized to access this resource")); + resourceSharingListener.onResponse(Boolean.FALSE); } } else { - getResourceListener.onFailure(new ResourceNotFoundException("Resource not found")); + resourceSharingListener.onFailure(new ResourceNotFoundException("Resource not found")); } } @@ -231,8 +127,7 @@ private void finishGetResourceIfUserIsAllowed(String resourceId, ActionListener< try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { GetRequest gr = new GetRequest(resourceIndex); gr.id(resourceId); - /* Index already exists, ignore and continue */ - ActionListener getListener = new ActionListener() { + ActionListener getListener = new ActionListener<>() { @Override public void onResponse(GetResponse getResponse) { try { From e055847f74de505c266be91cfafcc9dff4031fde Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 23 Dec 2024 16:21:35 -0500 Subject: [PATCH 74/80] Rename to isSharedWithCurrentUser Signed-off-by: Craig Perkins --- .../opensearch/security/spi/DefaultResourceSharingService.java | 2 +- .../org/opensearch/security/spi/ResourceSharingService.java | 2 +- .../spi/actions/resource/get/GetResourceTransportAction.java | 2 +- .../spi/actions/resource/list/ListResourceTransportAction.java | 2 +- .../security/resource/SecurityResourceSharingService.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java index ef40b0ae56..82cd32c4a5 100644 --- a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java @@ -5,7 +5,7 @@ public class DefaultResourceSharingService implements ResourceSharingService { @Override - public void hasResourceBeenSharedWith(String resourceId, ActionListener resourceSharingListener) { + public void isSharedWithCurrentUser(String resourceId, ActionListener resourceSharingListener) { resourceSharingListener.onResponse(Boolean.TRUE); } } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java index d2452a58bc..f60f2d1d01 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java @@ -3,5 +3,5 @@ import org.opensearch.core.action.ActionListener; public interface ResourceSharingService { - void hasResourceBeenSharedWith(String resourceId, ActionListener resourceSharingListener); + void isSharedWithCurrentUser(String resourceId, ActionListener resourceSharingListener); } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java index 2dc97f946a..8d93ed4c8b 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java @@ -111,7 +111,7 @@ public void onFailure(Exception e) { } }; - resourceSharingService.hasResourceBeenSharedWith(request.getResourceId(), shareListener); + resourceSharingService.isSharedWithCurrentUser(request.getResourceId(), shareListener); } catch (IOException e) { throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java index 77c4027d4a..d5639f62f3 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java @@ -123,7 +123,7 @@ public void onFailure(Exception e) { } }; - resourceSharingService.hasResourceBeenSharedWith(hit.getId(), shareListener); + resourceSharingService.isSharedWithCurrentUser(hit.getId(), shareListener); } catch (IOException e) { listResourceListener.onFailure( diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index 46b1ebc730..328fe711d4 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -81,7 +81,7 @@ private boolean hasPermissionsFor(User authenticatedUser, ResourceSharingEntry s } @Override - public void hasResourceBeenSharedWith(String resourceId, ActionListener resourceSharingListener) { + public void isSharedWithCurrentUser(String resourceId, ActionListener resourceSharingListener) { User authenticatedUser = (User) client.threadPool() .getThreadContext() .getPersistent(ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER); From b1c02dd4c15c2175d5f0457d1281ebc5343b9fd3 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 23 Dec 2024 16:56:54 -0500 Subject: [PATCH 75/80] Rename listener Signed-off-by: Craig Perkins --- .../org/opensearch/security/spi/ResourceSharingService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java index f60f2d1d01..31ef5e7f83 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java @@ -3,5 +3,5 @@ import org.opensearch.core.action.ActionListener; public interface ResourceSharingService { - void isSharedWithCurrentUser(String resourceId, ActionListener resourceSharingListener); + void isSharedWithCurrentUser(String resourceId, ActionListener shareListener); } From cae65dbd0c1567fe0ceb81646a6cd182389bc426 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 30 Dec 2024 16:59:43 -0500 Subject: [PATCH 76/80] Briefly uncomment Signed-off-by: Craig Perkins --- build.gradle | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/build.gradle b/build.gradle index d6b746da41..739663e48c 100644 --- a/build.gradle +++ b/build.gradle @@ -725,29 +725,29 @@ dependencies { compileOnly "org.opensearch:opensearch:${opensearch_version}" //integration test framework: -// integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { -// exclude(group: 'junit', module: 'junit') -// } -// integrationTestImplementation 'junit:junit:4.13.2' -// integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" -// integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" -// integrationTestImplementation 'commons-io:commons-io:2.18.0' -// integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" -// integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" -// integrationTestImplementation 'org.hamcrest:hamcrest:2.2' -// integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" -// integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" -// integrationTestImplementation('org.awaitility:awaitility:4.2.2') { -// exclude(group: 'org.hamcrest', module: 'hamcrest') -// } -// integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' -// integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" -// integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" -// integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" -// integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" -// integrationTestImplementation "org.mockito:mockito-core:5.14.2" + integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { + exclude(group: 'junit', module: 'junit') + } + integrationTestImplementation 'junit:junit:4.13.2' + integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" + integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" + integrationTestImplementation 'commons-io:commons-io:2.18.0' + integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" + integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" + integrationTestImplementation 'org.hamcrest:hamcrest:2.2' + integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" + integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" + integrationTestImplementation('org.awaitility:awaitility:4.2.2') { + exclude(group: 'org.hamcrest', module: 'hamcrest') + } + integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' + integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" + integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" + integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" + integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" + integrationTestImplementation "org.mockito:mockito-core:5.14.2" //spotless implementation('com.google.googlejavaformat:google-java-format:1.25.0') { From e066f6a61e2fb8de122c35a112e2f009d29abead Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 30 Dec 2024 17:02:54 -0500 Subject: [PATCH 77/80] sync with main Signed-off-by: Craig Perkins --- build.gradle | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index 976b910fd9..06b7aa156b 100644 --- a/build.gradle +++ b/build.gradle @@ -725,29 +725,29 @@ dependencies { compileOnly "org.opensearch:opensearch:${opensearch_version}" //integration test framework: - integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.2') { - exclude(group: 'junit', module: 'junit') - } - integrationTestImplementation 'junit:junit:4.13.2' - integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" - integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" - integrationTestImplementation 'commons-io:commons-io:2.18.0' - integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" - integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" - integrationTestImplementation 'org.hamcrest:hamcrest:2.2' - integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" - integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" - integrationTestImplementation('org.awaitility:awaitility:4.2.2') { - exclude(group: 'org.hamcrest', module: 'hamcrest') - } - integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' - integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" - integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" - integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" - integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" - integrationTestImplementation "org.mockito:mockito-core:5.14.2" +// integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.2') { +// exclude(group: 'junit', module: 'junit') +// } +// integrationTestImplementation 'junit:junit:4.13.2' +// integrationTestImplementation "org.opensearch.plugin:reindex-client:${opensearch_version}" +// integrationTestImplementation "org.opensearch.plugin:percolator-client:${opensearch_version}" +// integrationTestImplementation 'commons-io:commons-io:2.18.0' +// integrationTestImplementation "org.apache.logging.log4j:log4j-core:${versions.log4j}" +// integrationTestImplementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}" +// integrationTestImplementation 'org.hamcrest:hamcrest:2.2' +// integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}" +// integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}" +// integrationTestImplementation('org.awaitility:awaitility:4.2.2') { +// exclude(group: 'org.hamcrest', module: 'hamcrest') +// } +// integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14' +// integrationTestImplementation "org.opensearch.plugin:mapper-size:${opensearch_version}" +// integrationTestImplementation "org.apache.httpcomponents:httpclient-cache:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:httpclient:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:fluent-hc:4.5.14" +// integrationTestImplementation "org.apache.httpcomponents:httpcore:4.4.16" +// integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5" +// integrationTestImplementation "org.mockito:mockito-core:5.14.2" //spotless implementation('com.google.googlejavaformat:google-java-format:1.25.2') { @@ -762,7 +762,7 @@ allprojects { } dependencies { //integration test framework: - integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.1') { + integrationTestImplementation('com.carrotsearch.randomizedtesting:randomizedtesting-runner:2.8.2') { exclude(group: 'junit', module: 'junit') } integrationTestImplementation 'junit:junit:4.13.2' From 1c51afdb71de1d06ac81ab053ac242aba4d0261d Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Mon, 30 Dec 2024 17:09:00 -0500 Subject: [PATCH 78/80] Handle case where resource sharing service is null Signed-off-by: Craig Perkins --- .../security/sampleextension/SampleExtensionPlugin.java | 5 ----- .../actions/resource/list/ListResourceTransportAction.java | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 10bcbed1fa..359bfa8703 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -53,7 +53,6 @@ import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.sampleextension.resource.SampleResourceParser; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; -import org.opensearch.security.spi.DefaultResourceSharingService; import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingExtension; @@ -89,10 +88,6 @@ public Collection createComponents( Supplier repositoriesServiceSupplier ) { this.client = client; - if (SampleResourceSharingServiceProvider.getInstance().get() == null) { - System.out.println("Using DefaultResourceSharingService"); - SampleResourceSharingServiceProvider.getInstance().set(new DefaultResourceSharingService<>()); - } System.out.println( "SampleResourceSharingServiceProvider.getInstance(): " + SampleResourceSharingServiceProvider.getInstance().get() ); diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java index d5639f62f3..461bfdc5e0 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java @@ -29,6 +29,7 @@ import org.opensearch.index.query.MatchAllQueryBuilder; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; +import org.opensearch.security.spi.DefaultResourceSharingService; import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingService; @@ -61,7 +62,7 @@ public ListResourceTransportAction( ) { super(actionName, transportService, actionFilters, ListResourceRequest::new); this.client = client; - this.resourceSharingService = resourceSharingService; + this.resourceSharingService = resourceSharingService != null ? resourceSharingService : new DefaultResourceSharingService<>(); this.resourceIndex = resourceIndex; this.xContentRegistry = xContentRegistry; this.resourceParser = resourceParser; From c57687059b17e66f89c2fbe0af11ae0068d0c997 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 31 Dec 2024 15:51:04 -0500 Subject: [PATCH 79/80] Default resource parser Signed-off-by: Craig Perkins --- .../spi/ResourceSharingExtension.java | 4 +- .../get/GetResourceTransportAction.java | 2 + .../list/ListResourceTransportAction.java | 2 + .../security/OpenSearchSecurityPlugin.java | 4 +- .../SecurityResourceSharingService.java | 51 +------------------ 5 files changed, 9 insertions(+), 54 deletions(-) diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java index 1b92843d3e..dbad5d9ae3 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java @@ -25,7 +25,9 @@ public interface ResourceSharingExtension { /** * @return returns a parser for this resource */ - ResourceParser getResourceParser(); + default ResourceParser getResourceParser() { + return null; + }; void assignResourceSharingService(ResourceSharingService service); } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java index 8d93ed4c8b..e949ce86b8 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java @@ -9,6 +9,7 @@ package org.opensearch.security.spi.actions.resource.get; import java.io.IOException; +import java.util.Objects; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -60,6 +61,7 @@ public GetResourceTransportAction( ) { super(actionName, transportService, actionFilters, GetResourceRequest::new); this.resourceSharingService = resourceSharingService; + Objects.requireNonNull(resourceParser); this.resourceParser = resourceParser; this.resourceIndex = resourceIndex; this.client = client; diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java index 461bfdc5e0..d2d4a508cb 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java @@ -11,6 +11,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import org.opensearch.OpenSearchException; @@ -65,6 +66,7 @@ public ListResourceTransportAction( this.resourceSharingService = resourceSharingService != null ? resourceSharingService : new DefaultResourceSharingService<>(); this.resourceIndex = resourceIndex; this.xContentRegistry = xContentRegistry; + Objects.requireNonNull(resourceParser); this.resourceParser = resourceParser; } diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 47f83c2a7f..76867c89ed 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -1080,9 +1080,7 @@ public Collection createComponents( for (ResourceSharingExtension extension : resourceSharingExtensions) { ResourceSharingService resourceSharingService = new SecurityResourceSharingService<>( localClient, - extension.getResourceIndex(), - extension.getResourceParser(), - xContentRegistry + extension.getResourceIndex() ); extension.assignResourceSharingService(resourceSharingService); } diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index 328fe711d4..bd3158cf5f 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -11,29 +11,19 @@ package org.opensearch.security.resource; -import java.io.IOException; - import org.opensearch.OpenSearchException; import org.opensearch.ResourceNotFoundException; -import org.opensearch.action.get.GetRequest; -import org.opensearch.action.get.GetResponse; import org.opensearch.action.search.SearchRequest; import org.opensearch.action.search.SearchResponse; import org.opensearch.client.Client; import org.opensearch.common.util.concurrent.ThreadContext; -import org.opensearch.common.xcontent.LoggingDeprecationHandler; -import org.opensearch.common.xcontent.XContentHelper; -import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.action.ActionListener; -import org.opensearch.core.xcontent.NamedXContentRegistry; -import org.opensearch.core.xcontent.XContentParser; import org.opensearch.index.query.BoolQueryBuilder; import org.opensearch.index.query.QueryBuilders; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.security.rest.resource.ShareWith; import org.opensearch.security.spi.Resource; -import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.support.WildcardMatcher; @@ -44,19 +34,10 @@ public class SecurityResourceSharingService implements ResourceSharingService { private final Client client; private final String resourceIndex; - private final ResourceParser resourceParser; - private final NamedXContentRegistry xContentRegistry; - public SecurityResourceSharingService( - Client client, - String resourceIndex, - ResourceParser resourceParser, - NamedXContentRegistry xContentRegistry - ) { + public SecurityResourceSharingService(Client client, String resourceIndex) { this.client = client; this.resourceIndex = resourceIndex; - this.resourceParser = resourceParser; - this.xContentRegistry = xContentRegistry; } private boolean hasPermissionsFor(User authenticatedUser, ResourceSharingEntry sharedWith) { @@ -122,34 +103,4 @@ public void onFailure(Exception e) { client.search(searchRequest, searchListener); } } - - private void finishGetResourceIfUserIsAllowed(String resourceId, ActionListener getResourceListener) { - try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashContext()) { - GetRequest gr = new GetRequest(resourceIndex); - gr.id(resourceId); - ActionListener getListener = new ActionListener<>() { - @Override - public void onResponse(GetResponse getResponse) { - try { - XContentParser parser = XContentHelper.createParser( - xContentRegistry, - LoggingDeprecationHandler.INSTANCE, - getResponse.getSourceAsBytesRef(), - XContentType.JSON - ); - T resource = resourceParser.parse(parser, getResponse.getId()); - getResourceListener.onResponse(resource); - } catch (IOException e) { - throw new OpenSearchException("Caught exception while loading resources: " + e.getMessage()); - } - } - - @Override - public void onFailure(Exception e) { - getResourceListener.onFailure(new OpenSearchException("Caught exception while loading resources: " + e.getMessage())); - } - }; - client.get(gr, getListener); - } - } } From d64258226a9b2fe19cb8a2e306870f9ddae93557 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 2 Jan 2025 21:16:11 -0500 Subject: [PATCH 80/80] Rename to SharableResource Signed-off-by: Craig Perkins --- .../SampleExtensionPlugin.java | 9 ++--- .../CreateSampleResourceTransportAction.java | 2 +- .../actions/get/GetSampleResourceAction.java | 2 +- .../list/ListSampleResourceAction.java | 2 +- .../resource/SampleResource.java | 38 ++++++++++++++----- .../SampleResourceSharingServiceProvider.java | 8 ++-- ...e.java => NoopResourceSharingService.java} | 2 +- .../org/opensearch/security/spi/Resource.java | 6 --- .../security/spi/ResourceParser.java | 2 +- .../spi/ResourceSharingExtension.java | 4 +- .../security/spi/ResourceSharingService.java | 2 +- .../security/spi/SharableResource.java | 18 +++++++++ .../create/CreateResourceRequest.java | 6 +-- .../create/CreateResourceTransportAction.java | 6 +-- .../resource/get/GetResourceResponse.java | 4 +- .../get/GetResourceTransportAction.java | 10 +++-- .../resource/list/ListResourceResponse.java | 4 +- .../list/ListResourceTransportAction.java | 14 ++++--- .../security/OpenSearchSecurityPlugin.java | 8 ++-- .../SecurityResourceSharingService.java | 3 +- 20 files changed, 90 insertions(+), 60 deletions(-) rename spi/src/main/java/org/opensearch/security/spi/{DefaultResourceSharingService.java => NoopResourceSharingService.java} (73%) delete mode 100644 spi/src/main/java/org/opensearch/security/spi/Resource.java create mode 100644 spi/src/main/java/org/opensearch/security/spi/SharableResource.java diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java index 359bfa8703..6431446329 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/SampleExtensionPlugin.java @@ -50,13 +50,12 @@ import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceRestAction; import org.opensearch.security.sampleextension.actions.update.UpdateSampleResourceTransportAction; -import org.opensearch.security.sampleextension.resource.SampleResource; import org.opensearch.security.sampleextension.resource.SampleResourceParser; import org.opensearch.security.sampleextension.resource.SampleResourceSharingServiceProvider; -import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingExtension; import org.opensearch.security.spi.ResourceSharingService; +import org.opensearch.security.spi.SharableResource; import org.opensearch.threadpool.ThreadPool; import org.opensearch.watcher.ResourceWatcherService; @@ -139,13 +138,13 @@ public String getResourceIndex() { } @Override - public ResourceParser getResourceParser() { + public ResourceParser getResourceParser() { return new SampleResourceParser(); } @SuppressWarnings("unchecked") @Override - public void assignResourceSharingService(ResourceSharingService service) { - SampleResourceSharingServiceProvider.getInstance().set((ResourceSharingService) service); + public void assignResourceSharingService(ResourceSharingService service) { + SampleResourceSharingServiceProvider.getInstance().set(service); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java index 05f4c986de..a98f22c3f8 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/create/CreateSampleResourceTransportAction.java @@ -28,6 +28,6 @@ public class CreateSampleResourceTransportAction extends CreateResourceTransport @Inject public CreateSampleResourceTransportAction(TransportService transportService, ActionFilters actionFilters, Client nodeClient) { - super(transportService, actionFilters, nodeClient, CreateSampleResourceAction.NAME, RESOURCE_INDEX_NAME, SampleResource::from); + super(transportService, actionFilters, nodeClient, CreateSampleResourceAction.NAME, RESOURCE_INDEX_NAME, SampleResource::new); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java index 4ea3e20486..889b9f51b7 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/get/GetSampleResourceAction.java @@ -26,6 +26,6 @@ public class GetSampleResourceAction extends ActionType new GetResourceResponse<>(in, SampleResource::from)); + super(NAME, in -> new GetResourceResponse<>(in, SampleResource::new)); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java index e91bb7e111..0da69f169b 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/actions/list/ListSampleResourceAction.java @@ -26,6 +26,6 @@ public class ListSampleResourceAction extends ActionType new ListResourceResponse<>(in, SampleResource::from)); + super(NAME, in -> new ListResourceResponse<>(in, SampleResource::new)); } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java index 3a8e04629e..6d3ca30e56 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResource.java @@ -1,24 +1,26 @@ package org.opensearch.security.sampleextension.resource; import java.io.IOException; +import java.time.Instant; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.SharableResource; -public class SampleResource implements Resource { +public class SampleResource implements SharableResource { private String name; + private Instant lastUpdateTime; - public SampleResource() {} - - SampleResource(StreamInput in) throws IOException { - this.name = in.readString(); + public SampleResource() { + Instant now = Instant.now(); + this.lastUpdateTime = now; } - public static SampleResource from(StreamInput in) throws IOException { - return new SampleResource(in); + public SampleResource(StreamInput in) throws IOException { + this.name = in.readString(); + this.lastUpdateTime = in.readInstant(); } @Override @@ -27,8 +29,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws } @Override - public void writeTo(StreamOutput streamOutput) throws IOException { - streamOutput.writeString(name); + public void writeTo(StreamOutput out) throws IOException { + out.writeString(name); + out.writeInstant(lastUpdateTime); + } @Override @@ -36,7 +40,21 @@ public String getWriteableName() { return "sample_resource"; } + @Override + public String getName() { + return name; + } + + @Override + public Instant getLastUpdateTime() { + return lastUpdateTime; + } + public void setName(String name) { this.name = name; } + + public void setLastUpdateTime(Instant lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } } diff --git a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java index 7540c07977..92a1939274 100644 --- a/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java +++ b/sample-extension-plugin/src/main/java/org/opensearch/security/sampleextension/resource/SampleResourceSharingServiceProvider.java @@ -13,9 +13,9 @@ * This provider allows for flexible injection of different ResourceSharingService * implementations based on runtime conditions. */ -public final class SampleResourceSharingServiceProvider implements Provider> { +public final class SampleResourceSharingServiceProvider implements Provider { - private volatile ResourceSharingService resourceSharingService; + private volatile ResourceSharingService resourceSharingService; private static final Map instances = new ConcurrentHashMap<>(); @@ -38,7 +38,7 @@ public static SampleResourceSharingServiceProvider getInstance() { * @throws IllegalStateException if the service has already been set * @throws IllegalArgumentException if the provided service is null */ - public void set(ResourceSharingService resourceSharingService) { + public void set(ResourceSharingService resourceSharingService) { if (resourceSharingService == null) { throw new IllegalArgumentException("ResourceSharingService cannot be null"); } @@ -56,7 +56,7 @@ public void set(ResourceSharingService resourceSharingService) { * @return the configured ResourceSharingService */ @Override - public ResourceSharingService get() { + public ResourceSharingService get() { return resourceSharingService; } } diff --git a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/NoopResourceSharingService.java similarity index 73% rename from spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java rename to spi/src/main/java/org/opensearch/security/spi/NoopResourceSharingService.java index 82cd32c4a5..0b38533b60 100644 --- a/spi/src/main/java/org/opensearch/security/spi/DefaultResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/NoopResourceSharingService.java @@ -2,7 +2,7 @@ import org.opensearch.core.action.ActionListener; -public class DefaultResourceSharingService implements ResourceSharingService { +public class NoopResourceSharingService implements ResourceSharingService { @Override public void isSharedWithCurrentUser(String resourceId, ActionListener resourceSharingListener) { diff --git a/spi/src/main/java/org/opensearch/security/spi/Resource.java b/spi/src/main/java/org/opensearch/security/spi/Resource.java deleted file mode 100644 index b7df3ae131..0000000000 --- a/spi/src/main/java/org/opensearch/security/spi/Resource.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.opensearch.security.spi; - -import org.opensearch.core.common.io.stream.NamedWriteable; -import org.opensearch.core.xcontent.ToXContentObject; - -public interface Resource extends NamedWriteable, ToXContentObject {} diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceParser.java b/spi/src/main/java/org/opensearch/security/spi/ResourceParser.java index 0e4a3ac0bd..45b73a2260 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceParser.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceParser.java @@ -4,6 +4,6 @@ import org.opensearch.core.xcontent.XContentParser; -public interface ResourceParser { +public interface ResourceParser { T parse(XContentParser xContentParser, String id) throws IOException; } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java index dbad5d9ae3..7797b80ba6 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingExtension.java @@ -25,9 +25,9 @@ public interface ResourceSharingExtension { /** * @return returns a parser for this resource */ - default ResourceParser getResourceParser() { + default ResourceParser getResourceParser() { return null; }; - void assignResourceSharingService(ResourceSharingService service); + void assignResourceSharingService(ResourceSharingService service); } diff --git a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java index 31ef5e7f83..999cad0593 100644 --- a/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java +++ b/spi/src/main/java/org/opensearch/security/spi/ResourceSharingService.java @@ -2,6 +2,6 @@ import org.opensearch.core.action.ActionListener; -public interface ResourceSharingService { +public interface ResourceSharingService { void isSharedWithCurrentUser(String resourceId, ActionListener shareListener); } diff --git a/spi/src/main/java/org/opensearch/security/spi/SharableResource.java b/spi/src/main/java/org/opensearch/security/spi/SharableResource.java new file mode 100644 index 0000000000..392ca0f3de --- /dev/null +++ b/spi/src/main/java/org/opensearch/security/spi/SharableResource.java @@ -0,0 +1,18 @@ +package org.opensearch.security.spi; + +import java.time.Instant; + +import org.opensearch.core.common.io.stream.NamedWriteable; +import org.opensearch.core.xcontent.ToXContentObject; + +public interface SharableResource extends NamedWriteable, ToXContentObject { + /** + * @return resource name. + */ + String getName(); + + /** + * @return resource last update time. + */ + Instant getLastUpdateTime(); +} diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceRequest.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceRequest.java index 69576bc040..e89f297391 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceRequest.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceRequest.java @@ -15,12 +15,12 @@ import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.common.io.stream.Writeable; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.SharableResource; /** * Request object for CreateSampleResource transport action */ -public class CreateResourceRequest extends ActionRequest { +public class CreateResourceRequest extends ActionRequest { private final T resource; @@ -45,7 +45,7 @@ public ActionRequestValidationException validate() { return null; } - public Resource getResource() { + public SharableResource getResource() { return this.resource; } } diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceTransportAction.java index 5c62a0b5e9..3802b2495e 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/create/CreateResourceTransportAction.java @@ -25,7 +25,7 @@ import org.opensearch.core.action.ActionListener; import org.opensearch.core.common.io.stream.Writeable; import org.opensearch.core.xcontent.ToXContent; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.SharableResource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -34,7 +34,7 @@ /** * Transport action for CreateSampleResource. */ -public class CreateResourceTransportAction extends HandledTransportAction< +public class CreateResourceTransportAction extends HandledTransportAction< CreateResourceRequest, CreateResourceResponse> { private static final Logger log = LogManager.getLogger(CreateResourceTransportAction.class); @@ -74,7 +74,7 @@ protected void doExecute(Task task, CreateResourceRequest request, ActionList private void createResource(CreateResourceRequest request, ActionListener listener) { log.warn("Sample name: " + request.getResource()); - Resource sample = request.getResource(); + SharableResource sample = request.getResource(); try { IndexRequest ir = nodeClient.prepareIndex(resourceIndex) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java index 30b00e7aca..f097bb6f28 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceResponse.java @@ -16,12 +16,12 @@ import org.opensearch.core.common.io.stream.Writeable; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.SharableResource; /** * Response to a GetResourceRequest */ -public class GetResourceResponse extends ActionResponse implements ToXContentObject { +public class GetResourceResponse extends ActionResponse implements ToXContentObject { private final T resource; /** diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java index e949ce86b8..8dd4a63653 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/get/GetResourceTransportAction.java @@ -27,19 +27,21 @@ import org.opensearch.core.action.ActionListener; import org.opensearch.core.xcontent.NamedXContentRegistry; import org.opensearch.core.xcontent.XContentParser; -import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingService; +import org.opensearch.security.spi.SharableResource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; /** * Transport action for GetResource. */ -public class GetResourceTransportAction extends HandledTransportAction> { +public class GetResourceTransportAction extends HandledTransportAction< + GetResourceRequest, + GetResourceResponse> { private static final Logger log = LogManager.getLogger(GetResourceTransportAction.class); - private final ResourceSharingService resourceSharingService; + private final ResourceSharingService resourceSharingService; private final ResourceParser resourceParser; @@ -54,7 +56,7 @@ public GetResourceTransportAction( ActionFilters actionFilters, String actionName, String resourceIndex, - ResourceSharingService resourceSharingService, + ResourceSharingService resourceSharingService, ResourceParser resourceParser, Client client, NamedXContentRegistry xContentRegistry diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java index b0d7ccf81f..9c321d5732 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceResponse.java @@ -16,12 +16,12 @@ import org.opensearch.core.common.io.stream.StreamOutput; import org.opensearch.core.xcontent.ToXContentObject; import org.opensearch.core.xcontent.XContentBuilder; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.SharableResource; /** * Response to a ListResourceRequest */ -public class ListResourceResponse extends ActionResponse implements ToXContentObject { +public class ListResourceResponse extends ActionResponse implements ToXContentObject { private final List resources; /** diff --git a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java index d2d4a508cb..0b11bfa7cb 100644 --- a/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java +++ b/spi/src/main/java/org/opensearch/security/spi/actions/resource/list/ListResourceTransportAction.java @@ -30,18 +30,20 @@ import org.opensearch.index.query.MatchAllQueryBuilder; import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; -import org.opensearch.security.spi.DefaultResourceSharingService; -import org.opensearch.security.spi.Resource; +import org.opensearch.security.spi.NoopResourceSharingService; import org.opensearch.security.spi.ResourceParser; import org.opensearch.security.spi.ResourceSharingService; +import org.opensearch.security.spi.SharableResource; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; /** * Transport action for ListResource. */ -public class ListResourceTransportAction extends HandledTransportAction> { - private final ResourceSharingService resourceSharingService; +public class ListResourceTransportAction extends HandledTransportAction< + ListResourceRequest, + ListResourceResponse> { + private final ResourceSharingService resourceSharingService; private final ResourceParser resourceParser; @@ -56,14 +58,14 @@ public ListResourceTransportAction( ActionFilters actionFilters, String actionName, String resourceIndex, - ResourceSharingService resourceSharingService, + ResourceSharingService resourceSharingService, ResourceParser resourceParser, Client client, NamedXContentRegistry xContentRegistry ) { super(actionName, transportService, actionFilters, ListResourceRequest::new); this.client = client; - this.resourceSharingService = resourceSharingService != null ? resourceSharingService : new DefaultResourceSharingService<>(); + this.resourceSharingService = resourceSharingService != null ? resourceSharingService : new NoopResourceSharingService(); this.resourceIndex = resourceIndex; this.xContentRegistry = xContentRegistry; Objects.requireNonNull(resourceParser); diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 76867c89ed..095dc88e31 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -731,6 +731,7 @@ public void onIndexModule(IndexModule indexModule) { dlsFlsBaseContext ) ); + System.out.println("this.indicesToListen: " + this.indicesToListen); if (this.indicesToListen.contains(indexModule.getIndex().getName())) { indexModule.addIndexOperationListener(ResourceSharingListener.getInstance()); log.warn("Security started listening to operations on index {}", indexModule.getIndex().getName()); @@ -1078,10 +1079,7 @@ public Collection createComponents( ResourceSharingListener.getInstance().initialize(threadPool, localClient); // CS-SUPPRESS-SINGLE: RegexpSingleline SPI Extensions are unrelated to OpenSearch extensions for (ResourceSharingExtension extension : resourceSharingExtensions) { - ResourceSharingService resourceSharingService = new SecurityResourceSharingService<>( - localClient, - extension.getResourceIndex() - ); + ResourceSharingService resourceSharingService = new SecurityResourceSharingService(localClient, extension.getResourceIndex()); extension.assignResourceSharingService(resourceSharingService); } // CS-ENFORCE-SINGLE @@ -2199,9 +2197,9 @@ public Optional getSecureSettingFactory(Settings settings // CS-SUPPRESS-SINGLE: RegexpSingleline SPI Extensions are unrelated to OpenSearch extensions @Override public void loadExtensions(ExtensiblePlugin.ExtensionLoader loader) { + System.out.println("loadExtensions"); for (ResourceSharingExtension extension : loader.loadExtensions(ResourceSharingExtension.class)) { String resourceIndexName = extension.getResourceIndex(); - System.out.println("loadExtensions"); System.out.println("localClient: " + localClient); this.indicesToListen.add(resourceIndexName); resourceSharingExtensions.add(extension); diff --git a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java index bd3158cf5f..13f7308984 100644 --- a/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java +++ b/src/main/java/org/opensearch/security/resource/SecurityResourceSharingService.java @@ -23,7 +23,6 @@ import org.opensearch.search.SearchHit; import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.security.rest.resource.ShareWith; -import org.opensearch.security.spi.Resource; import org.opensearch.security.spi.ResourceSharingService; import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.support.WildcardMatcher; @@ -31,7 +30,7 @@ import static org.opensearch.security.resource.ResourceSharingListener.RESOURCE_SHARING_INDEX; -public class SecurityResourceSharingService implements ResourceSharingService { +public class SecurityResourceSharingService implements ResourceSharingService { private final Client client; private final String resourceIndex;