diff --git a/CHANGELOG.md b/CHANGELOG.md index c96ddf75e3282..890d3f2b470d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Introduce a new search node role to hold search only shards ([#17620](https://github.com/opensearch-project/OpenSearch/pull/17620)) - Fix systemd integTest on deb regarding path ownership check ([#17641](https://github.com/opensearch-project/OpenSearch/pull/17641)) - Add dfs transformation function in XContentMapValues ([#17612](https://github.com/opensearch-project/OpenSearch/pull/17612)) -- Added Kinesis support as a plugin for the pull-based ingestion ([#17615](https://github.com/opensearch-project/OpenSearch/pull/17615) +- Added Kinesis support as a plugin for the pull-based ingestion ([#17615](https://github.com/opensearch-project/OpenSearch/pull/17615)) +- [Security Manager Replacement] Create initial Java Agent to intercept Socket::connect calls ([#17724](https://github.com/opensearch-project/OpenSearch/pull/17724)) ### Changed - Migrate BC libs to their FIPS counterparts ([#14912](https://github.com/opensearch-project/OpenSearch/pull/14912)) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4ccb794137c14..e0a34482e2d7b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,7 @@ grpc = "1.68.2" json_smart = "2.5.2" # when updating the JNA version, also update the version in buildSrc/build.gradle -jna = "5.13.0" +jna = "5.16.0" netty = "4.1.118.Final" joda = "2.12.7" @@ -70,9 +70,9 @@ password4j = "1.8.2" randomizedrunner = "2.7.1" junit = "4.13.2" hamcrest = "2.1" -mockito = "5.14.2" +mockito = "5.16.1" objenesis = "3.3" -bytebuddy = "1.15.10" +bytebuddy = "1.17.4" # benchmark dependencies jmh = "1.35" diff --git a/libs/agent-sm/agent/build.gradle b/libs/agent-sm/agent/build.gradle new file mode 100644 index 0000000000000..266750f8d9529 --- /dev/null +++ b/libs/agent-sm/agent/build.gradle @@ -0,0 +1,64 @@ +apply plugin: 'opensearch.build' +apply plugin: 'opensearch.publish' + +base { + archivesName = 'opensearch-agent' +} + +configurations { + bootstrap.extendsFrom(implementation) +} + +dependencies { + implementation project(":libs:agent-sm:bootstrap") + implementation "net.bytebuddy:byte-buddy:${versions.bytebuddy}" + compileOnly "com.google.code.findbugs:jsr305:3.0.2" +} + +var bootClasspath = configurations.bootstrap.incoming.artifactView { }.files + .getFiles() + .collect { it.name } + +jar { + manifest { + attributes( + "Can-Redefine-Classes": "true", + "Can-Retransform-Classes": "true", + "Agent-Class": "org.opensearch.javaagent.Agent", + "Premain-Class": "org.opensearch.javaagent.Agent", + "Boot-Class-Path": bootClasspath.join(' ') + ) + } +} + +compileJava { + options.compilerArgs -= '-Werror' +} + +test.enabled = false +testingConventions.enabled = false + +tasks.named('forbiddenApisMain').configure { + replaceSignatureFiles 'jdk-signatures' +} + +task prepareAgent(type: Copy) { + from(configurations.runtimeClasspath) + into "$buildDir/distributions" + dependsOn jar +} + +thirdPartyAudit { + ignoreMissingClasses( + 'com.sun.jna.FunctionMapper', + 'com.sun.jna.JNIEnv', + 'com.sun.jna.Library', + 'com.sun.jna.Native', + 'com.sun.jna.NativeLibrary', + 'com.sun.jna.Platform' + ) +} + +tasks.named('validateNebulaPom') { + dependsOn prepareAgent +} diff --git a/libs/agent-sm/agent/licenses/byte-buddy-1.17.4.jar.sha1 b/libs/agent-sm/agent/licenses/byte-buddy-1.17.4.jar.sha1 new file mode 100644 index 0000000000000..ebf5d77477f30 --- /dev/null +++ b/libs/agent-sm/agent/licenses/byte-buddy-1.17.4.jar.sha1 @@ -0,0 +1 @@ +ffb8488d93290eff074fb542a596e4c5a26d0315 \ No newline at end of file diff --git a/libs/agent-sm/agent/licenses/byte-buddy-LICENSE.txt b/libs/agent-sm/agent/licenses/byte-buddy-LICENSE.txt new file mode 100644 index 0000000000000..719c6605bb9b4 --- /dev/null +++ b/libs/agent-sm/agent/licenses/byte-buddy-LICENSE.txt @@ -0,0 +1,180 @@ +This product bundles ASM 9.7.1, which is available under a "3-clause BSD" +license. For details, see licenses/ASM. For more information visit ${asm.url}. + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/libs/agent-sm/agent/licenses/byte-buddy-NOTICE.txt b/libs/agent-sm/agent/licenses/byte-buddy-NOTICE.txt new file mode 100644 index 0000000000000..929cbc6b18bba --- /dev/null +++ b/libs/agent-sm/agent/licenses/byte-buddy-NOTICE.txt @@ -0,0 +1,13 @@ +Copyright 2014 - Present Rafael Winterhalter + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/Agent.java b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/Agent.java new file mode 100644 index 0000000000000..6c5931f537956 --- /dev/null +++ b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/Agent.java @@ -0,0 +1,89 @@ +/* + * 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.javaagent; + +import org.opensearch.javaagent.bootstrap.AgentPolicy; + +import java.lang.instrument.Instrumentation; +import java.nio.channels.SocketChannel; +import java.util.Map; + +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.agent.builder.AgentBuilder; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.dynamic.ClassFileLocator; +import net.bytebuddy.dynamic.loading.ClassInjector; +import net.bytebuddy.implementation.Implementation; +import net.bytebuddy.matcher.ElementMatcher.Junction; +import net.bytebuddy.matcher.ElementMatchers; + +/** + * Java Agent + */ +public class Agent { + /** + * Constructor + */ + private Agent() {} + + /** + * Premain + * @param agentArguments agent arguments + * @param instrumentation instrumentation + * @throws Exception Exception + */ + public static void premain(String agentArguments, Instrumentation instrumentation) throws Exception { + initAgent(instrumentation); + } + + /** + * Agent Main + * @param agentArguments agent arguments + * @param instrumentation instrumentation + * @throws Exception Exception + */ + public static void agentmain(String agentArguments, Instrumentation instrumentation) throws Exception { + initAgent(instrumentation); + } + + private static AgentBuilder createAgentBuilder(Instrumentation inst) throws Exception { + final Junction systemType = ElementMatchers.isSubTypeOf(SocketChannel.class); + + final AgentBuilder.Transformer transformer = (b, typeDescription, classLoader, module, pd) -> b.visit( + Advice.to(SocketChannelInterceptor.class) + .on(ElementMatchers.named("connect").and(ElementMatchers.not(ElementMatchers.isAbstract()))) + ); + + ClassInjector.UsingUnsafe.ofBootLoader() + .inject( + Map.of( + new TypeDescription.ForLoadedType(StackCallerChainExtractor.class), + ClassFileLocator.ForClassLoader.read(StackCallerChainExtractor.class), + new TypeDescription.ForLoadedType(AgentPolicy.class), + ClassFileLocator.ForClassLoader.read(AgentPolicy.class) + ) + ); + + final ByteBuddy byteBuddy = new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE); + final AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy).with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE) + .with(AgentBuilder.RedefinitionStrategy.REDEFINITION) + .with(AgentBuilder.TypeStrategy.Default.REDEFINE) + .ignore(ElementMatchers.none()) + .type(systemType) + .transform(transformer); + + return agentBuilder; + } + + private static void initAgent(Instrumentation instrumentation) throws Exception { + AgentBuilder agentBuilder = createAgentBuilder(instrumentation); + agentBuilder.installOn(instrumentation); + } +} diff --git a/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/SocketChannelInterceptor.java b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/SocketChannelInterceptor.java new file mode 100644 index 0000000000000..b3e0251c6f1b1 --- /dev/null +++ b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/SocketChannelInterceptor.java @@ -0,0 +1,72 @@ +/* + * 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.javaagent; + +import org.opensearch.javaagent.bootstrap.AgentPolicy; + +import java.lang.StackWalker.Option; +import java.lang.reflect.Method; +import java.net.InetSocketAddress; +import java.net.NetPermission; +import java.net.SocketPermission; +import java.net.UnixDomainSocketAddress; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.util.List; + +import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.Origin; + +/** + * SocketChannelInterceptor + */ +public class SocketChannelInterceptor { + /** + * SocketChannelInterceptor + */ + public SocketChannelInterceptor() {} + + /** + * Interceptors + * @param args arguments + * @param method method + * @throws Exception exceptions + */ + @Advice.OnMethodEnter + @SuppressWarnings("removal") + public static void intercept(@Advice.AllArguments Object[] args, @Origin Method method) throws Exception { + final Policy policy = AgentPolicy.getPolicy(); + if (policy == null) { + return; /* noop */ + } + + final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE); + final List callers = walker.walk(new StackCallerChainExtractor()); + + if (args[0] instanceof InetSocketAddress address) { + if (!AgentPolicy.isTrustedHost(address.getHostString())) { + final String host = address.getHostString() + ":" + address.getPort(); + + final SocketPermission permission = new SocketPermission(host, "connect,resolve"); + for (final ProtectionDomain domain : callers) { + if (!policy.implies(domain, permission)) { + throw new SecurityException("Denied access to: " + host + ", domain " + domain); + } + } + } + } else if (args[0] instanceof UnixDomainSocketAddress address) { + final NetPermission permission = new NetPermission("accessUnixDomainSocket"); + for (final ProtectionDomain domain : callers) { + if (!policy.implies(domain, permission)) { + throw new SecurityException("Denied access to: " + address + ", domain " + domain); + } + } + } + } +} diff --git a/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/StackCallerChainExtractor.java b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/StackCallerChainExtractor.java new file mode 100644 index 0000000000000..6c33ca73e107d --- /dev/null +++ b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/StackCallerChainExtractor.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.javaagent; + +import java.lang.StackWalker.StackFrame; +import java.security.ProtectionDomain; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Stack Caller Chain Extractor + */ +public final class StackCallerChainExtractor implements Function, List> { + /** + * Constructor + */ + public StackCallerChainExtractor() {} + + /** + * Folds the stack + * @param frames stack frames + */ + @Override + public List apply(Stream frames) { + return frames.map(StackFrame::getDeclaringClass) + .map(Class::getProtectionDomain) + .filter(pd -> pd.getCodeSource() != null) /* JDK */ + .distinct() + .collect(Collectors.toList()); + } +} diff --git a/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/package-info.java b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/package-info.java new file mode 100644 index 0000000000000..447a0d8828875 --- /dev/null +++ b/libs/agent-sm/agent/src/main/java/org/opensearch/javaagent/package-info.java @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/** + * Java Agent + */ +package org.opensearch.javaagent; diff --git a/libs/agent-sm/agent/src/main/java/org/opensearch/package-info.java b/libs/agent-sm/agent/src/main/java/org/opensearch/package-info.java new file mode 100644 index 0000000000000..a15b5b51ae3de --- /dev/null +++ b/libs/agent-sm/agent/src/main/java/org/opensearch/package-info.java @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/** + * Java Agent + */ +package org.opensearch; diff --git a/libs/agent-sm/bootstrap/build.gradle b/libs/agent-sm/bootstrap/build.gradle new file mode 100644 index 0000000000000..1757e3cd75c99 --- /dev/null +++ b/libs/agent-sm/bootstrap/build.gradle @@ -0,0 +1,24 @@ +/* + * 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. + */ + +apply plugin: 'opensearch.build' +apply plugin: 'opensearch.publish' + +base { + archivesName = 'opensearch-agent-bootstrap' +} + +tasks.named('forbiddenApisMain').configure { + replaceSignatureFiles 'jdk-signatures' +} + +test.enabled = false +testingConventions.enabled = false diff --git a/libs/agent-sm/bootstrap/src/main/java/org/opensearch/javaagent/bootstrap/AgentPolicy.java b/libs/agent-sm/bootstrap/src/main/java/org/opensearch/javaagent/bootstrap/AgentPolicy.java new file mode 100644 index 0000000000000..d2c77fac011b5 --- /dev/null +++ b/libs/agent-sm/bootstrap/src/main/java/org/opensearch/javaagent/bootstrap/AgentPolicy.java @@ -0,0 +1,89 @@ +/* + * 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.javaagent.bootstrap; + +import java.lang.StackWalker.Option; +import java.lang.StackWalker.StackFrame; +import java.security.Permission; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * Agent Policy + */ +@SuppressWarnings("removal") +public class AgentPolicy { + private static final Logger LOGGER = Logger.getLogger(AgentPolicy.class.getName()); + private static volatile Policy policy; + private static volatile Set trustedHosts; + + private AgentPolicy() {} + + /** + * Set Agent policy + * @param policy policy + */ + public static void setPolicy(Policy policy) { + setPolicy(policy, Set.of()); + } + + /** + * Set Agent policy + * @param policy policy + * @param trustedHosts trusted hosts + */ + public static void setPolicy(Policy policy, final Set trustedHosts) { + if (AgentPolicy.policy == null) { + AgentPolicy.policy = policy; + AgentPolicy.trustedHosts = Collections.unmodifiableSet(trustedHosts); + LOGGER.info("Policy attached successfully: " + policy); + } else { + throw new SecurityException("The Policy has been set already: " + AgentPolicy.policy); + } + } + + /** + * Check permissions + * @param permission permission + */ + public static void checkPermission(Permission permission) { + final StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE); + final List callers = walker.walk( + frames -> frames.map(StackFrame::getDeclaringClass).map(Class::getProtectionDomain).distinct().collect(Collectors.toList()) + ); + + for (final ProtectionDomain domain : callers) { + if (!policy.implies(domain, permission)) { + throw new SecurityException("Denied access: " + permission); + } + } + } + + /** + * Get policy + * @return policy + */ + public static Policy getPolicy() { + return policy; + } + + /** + * Check if hostname is trusted + * @param hostname hostname + * @return is trusted or not + */ + public static boolean isTrustedHost(String hostname) { + return AgentPolicy.trustedHosts.contains(hostname); + } +} diff --git a/libs/agent-sm/bootstrap/src/main/java/org/opensearch/javaagent/bootstrap/package-info.java b/libs/agent-sm/bootstrap/src/main/java/org/opensearch/javaagent/bootstrap/package-info.java new file mode 100644 index 0000000000000..6172ae511a8f7 --- /dev/null +++ b/libs/agent-sm/bootstrap/src/main/java/org/opensearch/javaagent/bootstrap/package-info.java @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/** + * Java Agent Policy + */ +package org.opensearch.javaagent.bootstrap; diff --git a/libs/agent-sm/bootstrap/src/main/java/org/opensearch/package-info.java b/libs/agent-sm/bootstrap/src/main/java/org/opensearch/package-info.java new file mode 100644 index 0000000000000..8fb377151ae39 --- /dev/null +++ b/libs/agent-sm/bootstrap/src/main/java/org/opensearch/package-info.java @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/** + * Java Agent Policy Bootstrap + */ +package org.opensearch; diff --git a/libs/agent-sm/build.gradle b/libs/agent-sm/build.gradle new file mode 100644 index 0000000000000..656411a08080f --- /dev/null +++ b/libs/agent-sm/build.gradle @@ -0,0 +1,22 @@ +/* + * 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. + */ + +// This file is intentionally blank. All configuration of the +// distribution is done in the parent project. + +// See please https://docs.gradle.org/8.5/userguide/upgrading_version_8.html#deprecated_missing_project_directory + +base { + archivesName = 'opensearch-agent-sm' +} + +test.enabled = false +testingConventions.enabled = false diff --git a/libs/build.gradle b/libs/build.gradle index c0fcc1ff2b977..9bf359d936178 100644 --- a/libs/build.gradle +++ b/libs/build.gradle @@ -40,17 +40,19 @@ subprojects { * other libs. This keeps our dependencies simpler. */ project.afterEvaluate { - configurations.all { Configuration conf -> - dependencies.matching { it instanceof ProjectDependency }.all { ProjectDependency dep -> - Project depProject = project.project(dep.path) - if (depProject != null - && (false == depProject.path.equals(':libs:opensearch-core') && - false == depProject.path.equals(':libs:opensearch-common')) - && depProject.path.startsWith(':libs')) { - throw new InvalidUserDataException("projects in :libs " - + "may not depend on other projects libs except " - + ":libs:opensearch-core or :libs:opensearch-common but " - + "${project.path} depends on ${depProject.path}") + if (!project.path.equals(':libs:agent-sm:agent')) { + configurations.all { Configuration conf -> + dependencies.matching { it instanceof ProjectDependency }.all { ProjectDependency dep -> + Project depProject = project.project(dep.path) + if (depProject != null + && (false == depProject.path.equals(':libs:opensearch-core') && + false == depProject.path.equals(':libs:opensearch-common')) + && depProject.path.startsWith(':libs')) { + throw new InvalidUserDataException("projects in :libs " + + "may not depend on other projects libs except " + + ":libs:opensearch-core or :libs:opensearch-common but " + + "${project.path} depends on ${depProject.path}") + } } } } diff --git a/plugins/repository-azure/licenses/jna-platform-5.13.0.jar.sha1 b/plugins/repository-azure/licenses/jna-platform-5.13.0.jar.sha1 deleted file mode 100644 index e2a8ba1c1bbd3..0000000000000 --- a/plugins/repository-azure/licenses/jna-platform-5.13.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -88e9a306715e9379f3122415ef4ae759a352640d \ No newline at end of file diff --git a/plugins/repository-azure/licenses/jna-platform-5.16.0.jar.sha1 b/plugins/repository-azure/licenses/jna-platform-5.16.0.jar.sha1 new file mode 100644 index 0000000000000..84b5ec150d7a5 --- /dev/null +++ b/plugins/repository-azure/licenses/jna-platform-5.16.0.jar.sha1 @@ -0,0 +1 @@ +b2a9065f97c166893d504b164706512338e3bbc2 \ No newline at end of file diff --git a/server/licenses/jna-5.13.0.jar.sha1 b/server/licenses/jna-5.13.0.jar.sha1 deleted file mode 100644 index faf2012f0b5c0..0000000000000 --- a/server/licenses/jna-5.13.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -1200e7ebeedbe0d10062093f32925a912020e747 \ No newline at end of file diff --git a/server/licenses/jna-5.16.0.jar.sha1 b/server/licenses/jna-5.16.0.jar.sha1 new file mode 100644 index 0000000000000..4b45642a01952 --- /dev/null +++ b/server/licenses/jna-5.16.0.jar.sha1 @@ -0,0 +1 @@ +ebea09f91dc9f7048099f963fb8d6f919f0a4d9c \ No newline at end of file diff --git a/test/framework/licenses/byte-buddy-1.15.10.jar.sha1 b/test/framework/licenses/byte-buddy-1.15.10.jar.sha1 deleted file mode 100644 index b89163a2aa842..0000000000000 --- a/test/framework/licenses/byte-buddy-1.15.10.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -635c873fadd853c084f84fdc3cbd58c5dd8537f9 \ No newline at end of file diff --git a/test/framework/licenses/byte-buddy-1.17.4.jar.sha1 b/test/framework/licenses/byte-buddy-1.17.4.jar.sha1 new file mode 100644 index 0000000000000..ebf5d77477f30 --- /dev/null +++ b/test/framework/licenses/byte-buddy-1.17.4.jar.sha1 @@ -0,0 +1 @@ +ffb8488d93290eff074fb542a596e4c5a26d0315 \ No newline at end of file diff --git a/test/framework/licenses/mockito-core-5.14.2.jar.sha1 b/test/framework/licenses/mockito-core-5.14.2.jar.sha1 deleted file mode 100644 index a9fe959400ceb..0000000000000 --- a/test/framework/licenses/mockito-core-5.14.2.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -f7bf936008d7664e2002c3faf0c02071c8d10e7c \ No newline at end of file diff --git a/test/framework/licenses/mockito-core-5.16.1.jar.sha1 b/test/framework/licenses/mockito-core-5.16.1.jar.sha1 new file mode 100644 index 0000000000000..7ced27fb416bf --- /dev/null +++ b/test/framework/licenses/mockito-core-5.16.1.jar.sha1 @@ -0,0 +1 @@ +be8bf71080016b793f32456faff861e2c3a77f62 \ No newline at end of file