From 81af97203dd3edc6363d51f316ada0d996d64cb6 Mon Sep 17 00:00:00 2001 From: Peter Nied Date: Wed, 18 Jan 2023 19:14:44 +0000 Subject: [PATCH 01/33] Identity and access control for OpenSearch Adding a new module and plugin interface that provides identity and access control inside of OpenSearch. This is the founding building block, see more high level thoughts here on our recent blog. https://opensearch.org/blog/Introducing-Identity/ The new extension point, IdentityPlugin, is added with IdentityService handling that plugin interface. IdentitySevice authenticates users and enables access control systems. Adding HTTP basic authentication in the RestController the default NoopIdentityPlugin changes no behavior. When the identity feature flag is enabled the identity-shiro module is loaded into the IdentityService. This implementations includes an admin user backed through the Apache Shiro system. By partitioning these features through a plugin interface it isolate the dependencies if we ever switch out the underlying library. Project tracking addition features and functionality - https://github.com/orgs/opensearch-project/projects/89?pane=info Signed-off-by: Peter Nied --- .gitignore | 2 +- CHANGELOG.md | 5 + gradle/missing-javadoc.gradle | 1 + modules/identity-shiro/build.gradle | 66 ++++++ .../licenses/bcprov-jdk15on-1.70.jar.sha1 | 1 + .../licenses/bcprov-jdk15on-LICENSE.txt | 22 ++ .../licenses/bcprov-jdk15on-NOTICE.txt | 0 .../licenses/commons-beanutils-1.9.4.jar.sha1 | 1 + .../licenses/commons-beanutils-LICENSE.txt | 202 ++++++++++++++++++ .../licenses/commons-beanutils-NOTICE.txt | 5 + .../licenses/commons-lang-2.6.jar.sha1 | 1 + .../licenses/commons-lang-LICENSE.txt | 202 ++++++++++++++++++ .../licenses/commons-lang-NOTICE.txt | 5 + .../licenses/commons-logging-1.2.jar.sha1 | 1 + .../licenses/commons-logging-LICENSE.txt | 202 ++++++++++++++++++ .../licenses/commons-logging-NOTICE.txt | 5 + .../licenses/shiro-core-1.9.1.jar.sha1 | 1 + .../licenses/shiro-core-LICENSE.txt | 201 +++++++++++++++++ .../licenses/shiro-core-NOTICE.txt | 15 ++ .../licenses/slf4j-api-1.7.36.jar.sha1 | 1 + .../licenses/slf4j-api-LICENSE.txt | 21 ++ .../licenses/slf4j-api-NOTICE.txt | 0 .../identity/BasicAuthenticationIT.java | 71 ++++++ .../HttpSmokeTestCaseWithIdentity.java | 91 ++++++++ .../identity/shiro/AuthTokenHandler.java | 41 ++++ .../identity/shiro/ShiroIdentityPlugin.java | 43 ++++ .../identity/shiro/ShiroSecurityManager.java | 45 ++++ .../identity/shiro/ShiroSubject.java | 64 ++++++ .../identity/shiro/package-info.java | 12 ++ .../shiro/realm/BCryptPasswordMatcher.java | 32 +++ .../identity/shiro/realm/InternalRealm.java | 107 ++++++++++ .../opensearch/identity/shiro/realm/User.java | 38 ++++ .../identity/shiro/realm/package-info.java | 10 + .../plugin-metadata/plugin-security.policy | 11 + .../identity/AbstractIdentityTestCase.java | 52 +++++ .../identity/shiro/AuthTokenHandlerTests.java | 61 ++++++ .../identity/shiro/ShiroSubjectTests.java | 75 +++++++ .../realm/BCryptPasswordMatcherTests.java | 46 ++++ .../shiro/realm/InternalRealmTests.java | 39 ++++ sandbox/modules/build.gradle | 15 +- .../org/opensearch/action/ActionModule.java | 6 +- .../common/settings/FeatureFlagSettings.java | 3 +- .../opensearch/common/util/FeatureFlags.java | 7 + .../opensearch/identity/IdentityService.java | 52 +++++ .../org/opensearch/identity/Principals.java | 35 +++ .../opensearch/identity/StringPrincipal.java | 50 +++++ .../java/org/opensearch/identity/Subject.java | 32 +++ .../identity/noop/NoopIdentityPlugin.java | 28 +++ .../opensearch/identity/noop/NoopSubject.java | 57 +++++ .../identity/noop/package-info.java | 10 + .../org/opensearch/identity/package-info.java | 7 + .../opensearch/identity/tokens/AuthToken.java | 18 ++ .../identity/tokens/BasicAuthToken.java | 44 ++++ .../identity/tokens/RestTokenExtractor.java | 56 +++++ .../identity/tokens/package-info.java | 10 + .../main/java/org/opensearch/node/Node.java | 13 +- .../opensearch/plugins/IdentityPlugin.java | 24 +++ .../org/opensearch/rest/RestController.java | 49 ++++- .../opensearch/action/ActionModuleTests.java | 2 + .../extensions/ExtensionsManagerTests.java | 3 +- .../opensearch/rest/RestControllerTests.java | 17 +- .../rest/RestHttpResponseHeadersTests.java | 4 +- .../indices/RestValidateQueryActionTests.java | 3 +- .../test/rest/RestActionTestCase.java | 12 +- 64 files changed, 2335 insertions(+), 20 deletions(-) create mode 100644 modules/identity-shiro/build.gradle create mode 100644 modules/identity-shiro/licenses/bcprov-jdk15on-1.70.jar.sha1 create mode 100644 modules/identity-shiro/licenses/bcprov-jdk15on-LICENSE.txt create mode 100644 modules/identity-shiro/licenses/bcprov-jdk15on-NOTICE.txt create mode 100644 modules/identity-shiro/licenses/commons-beanutils-1.9.4.jar.sha1 create mode 100644 modules/identity-shiro/licenses/commons-beanutils-LICENSE.txt create mode 100644 modules/identity-shiro/licenses/commons-beanutils-NOTICE.txt create mode 100644 modules/identity-shiro/licenses/commons-lang-2.6.jar.sha1 create mode 100644 modules/identity-shiro/licenses/commons-lang-LICENSE.txt create mode 100644 modules/identity-shiro/licenses/commons-lang-NOTICE.txt create mode 100644 modules/identity-shiro/licenses/commons-logging-1.2.jar.sha1 create mode 100644 modules/identity-shiro/licenses/commons-logging-LICENSE.txt create mode 100644 modules/identity-shiro/licenses/commons-logging-NOTICE.txt create mode 100644 modules/identity-shiro/licenses/shiro-core-1.9.1.jar.sha1 create mode 100644 modules/identity-shiro/licenses/shiro-core-LICENSE.txt create mode 100644 modules/identity-shiro/licenses/shiro-core-NOTICE.txt create mode 100644 modules/identity-shiro/licenses/slf4j-api-1.7.36.jar.sha1 create mode 100644 modules/identity-shiro/licenses/slf4j-api-LICENSE.txt create mode 100644 modules/identity-shiro/licenses/slf4j-api-NOTICE.txt create mode 100644 modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java create mode 100644 modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroIdentityPlugin.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/package-info.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcher.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/User.java create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/package-info.java create mode 100644 modules/identity-shiro/src/main/plugin-metadata/plugin-security.policy create mode 100644 modules/identity-shiro/src/test/java/org/opensearch/identity/AbstractIdentityTestCase.java create mode 100644 modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/AuthTokenHandlerTests.java create mode 100644 modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/ShiroSubjectTests.java create mode 100644 modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcherTests.java create mode 100644 modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/InternalRealmTests.java create mode 100644 server/src/main/java/org/opensearch/identity/IdentityService.java create mode 100644 server/src/main/java/org/opensearch/identity/Principals.java create mode 100644 server/src/main/java/org/opensearch/identity/StringPrincipal.java create mode 100644 server/src/main/java/org/opensearch/identity/Subject.java create mode 100644 server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java create mode 100644 server/src/main/java/org/opensearch/identity/noop/NoopSubject.java create mode 100644 server/src/main/java/org/opensearch/identity/noop/package-info.java create mode 100644 server/src/main/java/org/opensearch/identity/package-info.java create mode 100644 server/src/main/java/org/opensearch/identity/tokens/AuthToken.java create mode 100644 server/src/main/java/org/opensearch/identity/tokens/BasicAuthToken.java create mode 100644 server/src/main/java/org/opensearch/identity/tokens/RestTokenExtractor.java create mode 100644 server/src/main/java/org/opensearch/identity/tokens/package-info.java create mode 100644 server/src/main/java/org/opensearch/plugins/IdentityPlugin.java diff --git a/.gitignore b/.gitignore index 9ab7de894636a..00314eda7aff1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ out/ !.idea/vcs.xml !.idea/icon.svg -# These files are generated in the main tree by annotation processors +# These files are generated in the main tree by IntelliJ benchmarks/src/main/generated/* benchmarks/bin/* benchmarks/build-eclipse-default/* diff --git a/CHANGELOG.md b/CHANGELOG.md index de7839ee6e1db..367205c8578b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Add getter for path field in NestedQueryBuilder ([#4636](https://github.com/opensearch-project/OpenSearch/pull/4636)) - Allow mmap to use new JDK-19 preview APIs in Apache Lucene 9.4+ ([#5151](https://github.com/opensearch-project/OpenSearch/pull/5151)) - Add support for ppc64le architecture ([#5459](https://github.com/opensearch-project/OpenSearch/pull/5459)) +- Add support to disallow search request with preference parameter with strict weighted shard routing([#5874](https://github.com/opensearch-project/OpenSearch/pull/5874)) +- Add identity and access control extension point ([5925](https://github.com/opensearch-project/OpenSearch/pull/5925)) ### Dependencies +- Bumps `wiremock-jre8-standalone` from 2.33.2 to 2.35.0 +- Bumps `gson` from 2.10 to 2.10.1 +- Bumps `json-schema-validator` from 1.0.73 to 1.0.76 - Bumps `log4j-core` from 2.18.0 to 2.19.0 - Bumps `reactor-netty-http` from 1.0.18 to 1.0.23 - Bumps `jettison` from 1.5.0 to 1.5.3 diff --git a/gradle/missing-javadoc.gradle b/gradle/missing-javadoc.gradle index 98619f4722afa..9a25558ca829b 100644 --- a/gradle/missing-javadoc.gradle +++ b/gradle/missing-javadoc.gradle @@ -107,6 +107,7 @@ configure([ project(":modules:aggs-matrix-stats"), project(":modules:analysis-common"), project(":modules:geo"), + project(":modules:identity-shiro"), project(":modules:ingest-common"), project(":modules:ingest-geoip"), project(":modules:ingest-user-agent"), diff --git a/modules/identity-shiro/build.gradle b/modules/identity-shiro/build.gradle new file mode 100644 index 0000000000000..67e1dbafba043 --- /dev/null +++ b/modules/identity-shiro/build.gradle @@ -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. + */ + +apply plugin: 'opensearch.internal-cluster-test' + +opensearchplugin { + description 'Plugin for identity features in OpenSearch.' + classname 'org.opensearch.identity.shiro.ShiroIdentityPlugin' + name project.name + licenseFile rootProject.file('licenses/APACHE-LICENSE-2.0.txt') + noticeFile rootProject.file('NOTICE.txt') +} + +dependencies { + implementation 'org.apache.shiro:shiro-core:1.9.1' + // Needed for shiro + implementation "org.slf4j:slf4j-api:${versions.slf4j}" + + implementation 'commons-beanutils:commons-beanutils:1.9.4' + implementation 'commons-logging:commons-logging:1.2' + implementation 'commons-lang:commons-lang:2.6' + + implementation "org.bouncycastle:bcprov-jdk15on:${versions.bouncycastle}" + + testImplementation project(path: ':modules:transport-netty4') // for http + testImplementation project(path: ':plugins:transport-nio') // for http + testImplementation "org.mockito:mockito-core:${versions.mockito}" +} + +/* + * We have to disable setting the number of available processors as tests in the same JVM randomize processors and will step on each + * other if we allow them to set the number of available processors as it's set-once in Netty. + */ +test { + systemProperty 'opensearch.set.netty.runtime.available.processors', 'false' +} + +internalClusterTest { + systemProperty 'opensearch.set.netty.runtime.available.processors', 'false' +} + +thirdPartyAudit.ignoreMissingClasses( + 'javax.servlet.ServletContextEvent', + 'javax.servlet.ServletContextListener', + 'org.apache.avalon.framework.logger.Logger', + 'org.apache.commons.collections.Closure', + 'org.apache.commons.collections.FastHashMap', + 'org.apache.commons.collections.Predicate', + 'org.apache.commons.collections.Transformer', + 'org.apache.commons.collections.comparators.ComparableComparator', + 'org.apache.commons.collections.keyvalue.AbstractMapEntry', + 'org.apache.commons.configuration2.interpol.ConfigurationInterpolator', + 'org.apache.log.Hierarchy', + 'org.apache.log.Logger', + 'org.apache.log4j.Level', + 'org.apache.log4j.Logger', + 'org.apache.log4j.Priority', + 'org.slf4j.impl.StaticLoggerBinder', + 'org.slf4j.impl.StaticMDCBinder', + 'org.slf4j.impl.StaticMarkerBinder' +) diff --git a/modules/identity-shiro/licenses/bcprov-jdk15on-1.70.jar.sha1 b/modules/identity-shiro/licenses/bcprov-jdk15on-1.70.jar.sha1 new file mode 100644 index 0000000000000..f5e89c0f5ed45 --- /dev/null +++ b/modules/identity-shiro/licenses/bcprov-jdk15on-1.70.jar.sha1 @@ -0,0 +1 @@ +4636a0d01f74acaf28082fb62b317f1080118371 \ No newline at end of file diff --git a/modules/identity-shiro/licenses/bcprov-jdk15on-LICENSE.txt b/modules/identity-shiro/licenses/bcprov-jdk15on-LICENSE.txt new file mode 100644 index 0000000000000..9f27bafe96885 --- /dev/null +++ b/modules/identity-shiro/licenses/bcprov-jdk15on-LICENSE.txt @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2000 - 2013 The Legion of the Bouncy Castle Inc. + (http://www.bouncycastle.org) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/modules/identity-shiro/licenses/bcprov-jdk15on-NOTICE.txt b/modules/identity-shiro/licenses/bcprov-jdk15on-NOTICE.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/modules/identity-shiro/licenses/commons-beanutils-1.9.4.jar.sha1 b/modules/identity-shiro/licenses/commons-beanutils-1.9.4.jar.sha1 new file mode 100644 index 0000000000000..b91aa1e1d1f4f --- /dev/null +++ b/modules/identity-shiro/licenses/commons-beanutils-1.9.4.jar.sha1 @@ -0,0 +1 @@ +d52b9abcd97f38c81342bb7e7ae1eee9b73cba51 \ No newline at end of file diff --git a/modules/identity-shiro/licenses/commons-beanutils-LICENSE.txt b/modules/identity-shiro/licenses/commons-beanutils-LICENSE.txt new file mode 100644 index 0000000000000..d645695673349 --- /dev/null +++ b/modules/identity-shiro/licenses/commons-beanutils-LICENSE.txt @@ -0,0 +1,202 @@ + + 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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/modules/identity-shiro/licenses/commons-beanutils-NOTICE.txt b/modules/identity-shiro/licenses/commons-beanutils-NOTICE.txt new file mode 100644 index 0000000000000..e1529d40c6bb6 --- /dev/null +++ b/modules/identity-shiro/licenses/commons-beanutils-NOTICE.txt @@ -0,0 +1,5 @@ +Apache Commons BeanUtils +Copyright 2000-2019 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/modules/identity-shiro/licenses/commons-lang-2.6.jar.sha1 b/modules/identity-shiro/licenses/commons-lang-2.6.jar.sha1 new file mode 100644 index 0000000000000..4ee9249d2b76f --- /dev/null +++ b/modules/identity-shiro/licenses/commons-lang-2.6.jar.sha1 @@ -0,0 +1 @@ +0ce1edb914c94ebc388f086c6827e8bdeec71ac2 \ No newline at end of file diff --git a/modules/identity-shiro/licenses/commons-lang-LICENSE.txt b/modules/identity-shiro/licenses/commons-lang-LICENSE.txt new file mode 100644 index 0000000000000..d645695673349 --- /dev/null +++ b/modules/identity-shiro/licenses/commons-lang-LICENSE.txt @@ -0,0 +1,202 @@ + + 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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/modules/identity-shiro/licenses/commons-lang-NOTICE.txt b/modules/identity-shiro/licenses/commons-lang-NOTICE.txt new file mode 100644 index 0000000000000..780ac0edb3c94 --- /dev/null +++ b/modules/identity-shiro/licenses/commons-lang-NOTICE.txt @@ -0,0 +1,5 @@ +Apache Commons Lang +Copyright 2001-2022 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (https://www.apache.org/). diff --git a/modules/identity-shiro/licenses/commons-logging-1.2.jar.sha1 b/modules/identity-shiro/licenses/commons-logging-1.2.jar.sha1 new file mode 100644 index 0000000000000..f40f0242448e8 --- /dev/null +++ b/modules/identity-shiro/licenses/commons-logging-1.2.jar.sha1 @@ -0,0 +1 @@ +4bfc12adfe4842bf07b657f0369c4cb522955686 \ No newline at end of file diff --git a/modules/identity-shiro/licenses/commons-logging-LICENSE.txt b/modules/identity-shiro/licenses/commons-logging-LICENSE.txt new file mode 100644 index 0000000000000..d645695673349 --- /dev/null +++ b/modules/identity-shiro/licenses/commons-logging-LICENSE.txt @@ -0,0 +1,202 @@ + + 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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/modules/identity-shiro/licenses/commons-logging-NOTICE.txt b/modules/identity-shiro/licenses/commons-logging-NOTICE.txt new file mode 100644 index 0000000000000..1a45218353e87 --- /dev/null +++ b/modules/identity-shiro/licenses/commons-logging-NOTICE.txt @@ -0,0 +1,5 @@ +Apache Commons Logging +Copyright 2003-2016 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/modules/identity-shiro/licenses/shiro-core-1.9.1.jar.sha1 b/modules/identity-shiro/licenses/shiro-core-1.9.1.jar.sha1 new file mode 100644 index 0000000000000..8cd594d254f9b --- /dev/null +++ b/modules/identity-shiro/licenses/shiro-core-1.9.1.jar.sha1 @@ -0,0 +1 @@ +90263d749749198f0a6dbdca57b52fa6d903d3db \ No newline at end of file diff --git a/modules/identity-shiro/licenses/shiro-core-LICENSE.txt b/modules/identity-shiro/licenses/shiro-core-LICENSE.txt new file mode 100644 index 0000000000000..261eeb9e9f8b2 --- /dev/null +++ b/modules/identity-shiro/licenses/shiro-core-LICENSE.txt @@ -0,0 +1,201 @@ + 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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/modules/identity-shiro/licenses/shiro-core-NOTICE.txt b/modules/identity-shiro/licenses/shiro-core-NOTICE.txt new file mode 100644 index 0000000000000..1a356397fa88c --- /dev/null +++ b/modules/identity-shiro/licenses/shiro-core-NOTICE.txt @@ -0,0 +1,15 @@ +Apache Shiro +Copyright 2008-2022 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +The implementation for org.apache.shiro.util.SoftHashMap is based +on initial ideas from Dr. Heinz Kabutz's publicly posted version +available at http://www.javaspecialists.eu/archive/Issue015.html, +with continued modifications. + +Certain parts (StringUtils, IpAddressMatcher, AntPathMatcherTests, etc.) of the +source code for this product was copied for simplicity and to reduce +dependencies from the source code developed by the Spring Framework Project +(http://www.springframework.org). diff --git a/modules/identity-shiro/licenses/slf4j-api-1.7.36.jar.sha1 b/modules/identity-shiro/licenses/slf4j-api-1.7.36.jar.sha1 new file mode 100644 index 0000000000000..77b9917528382 --- /dev/null +++ b/modules/identity-shiro/licenses/slf4j-api-1.7.36.jar.sha1 @@ -0,0 +1 @@ +6c62681a2f655b49963a5983b8b0950a6120ae14 \ No newline at end of file diff --git a/modules/identity-shiro/licenses/slf4j-api-LICENSE.txt b/modules/identity-shiro/licenses/slf4j-api-LICENSE.txt new file mode 100644 index 0000000000000..8fda22f4d72f6 --- /dev/null +++ b/modules/identity-shiro/licenses/slf4j-api-LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) 2004-2014 QOS.ch +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/modules/identity-shiro/licenses/slf4j-api-NOTICE.txt b/modules/identity-shiro/licenses/slf4j-api-NOTICE.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java new file mode 100644 index 0000000000000..18ee40ed2d9f6 --- /dev/null +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java @@ -0,0 +1,71 @@ +/* + * 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.identity.shiro; + +import org.opensearch.client.Request; +import org.opensearch.client.RequestOptions; +import org.opensearch.client.Response; +import org.opensearch.client.ResponseException; +import org.opensearch.test.OpenSearchIntegTestCase; +import org.opensearch.test.OpenSearchIntegTestCase.ClusterScope; +import org.opensearch.rest.RestStatus; + +import java.nio.charset.StandardCharsets; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertThat; + +@ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, numDataNodes = 0) +public class BasicAuthenticationIT extends HttpSmokeTestCaseWithIdentity { + + public void testBasicAuthSuccess() throws Exception { + final Response response = createHealthRequest("Basic YWRtaW46YWRtaW4="); // admin:admin + final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); + + assertEquals(RestStatus.OK.getStatus(), response.getStatusLine().getStatusCode()); + assertThat(content, containsString("green")); + } + + public void testBasicAuthUnauthorized_invalidHeader() throws Exception { + final Response response = createHealthRequest("Basic aaaa"); // invalid + final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); + + assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); + assertThat(content, containsString("Illegally formed basic authorization header")); + } + + public void testBasicAuthUnauthorized_wrongPassword() throws Exception { + final Response response = createHealthRequest("Basic YWRtaW46aW52YWxpZFBhc3N3b3Jk"); // admin:invalidPassword + final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); + + assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); + } + + public void testBasicAuthUnauthorized_unknownUser() throws Exception { + final Response response = createHealthRequest("Basic dXNlcjpkb2VzTm90RXhpc3Q="); // user:doesNotExist + final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); + + assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); + } + + private Response createHealthRequest(final String authorizationHeaderValue) throws Exception { + final Request request = new Request("GET", "/_cluster/health"); + final RequestOptions options = RequestOptions.DEFAULT.toBuilder().addHeader("Authorization", authorizationHeaderValue).build(); + request.setOptions(options); + + try { + final Response response = getRestClient().performRequest(request); + return response; + } catch (final ResponseException re) { + return re.getResponse(); + } + } +} diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java new file mode 100644 index 0000000000000..7d29e8c160a5d --- /dev/null +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java @@ -0,0 +1,91 @@ +/* + * 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.identity.shiro; + +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; +import org.opensearch.common.network.NetworkModule; +import org.opensearch.common.settings.Settings; +import org.opensearch.plugins.Plugin; +import org.opensearch.test.OpenSearchIntegTestCase; +import org.opensearch.transport.Netty4ModulePlugin; +import org.opensearch.transport.nio.MockNioTransportPlugin; +import org.opensearch.transport.nio.NioTransportPlugin; +import org.junit.BeforeClass; +import org.opensearch.common.util.FeatureFlags; + +import java.util.Arrays; +import java.util.Collection; + +/** + * Abstract Rest Test Case installs and enables ShiroIdentityPlugin and removes mock + * http transport to enable REST requests against a test cluster + * + * @opensearch.experimental + */ +// TODO not sure why ThreadLeakScope.NONE is required +@ThreadLeakScope(ThreadLeakScope.Scope.NONE) +public abstract class HttpSmokeTestCaseWithIdentity extends OpenSearchIntegTestCase { + + private static String nodeTransportTypeKey; + private static String nodeHttpTypeKey; + private static String clientTypeKey; + + @SuppressWarnings("unchecked") + @BeforeClass + public static void setUpTransport() { + nodeTransportTypeKey = getTypeKey(randomFrom(getTestTransportPlugin(), Netty4ModulePlugin.class, NioTransportPlugin.class)); + nodeHttpTypeKey = getHttpTypeKey(randomFrom(Netty4ModulePlugin.class, NioTransportPlugin.class)); + clientTypeKey = getTypeKey(randomFrom(getTestTransportPlugin(), Netty4ModulePlugin.class, NioTransportPlugin.class)); + } + + private static String getTypeKey(Class clazz) { + if (clazz.equals(MockNioTransportPlugin.class)) { + return MockNioTransportPlugin.MOCK_NIO_TRANSPORT_NAME; + } else if (clazz.equals(NioTransportPlugin.class)) { + return NioTransportPlugin.NIO_TRANSPORT_NAME; + } else { + assert clazz.equals(Netty4ModulePlugin.class); + return Netty4ModulePlugin.NETTY_TRANSPORT_NAME; + } + } + + private static String getHttpTypeKey(Class clazz) { + if (clazz.equals(NioTransportPlugin.class)) { + return NioTransportPlugin.NIO_HTTP_TRANSPORT_NAME; + } else { + assert clazz.equals(Netty4ModulePlugin.class); + return Netty4ModulePlugin.NETTY_HTTP_TRANSPORT_NAME; + } + } + + @Override + protected boolean addMockHttpTransport() { + return false; // enable http + } + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.builder() + .put(super.nodeSettings(nodeOrdinal)) + .put(NetworkModule.TRANSPORT_TYPE_KEY, nodeTransportTypeKey) + .put(NetworkModule.HTTP_TYPE_KEY, nodeHttpTypeKey) + .put(FeatureFlags.IDENTITY, true) + .build(); + } + + @Override + protected Collection> nodePlugins() { + return Arrays.asList(getTestTransportPlugin(), Netty4ModulePlugin.class, NioTransportPlugin.class, ShiroIdentityPlugin.class); + } + + @Override + protected boolean ignoreExternalCluster() { + return true; + } +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java new file mode 100644 index 0000000000000..745b452136ebc --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java @@ -0,0 +1,41 @@ +/* + * 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.identity.shiro; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.opensearch.identity.tokens.BasicAuthToken; + +/** + * Extracts Shiro's {@link AuthenticationToken} from different types of auth headers + * + * @opensearch.experimental + */ +class AuthTokenHandler { + + private static final Logger logger = LogManager.getLogger(AuthTokenHandler.class); + + /** + * Translates shiro auth token from the given header token + * @param authenticationToken the token from which to translate + * @return the shiro auth token to be for login + */ + public AuthenticationToken translateAuthToken(org.opensearch.identity.tokens.AuthToken authenticationToken) { + final AuthenticationToken authToken = null; + + if (authenticationToken instanceof BasicAuthToken) { + final BasicAuthToken basicAuthToken = (BasicAuthToken) authenticationToken; + return new UsernamePasswordToken(basicAuthToken.getUser(), basicAuthToken.getPassword()); + } + + return authToken; + } +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroIdentityPlugin.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroIdentityPlugin.java new file mode 100644 index 0000000000000..d3a2c6d342d97 --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroIdentityPlugin.java @@ -0,0 +1,43 @@ +/* + * 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.identity.shiro; + +import org.opensearch.identity.Subject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.opensearch.plugins.IdentityPlugin; +import org.opensearch.common.settings.Settings; +import org.opensearch.plugins.Plugin; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.mgt.SecurityManager; + +/** + * Identity implementation with Shiro + * + * @opensearch.experimental + */ +public final class ShiroIdentityPlugin extends Plugin implements IdentityPlugin { + private Logger log = LogManager.getLogger(this.getClass()); + + private final Settings settings; + private final AuthTokenHandler authTokenHandler; + + public ShiroIdentityPlugin(final Settings settings) { + this.settings = settings; + authTokenHandler = new AuthTokenHandler(); + + SecurityManager securityManager = new ShiroSecurityManager(); + SecurityUtils.setSecurityManager(securityManager); + } + + @Override + public Subject getSubject() { + return new ShiroSubject(authTokenHandler, SecurityUtils.getSubject()); + } +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java new file mode 100644 index 0000000000000..d74af8fdc6902 --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.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.identity.shiro; + +import org.apache.shiro.subject.Subject; +import org.apache.shiro.mgt.DefaultSecurityManager; +import org.apache.shiro.mgt.SubjectDAO; +import org.opensearch.identity.shiro.realm.InternalRealm; + +/** + * OpenSearch specific security manager implementation + * + * @opensearch.experimental + */ +public class ShiroSecurityManager extends DefaultSecurityManager { + + /** + * Creates the security manager using a default realm and no session storage + */ + public ShiroSecurityManager() { + super(InternalRealm.INSTANCE); + + // By default shiro stores session information into a cache, there were performance + // issues with this sessions cache and so are defaulting to a stateless configuration + this.subjectDAO = new StatelessDAO(); + } + + /** + * + * @opensearch.experimental + */ + private static class StatelessDAO implements SubjectDAO { + public Subject save(final Subject s) { + return s; + } + + public void delete(final Subject s) {} + } +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java new file mode 100644 index 0000000000000..b46a03d0c5de5 --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java @@ -0,0 +1,64 @@ +/* + * 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.identity.shiro; + +import java.security.Principal; +import java.util.Objects; + +import org.opensearch.identity.Subject; +import org.opensearch.identity.tokens.AuthToken; + +/** + * Subject backed by Shiro + * + * @opensearch.experimental + */ +public class ShiroSubject implements Subject { + private final AuthTokenHandler authTokenHandler; + private final org.apache.shiro.subject.Subject shiroSubject; + + public ShiroSubject(final AuthTokenHandler authTokenHandler, final org.apache.shiro.subject.Subject subject) { + this.authTokenHandler = authTokenHandler; + this.shiroSubject = subject; + } + + @Override + public Principal getPrincipal() { + final Object o = shiroSubject.getPrincipal(); + if (o == null) return null; + if (o instanceof Principal) return (Principal) o; + return () -> o.toString(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + final Subject that = (Subject) obj; + return Objects.equals(getPrincipal(), that.getPrincipal()); + } + + @Override + public int hashCode() { + return Objects.hash(getPrincipal()); + } + + @Override + public String toString() { + return "ShiroSubject(principal=" + getPrincipal() + ")"; + } + + /** + * Logs the user in via authenticating the user against current Shiro realm + */ + public void login(AuthToken authenticationToken) { + final org.apache.shiro.authc.AuthenticationToken authToken = authTokenHandler.translateAuthToken(authenticationToken); + shiroSubject.login(authToken); + } +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/package-info.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/package-info.java new file mode 100644 index 0000000000000..49e276f11f660 --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/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. + */ + +/** + * Identity implementation using Shiro + */ +package org.opensearch.identity.shiro; diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcher.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcher.java new file mode 100644 index 0000000000000..ca73d7b85c235 --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcher.java @@ -0,0 +1,32 @@ +/* + * 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.identity.shiro.realm; + +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authc.credential.CredentialsMatcher; +import org.bouncycastle.crypto.generators.OpenBSDBCrypt; + +/** + * Password matcher for BCrypt + * + * @opensearch.experimental + */ +public class BCryptPasswordMatcher implements CredentialsMatcher { + + @Override + public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { + final UsernamePasswordToken userToken = (UsernamePasswordToken) token; + final String password = new String(userToken.getPassword()); + final String hashedCredentials = (String) info.getCredentials(); + return OpenBSDBCrypt.checkPassword(hashedCredentials, password.toCharArray()); + } + +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java new file mode 100644 index 0000000000000..f61e2c3aca70c --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java @@ -0,0 +1,107 @@ +/* + * 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.identity.shiro.realm; + +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.IncorrectCredentialsException; +import org.apache.shiro.authc.SimpleAuthenticationInfo; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authc.pam.UnsupportedTokenException; +import org.apache.shiro.realm.AuthenticatingRealm; +import org.apache.shiro.authc.UsernamePasswordToken; + +import org.opensearch.identity.StringPrincipal; + +import java.util.Objects; +import java.util.Map; + +/** + * Internal Realm is a custom realm using the internal OpenSearch IdP + * + * @opensearch.experimental + */ +public class InternalRealm extends AuthenticatingRealm { + private static final String DEFAULT_REALM_NAME = "internal"; + + public static final InternalRealm INSTANCE = new InternalRealm.Builder(DEFAULT_REALM_NAME).build(); + + private final String realmName; + + private Map internalUsers; + + private InternalRealm(final String realmName, final Map internalUsers) { + super(new BCryptPasswordMatcher()); + this.realmName = realmName; + this.internalUsers = internalUsers; + setAuthenticationTokenClass(UsernamePasswordToken.class); + } + + public static final class Builder { + private final String name; + + public Builder(final String name) { + this.name = Objects.requireNonNull(name); + } + + public InternalRealm build() { + // TODO: Replace hardcoded admin user / user map with an external provider + final User adminUser = new User(); + adminUser.setUsername(new StringPrincipal("admin")); + adminUser.setBcryptHash("$2a$12$VcCDgh2NDk07JGN0rjGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG"); // Password 'admin' + final Map internalUsers = Map.of("admin", adminUser); + return new InternalRealm(name, internalUsers); + } + } + + public User getInternalUser(final String principalIdentifier) throws UnknownAccountException { + final User userRecord = internalUsers.get(principalIdentifier); + if (userRecord == null) { + throw new UnknownAccountException(); + } + return userRecord; + } + + @Override + protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) throws AuthenticationException { + if (token instanceof UsernamePasswordToken) { + final String username = ((UsernamePasswordToken) token).getUsername(); + // Look up the user by the provide username + final User userRecord = getInternalUser(username); + // TODO: Check for other things, like a locked account, expired password, etc. + + // Verify the user + final SimpleAuthenticationInfo sai = new SimpleAuthenticationInfo( + userRecord.getUsername(), + userRecord.getBcryptHash(), + realmName + ); + + // TODO: Doesn't appear to check the password + final boolean successfulAuthentication = getCredentialsMatcher().doCredentialsMatch(token, sai); + + if (successfulAuthentication) { + // TODO: Check for anything else that might prevent login (expired password, locked account, etc.) + // if (other problems) { + // throw new CredentialsException(); // Or something more specific + // } + // Success! + return sai; + } else { + // Bad password + throw new IncorrectCredentialsException(); + } + } + + // If the token was not handled, it was unsupported + throw new UnsupportedTokenException("Unable to support authentication token " + token.getClass().getName()); + } +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/User.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/User.java new file mode 100644 index 0000000000000..162094c9d5d87 --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/User.java @@ -0,0 +1,38 @@ +/* + * 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.identity.shiro.realm; + +import org.opensearch.identity.StringPrincipal; + +/** + * A non-volatile and immutable object in the storage. + * + * @opensearch.experimental + */ +public class User { + + private StringPrincipal username; + private String bcryptHash; + + public StringPrincipal getUsername() { + return username; + } + + public void setUsername(StringPrincipal username) { + this.username = username; + } + + public String getBcryptHash() { + return bcryptHash; + } + + public void setBcryptHash(String bcryptHash) { + this.bcryptHash = bcryptHash; + } +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/package-info.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/package-info.java new file mode 100644 index 0000000000000..68ba6f2c3e90b --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/package-info.java @@ -0,0 +1,10 @@ +/* + * 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. + */ + +/** Classes for the internal OpenSearch realm */ +package org.opensearch.identity.realm; diff --git a/modules/identity-shiro/src/main/plugin-metadata/plugin-security.policy b/modules/identity-shiro/src/main/plugin-metadata/plugin-security.policy new file mode 100644 index 0000000000000..120d1d8fbdb3a --- /dev/null +++ b/modules/identity-shiro/src/main/plugin-metadata/plugin-security.policy @@ -0,0 +1,11 @@ +/* + * 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. + */ + +grant { + +}; diff --git a/modules/identity-shiro/src/test/java/org/opensearch/identity/AbstractIdentityTestCase.java b/modules/identity-shiro/src/test/java/org/opensearch/identity/AbstractIdentityTestCase.java new file mode 100644 index 0000000000000..b32145cdc2db8 --- /dev/null +++ b/modules/identity-shiro/src/test/java/org/opensearch/identity/AbstractIdentityTestCase.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.identity.shiro; + +import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; +import org.opensearch.common.settings.Settings; +import org.opensearch.common.util.FeatureFlags; +import org.opensearch.http.CorsHandler; +import org.opensearch.http.HttpTransportSettings; +import org.opensearch.plugins.Plugin; +import org.opensearch.test.OpenSearchIntegTestCase; +import org.opensearch.transport.Netty4ModulePlugin; + +import java.util.Collection; +import java.util.List; + +/** + * Base test case for integration tests against the identity plugin. + */ +@ThreadLeakScope(ThreadLeakScope.Scope.NONE) +public abstract class AbstractIdentityTestCase extends OpenSearchIntegTestCase { + + @Override + protected Collection> nodePlugins() { + return List.of(ShiroIdentityPlugin.class, Netty4ModulePlugin.class); + } + + @Override + protected boolean addMockHttpTransport() { + return false; // enable http + } + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.builder().put(super.nodeSettings(nodeOrdinal)).put(nodeSettings()).build(); + } + + final Settings nodeSettings() { + return Settings.builder() + .put(HttpTransportSettings.SETTING_CORS_ENABLED.getKey(), true) + .put(HttpTransportSettings.SETTING_CORS_ALLOW_ORIGIN.getKey(), CorsHandler.ANY_ORIGIN) + .put(HttpTransportSettings.SETTING_CORS_ALLOW_CREDENTIALS.getKey(), true) + .put(FeatureFlags.IDENTITY, true) + .build(); + } +} diff --git a/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/AuthTokenHandlerTests.java b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/AuthTokenHandlerTests.java new file mode 100644 index 0000000000000..0b4cd21737c38 --- /dev/null +++ b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/AuthTokenHandlerTests.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.identity.shiro; + +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.opensearch.identity.tokens.BasicAuthToken; +import org.opensearch.test.OpenSearchTestCase; +import org.junit.Before; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; + +public class AuthTokenHandlerTests extends OpenSearchTestCase { + + private AuthTokenHandler authTokenHandler; + + @Before + public void testSetup() { + authTokenHandler = new AuthTokenHandler(); + } + + public void testShouldExtractBasicAuthTokenSuccessfully() { + final BasicAuthToken authToken = new BasicAuthToken("Basic YWRtaW46YWRtaW4="); // admin:admin + + final AuthenticationToken translatedToken = authTokenHandler.translateAuthToken(authToken); + assertThat(translatedToken, is(instanceOf(UsernamePasswordToken.class))); + + final UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) translatedToken; + assertThat(usernamePasswordToken, notNullValue()); + assertThat(usernamePasswordToken.getUsername(), equalTo("admin")); + assertThat(new String(usernamePasswordToken.getPassword()), equalTo("admin")); + } + + public void testShouldExtractBasicAuthTokenSuccessfully_twoSemiColonPassword() { + final BasicAuthToken authToken = new BasicAuthToken("Basic dGVzdDp0ZTpzdA=="); // test:te:st + + final AuthenticationToken translatedToken = authTokenHandler.translateAuthToken(authToken); + assertThat(translatedToken, is(instanceOf(UsernamePasswordToken.class))); + + final UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) translatedToken; + assertThat(usernamePasswordToken, notNullValue()); + assertThat(usernamePasswordToken.getUsername(), equalTo("test")); + assertThat(new String(usernamePasswordToken.getPassword()), equalTo("te:st")); + } + + public void testShouldReturnNullWhenExtractingNullToken() { + final AuthenticationToken translatedToken = authTokenHandler.translateAuthToken(null); + + assertThat(translatedToken, nullValue()); + } +} diff --git a/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/ShiroSubjectTests.java b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/ShiroSubjectTests.java new file mode 100644 index 0000000000000..cbba23b070dfe --- /dev/null +++ b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/ShiroSubjectTests.java @@ -0,0 +1,75 @@ +/* + * 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.identity.shiro; + +import org.opensearch.test.OpenSearchTestCase; + +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import org.junit.Before; +import org.junit.After; + +import java.security.Principal; + +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.equalTo; + +public class ShiroSubjectTests extends OpenSearchTestCase { + + private org.apache.shiro.subject.Subject shiroSubject; + private AuthTokenHandler authTokenHandler; + private ShiroSubject subject; + + @Before + public void setup() { + shiroSubject = mock(org.apache.shiro.subject.Subject.class); + authTokenHandler = mock(AuthTokenHandler.class); + subject = new ShiroSubject(authTokenHandler, shiroSubject); + } + + @After + public void cleanup() { + verifyNoMoreInteractions(shiroSubject); + } + + public void testGetPrincipal_null() { + when(shiroSubject.getPrincipal()).thenReturn(null); + + final Principal result = subject.getPrincipal(); + + assertThat(result, nullValue()); + verify(shiroSubject).getPrincipal(); + } + + public void testGetPrincipal_principal() { + final Principal mockPrincipal = mock(Principal.class); + when(shiroSubject.getPrincipal()).thenReturn(mockPrincipal); + + final Principal result = subject.getPrincipal(); + + assertThat(result, equalTo(mockPrincipal)); + verify(shiroSubject).getPrincipal(); + } + + public void testGetPrincipal_otherType() { + final Object objPrincipal = mock(Object.class); + when(shiroSubject.getPrincipal()).thenReturn(objPrincipal); + when(objPrincipal.toString()).thenReturn("objectPrincipalString"); + + final Principal result = subject.getPrincipal(); + + // assertThat(result, equalTo("objectPrincipalString")); + verify(shiroSubject).getPrincipal(); + verifyNoMoreInteractions(objPrincipal); + } + +} diff --git a/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcherTests.java b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcherTests.java new file mode 100644 index 0000000000000..07a4c05bbc8da --- /dev/null +++ b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcherTests.java @@ -0,0 +1,46 @@ +/* + * 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.identity.shiro.realm; + +import org.opensearch.test.OpenSearchTestCase; + +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.hamcrest.Matchers.equalTo; + +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authc.AuthenticationInfo; + +public class BCryptPasswordMatcherTests extends OpenSearchTestCase { + + public void testCredentialMatch() { + final UsernamePasswordToken token = mock(UsernamePasswordToken.class); + when(token.getPassword()).thenReturn("admin".toCharArray()); + final AuthenticationInfo info = mock(AuthenticationInfo.class); + when(info.getCredentials()).thenReturn("$2a$12$VcCDgh2NDk07JGN0rjGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG"); + + final BCryptPasswordMatcher matcher = new BCryptPasswordMatcher(); + final boolean result = matcher.doCredentialsMatch(token, info); + + assertThat(result, equalTo(true)); + } + + public void testCredentialDoNotMatch() { + final UsernamePasswordToken token = mock(UsernamePasswordToken.class); + when(token.getPassword()).thenReturn("HashedPassword".toCharArray()); + final AuthenticationInfo info = mock(AuthenticationInfo.class); + when(info.getCredentials()).thenReturn("$2a$12$VcCDgh2NDk07JGN0rQGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG"); + + final BCryptPasswordMatcher matcher = new BCryptPasswordMatcher(); + final boolean result = matcher.doCredentialsMatch(token, info); + + assertThat(result, equalTo(false)); + } +} diff --git a/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/InternalRealmTests.java b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/InternalRealmTests.java new file mode 100644 index 0000000000000..1ed32a9484210 --- /dev/null +++ b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/InternalRealmTests.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.identity.shiro.realm; + +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.IncorrectCredentialsException; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.junit.Before; +import org.opensearch.test.OpenSearchTestCase; + +public class InternalRealmTests extends OpenSearchTestCase { + + private InternalRealm realm; + + @Before + public void setup() { + realm = new InternalRealm.Builder("test").build(); + } + + public void testGetAuthenticationInfoUserExists() { + final UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin"); + final User admin = realm.getInternalUser("admin"); + final AuthenticationInfo adminInfo = realm.getAuthenticationInfo(token); + assertNotNull(adminInfo); + } + + public void testGetAuthenticationInfoUserExistsWrongPassword() { + final UsernamePasswordToken token = new UsernamePasswordToken("admin", "wrong_password"); + final User admin = realm.getInternalUser("admin"); + + assertThrows(IncorrectCredentialsException.class, () -> realm.getAuthenticationInfo(token)); + } +} diff --git a/sandbox/modules/build.gradle b/sandbox/modules/build.gradle index 61afb2c568e1b..7021a36a6b7fc 100644 --- a/sandbox/modules/build.gradle +++ b/sandbox/modules/build.gradle @@ -7,13 +7,22 @@ */ configure(subprojects.findAll { it.parent.path == project.path }) { - group = 'org.opensearch.sandbox' + group = 'org.opensearch.sandbox.plugin' // for modules which publish client jars apply plugin: 'opensearch.testclusters' apply plugin: 'opensearch.opensearchplugin' opensearchplugin { + // for local OpenSearch plugins, the name of the plugin is the same as the directory name project.name - licenseFile rootProject.file('licenses/APACHE-LICENSE-2.0.txt') - noticeFile rootProject.file('NOTICE.txt') + } + + if (project.file('src/main/packaging').exists()) { + throw new InvalidModelException("Modules cannot contain packaging files") + } + if (project.file('src/main/bin').exists()) { + throw new InvalidModelException("Modules cannot contain bin files") + } + if (project.file('src/main/config').exists()) { + throw new InvalidModelException("Modules cannot contain config files") } } diff --git a/server/src/main/java/org/opensearch/action/ActionModule.java b/server/src/main/java/org/opensearch/action/ActionModule.java index bba3aabdd61f9..d1df6cd9953b0 100644 --- a/server/src/main/java/org/opensearch/action/ActionModule.java +++ b/server/src/main/java/org/opensearch/action/ActionModule.java @@ -287,6 +287,7 @@ import org.opensearch.common.settings.SettingsFilter; import org.opensearch.common.util.FeatureFlags; import org.opensearch.index.seqno.RetentionLeaseActions; +import org.opensearch.identity.IdentityService; import org.opensearch.indices.SystemIndices; import org.opensearch.indices.breaker.CircuitBreakerService; import org.opensearch.persistent.CompletionPersistentTaskAction; @@ -488,7 +489,8 @@ public ActionModule( NodeClient nodeClient, CircuitBreakerService circuitBreakerService, UsageService usageService, - SystemIndices systemIndices + SystemIndices systemIndices, + IdentityService identityService ) { this.settings = settings; this.indexNameExpressionResolver = indexNameExpressionResolver; @@ -523,7 +525,7 @@ public ActionModule( actionPlugins.stream().flatMap(p -> p.indicesAliasesRequestValidators().stream()).collect(Collectors.toList()) ); - restController = new RestController(headers, restWrapper, nodeClient, circuitBreakerService, usageService); + restController = new RestController(headers, restWrapper, nodeClient, circuitBreakerService, usageService, identityService); } public Map> getActions() { diff --git a/server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java b/server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java index 8fb6cd115f24b..96088115e48ab 100644 --- a/server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java @@ -37,7 +37,8 @@ protected FeatureFlagSettings( FeatureFlags.REPLICATION_TYPE_SETTING, FeatureFlags.REMOTE_STORE_SETTING, FeatureFlags.SEARCHABLE_SNAPSHOT_SETTING, - FeatureFlags.EXTENSIONS_SETTING + FeatureFlags.EXTENSIONS_SETTING, + FeatureFlags.IDENTITY_SETTING ) ) ); diff --git a/server/src/main/java/org/opensearch/common/util/FeatureFlags.java b/server/src/main/java/org/opensearch/common/util/FeatureFlags.java index 72b7349180bad..b7462422775df 100644 --- a/server/src/main/java/org/opensearch/common/util/FeatureFlags.java +++ b/server/src/main/java/org/opensearch/common/util/FeatureFlags.java @@ -54,6 +54,11 @@ public class FeatureFlags { */ public static final String EXTENSIONS = "opensearch.experimental.feature.extensions.enabled"; + /** + * Gates the functionality of identity. + */ + public static final String IDENTITY = "opensearch.experimental.feature.identity.enabled"; + /** * Should store the settings from opensearch.yml. */ @@ -89,4 +94,6 @@ public static boolean isEnabled(String featureFlagName) { public static final Setting SEARCHABLE_SNAPSHOT_SETTING = Setting.boolSetting(SEARCHABLE_SNAPSHOT, false, Property.NodeScope); public static final Setting EXTENSIONS_SETTING = Setting.boolSetting(EXTENSIONS, false, Property.NodeScope); + + public static final Setting IDENTITY_SETTING = Setting.boolSetting(IDENTITY, false, Property.NodeScope); } diff --git a/server/src/main/java/org/opensearch/identity/IdentityService.java b/server/src/main/java/org/opensearch/identity/IdentityService.java new file mode 100644 index 0000000000000..d262b7018f43b --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/IdentityService.java @@ -0,0 +1,52 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.identity; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.opensearch.OpenSearchException; +import org.opensearch.identity.noop.NoopIdentityPlugin; +import java.util.List; +import org.opensearch.common.settings.Settings; +import org.opensearch.plugins.IdentityPlugin; +import java.util.stream.Collectors; + +/** + * Identity and access control for OpenSearch. + * + * @opensearch.experimental + * */ +public class IdentityService { + private static final Logger logger = LogManager.getLogger(IdentityService.class); + + private final Settings settings; + private final IdentityPlugin identityPlugin; + + public IdentityService(final Settings settings, final List identityPlugins) { + this.settings = settings; + + if (identityPlugins.size() == 0) { + identityPlugin = new NoopIdentityPlugin(); + } else if (identityPlugins.size() == 1) { + identityPlugin = identityPlugins.get(0); + } else { + throw new OpenSearchException( + "Multiple identity plugins are not supported, found: " + + identityPlugins.stream().map(Object::getClass).map(Class::getName).collect(Collectors.joining(",")) + ); + } + + logger.info("Identity module loaded with " + identityPlugin.getClass().getName()); + logger.info("Current subject " + getSubject()); + } + + /** + * Gets the current subject + */ + public Subject getSubject() { + return identityPlugin.getSubject(); + } +} diff --git a/server/src/main/java/org/opensearch/identity/Principals.java b/server/src/main/java/org/opensearch/identity/Principals.java new file mode 100644 index 0000000000000..7ce662425cb0e --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/Principals.java @@ -0,0 +1,35 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.identity; + +import java.security.Principal; + +/** + * Available OpenSearch internal principals + * + * @opensearch.experimental + */ +public enum Principals { + + /** + * Represents a principal which has not been authenticated + */ + UNAUTHENTICATED(new StringPrincipal("Unauthenticated")); + + private final Principal principal; + + Principals(final Principal principal) { + this.principal = principal; + } + + /** + * Returns the underlying principal for this + */ + public Principal getPrincipal() { + return principal; + } + +} diff --git a/server/src/main/java/org/opensearch/identity/StringPrincipal.java b/server/src/main/java/org/opensearch/identity/StringPrincipal.java new file mode 100644 index 0000000000000..a3d0b49f7863a --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/StringPrincipal.java @@ -0,0 +1,50 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.identity; + +import java.security.Principal; +import java.util.Objects; + +/** + * Create a principal from a string + * + * @opensearch.experimental + */ +public class StringPrincipal implements Principal { + + private final String name; + + /** + * Creates a principal for an identity specified as a string + * @param name A persistent string that represent an identity + */ + public StringPrincipal(final String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + final Principal that = (Principal) obj; + return Objects.equals(name, that.getName()); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + + @Override + public String toString() { + return "StringPrincipal(" + "name=" + name + ")"; + } +} diff --git a/server/src/main/java/org/opensearch/identity/Subject.java b/server/src/main/java/org/opensearch/identity/Subject.java new file mode 100644 index 0000000000000..8d20f99a246e8 --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/Subject.java @@ -0,0 +1,32 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.identity; + +import org.opensearch.identity.tokens.AuthToken; + +import java.security.Principal; + +/** + * An individual, process, or device that causes information to flow among objects or change to the system state. + * + * @opensearch.experimental + */ +public interface Subject { + + /** + * Get the application-wide uniquely identifying principal + * */ + Principal getPrincipal(); + + /** + * Login through an authentication token + * throws UnsupportedAuthenticationMethod + * throws InvalidAuthenticationToken + * throws SubjectNotFound + * throws SubjectDisabled + */ + void login(final AuthToken token); +} diff --git a/server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java b/server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java new file mode 100644 index 0000000000000..e4d17a8c2a25d --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java @@ -0,0 +1,28 @@ +/* + * 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.identity.noop; + +import org.opensearch.plugins.IdentityPlugin; +import org.opensearch.identity.Subject; + +/** + * Implementation of identity plugin that does not enforce authentication or authorization + * + * This class and related classes in this package will not return nulls or fail access checks + * + * @opensearch.internal + */ +public class NoopIdentityPlugin implements IdentityPlugin { + + @Override + public Subject getSubject() { + return new NoopSubject(); + } + +} diff --git a/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java b/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java new file mode 100644 index 0000000000000..c2c95dea7f1c6 --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/noop/NoopSubject.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.identity.noop; + +import java.security.Principal; +import java.util.Objects; + +import org.opensearch.identity.tokens.AuthToken; +import org.opensearch.identity.Subject; +import org.opensearch.identity.Principals; + +/** + * Implementation of subject that is always authenticated + * + * This class and related classes in this package will not return nulls or fail permissions checks + * + * @opensearch.internal + */ +public class NoopSubject implements Subject { + + @Override + public Principal getPrincipal() { + return Principals.UNAUTHENTICATED.getPrincipal(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Subject that = (Subject) obj; + return Objects.equals(getPrincipal(), that.getPrincipal()); + } + + @Override + public int hashCode() { + return Objects.hash(getPrincipal()); + } + + @Override + public String toString() { + return "NoopSubject(principal=" + getPrincipal() + ")"; + } + + /** + * Logs the user in + */ + @Override + public void login(AuthToken AuthToken) { + // Do nothing as noop subject is always logged in + } +} diff --git a/server/src/main/java/org/opensearch/identity/noop/package-info.java b/server/src/main/java/org/opensearch/identity/noop/package-info.java new file mode 100644 index 0000000000000..fcdd70db7f020 --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/noop/package-info.java @@ -0,0 +1,10 @@ +/* + * 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. + */ + +/** Classes for the noop authentication in OpenSearch */ +package org.opensearch.identity.noop; diff --git a/server/src/main/java/org/opensearch/identity/package-info.java b/server/src/main/java/org/opensearch/identity/package-info.java new file mode 100644 index 0000000000000..4693206af62a5 --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/package-info.java @@ -0,0 +1,7 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/** Core identity and access controls for OpenSearch */ +package org.opensearch.identity; diff --git a/server/src/main/java/org/opensearch/identity/tokens/AuthToken.java b/server/src/main/java/org/opensearch/identity/tokens/AuthToken.java new file mode 100644 index 0000000000000..6e113f6eaa96a --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/tokens/AuthToken.java @@ -0,0 +1,18 @@ +/* + * 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.identity.tokens; + +/** + * Interface for all token formats to support to authenticate user such as UserName/Password tokens, Access tokens, and more. + * + * @opensearch.experimental + */ +public interface AuthToken { + +} diff --git a/server/src/main/java/org/opensearch/identity/tokens/BasicAuthToken.java b/server/src/main/java/org/opensearch/identity/tokens/BasicAuthToken.java new file mode 100644 index 0000000000000..e5000cb3d6965 --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/tokens/BasicAuthToken.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.identity.tokens; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +/** + * Basic (Base64 encoded) Authentication Token in a http request header + */ +public final class BasicAuthToken implements AuthToken { + + public final static String TOKEN_IDENIFIER = "Basic"; + + private String user; + private String password; + + public BasicAuthToken(final String headerValue) { + final String base64Encoded = headerValue.substring(TOKEN_IDENIFIER.length()).trim(); + final byte[] rawDecoded = Base64.getDecoder().decode(base64Encoded); + final String usernamepassword = new String(rawDecoded, StandardCharsets.UTF_8); + + final String[] tokenParts = usernamepassword.split(":", 2); + if (tokenParts.length != 2) { + throw new IllegalStateException("Illegally formed basic authorization header " + tokenParts[0]); + } + user = tokenParts[0]; + password = tokenParts[1]; + } + + public String getUser() { + return user; + } + + public String getPassword() { + return password; + } +} diff --git a/server/src/main/java/org/opensearch/identity/tokens/RestTokenExtractor.java b/server/src/main/java/org/opensearch/identity/tokens/RestTokenExtractor.java new file mode 100644 index 0000000000000..844d1295c56b5 --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/tokens/RestTokenExtractor.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.identity.tokens; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.opensearch.common.Strings; +import org.opensearch.rest.RestRequest; + +import java.util.Collections; +import java.util.Optional; + +/** + * Extracts tokens from RestRequests used for authentication + */ +public class RestTokenExtractor { + + private static final Logger logger = LogManager.getLogger(RestTokenExtractor.class); + + public final static String AUTH_HEADER_NAME = "Authorization"; + + /** + * Given a rest request it will extract authentication token + * + * If no token was found, returns null. + */ + public static AuthToken extractToken(final RestRequest request) { + + // Extract authentication information from headers + final Optional authHeaderValue = request.getHeaders() + .getOrDefault(AUTH_HEADER_NAME, Collections.emptyList()) + .stream() + .findFirst(); + + if (authHeaderValue.isPresent()) { + final String authHeaderValueStr = authHeaderValue.get(); + + if (authHeaderValueStr.startsWith(BasicAuthToken.TOKEN_IDENIFIER)) { + return new BasicAuthToken(authHeaderValueStr); + } else { + if (logger.isDebugEnabled()) { + String tokenTypeTruncated = Strings.substring(authHeaderValueStr, 0, 5); + logger.debug("An authentication header was detected but the token type was not supported " + tokenTypeTruncated); + } + } + } + + logger.trace("No auth token could be extracted"); + return null; + } +} \ No newline at end of file diff --git a/server/src/main/java/org/opensearch/identity/tokens/package-info.java b/server/src/main/java/org/opensearch/identity/tokens/package-info.java new file mode 100644 index 0000000000000..b63ea40c61659 --- /dev/null +++ b/server/src/main/java/org/opensearch/identity/tokens/package-info.java @@ -0,0 +1,10 @@ +/* + * 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. + */ + +/** Classes for the authentication tokens in OpenSearch */ +package org.opensearch.identity.tokens; diff --git a/server/src/main/java/org/opensearch/node/Node.java b/server/src/main/java/org/opensearch/node/Node.java index ca27c639bec09..feafe50f56df4 100644 --- a/server/src/main/java/org/opensearch/node/Node.java +++ b/server/src/main/java/org/opensearch/node/Node.java @@ -132,6 +132,7 @@ import org.opensearch.gateway.MetaStateService; import org.opensearch.gateway.PersistedClusterStateService; import org.opensearch.http.HttpServerTransport; +import org.opensearch.identity.IdentityService; import org.opensearch.index.IndexSettings; import org.opensearch.index.analysis.AnalysisRegistry; import org.opensearch.index.engine.EngineFactory; @@ -164,6 +165,7 @@ import org.opensearch.plugins.ClusterPlugin; import org.opensearch.plugins.DiscoveryPlugin; import org.opensearch.plugins.EnginePlugin; +import org.opensearch.plugins.IdentityPlugin; import org.opensearch.plugins.IndexStorePlugin; import org.opensearch.plugins.IngestPlugin; import org.opensearch.plugins.MapperPlugin; @@ -433,6 +435,13 @@ protected Node( // Ensure to initialize Feature Flags via the settings from opensearch.yml FeatureFlags.initializeFeatureFlags(settings); + final List identityPlugins = new ArrayList<>(); + if (FeatureFlags.isEnabled(FeatureFlags.IDENTITY)) { + // If identity is enabled load plugins implementing the extension point + identityPlugins.addAll(pluginsService.filterPlugins(IdentityPlugin.class)); + } + final IdentityService identityService = new IdentityService(settings, identityPlugins); + if (FeatureFlags.isEnabled(FeatureFlags.EXTENSIONS)) { this.extensionsManager = new ExtensionsManager(tmpSettings, initialEnvironment.extensionDir()); } else { @@ -782,7 +791,8 @@ protected Node( client, circuitBreakerService, usageService, - systemIndices + systemIndices, + identityService ); modules.add(actionModule); @@ -1081,6 +1091,7 @@ protected Node( b.bind(ShardLimitValidator.class).toInstance(shardLimitValidator); b.bind(FsHealthService.class).toInstance(fsHealthService); b.bind(SystemIndices.class).toInstance(systemIndices); + b.bind(IdentityService.class).toInstance(identityService); }); injector = modules.createInjector(); diff --git a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java new file mode 100644 index 0000000000000..a8855eb1727ea --- /dev/null +++ b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java @@ -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. + */ + +package org.opensearch.plugins; + +import org.opensearch.identity.Subject; + +/** + * Plugin that provides identity and access control for OpenSearch + * + * @opensearch.experimental + */ +public interface IdentityPlugin { + + /** + * Get the current subject + * */ + public Subject getSubject(); +} diff --git a/server/src/main/java/org/opensearch/rest/RestController.java b/server/src/main/java/org/opensearch/rest/RestController.java index 78bebcb9a0af1..ecfa6b9f3e0c6 100644 --- a/server/src/main/java/org/opensearch/rest/RestController.java +++ b/server/src/main/java/org/opensearch/rest/RestController.java @@ -46,10 +46,15 @@ import org.opensearch.common.logging.DeprecationLogger; import org.opensearch.common.path.PathTrie; import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.common.util.FeatureFlags; import org.opensearch.common.xcontent.XContentBuilder; import org.opensearch.common.xcontent.XContentType; import org.opensearch.core.internal.io.Streams; import org.opensearch.http.HttpServerTransport; +import org.opensearch.identity.IdentityService; +import org.opensearch.identity.Subject; +import org.opensearch.identity.tokens.AuthToken; +import org.opensearch.identity.tokens.RestTokenExtractor; import org.opensearch.indices.breaker.CircuitBreakerService; import org.opensearch.usage.UsageService; @@ -110,13 +115,15 @@ public class RestController implements HttpServerTransport.Dispatcher { /** Rest headers that are copied to internal requests made during a rest request. */ private final Set headersToCopy; private final UsageService usageService; + private final IdentityService identityService; public RestController( Set headersToCopy, UnaryOperator handlerWrapper, NodeClient client, CircuitBreakerService circuitBreakerService, - UsageService usageService + UsageService usageService, + IdentityService identityService ) { this.headersToCopy = headersToCopy; this.usageService = usageService; @@ -126,6 +133,7 @@ public RestController( this.handlerWrapper = handlerWrapper; this.client = client; this.circuitBreakerService = circuitBreakerService; + this.identityService = identityService; registerHandlerNoWrap( RestRequest.Method.GET, "/favicon.ico", @@ -395,6 +403,9 @@ private void tryAllHandlers(final RestRequest request, final RestChannel channel return; } } else { + if (!handleAuthenticateUser(request, channel)) { + return; + } dispatchRequest(request, channel, handler); return; } @@ -505,6 +516,42 @@ private void handleBadRequest(String uri, RestRequest.Method method, RestChannel } } + /** + * Attempts to extracts auth token and login. + * + * @returns false if there was an error and the request should not continue being dispatched + * */ + private boolean handleAuthenticateUser(final RestRequest request, final RestChannel channel) { + if (!FeatureFlags.isEnabled(FeatureFlags.IDENTITY)) { + return true; + } + + try { + final AuthToken token = RestTokenExtractor.extractToken(request); + // If no token was found, continue executing the request + if (token == null) { + return true; + } + final Subject currentSubject = identityService.getSubject(); + currentSubject.login(token); + logger.info("Logged in as user " + currentSubject); + } catch (final Exception e) { + try { + final BytesRestResponse bytesRestResponse = BytesRestResponse.createSimpleErrorResponse( + channel, + RestStatus.UNAUTHORIZED, + e.getMessage() + ); + channel.sendResponse(bytesRestResponse); + } catch (final Exception _ignored) { + // TODO: clean this up + } + return false; + } + + return true; + } + /** * Get the valid set of HTTP methods for a REST request. */ diff --git a/server/src/test/java/org/opensearch/action/ActionModuleTests.java b/server/src/test/java/org/opensearch/action/ActionModuleTests.java index 3193a8d953763..dcc5b5f02ce4a 100644 --- a/server/src/test/java/org/opensearch/action/ActionModuleTests.java +++ b/server/src/test/java/org/opensearch/action/ActionModuleTests.java @@ -192,6 +192,7 @@ public String getName() { null, null, usageService, + null, null ); Exception e = expectThrows(IllegalArgumentException.class, () -> actionModule.initRestHandlers(null)); @@ -241,6 +242,7 @@ public List getRestHandlers( null, null, usageService, + null, null ); actionModule.initRestHandlers(null); diff --git a/server/src/test/java/org/opensearch/extensions/ExtensionsManagerTests.java b/server/src/test/java/org/opensearch/extensions/ExtensionsManagerTests.java index 05ff119cbe082..6be6fde43f850 100644 --- a/server/src/test/java/org/opensearch/extensions/ExtensionsManagerTests.java +++ b/server/src/test/java/org/opensearch/extensions/ExtensionsManagerTests.java @@ -163,7 +163,8 @@ public void setup() throws Exception { null, new NodeClient(Settings.EMPTY, threadPool), new NoneCircuitBreakerService(), - new UsageService() + new UsageService(), + new IdentityService(Settings.EMPTY, List.of()); ); settingsModule = new SettingsModule(Settings.EMPTY, emptyList(), emptyList(), emptySet()); clusterService = createClusterService(threadPool); diff --git a/server/src/test/java/org/opensearch/rest/RestControllerTests.java b/server/src/test/java/org/opensearch/rest/RestControllerTests.java index 03f6b7fca748e..110e83fb89ef1 100644 --- a/server/src/test/java/org/opensearch/rest/RestControllerTests.java +++ b/server/src/test/java/org/opensearch/rest/RestControllerTests.java @@ -92,6 +92,7 @@ public class RestControllerTests extends OpenSearchTestCase { private RestController restController; private HierarchyCircuitBreakerService circuitBreakerService; private UsageService usageService; + private IdentityService identityService; private NodeClient client; @Before @@ -109,9 +110,11 @@ public void setup() { // we can do this here only because we know that we don't adjust breaker settings dynamically in the test inFlightRequestsBreaker = circuitBreakerService.getBreaker(CircuitBreaker.IN_FLIGHT_REQUESTS); + identityService = new IdentityService(Settings.EMPTY, List.of()); + HttpServerTransport httpServerTransport = new TestHttpServerTransport(); client = new NoOpNodeClient(this.getTestName()); - restController = new RestController(Collections.emptySet(), null, client, circuitBreakerService, usageService); + restController = new RestController(Collections.emptySet(), null, client, circuitBreakerService, usageService, identityService); restController.registerHandler( RestRequest.Method.GET, "/", @@ -138,7 +141,7 @@ public void testApplyRelevantHeaders() throws Exception { Set headers = new HashSet<>( Arrays.asList(new RestHeaderDefinition("header.1", true), new RestHeaderDefinition("header.2", true)) ); - final RestController restController = new RestController(headers, null, null, circuitBreakerService, usageService); + final RestController restController = new RestController(headers, null, null, circuitBreakerService, usageService, identityService); Map> restHeaders = new HashMap<>(); restHeaders.put("header.1", Collections.singletonList("true")); restHeaders.put("header.2", Collections.singletonList("true")); @@ -174,7 +177,7 @@ public void testRequestWithDisallowedMultiValuedHeader() { Set headers = new HashSet<>( Arrays.asList(new RestHeaderDefinition("header.1", true), new RestHeaderDefinition("header.2", false)) ); - final RestController restController = new RestController(headers, null, null, circuitBreakerService, usageService); + final RestController restController = new RestController(headers, null, null, circuitBreakerService, usageService, identityService); Map> restHeaders = new HashMap<>(); restHeaders.put("header.1", Collections.singletonList("boo")); restHeaders.put("header.2", Arrays.asList("foo", "bar")); @@ -189,7 +192,7 @@ public void testRequestWithDisallowedMultiValuedHeaderButSameValues() { Set headers = new HashSet<>( Arrays.asList(new RestHeaderDefinition("header.1", true), new RestHeaderDefinition("header.2", false)) ); - final RestController restController = new RestController(headers, null, client, circuitBreakerService, usageService); + final RestController restController = new RestController(headers, null, client, circuitBreakerService, usageService, identityService); Map> restHeaders = new HashMap<>(); restHeaders.put("header.1", Collections.singletonList("boo")); restHeaders.put("header.2", Arrays.asList("foo", "foo")); @@ -250,7 +253,7 @@ public void testRegisterWithDeprecatedHandler() { } public void testRegisterSecondMethodWithDifferentNamedWildcard() { - final RestController restController = new RestController(null, null, null, circuitBreakerService, usageService); + final RestController restController = new RestController(null, null, null, circuitBreakerService, usageService, identityService); RestRequest.Method firstMethod = randomFrom(RestRequest.Method.values()); RestRequest.Method secondMethod = randomFrom( @@ -278,7 +281,7 @@ public void testRestHandlerWrapper() throws Exception { final RestController restController = new RestController(Collections.emptySet(), h -> { assertSame(handler, h); return (RestRequest request, RestChannel channel, NodeClient client) -> wrapperCalled.set(true); - }, client, circuitBreakerService, usageService); + }, client, circuitBreakerService, usageServic, identityService); restController.registerHandler(RestRequest.Method.GET, "/wrapped", handler); RestRequest request = testRestRequest("/wrapped", "{}", XContentType.JSON); AssertingChannel channel = new AssertingChannel(request, true, RestStatus.BAD_REQUEST); @@ -341,7 +344,7 @@ public void testDispatchRequiresContentTypeForRequestsWithContent() { String content = randomAlphaOfLength((int) Math.round(BREAKER_LIMIT.getBytes() / inFlightRequestsBreaker.getOverhead())); RestRequest request = testRestRequest("/", content, null); AssertingChannel channel = new AssertingChannel(request, true, RestStatus.NOT_ACCEPTABLE); - restController = new RestController(Collections.emptySet(), null, null, circuitBreakerService, usageService); + restController = new RestController(Collections.emptySet(), null, null, circuitBreakerService, usageService, identityService); restController.registerHandler( RestRequest.Method.GET, "/", diff --git a/server/src/test/java/org/opensearch/rest/RestHttpResponseHeadersTests.java b/server/src/test/java/org/opensearch/rest/RestHttpResponseHeadersTests.java index 2ac2b3bb5a964..747f708e144fb 100644 --- a/server/src/test/java/org/opensearch/rest/RestHttpResponseHeadersTests.java +++ b/server/src/test/java/org/opensearch/rest/RestHttpResponseHeadersTests.java @@ -37,6 +37,7 @@ import org.opensearch.common.settings.ClusterSettings; import org.opensearch.common.settings.Settings; import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.identity.IdentityService; import org.opensearch.indices.breaker.CircuitBreakerService; import org.opensearch.indices.breaker.HierarchyCircuitBreakerService; import org.opensearch.test.OpenSearchTestCase; @@ -104,7 +105,8 @@ public void testUnsupportedMethodResponseHttpHeader() throws Exception { final Settings settings = Settings.EMPTY; UsageService usageService = new UsageService(); - RestController restController = new RestController(Collections.emptySet(), null, null, circuitBreakerService, usageService); + final IdentityService identityService = new IdentityService(settings, List.of()); + RestController restController = new RestController(Collections.emptySet(), null, null, circuitBreakerService, usageService, identityService); // A basic RestHandler handles requests to the endpoint RestHandler restHandler = new RestHandler() { diff --git a/server/src/test/java/org/opensearch/rest/action/admin/indices/RestValidateQueryActionTests.java b/server/src/test/java/org/opensearch/rest/action/admin/indices/RestValidateQueryActionTests.java index cc1a9d4fd2e40..18ccc71273be7 100644 --- a/server/src/test/java/org/opensearch/rest/action/admin/indices/RestValidateQueryActionTests.java +++ b/server/src/test/java/org/opensearch/rest/action/admin/indices/RestValidateQueryActionTests.java @@ -72,7 +72,8 @@ public class RestValidateQueryActionTests extends AbstractSearchTestCase { private static NodeClient client = new NodeClient(Settings.EMPTY, threadPool); private static UsageService usageService = new UsageService(); - private static RestController controller = new RestController(emptySet(), null, client, new NoneCircuitBreakerService(), usageService); + private static IdentityService identityService = new IdentityService(settings, List.of()); + private static RestController controller = new RestController(emptySet(), null, client, new NoneCircuitBreakerService(), usageService, identityService); private static RestValidateQueryAction action = new RestValidateQueryAction(); /** diff --git a/test/framework/src/main/java/org/opensearch/test/rest/RestActionTestCase.java b/test/framework/src/main/java/org/opensearch/test/rest/RestActionTestCase.java index 7d1e393a82bb7..a54c27e1e26e1 100644 --- a/test/framework/src/main/java/org/opensearch/test/rest/RestActionTestCase.java +++ b/test/framework/src/main/java/org/opensearch/test/rest/RestActionTestCase.java @@ -38,6 +38,7 @@ import org.opensearch.action.ActionType; import org.opensearch.common.settings.Settings; import org.opensearch.common.util.concurrent.ThreadContext; +import org.opensearch.identity.IdentityService; import org.opensearch.indices.breaker.NoneCircuitBreakerService; import org.opensearch.client.node.NodeClient; import org.opensearch.rest.RestController; @@ -51,6 +52,7 @@ import org.junit.Before; import java.util.Collections; +import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiFunction; @@ -65,7 +67,15 @@ public abstract class RestActionTestCase extends OpenSearchTestCase { @Before public void setUpController() { verifyingClient = new VerifyingClient(this.getTestName()); - controller = new RestController(Collections.emptySet(), null, verifyingClient, new NoneCircuitBreakerService(), new UsageService()); + final IdentityService identityService = new IdentityService(Settings.EMPTY, List.of()); + controller = new RestController( + Collections.emptySet(), + null, + verifyingClient, + new NoneCircuitBreakerService(), + new UsageService(), + identityService + ); } @After From 4d8149543e2ac5041b63b24b15c89eb3da0a8070 Mon Sep 17 00:00:00 2001 From: Peter Nied Date: Fri, 17 Feb 2023 17:49:44 +0000 Subject: [PATCH 02/33] partial review feedback Signed-off-by: Peter Nied --- .gitignore | 2 +- CHANGELOG.md | 29 +++++++++++++------ .../HttpSmokeTestCaseWithIdentity.java | 3 -- .../identity/shiro/AuthTokenHandler.java | 14 ++++----- .../identity/shiro/ShiroSecurityManager.java | 21 +++++--------- .../identity/shiro/ShiroSubject.java | 7 +++-- .../shiro/UnsupportedAuthenticationToken.java | 12 ++++++++ .../shiro/realm/BCryptPasswordMatcher.java | 4 +-- .../identity/shiro/realm/InternalRealm.java | 5 ++-- .../identity/shiro/AuthTokenHandlerTests.java | 11 +++---- sandbox/modules/build.gradle | 15 ++-------- .../identity/tokens/RestTokenExtractor.java | 2 +- .../org/opensearch/rest/RestController.java | 12 ++++---- 13 files changed, 71 insertions(+), 66 deletions(-) create mode 100644 modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/UnsupportedAuthenticationToken.java diff --git a/.gitignore b/.gitignore index 00314eda7aff1..9ab7de894636a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ out/ !.idea/vcs.xml !.idea/icon.svg -# These files are generated in the main tree by IntelliJ +# These files are generated in the main tree by annotation processors benchmarks/src/main/generated/* benchmarks/bin/* benchmarks/build-eclipse-default/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 367205c8578b2..8a7eb6c3b477a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,16 +8,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Support for HTTP/2 (server-side) ([#3847](https://github.com/opensearch-project/OpenSearch/pull/3847)) - Add getter for path field in NestedQueryBuilder ([#4636](https://github.com/opensearch-project/OpenSearch/pull/4636)) - Allow mmap to use new JDK-19 preview APIs in Apache Lucene 9.4+ ([#5151](https://github.com/opensearch-project/OpenSearch/pull/5151)) -- Add support for ppc64le architecture ([#5459](https://github.com/opensearch-project/OpenSearch/pull/5459)) -- Add support to disallow search request with preference parameter with strict weighted shard routing([#5874](https://github.com/opensearch-project/OpenSearch/pull/5874)) -- Add identity and access control extension point ([5925](https://github.com/opensearch-project/OpenSearch/pull/5925)) ### Dependencies -- Bumps `wiremock-jre8-standalone` from 2.33.2 to 2.35.0 -- Bumps `gson` from 2.10 to 2.10.1 -- Bumps `json-schema-validator` from 1.0.73 to 1.0.76 - Bumps `log4j-core` from 2.18.0 to 2.19.0 -- Bumps `reactor-netty-http` from 1.0.18 to 1.0.23 +- Bumps `reactor-netty-http` from 1.0.24 to 1.1.2 +- Bumps `reactor-netty-http` from 1.0.18 to 1.1.2 - Bumps `jettison` from 1.5.0 to 1.5.3 - Bumps `forbiddenapis` from 3.3 to 3.4 - Bumps `avro` from 1.11.0 to 1.11.1 @@ -43,6 +38,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Bumps `json-schema-validator` from 1.0.73 to 1.0.76 - Bumps `jna` from 5.11.0 to 5.13.0 - Bumps `joni` from 2.1.44 to 2.1.45 +- Bumps `commons-io:commons-io` from 2.7 to 2.11.0 +- Bumps `org.jruby.joni:joni` from 2.1.45 to 2.1.48 +- Bumps `org.apache.ant:ant` from 1.10.12 to 1.10.13 +- Bumps `com.azure:azure-storage-common` from 12.18.1 to 12.19.3 ### Changed - [CCR] Add getHistoryOperationsFromTranslog method to fetch the history snapshot from translogs ([#3948](https://github.com/opensearch-project/OpenSearch/pull/3948)) @@ -51,6 +50,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Changed http code on create index API with bad input raising NotXContentException from 500 to 400 ([#4773](https://github.com/opensearch-project/OpenSearch/pull/4773)) - Change http code for DecommissioningFailedException from 500 to 400 ([#5283](https://github.com/opensearch-project/OpenSearch/pull/5283)) - Require MediaType in Strings.toString API ([#6009](https://github.com/opensearch-project/OpenSearch/pull/6009)) +- Improve summary error message for invalid setting updates ([#4792](https://github.com/opensearch-project/OpenSearch/pull/4792)) ### Deprecated @@ -73,7 +73,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Fix 'org.apache.hc.core5.http.ParseException: Invalid protocol version' under JDK 16+ ([#4827](https://github.com/opensearch-project/OpenSearch/pull/4827)) - Fixed compression support for h2c protocol ([#4944](https://github.com/opensearch-project/OpenSearch/pull/4944)) - Support OpenSSL Provider with default Netty allocator ([#5460](https://github.com/opensearch-project/OpenSearch/pull/5460)) -- Segment Replication - Fixed bug where inaccurate sequence numbers were sent during replication ([#6122](https://github.com/opensearch-project/OpenSearch/pull/6122)) ### Security @@ -84,11 +83,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Added support for feature flags in opensearch.yml ([#4959](https://github.com/opensearch-project/OpenSearch/pull/4959)) - Add query for initialized extensions ([#5658](https://github.com/opensearch-project/OpenSearch/pull/5658)) - Add update-index-settings allowlist for searchable snapshot ([#5907](https://github.com/opensearch-project/OpenSearch/pull/5907)) +- Add new cat/segment_replication API to surface Segment Replication metrics ([#5718](https://github.com/opensearch-project/OpenSearch/pull/5718)). - Replace latches with CompletableFutures for extensions ([#5646](https://github.com/opensearch-project/OpenSearch/pull/5646)) - Add GeoTile and GeoHash Grid aggregations on GeoShapes. ([#5589](https://github.com/opensearch-project/OpenSearch/pull/5589)) - Add support to disallow search request with preference parameter with strict weighted shard routing([#5874](https://github.com/opensearch-project/OpenSearch/pull/5874)) -- Changing ExtensionActionRequest streaminput constructor to be public ([#6094](https://github.com/opensearch-project/OpenSearch/pull/6094)) +- Added support to apply index create block ([#4603](https://github.com/opensearch-project/OpenSearch/issues/4603)) - Adds support for minimum compatible version for extensions ([#6003](https://github.com/opensearch-project/OpenSearch/pull/6003)) +- Add a guardrail to limit maximum number of shard on the cluster ([#6143](https://github.com/opensearch-project/OpenSearch/pull/6143)) +- Add cancellation of in-flight SearchTasks based on resource consumption ([#5606](https://github.com/opensearch-project/OpenSearch/pull/5605)) +- Add support for ppc64le architecture ([#5459](https://github.com/opensearch-project/OpenSearch/pull/5459)) +- [Segment Replication] Add primary weight factor for balanced primary distribution ([#6017](https://github.com/opensearch-project/OpenSearch/pull/6017)) +- Add a setting to control auto release of OpenSearch managed index creation block ([#6277](https://github.com/opensearch-project/OpenSearch/pull/6277)) +- Fix timeout error when adding a document to an index with extension running ([#6275](https://github.com/opensearch-project/OpenSearch/pull/6275)) +- Clean up temporary files created during segment merge incase segment merge fails ([#6324](https://github.com/opensearch-project/OpenSearch/pull/6324)) +- Add identity and access control extension point ([5925](https://github.com/opensearch-project/OpenSearch/pull/5925)) ### Dependencies - Update nebula-publishing-plugin to 19.2.0 ([#5704](https://github.com/opensearch-project/OpenSearch/pull/5704)) @@ -105,6 +113,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - [Refactor] Use local opensearch.common.SetOnce instead of lucene's utility class ([#5947](https://github.com/opensearch-project/OpenSearch/pull/5947)) - Cluster health call to throw decommissioned exception for local decommissioned node([#6008](https://github.com/opensearch-project/OpenSearch/pull/6008)) - [Refactor] core.common to new opensearch-common library ([#5976](https://github.com/opensearch-project/OpenSearch/pull/5976)) +- Cluster local health call to throw exception if node is decommissioned or weighed away ([#6198](https://github.com/opensearch-project/OpenSearch/pull/6198)) ### Deprecated @@ -113,6 +122,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Fixed - [Segment Replication] Fix for peer recovery ([#5344](https://github.com/opensearch-project/OpenSearch/pull/5344)) - Fix weighted shard routing state across search requests([#6004](https://github.com/opensearch-project/OpenSearch/pull/6004)) +- [Segment Replication] Fix bug where inaccurate sequence numbers are sent during replication ([#6122](https://github.com/opensearch-project/OpenSearch/pull/6122)) +- Enable numeric sort optimisation for few numerical sort types ([#6321](https://github.com/opensearch-project/OpenSearch/pull/6321)) ### Security diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java index 7d29e8c160a5d..ad347bd135d08 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java @@ -8,7 +8,6 @@ package org.opensearch.identity.shiro; -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; import org.opensearch.common.network.NetworkModule; import org.opensearch.common.settings.Settings; import org.opensearch.plugins.Plugin; @@ -28,8 +27,6 @@ * * @opensearch.experimental */ -// TODO not sure why ThreadLeakScope.NONE is required -@ThreadLeakScope(ThreadLeakScope.Scope.NONE) public abstract class HttpSmokeTestCaseWithIdentity extends OpenSearchIntegTestCase { private static String nodeTransportTypeKey; diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java index 745b452136ebc..412487e944aa9 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java @@ -8,6 +8,8 @@ package org.opensearch.identity.shiro; +import java.util.Optional; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.shiro.authc.AuthenticationToken; @@ -24,18 +26,16 @@ class AuthTokenHandler { private static final Logger logger = LogManager.getLogger(AuthTokenHandler.class); /** - * Translates shiro auth token from the given header token + * Translates into shiro auth token from the given header token * @param authenticationToken the token from which to translate - * @return the shiro auth token to be for login + * @return An optional of the shiro auth token for login */ - public AuthenticationToken translateAuthToken(org.opensearch.identity.tokens.AuthToken authenticationToken) { - final AuthenticationToken authToken = null; - + public Optional translateAuthToken(org.opensearch.identity.tokens.AuthToken authenticationToken) { if (authenticationToken instanceof BasicAuthToken) { final BasicAuthToken basicAuthToken = (BasicAuthToken) authenticationToken; - return new UsernamePasswordToken(basicAuthToken.getUser(), basicAuthToken.getPassword()); + return Optional.of(new UsernamePasswordToken(basicAuthToken.getUser(), basicAuthToken.getPassword())); } - return authToken; + return Optional.empty(); } } diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java index d74af8fdc6902..399199eda6cea 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java @@ -8,9 +8,9 @@ package org.opensearch.identity.shiro; -import org.apache.shiro.subject.Subject; import org.apache.shiro.mgt.DefaultSecurityManager; -import org.apache.shiro.mgt.SubjectDAO; +import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; +import org.apache.shiro.mgt.DefaultSubjectDAO; import org.opensearch.identity.shiro.realm.InternalRealm; /** @@ -28,18 +28,11 @@ public ShiroSecurityManager() { // By default shiro stores session information into a cache, there were performance // issues with this sessions cache and so are defaulting to a stateless configuration - this.subjectDAO = new StatelessDAO(); - } - - /** - * - * @opensearch.experimental - */ - private static class StatelessDAO implements SubjectDAO { - public Subject save(final Subject s) { - return s; - } + final DefaultSessionStorageEvaluator evaluator = new DefaultSessionStorageEvaluator(); + evaluator.setSessionStorageEnabled(false); - public void delete(final Subject s) {} + final DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO(); + subjectDAO.setSessionStorageEvaluator(evaluator); + setSubjectDAO(subjectDAO); } } diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java index b46a03d0c5de5..2a9b17d5870e9 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java @@ -24,8 +24,8 @@ public class ShiroSubject implements Subject { private final org.apache.shiro.subject.Subject shiroSubject; public ShiroSubject(final AuthTokenHandler authTokenHandler, final org.apache.shiro.subject.Subject subject) { - this.authTokenHandler = authTokenHandler; - this.shiroSubject = subject; + this.authTokenHandler = Objects.requireNonNull(authTokenHandler); + this.shiroSubject = Objects.requireNonNull(subject); } @Override @@ -58,7 +58,8 @@ public String toString() { * Logs the user in via authenticating the user against current Shiro realm */ public void login(AuthToken authenticationToken) { - final org.apache.shiro.authc.AuthenticationToken authToken = authTokenHandler.translateAuthToken(authenticationToken); + final org.apache.shiro.authc.AuthenticationToken authToken = authTokenHandler.translateAuthToken(authenticationToken) + .orElseThrow(() -> new UnsupportedAuthenticationToken()); shiroSubject.login(authToken); } } diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/UnsupportedAuthenticationToken.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/UnsupportedAuthenticationToken.java new file mode 100644 index 0000000000000..f216bbfefe940 --- /dev/null +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/UnsupportedAuthenticationToken.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. + */ + +package org.opensearch.identity.shiro; + +/** Thrown if the authentication token was invalid */ +public class UnsupportedAuthenticationToken extends RuntimeException {} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcher.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcher.java index ca73d7b85c235..08e9c426efe23 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcher.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/BCryptPasswordMatcher.java @@ -24,9 +24,7 @@ public class BCryptPasswordMatcher implements CredentialsMatcher { @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { final UsernamePasswordToken userToken = (UsernamePasswordToken) token; - final String password = new String(userToken.getPassword()); - final String hashedCredentials = (String) info.getCredentials(); - return OpenBSDBCrypt.checkPassword(hashedCredentials, password.toCharArray()); + return OpenBSDBCrypt.checkPassword((String) info.getCredentials(), userToken.getPassword()); } } diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java index f61e2c3aca70c..f493544143c4a 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java @@ -23,6 +23,7 @@ import java.util.Objects; import java.util.Map; +import java.util.Optional; /** * Internal Realm is a custom realm using the internal OpenSearch IdP @@ -85,7 +86,6 @@ protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken t realmName ); - // TODO: Doesn't appear to check the password final boolean successfulAuthentication = getCredentialsMatcher().doCredentialsMatch(token, sai); if (successfulAuthentication) { @@ -102,6 +102,7 @@ protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken t } // If the token was not handled, it was unsupported - throw new UnsupportedTokenException("Unable to support authentication token " + token.getClass().getName()); + final String tokenClassName = Optional.ofNullable(token).map(Object::getClass).map(Class::getName).orElse("null"); + throw new UnsupportedTokenException("Unable to support authentication token " + tokenClassName); } } diff --git a/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/AuthTokenHandlerTests.java b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/AuthTokenHandlerTests.java index 0b4cd21737c38..942d777df2086 100644 --- a/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/AuthTokenHandlerTests.java +++ b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/AuthTokenHandlerTests.java @@ -18,7 +18,8 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; + +import java.util.Optional; public class AuthTokenHandlerTests extends OpenSearchTestCase { @@ -32,7 +33,7 @@ public void testSetup() { public void testShouldExtractBasicAuthTokenSuccessfully() { final BasicAuthToken authToken = new BasicAuthToken("Basic YWRtaW46YWRtaW4="); // admin:admin - final AuthenticationToken translatedToken = authTokenHandler.translateAuthToken(authToken); + final AuthenticationToken translatedToken = authTokenHandler.translateAuthToken(authToken).get(); assertThat(translatedToken, is(instanceOf(UsernamePasswordToken.class))); final UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) translatedToken; @@ -44,7 +45,7 @@ public void testShouldExtractBasicAuthTokenSuccessfully() { public void testShouldExtractBasicAuthTokenSuccessfully_twoSemiColonPassword() { final BasicAuthToken authToken = new BasicAuthToken("Basic dGVzdDp0ZTpzdA=="); // test:te:st - final AuthenticationToken translatedToken = authTokenHandler.translateAuthToken(authToken); + final AuthenticationToken translatedToken = authTokenHandler.translateAuthToken(authToken).get(); assertThat(translatedToken, is(instanceOf(UsernamePasswordToken.class))); final UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) translatedToken; @@ -54,8 +55,8 @@ public void testShouldExtractBasicAuthTokenSuccessfully_twoSemiColonPassword() { } public void testShouldReturnNullWhenExtractingNullToken() { - final AuthenticationToken translatedToken = authTokenHandler.translateAuthToken(null); + final Optional translatedToken = authTokenHandler.translateAuthToken(null); - assertThat(translatedToken, nullValue()); + assertThat(translatedToken.isEmpty(), is(true)); } } diff --git a/sandbox/modules/build.gradle b/sandbox/modules/build.gradle index 7021a36a6b7fc..61afb2c568e1b 100644 --- a/sandbox/modules/build.gradle +++ b/sandbox/modules/build.gradle @@ -7,22 +7,13 @@ */ configure(subprojects.findAll { it.parent.path == project.path }) { - group = 'org.opensearch.sandbox.plugin' // for modules which publish client jars + group = 'org.opensearch.sandbox' apply plugin: 'opensearch.testclusters' apply plugin: 'opensearch.opensearchplugin' opensearchplugin { - // for local OpenSearch plugins, the name of the plugin is the same as the directory name project.name - } - - if (project.file('src/main/packaging').exists()) { - throw new InvalidModelException("Modules cannot contain packaging files") - } - if (project.file('src/main/bin').exists()) { - throw new InvalidModelException("Modules cannot contain bin files") - } - if (project.file('src/main/config').exists()) { - throw new InvalidModelException("Modules cannot contain config files") + licenseFile rootProject.file('licenses/APACHE-LICENSE-2.0.txt') + noticeFile rootProject.file('NOTICE.txt') } } diff --git a/server/src/main/java/org/opensearch/identity/tokens/RestTokenExtractor.java b/server/src/main/java/org/opensearch/identity/tokens/RestTokenExtractor.java index 844d1295c56b5..e0458f002a2e2 100644 --- a/server/src/main/java/org/opensearch/identity/tokens/RestTokenExtractor.java +++ b/server/src/main/java/org/opensearch/identity/tokens/RestTokenExtractor.java @@ -53,4 +53,4 @@ public static AuthToken extractToken(final RestRequest request) { logger.trace("No auth token could be extracted"); return null; } -} \ No newline at end of file +} diff --git a/server/src/main/java/org/opensearch/rest/RestController.java b/server/src/main/java/org/opensearch/rest/RestController.java index ecfa6b9f3e0c6..d8717cd517694 100644 --- a/server/src/main/java/org/opensearch/rest/RestController.java +++ b/server/src/main/java/org/opensearch/rest/RestController.java @@ -403,8 +403,10 @@ private void tryAllHandlers(final RestRequest request, final RestChannel channel return; } } else { - if (!handleAuthenticateUser(request, channel)) { - return; + if (FeatureFlags.isEnabled(FeatureFlags.IDENTITY)) { + if (!handleAuthenticateUser(request, channel)) { + return; + } } dispatchRequest(request, channel, handler); return; @@ -522,14 +524,11 @@ private void handleBadRequest(String uri, RestRequest.Method method, RestChannel * @returns false if there was an error and the request should not continue being dispatched * */ private boolean handleAuthenticateUser(final RestRequest request, final RestChannel channel) { - if (!FeatureFlags.isEnabled(FeatureFlags.IDENTITY)) { - return true; - } - try { final AuthToken token = RestTokenExtractor.extractToken(request); // If no token was found, continue executing the request if (token == null) { + // Authentication did not fail so return true. Authorization is handled at the action level. return true; } final Subject currentSubject = identityService.getSubject(); @@ -549,6 +548,7 @@ private boolean handleAuthenticateUser(final RestRequest request, final RestChan return false; } + // Authentication did not fail so return true. Authorization is handled at the action level. return true; } From a9b4f0dfb4d74e1f13259bd31c521028beb75786 Mon Sep 17 00:00:00 2001 From: Peter Nied Date: Fri, 17 Feb 2023 22:42:47 +0000 Subject: [PATCH 03/33] More feedback Signed-off-by: Peter Nied --- .../identity/BasicAuthenticationIT.java | 2 +- .../identity/shiro/ShiroSecurityManager.java | 4 +- ...nternalRealm.java => OpenSearchRealm.java} | 10 ++-- .../identity/AbstractIdentityTestCase.java | 52 ------------------- ...lmTests.java => OpenSearchRealmTests.java} | 6 +-- 5 files changed, 11 insertions(+), 63 deletions(-) rename modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/{InternalRealm.java => OpenSearchRealm.java} (91%) delete mode 100644 modules/identity-shiro/src/test/java/org/opensearch/identity/AbstractIdentityTestCase.java rename modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/{InternalRealmTests.java => OpenSearchRealmTests.java} (88%) diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java index 18ee40ed2d9f6..84cdd96096156 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java @@ -30,7 +30,7 @@ public void testBasicAuthSuccess() throws Exception { final Response response = createHealthRequest("Basic YWRtaW46YWRtaW4="); // admin:admin final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); - assertEquals(RestStatus.OK.getStatus(), response.getStatusLine().getStatusCode()); + assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); assertThat(content, containsString("green")); } diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java index 399199eda6cea..96cf05ac53a1a 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSecurityManager.java @@ -11,7 +11,7 @@ import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; import org.apache.shiro.mgt.DefaultSubjectDAO; -import org.opensearch.identity.shiro.realm.InternalRealm; +import org.opensearch.identity.shiro.realm.OpenSearchRealm; /** * OpenSearch specific security manager implementation @@ -24,7 +24,7 @@ public class ShiroSecurityManager extends DefaultSecurityManager { * Creates the security manager using a default realm and no session storage */ public ShiroSecurityManager() { - super(InternalRealm.INSTANCE); + super(OpenSearchRealm.INSTANCE); // By default shiro stores session information into a cache, there were performance // issues with this sessions cache and so are defaulting to a stateless configuration diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/OpenSearchRealm.java similarity index 91% rename from modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java rename to modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/OpenSearchRealm.java index f493544143c4a..4a4a473d5f2eb 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/InternalRealm.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/OpenSearchRealm.java @@ -30,16 +30,16 @@ * * @opensearch.experimental */ -public class InternalRealm extends AuthenticatingRealm { +public class OpenSearchRealm extends AuthenticatingRealm { private static final String DEFAULT_REALM_NAME = "internal"; - public static final InternalRealm INSTANCE = new InternalRealm.Builder(DEFAULT_REALM_NAME).build(); + public static final OpenSearchRealm INSTANCE = new OpenSearchRealm.Builder(DEFAULT_REALM_NAME).build(); private final String realmName; private Map internalUsers; - private InternalRealm(final String realmName, final Map internalUsers) { + private OpenSearchRealm(final String realmName, final Map internalUsers) { super(new BCryptPasswordMatcher()); this.realmName = realmName; this.internalUsers = internalUsers; @@ -53,13 +53,13 @@ public Builder(final String name) { this.name = Objects.requireNonNull(name); } - public InternalRealm build() { + public OpenSearchRealm build() { // TODO: Replace hardcoded admin user / user map with an external provider final User adminUser = new User(); adminUser.setUsername(new StringPrincipal("admin")); adminUser.setBcryptHash("$2a$12$VcCDgh2NDk07JGN0rjGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG"); // Password 'admin' final Map internalUsers = Map.of("admin", adminUser); - return new InternalRealm(name, internalUsers); + return new OpenSearchRealm(name, internalUsers); } } diff --git a/modules/identity-shiro/src/test/java/org/opensearch/identity/AbstractIdentityTestCase.java b/modules/identity-shiro/src/test/java/org/opensearch/identity/AbstractIdentityTestCase.java deleted file mode 100644 index b32145cdc2db8..0000000000000 --- a/modules/identity-shiro/src/test/java/org/opensearch/identity/AbstractIdentityTestCase.java +++ /dev/null @@ -1,52 +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.identity.shiro; - -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import org.opensearch.common.settings.Settings; -import org.opensearch.common.util.FeatureFlags; -import org.opensearch.http.CorsHandler; -import org.opensearch.http.HttpTransportSettings; -import org.opensearch.plugins.Plugin; -import org.opensearch.test.OpenSearchIntegTestCase; -import org.opensearch.transport.Netty4ModulePlugin; - -import java.util.Collection; -import java.util.List; - -/** - * Base test case for integration tests against the identity plugin. - */ -@ThreadLeakScope(ThreadLeakScope.Scope.NONE) -public abstract class AbstractIdentityTestCase extends OpenSearchIntegTestCase { - - @Override - protected Collection> nodePlugins() { - return List.of(ShiroIdentityPlugin.class, Netty4ModulePlugin.class); - } - - @Override - protected boolean addMockHttpTransport() { - return false; // enable http - } - - @Override - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.builder().put(super.nodeSettings(nodeOrdinal)).put(nodeSettings()).build(); - } - - final Settings nodeSettings() { - return Settings.builder() - .put(HttpTransportSettings.SETTING_CORS_ENABLED.getKey(), true) - .put(HttpTransportSettings.SETTING_CORS_ALLOW_ORIGIN.getKey(), CorsHandler.ANY_ORIGIN) - .put(HttpTransportSettings.SETTING_CORS_ALLOW_CREDENTIALS.getKey(), true) - .put(FeatureFlags.IDENTITY, true) - .build(); - } -} diff --git a/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/InternalRealmTests.java b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/OpenSearchRealmTests.java similarity index 88% rename from modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/InternalRealmTests.java rename to modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/OpenSearchRealmTests.java index 1ed32a9484210..d6129c238408a 100644 --- a/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/InternalRealmTests.java +++ b/modules/identity-shiro/src/test/java/org/opensearch/identity/shiro/realm/OpenSearchRealmTests.java @@ -14,13 +14,13 @@ import org.junit.Before; import org.opensearch.test.OpenSearchTestCase; -public class InternalRealmTests extends OpenSearchTestCase { +public class OpenSearchRealmTests extends OpenSearchTestCase { - private InternalRealm realm; + private OpenSearchRealm realm; @Before public void setup() { - realm = new InternalRealm.Builder("test").build(); + realm = new OpenSearchRealm.Builder("test").build(); } public void testGetAuthenticationInfoUserExists() { From 05d06574eda5ee4a241547088ef1e01c8c83f679 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Wed, 19 Apr 2023 11:46:49 -0400 Subject: [PATCH 04/33] Address comments, fix tests Signed-off-by: Stephen Crawford --- .../java/org/opensearch/common/NotNull.java | 55 +++++++++++++++++++ .../identity/shiro/realm/OpenSearchRealm.java | 4 +- .../opensearch/identity/shiro/realm/User.java | 8 +-- .../opensearch/identity/IdentityService.java | 2 + ...ringPrincipal.java => NamedPrincipal.java} | 6 +- .../{Principals.java => NativePrincipal.java} | 8 +-- .../opensearch/identity/noop/NoopSubject.java | 4 +- .../opensearch/plugins/IdentityPlugin.java | 2 + .../opensearch/rest/RestControllerTests.java | 3 +- .../indices/RestValidateQueryActionTests.java | 4 +- 10 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 libs/common/src/main/java/org/opensearch/common/NotNull.java rename server/src/main/java/org/opensearch/identity/{StringPrincipal.java => NamedPrincipal.java} (85%) rename server/src/main/java/org/opensearch/identity/{Principals.java => NativePrincipal.java} (68%) diff --git a/libs/common/src/main/java/org/opensearch/common/NotNull.java b/libs/common/src/main/java/org/opensearch/common/NotNull.java new file mode 100644 index 0000000000000..55fdd179f7034 --- /dev/null +++ b/libs/common/src/main/java/org/opensearch/common/NotNull.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. + */ + +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you 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. + */ + +/* + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.common; + +import javax.annotation.Nonnull; +import javax.annotation.meta.TypeQualifierNickname; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The presence of this annotation above a method indicates that + * {@code null} cannot be returned by that method. + * + * @opensearch.api + */ +@Documented +@TypeQualifierNickname +@Nonnull +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface NotNull { +} diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/OpenSearchRealm.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/OpenSearchRealm.java index 4a4a473d5f2eb..064bff79b50b2 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/OpenSearchRealm.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/OpenSearchRealm.java @@ -19,7 +19,7 @@ import org.apache.shiro.realm.AuthenticatingRealm; import org.apache.shiro.authc.UsernamePasswordToken; -import org.opensearch.identity.StringPrincipal; +import org.opensearch.identity.NamedPrincipal; import java.util.Objects; import java.util.Map; @@ -56,7 +56,7 @@ public Builder(final String name) { public OpenSearchRealm build() { // TODO: Replace hardcoded admin user / user map with an external provider final User adminUser = new User(); - adminUser.setUsername(new StringPrincipal("admin")); + adminUser.setUsername(new NamedPrincipal("admin")); adminUser.setBcryptHash("$2a$12$VcCDgh2NDk07JGN0rjGbM.Ad41qVR/YFJcgHp0UGns5JDymv..TOG"); // Password 'admin' final Map internalUsers = Map.of("admin", adminUser); return new OpenSearchRealm(name, internalUsers); diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/User.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/User.java index 162094c9d5d87..8b0968271c9b0 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/User.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/realm/User.java @@ -8,7 +8,7 @@ package org.opensearch.identity.shiro.realm; -import org.opensearch.identity.StringPrincipal; +import org.opensearch.identity.NamedPrincipal; /** * A non-volatile and immutable object in the storage. @@ -17,14 +17,14 @@ */ public class User { - private StringPrincipal username; + private NamedPrincipal username; private String bcryptHash; - public StringPrincipal getUsername() { + public NamedPrincipal getUsername() { return username; } - public void setUsername(StringPrincipal username) { + public void setUsername(NamedPrincipal username) { this.username = username; } diff --git a/server/src/main/java/org/opensearch/identity/IdentityService.java b/server/src/main/java/org/opensearch/identity/IdentityService.java index d262b7018f43b..cf11300aad17d 100644 --- a/server/src/main/java/org/opensearch/identity/IdentityService.java +++ b/server/src/main/java/org/opensearch/identity/IdentityService.java @@ -8,6 +8,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.opensearch.OpenSearchException; +import org.opensearch.common.NotNull; import org.opensearch.identity.noop.NoopIdentityPlugin; import java.util.List; import org.opensearch.common.settings.Settings; @@ -46,6 +47,7 @@ public IdentityService(final Settings settings, final List ident /** * Gets the current subject */ + @NotNull public Subject getSubject() { return identityPlugin.getSubject(); } diff --git a/server/src/main/java/org/opensearch/identity/StringPrincipal.java b/server/src/main/java/org/opensearch/identity/NamedPrincipal.java similarity index 85% rename from server/src/main/java/org/opensearch/identity/StringPrincipal.java rename to server/src/main/java/org/opensearch/identity/NamedPrincipal.java index a3d0b49f7863a..8de05d9bd9330 100644 --- a/server/src/main/java/org/opensearch/identity/StringPrincipal.java +++ b/server/src/main/java/org/opensearch/identity/NamedPrincipal.java @@ -13,7 +13,7 @@ * * @opensearch.experimental */ -public class StringPrincipal implements Principal { +public class NamedPrincipal implements Principal { private final String name; @@ -21,7 +21,7 @@ public class StringPrincipal implements Principal { * Creates a principal for an identity specified as a string * @param name A persistent string that represent an identity */ - public StringPrincipal(final String name) { + public NamedPrincipal(final String name) { this.name = name; } @@ -45,6 +45,6 @@ public int hashCode() { @Override public String toString() { - return "StringPrincipal(" + "name=" + name + ")"; + return "NamedPrincipal(" + "name=" + name + ")"; } } diff --git a/server/src/main/java/org/opensearch/identity/Principals.java b/server/src/main/java/org/opensearch/identity/NativePrincipal.java similarity index 68% rename from server/src/main/java/org/opensearch/identity/Principals.java rename to server/src/main/java/org/opensearch/identity/NativePrincipal.java index 7ce662425cb0e..b6c4901dc9ac7 100644 --- a/server/src/main/java/org/opensearch/identity/Principals.java +++ b/server/src/main/java/org/opensearch/identity/NativePrincipal.java @@ -12,17 +12,17 @@ * * @opensearch.experimental */ -public enum Principals { +public class NativePrincipal { /** * Represents a principal which has not been authenticated */ - UNAUTHENTICATED(new StringPrincipal("Unauthenticated")); + public static final NativePrincipal UNAUTHENTICATED = new NativePrincipal("Unauthenticated"); private final Principal principal; - Principals(final Principal principal) { - this.principal = principal; + NativePrincipal(final String principal) { + this.principal = new NamedPrincipal(principal); } /** diff --git a/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java b/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java index c2c95dea7f1c6..b15acc1dcc1e0 100644 --- a/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java +++ b/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java @@ -11,9 +11,9 @@ import java.security.Principal; import java.util.Objects; +import org.opensearch.identity.NativePrincipal; import org.opensearch.identity.tokens.AuthToken; import org.opensearch.identity.Subject; -import org.opensearch.identity.Principals; /** * Implementation of subject that is always authenticated @@ -26,7 +26,7 @@ public class NoopSubject implements Subject { @Override public Principal getPrincipal() { - return Principals.UNAUTHENTICATED.getPrincipal(); + return NativePrincipal.UNAUTHENTICATED.getPrincipal(); } @Override diff --git a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java index a8855eb1727ea..7246720cba3aa 100644 --- a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java +++ b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java @@ -8,6 +8,7 @@ package org.opensearch.plugins; +import org.opensearch.common.Nullable; import org.opensearch.identity.Subject; /** @@ -20,5 +21,6 @@ public interface IdentityPlugin { /** * Get the current subject * */ + @Nullable public Subject getSubject(); } diff --git a/server/src/test/java/org/opensearch/rest/RestControllerTests.java b/server/src/test/java/org/opensearch/rest/RestControllerTests.java index 9e3602d8c3529..489419fc24526 100644 --- a/server/src/test/java/org/opensearch/rest/RestControllerTests.java +++ b/server/src/test/java/org/opensearch/rest/RestControllerTests.java @@ -52,6 +52,7 @@ import org.opensearch.http.HttpResponse; import org.opensearch.http.HttpServerTransport; import org.opensearch.http.HttpStats; +import org.opensearch.identity.IdentityService; import org.opensearch.indices.breaker.HierarchyCircuitBreakerService; import org.opensearch.rest.action.admin.indices.RestCreateIndexAction; import org.opensearch.test.OpenSearchTestCase; @@ -286,7 +287,7 @@ public void testRestHandlerWrapper() throws Exception { final RestController restController = new RestController(Collections.emptySet(), h -> { assertSame(handler, h); return (RestRequest request, RestChannel channel, NodeClient client) -> wrapperCalled.set(true); - }, client, circuitBreakerService, usageServic, identityService); + }, client, circuitBreakerService, usageService, identityService); restController.registerHandler(RestRequest.Method.GET, "/wrapped", handler); RestRequest request = testRestRequest("/wrapped", "{}", XContentType.JSON); AssertingChannel channel = new AssertingChannel(request, true, RestStatus.BAD_REQUEST); diff --git a/server/src/test/java/org/opensearch/rest/action/admin/indices/RestValidateQueryActionTests.java b/server/src/test/java/org/opensearch/rest/action/admin/indices/RestValidateQueryActionTests.java index 4a2148e90c498..e14b003e7ccad 100644 --- a/server/src/test/java/org/opensearch/rest/action/admin/indices/RestValidateQueryActionTests.java +++ b/server/src/test/java/org/opensearch/rest/action/admin/indices/RestValidateQueryActionTests.java @@ -31,6 +31,7 @@ package org.opensearch.rest.action.admin.indices; +import java.util.List; import org.opensearch.action.ActionListener; import org.opensearch.action.ActionRequest; import org.opensearch.action.ActionType; @@ -43,6 +44,7 @@ import org.opensearch.common.io.stream.NamedWriteableRegistry; import org.opensearch.common.settings.Settings; import org.opensearch.common.xcontent.XContentType; +import org.opensearch.identity.IdentityService; import org.opensearch.indices.breaker.NoneCircuitBreakerService; import org.opensearch.rest.RestController; import org.opensearch.rest.RestRequest; @@ -73,7 +75,7 @@ public class RestValidateQueryActionTests extends AbstractSearchTestCase { private static NodeClient client = new NodeClient(Settings.EMPTY, threadPool); private static UsageService usageService = new UsageService(); - private static IdentityService identityService = new IdentityService(settings, List.of()); + private static IdentityService identityService = new IdentityService(Settings.EMPTY, List.of()); private static RestController controller = new RestController( emptySet(), null, From 650ff4b60b60e3fee5724ea26e2c6ebbc0c46dc3 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Wed, 19 Apr 2023 12:06:33 -0400 Subject: [PATCH 05/33] add noop to actionmoduletests Signed-off-by: Stephen Crawford --- .../test/java/org/opensearch/action/ActionModuleTests.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/test/java/org/opensearch/action/ActionModuleTests.java b/server/src/test/java/org/opensearch/action/ActionModuleTests.java index 09b4597effe2a..41375dc005ef3 100644 --- a/server/src/test/java/org/opensearch/action/ActionModuleTests.java +++ b/server/src/test/java/org/opensearch/action/ActionModuleTests.java @@ -32,6 +32,7 @@ package org.opensearch.action; +import java.util.ArrayList; import org.opensearch.action.ActionModule.DynamicActionRegistry; import org.opensearch.action.main.MainAction; import org.opensearch.action.main.TransportMainAction; @@ -50,6 +51,7 @@ import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.extensions.action.ExtensionAction; import org.opensearch.extensions.action.ExtensionTransportAction; +import org.opensearch.identity.IdentityService; import org.opensearch.plugins.ActionPlugin; import org.opensearch.plugins.ActionPlugin.ActionHandler; @@ -143,7 +145,8 @@ public void testSetupRestHandlerContainsKnownBuiltin() { null, null, usageService, - null + null, + new IdentityService(Settings.EMPTY, new ArrayList<>()) ); actionModule.initRestHandlers(null); // At this point the easiest way to confirm that a handler is loaded is to try to register another one on top of it and to fail From b12300cb0f2592319e29e514b6fd4f2361c8ce5f Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Wed, 19 Apr 2023 12:33:11 -0400 Subject: [PATCH 06/33] Fix windows precommit Signed-off-by: Stephen Crawford --- .../java/org/opensearch/identity/BasicAuthenticationIT.java | 1 + .../indices/replication/SegmentReplicationIT.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java index 84cdd96096156..13d4e146eea9d 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java @@ -32,6 +32,7 @@ public void testBasicAuthSuccess() throws Exception { assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); assertThat(content, containsString("green")); + System.out.println("Successfully passed assertions in basic auth success"); } public void testBasicAuthUnauthorized_invalidHeader() throws Exception { diff --git a/server/src/internalClusterTest/java/org/opensearch/indices/replication/SegmentReplicationIT.java b/server/src/internalClusterTest/java/org/opensearch/indices/replication/SegmentReplicationIT.java index 36b40924d3ade..e3e9fc569aee6 100644 --- a/server/src/internalClusterTest/java/org/opensearch/indices/replication/SegmentReplicationIT.java +++ b/server/src/internalClusterTest/java/org/opensearch/indices/replication/SegmentReplicationIT.java @@ -359,7 +359,7 @@ public void testClosedIndices() { /** * This test validates the primary node drop does not result in shard failure on replica. - * @throws Exception + * @throws Exception when issue is encountered */ public void testNodeDropWithOngoingReplication() throws Exception { internalCluster().startClusterManagerOnlyNode(); @@ -869,7 +869,7 @@ public void testPressureServiceStats() throws Exception { /** * Tests a scroll query on the replica - * @throws Exception + * @throws Exception when issue is encountered */ public void testScrollCreatedOnReplica() throws Exception { // create the cluster with one primary node containing primary shard and replica node containing replica shard @@ -958,7 +958,7 @@ public void testScrollCreatedOnReplica() throws Exception { * Tests that when scroll query is cleared, it does not delete the temporary replication files, which are part of * ongoing round of segment replication * - * @throws Exception + * @throws Exception when issue is encountered */ public void testScrollWithOngoingSegmentReplication() throws Exception { // create the cluster with one primary node containing primary shard and replica node containing replica shard From 9891f85753aadfc71bb11f6a3e260f89b934cbb7 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Wed, 19 Apr 2023 12:54:14 -0400 Subject: [PATCH 07/33] move dir Signed-off-by: Stephen Crawford --- .../java/org/opensearch/identity/BasicAuthenticationIT.java | 5 ++--- .../opensearch/identity/HttpSmokeTestCaseWithIdentity.java | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java index 13d4e146eea9d..d6a1fe777b076 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java @@ -6,7 +6,7 @@ * compatible open source license. */ -package org.opensearch.identity.shiro; +package org.opensearch.identity; import org.opensearch.client.Request; import org.opensearch.client.RequestOptions; @@ -23,7 +23,7 @@ import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertThat; -@ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, numDataNodes = 0) +@OpenSearchIntegTestCase.ClusterScope(numDataNodes = 0, numClientNodes = 0, scope = OpenSearchIntegTestCase.Scope.TEST) public class BasicAuthenticationIT extends HttpSmokeTestCaseWithIdentity { public void testBasicAuthSuccess() throws Exception { @@ -32,7 +32,6 @@ public void testBasicAuthSuccess() throws Exception { assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); assertThat(content, containsString("green")); - System.out.println("Successfully passed assertions in basic auth success"); } public void testBasicAuthUnauthorized_invalidHeader() throws Exception { diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java index ad347bd135d08..b39a4a2ef85d7 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java @@ -6,10 +6,11 @@ * compatible open source license. */ -package org.opensearch.identity.shiro; +package org.opensearch.identity; import org.opensearch.common.network.NetworkModule; import org.opensearch.common.settings.Settings; +import org.opensearch.identity.shiro.ShiroIdentityPlugin; import org.opensearch.plugins.Plugin; import org.opensearch.test.OpenSearchIntegTestCase; import org.opensearch.transport.Netty4ModulePlugin; @@ -27,6 +28,7 @@ * * @opensearch.experimental */ +@OpenSearchIntegTestCase.ClusterScope(numDataNodes = 0, numClientNodes = 0, scope = OpenSearchIntegTestCase.Scope.TEST) public abstract class HttpSmokeTestCaseWithIdentity extends OpenSearchIntegTestCase { private static String nodeTransportTypeKey; From 279f589b384bc21f2105369ddd420ace120dfd8f Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Wed, 19 Apr 2023 12:56:22 -0400 Subject: [PATCH 08/33] Remove imports Signed-off-by: Stephen Crawford --- .../java/org/opensearch/identity/BasicAuthenticationIT.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java index d6a1fe777b076..6054f95c20ff9 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java @@ -13,15 +13,12 @@ import org.opensearch.client.Response; import org.opensearch.client.ResponseException; import org.opensearch.test.OpenSearchIntegTestCase; -import org.opensearch.test.OpenSearchIntegTestCase.ClusterScope; import org.opensearch.rest.RestStatus; import java.nio.charset.StandardCharsets; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.core.StringContains.containsString; -import static org.junit.Assert.assertThat; @OpenSearchIntegTestCase.ClusterScope(numDataNodes = 0, numClientNodes = 0, scope = OpenSearchIntegTestCase.Scope.TEST) public class BasicAuthenticationIT extends HttpSmokeTestCaseWithIdentity { From 9a0ad21241faa91cbd8b0688d78efd263fb6903f Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Thu, 20 Apr 2023 10:55:22 -0400 Subject: [PATCH 09/33] Rollback Signed-off-by: Stephen Crawford --- .../java/org/opensearch/common/NotNull.java | 55 ------------------- .../opensearch/identity/IdentityService.java | 2 - 2 files changed, 57 deletions(-) delete mode 100644 libs/common/src/main/java/org/opensearch/common/NotNull.java diff --git a/libs/common/src/main/java/org/opensearch/common/NotNull.java b/libs/common/src/main/java/org/opensearch/common/NotNull.java deleted file mode 100644 index 55fdd179f7034..0000000000000 --- a/libs/common/src/main/java/org/opensearch/common/NotNull.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. - */ - -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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. - */ - -/* - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -package org.opensearch.common; - -import javax.annotation.Nonnull; -import javax.annotation.meta.TypeQualifierNickname; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * The presence of this annotation above a method indicates that - * {@code null} cannot be returned by that method. - * - * @opensearch.api - */ -@Documented -@TypeQualifierNickname -@Nonnull -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.METHOD }) -public @interface NotNull { -} diff --git a/server/src/main/java/org/opensearch/identity/IdentityService.java b/server/src/main/java/org/opensearch/identity/IdentityService.java index cf11300aad17d..d262b7018f43b 100644 --- a/server/src/main/java/org/opensearch/identity/IdentityService.java +++ b/server/src/main/java/org/opensearch/identity/IdentityService.java @@ -8,7 +8,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.opensearch.OpenSearchException; -import org.opensearch.common.NotNull; import org.opensearch.identity.noop.NoopIdentityPlugin; import java.util.List; import org.opensearch.common.settings.Settings; @@ -47,7 +46,6 @@ public IdentityService(final Settings settings, final List ident /** * Gets the current subject */ - @NotNull public Subject getSubject() { return identityPlugin.getSubject(); } From 12b3928ad89d4ecb65c237384bc9f1a5f6cb377a Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Thu, 20 Apr 2023 11:16:00 -0400 Subject: [PATCH 10/33] add annotation Signed-off-by: Stephen Crawford --- .../java/org/opensearch/common/NotNull.java | 32 +++++++++++++++++++ server/build.gradle | 2 ++ .../opensearch/plugins/IdentityPlugin.java | 4 +-- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 libs/common/src/main/java/org/opensearch/common/NotNull.java diff --git a/libs/common/src/main/java/org/opensearch/common/NotNull.java b/libs/common/src/main/java/org/opensearch/common/NotNull.java new file mode 100644 index 0000000000000..ecbd2851291ae --- /dev/null +++ b/libs/common/src/main/java/org/opensearch/common/NotNull.java @@ -0,0 +1,32 @@ +/* + * 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.common; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import javax.annotation.Nonnull; +import javax.annotation.meta.TypeQualifierNickname; + +/** + * The presence of this annotation on a method indicates that + * {@code null} will not be returned from that method. + * + * @opensearch.api + */ +@Documented +@TypeQualifierNickname +@Nonnull +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +public @interface NotNull { +} + diff --git a/server/build.gradle b/server/build.gradle index 2eea312699798..b9e2b88b4532c 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -92,6 +92,8 @@ dependencies { api project(':libs:opensearch-secure-sm') api project(':libs:opensearch-x-content') api project(":libs:opensearch-geo") + implementation 'org.jetbrains:annotations:23.0.0' + implementation 'org.jetbrains:annotations:23.0.0' compileOnly project(':libs:opensearch-plugin-classloader') testRuntimeOnly project(':libs:opensearch-plugin-classloader') diff --git a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java index 7246720cba3aa..924d45243faea 100644 --- a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java +++ b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java @@ -8,7 +8,7 @@ package org.opensearch.plugins; -import org.opensearch.common.Nullable; +import org.opensearch.common.NotNull; import org.opensearch.identity.Subject; /** @@ -21,6 +21,6 @@ public interface IdentityPlugin { /** * Get the current subject * */ - @Nullable + @NotNull public Subject getSubject(); } From 72999b53a8cfd64a01486b486ca710a2bd8595b4 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Thu, 20 Apr 2023 11:23:02 -0400 Subject: [PATCH 11/33] Spotless Signed-off-by: Stephen Crawford --- libs/common/src/main/java/org/opensearch/common/NotNull.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/common/src/main/java/org/opensearch/common/NotNull.java b/libs/common/src/main/java/org/opensearch/common/NotNull.java index ecbd2851291ae..62cd2b61b16da 100644 --- a/libs/common/src/main/java/org/opensearch/common/NotNull.java +++ b/libs/common/src/main/java/org/opensearch/common/NotNull.java @@ -29,4 +29,3 @@ @Target({ ElementType.METHOD }) public @interface NotNull { } - From 616faa96d30369a59ee797f835c52a93feea516a Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Thu, 20 Apr 2023 11:34:04 -0400 Subject: [PATCH 12/33] update shas Signed-off-by: Stephen Crawford --- server/licenses/annotations-23.0.0.jar.sha1 | 1 + 1 file changed, 1 insertion(+) create mode 100644 server/licenses/annotations-23.0.0.jar.sha1 diff --git a/server/licenses/annotations-23.0.0.jar.sha1 b/server/licenses/annotations-23.0.0.jar.sha1 new file mode 100644 index 0000000000000..b8127bb8e271e --- /dev/null +++ b/server/licenses/annotations-23.0.0.jar.sha1 @@ -0,0 +1 @@ +8cc20c07506ec18e0834947b84a864bfc094484e \ No newline at end of file From e3c40bb7bbb4b6b1d4e2ba4dd1cdfd01180fc112 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Thu, 20 Apr 2023 11:54:29 -0400 Subject: [PATCH 13/33] Remove intellij annotation dependency Signed-off-by: Stephen Crawford --- server/build.gradle | 2 -- server/licenses/annotations-23.0.0.jar.sha1 | 1 - 2 files changed, 3 deletions(-) delete mode 100644 server/licenses/annotations-23.0.0.jar.sha1 diff --git a/server/build.gradle b/server/build.gradle index b9e2b88b4532c..2eea312699798 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -92,8 +92,6 @@ dependencies { api project(':libs:opensearch-secure-sm') api project(':libs:opensearch-x-content') api project(":libs:opensearch-geo") - implementation 'org.jetbrains:annotations:23.0.0' - implementation 'org.jetbrains:annotations:23.0.0' compileOnly project(':libs:opensearch-plugin-classloader') testRuntimeOnly project(':libs:opensearch-plugin-classloader') diff --git a/server/licenses/annotations-23.0.0.jar.sha1 b/server/licenses/annotations-23.0.0.jar.sha1 deleted file mode 100644 index b8127bb8e271e..0000000000000 --- a/server/licenses/annotations-23.0.0.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -8cc20c07506ec18e0834947b84a864bfc094484e \ No newline at end of file From 6e482bb1cf7c734e4346e5a21e51d1d4d6cc5824 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Thu, 20 Apr 2023 12:31:43 -0400 Subject: [PATCH 14/33] remove not null as causes cluster hang Signed-off-by: Stephen Crawford --- .../java/org/opensearch/common/NotNull.java | 31 ------------------- .../opensearch/plugins/IdentityPlugin.java | 2 -- 2 files changed, 33 deletions(-) delete mode 100644 libs/common/src/main/java/org/opensearch/common/NotNull.java diff --git a/libs/common/src/main/java/org/opensearch/common/NotNull.java b/libs/common/src/main/java/org/opensearch/common/NotNull.java deleted file mode 100644 index 62cd2b61b16da..0000000000000 --- a/libs/common/src/main/java/org/opensearch/common/NotNull.java +++ /dev/null @@ -1,31 +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.common; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import javax.annotation.Nonnull; -import javax.annotation.meta.TypeQualifierNickname; - -/** - * The presence of this annotation on a method indicates that - * {@code null} will not be returned from that method. - * - * @opensearch.api - */ -@Documented -@TypeQualifierNickname -@Nonnull -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.METHOD }) -public @interface NotNull { -} diff --git a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java index 924d45243faea..a8855eb1727ea 100644 --- a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java +++ b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java @@ -8,7 +8,6 @@ package org.opensearch.plugins; -import org.opensearch.common.NotNull; import org.opensearch.identity.Subject; /** @@ -21,6 +20,5 @@ public interface IdentityPlugin { /** * Get the current subject * */ - @NotNull public Subject getSubject(); } From 9fa91e23cdbe50616ab31fce3612a62cef524d67 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Fri, 21 Apr 2023 11:07:39 -0400 Subject: [PATCH 15/33] Trigger rerun Signed-off-by: Stephen Crawford --- .../java/org/opensearch/identity/BasicAuthenticationIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java index 6054f95c20ff9..b83cd74402eb3 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java @@ -32,7 +32,7 @@ public void testBasicAuthSuccess() throws Exception { } public void testBasicAuthUnauthorized_invalidHeader() throws Exception { - final Response response = createHealthRequest("Basic aaaa"); // invalid + final Response response = createHealthRequest("Basic aaaa"); // invalid username password final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); From f530fa1cbb38e803edab6df5379df918fe0a3ca2 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Fri, 21 Apr 2023 16:39:15 -0400 Subject: [PATCH 16/33] Feedback from RETA Signed-off-by: Stephen Crawford --- CHANGELOG.md | 46 +++++++++---------- .../identity/BasicAuthenticationIT.java | 1 - .../identity/shiro/AuthTokenHandler.java | 4 -- .../identity/shiro/ShiroSubject.java | 6 +++ .../opensearch/identity/NamedPrincipal.java | 15 ++++++ .../opensearch/identity/NativePrincipal.java | 35 -------------- .../identity/noop/NoopIdentityPlugin.java | 4 ++ .../opensearch/identity/noop/NoopSubject.java | 4 +- .../opensearch/plugins/IdentityPlugin.java | 2 + .../org/opensearch/rest/RestController.java | 5 +- 10 files changed, 55 insertions(+), 67 deletions(-) delete mode 100644 server/src/main/java/org/opensearch/identity/NativePrincipal.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aa036d03a869..f3ab31286aa49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,37 +12,37 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Dependencies - Bump `log4j-core` from 2.18.0 to 2.19.0 -- Bumps `reactor-netty-http` from 1.0.24 to 1.1.2 -- Bumps `reactor-netty-http` from 1.0.18 to 1.1.2 -- Bumps `jettison` from 1.5.0 to 1.5.3 +- Bump `reactor-netty-http` from 1.0.24 to 1.1.2 +- Bump `reactor-netty-http` from 1.0.18 to 1.1.2 +- Bump `jettison` from 1.5.0 to 1.5.3 - Bump `forbiddenapis` from 3.3 to 3.4 - Bump `avro` from 1.11.0 to 1.11.1 - Bump `woodstox-core` from 6.3.0 to 6.3.1 - Bump `xmlbeans` from 5.1.0 to 5.1.1 ([#4354](https://github.com/opensearch-project/OpenSearch/pull/4354)) - Bump `azure-storage-common` from 12.18.0 to 12.18.1 ([#4164](https://github.com/opensearch-project/OpenSearch/pull/4664)) -- Bumps `org.gradle.test-retry` from 1.4.0 to 1.4.1 ([#4411](https://github.com/opensearch-project/OpenSearch/pull/4411)) -- Bumps `reactive-streams` from 1.0.3 to 1.0.4 ([#4488](https://github.com/opensearch-project/OpenSearch/pull/4488)) +- Bump `org.gradle.test-retry` from 1.4.0 to 1.4.1 ([#4411](https://github.com/opensearch-project/OpenSearch/pull/4411)) +- Bump `reactive-streams` from 1.0.3 to 1.0.4 ([#4488](https://github.com/opensearch-project/OpenSearch/pull/4488)) - Bump `reactor-netty-core` from 1.0.19 to 1.0.22 ([#4447](https://github.com/opensearch-project/OpenSearch/pull/4447)) - Bump `reactive-streams` from 1.0.3 to 1.0.4 ([#4488](https://github.com/opensearch-project/OpenSearch/pull/4488)) - Bump `reactor-core` from 3.4.23 to 3.5.1 ([#5604](https://github.com/opensearch-project/OpenSearch/pull/5604)) - Bump `jempbox` from 1.8.16 to 1.8.17 ([#4550](https://github.com/opensearch-project/OpenSearch/pull/4550)) - Bump `spock-core` from 2.1-groovy-3.0 to 2.3-groovy-3.0 ([#5315](https://github.com/opensearch-project/OpenSearch/pull/5315)) -- Update to Gradle 7.6 and JDK-19 ([#4973](https://github.com/opensearch-project/OpenSearch/pull/4973)) -- Update Apache Lucene to 9.5.0-snapshot-d5cef1c ([#5570](https://github.com/opensearch-project/OpenSearch/pull/5570)) +- Bump to Gradle 7.6 and JDK-19 ([#4973](https://github.com/opensearch-project/OpenSearch/pull/4973)) +- Bump Apache Lucene to 9.5.0-snapshot-d5cef1c ([#5570](https://github.com/opensearch-project/OpenSearch/pull/5570)) - Bump antlr4 from 4.9.3 to 4.11.1 ([#4546](https://github.com/opensearch-project/OpenSearch/pull/4546)) - Bump `maven-model` from 3.6.2 to 3.8.6 ([#5599](https://github.com/opensearch-project/OpenSearch/pull/5599)) - Bump `maxmind-db` from 2.1.0 to 3.0.0 ([#5601](https://github.com/opensearch-project/OpenSearch/pull/5601)) -- Bumps `protobuf-java` from 3.21.11 to 3.21.12 ([#5603](https://github.com/opensearch-project/OpenSearch/pull/5603)) -- Bumps `azure-core-http-netty` from 1.12.7 to 1.12.8 -- Bumps `wiremock-jre8-standalone` from 2.33.2 to 2.35.0 -- Bumps `gson` from 2.10 to 2.10.1 -- Bumps `json-schema-validator` from 1.0.73 to 1.0.76 -- Bumps `jna` from 5.11.0 to 5.13.0 -- Bumps `joni` from 2.1.44 to 2.1.45 -- Bumps `commons-io:commons-io` from 2.7 to 2.11.0 -- Bumps `org.jruby.joni:joni` from 2.1.45 to 2.1.48 -- Bumps `org.apache.ant:ant` from 1.10.12 to 1.10.13 -- Bumps `com.azure:azure-storage-common` from 12.18.1 to 12.19.3 +- Bump `protobuf-java` from 3.21.11 to 3.21.12 ([#5603](https://github.com/opensearch-project/OpenSearch/pull/5603)) +- Bump `azure-core-http-netty` from 1.12.7 to 1.12.8 +- Bump `wiremock-jre8-standalone` from 2.33.2 to 2.35.0 +- Bump `gson` from 2.10 to 2.10.1 +- Bump `json-schema-validator` from 1.0.73 to 1.0.76 +- Bump `jna` from 5.11.0 to 5.13.0 +- Bump `joni` from 2.1.44 to 2.1.45 +- Bump `commons-io:commons-io` from 2.7 to 2.11.0 +- Bump `org.jruby.joni:joni` from 2.1.45 to 2.1.48 +- Bump `org.apache.ant:ant` from 1.10.12 to 1.10.13 +- Bump `com.azure:azure-storage-common` from 12.18.1 to 12.19.3 - Bump `wiremock-jre8-standalone` from 2.33.2 to 2.35.0 - Bump `gson` from 2.10 to 2.10.1 - Bump `json-schema-validator` from 1.0.73 to 1.0.76 @@ -98,17 +98,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased 2.x] ### Added -- Adding index create block when all nodes have breached high disk watermark ([#5852](https://github.com/opensearch-project/OpenSearch/pull/5852)) -- Added cluster manager throttling stats in nodes/stats API ([#5790](https://github.com/opensearch-project/OpenSearch/pull/5790)) -- Added support for feature flags in opensearch.yml ([#4959](https://github.com/opensearch-project/OpenSearch/pull/4959)) +- Add index create block when all nodes have breached high disk watermark ([#5852](https://github.com/opensearch-project/OpenSearch/pull/5852)) +- Add cluster manager throttling stats in nodes/stats API ([#5790](https://github.com/opensearch-project/OpenSearch/pull/5790)) +- Add support for feature flags in opensearch.yml ([#4959](https://github.com/opensearch-project/OpenSearch/pull/4959)) - Add query for initialized extensions ([#5658](https://github.com/opensearch-project/OpenSearch/pull/5658)) - Add update-index-settings allowlist for searchable snapshot ([#5907](https://github.com/opensearch-project/OpenSearch/pull/5907)) - Add new cat/segment_replication API to surface Segment Replication metrics ([#5718](https://github.com/opensearch-project/OpenSearch/pull/5718)). - Replace latches with CompletableFutures for extensions ([#5646](https://github.com/opensearch-project/OpenSearch/pull/5646)) - Add GeoTile and GeoHash Grid aggregations on GeoShapes. ([#5589](https://github.com/opensearch-project/OpenSearch/pull/5589)) - Add support to disallow search request with preference parameter with strict weighted shard routing([#5874](https://github.com/opensearch-project/OpenSearch/pull/5874)) -- Added support to apply index create block ([#4603](https://github.com/opensearch-project/OpenSearch/issues/4603)) -- Adds support for minimum compatible version for extensions ([#6003](https://github.com/opensearch-project/OpenSearch/pull/6003)) +- Add support to apply index create block ([#4603](https://github.com/opensearch-project/OpenSearch/issues/4603)) +- Add support for minimum compatible version for extensions ([#6003](https://github.com/opensearch-project/OpenSearch/pull/6003)) - Add a guardrail to limit maximum number of shard on the cluster ([#6143](https://github.com/opensearch-project/OpenSearch/pull/6143)) - Add cancellation of in-flight SearchTasks based on resource consumption ([#5606](https://github.com/opensearch-project/OpenSearch/pull/5605)) - Add support for ppc64le architecture ([#5459](https://github.com/opensearch-project/OpenSearch/pull/5459)) diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java index b83cd74402eb3..8695591d2c74e 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java @@ -20,7 +20,6 @@ import static org.hamcrest.core.StringContains.containsString; -@OpenSearchIntegTestCase.ClusterScope(numDataNodes = 0, numClientNodes = 0, scope = OpenSearchIntegTestCase.Scope.TEST) public class BasicAuthenticationIT extends HttpSmokeTestCaseWithIdentity { public void testBasicAuthSuccess() throws Exception { diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java index 412487e944aa9..14801b665f14f 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/AuthTokenHandler.java @@ -10,8 +10,6 @@ import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.UsernamePasswordToken; import org.opensearch.identity.tokens.BasicAuthToken; @@ -23,8 +21,6 @@ */ class AuthTokenHandler { - private static final Logger logger = LogManager.getLogger(AuthTokenHandler.class); - /** * Translates into shiro auth token from the given header token * @param authenticationToken the token from which to translate diff --git a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java index 2a9b17d5870e9..375fc0d4ff587 100644 --- a/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java +++ b/modules/identity-shiro/src/main/java/org/opensearch/identity/shiro/ShiroSubject.java @@ -23,6 +23,12 @@ public class ShiroSubject implements Subject { private final AuthTokenHandler authTokenHandler; private final org.apache.shiro.subject.Subject shiroSubject; + /** + * Creates a new shiro subject for use with the IdentityPlugin + * Cannot return null + * @param authTokenHandler Used to extract auth header info + * @param subject The specific subject being authc/z'd + */ public ShiroSubject(final AuthTokenHandler authTokenHandler, final org.apache.shiro.subject.Subject subject) { this.authTokenHandler = Objects.requireNonNull(authTokenHandler); this.shiroSubject = Objects.requireNonNull(subject); diff --git a/server/src/main/java/org/opensearch/identity/NamedPrincipal.java b/server/src/main/java/org/opensearch/identity/NamedPrincipal.java index 8de05d9bd9330..8de801b749700 100644 --- a/server/src/main/java/org/opensearch/identity/NamedPrincipal.java +++ b/server/src/main/java/org/opensearch/identity/NamedPrincipal.java @@ -15,6 +15,11 @@ */ public class NamedPrincipal implements Principal { + /** + * Represents a principal which has not been authenticated + */ + public static final NamedPrincipal UNAUTHENTICATED = new NamedPrincipal("Unauthenticated"); + private final String name; /** @@ -47,4 +52,14 @@ public int hashCode() { public String toString() { return "NamedPrincipal(" + "name=" + name + ")"; } + + /** + * Returns the NamedPrincipal instanced, should only be used for UNAUTHENTICATED + * + * @return The specific principal instance + */ + public Principal getPrincipal() { + return this; + } + } diff --git a/server/src/main/java/org/opensearch/identity/NativePrincipal.java b/server/src/main/java/org/opensearch/identity/NativePrincipal.java deleted file mode 100644 index b6c4901dc9ac7..0000000000000 --- a/server/src/main/java/org/opensearch/identity/NativePrincipal.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.opensearch.identity; - -import java.security.Principal; - -/** - * Available OpenSearch internal principals - * - * @opensearch.experimental - */ -public class NativePrincipal { - - /** - * Represents a principal which has not been authenticated - */ - public static final NativePrincipal UNAUTHENTICATED = new NativePrincipal("Unauthenticated"); - - private final Principal principal; - - NativePrincipal(final String principal) { - this.principal = new NamedPrincipal(principal); - } - - /** - * Returns the underlying principal for this - */ - public Principal getPrincipal() { - return principal; - } - -} diff --git a/server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java b/server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java index e4d17a8c2a25d..382961def275f 100644 --- a/server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java +++ b/server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java @@ -20,6 +20,10 @@ */ public class NoopIdentityPlugin implements IdentityPlugin { + /** + * Get the currect subject + * @return Must never return null + */ @Override public Subject getSubject() { return new NoopSubject(); diff --git a/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java b/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java index b15acc1dcc1e0..d30615b2a7e6a 100644 --- a/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java +++ b/server/src/main/java/org/opensearch/identity/noop/NoopSubject.java @@ -11,7 +11,7 @@ import java.security.Principal; import java.util.Objects; -import org.opensearch.identity.NativePrincipal; +import org.opensearch.identity.NamedPrincipal; import org.opensearch.identity.tokens.AuthToken; import org.opensearch.identity.Subject; @@ -26,7 +26,7 @@ public class NoopSubject implements Subject { @Override public Principal getPrincipal() { - return NativePrincipal.UNAUTHENTICATED.getPrincipal(); + return NamedPrincipal.UNAUTHENTICATED.getPrincipal(); } @Override diff --git a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java index a8855eb1727ea..4cb15f4ab3cbe 100644 --- a/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java +++ b/server/src/main/java/org/opensearch/plugins/IdentityPlugin.java @@ -19,6 +19,8 @@ public interface IdentityPlugin { /** * Get the current subject + * + * Should never return null * */ public Subject getSubject(); } diff --git a/server/src/main/java/org/opensearch/rest/RestController.java b/server/src/main/java/org/opensearch/rest/RestController.java index 2d3ead5fa17f0..9aefae64e7adf 100644 --- a/server/src/main/java/org/opensearch/rest/RestController.java +++ b/server/src/main/java/org/opensearch/rest/RestController.java @@ -519,7 +519,7 @@ private void handleBadRequest(String uri, RestRequest.Method method, RestChannel } /** - * Attempts to extracts auth token and login. + * Attempts to extract auth token and login. * * @returns false if there was an error and the request should not continue being dispatched * */ @@ -543,7 +543,8 @@ private boolean handleAuthenticateUser(final RestRequest request, final RestChan ); channel.sendResponse(bytesRestResponse); } catch (final Exception _ignored) { - // TODO: clean this up + final BytesRestResponse bytesRestResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, _ignored.getMessage()); + channel.sendResponse(bytesRestResponse); } return false; } From 8e79a34273ac7b0d283c794e5950636800ce86d9 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Fri, 21 Apr 2023 16:47:53 -0400 Subject: [PATCH 17/33] Spotless Signed-off-by: Stephen Crawford --- .../java/org/opensearch/identity/BasicAuthenticationIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java index 8695591d2c74e..7dc9da4c1bf8b 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java @@ -12,7 +12,6 @@ import org.opensearch.client.RequestOptions; import org.opensearch.client.Response; import org.opensearch.client.ResponseException; -import org.opensearch.test.OpenSearchIntegTestCase; import org.opensearch.rest.RestStatus; import java.nio.charset.StandardCharsets; From b3a42db60f9bc70a2692df0bb94464e302ef912c Mon Sep 17 00:00:00 2001 From: Stephen Crawford <65832608+scrawfor99@users.noreply.github.com> Date: Fri, 21 Apr 2023 16:58:31 -0400 Subject: [PATCH 18/33] Update server/src/main/java/org/opensearch/rest/RestController.java Haha oops. Co-authored-by: Andriy Redko Signed-off-by: Stephen Crawford <65832608+scrawfor99@users.noreply.github.com> --- server/src/main/java/org/opensearch/rest/RestController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/opensearch/rest/RestController.java b/server/src/main/java/org/opensearch/rest/RestController.java index 9aefae64e7adf..638dd7442a891 100644 --- a/server/src/main/java/org/opensearch/rest/RestController.java +++ b/server/src/main/java/org/opensearch/rest/RestController.java @@ -542,7 +542,7 @@ private boolean handleAuthenticateUser(final RestRequest request, final RestChan e.getMessage() ); channel.sendResponse(bytesRestResponse); - } catch (final Exception _ignored) { + } catch (final Exception ex) { final BytesRestResponse bytesRestResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, _ignored.getMessage()); channel.sendResponse(bytesRestResponse); } From 613cbe09f9c1d3a66775aa2385529486528d03cb Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Fri, 21 Apr 2023 17:14:43 -0400 Subject: [PATCH 19/33] fix changelog Signed-off-by: Stephen Crawford --- CHANGELOG.md | 61 ++++++++++++++++++++-------------------------------- 1 file changed, 23 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3ab31286aa49..a4d479d0c825d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,45 +12,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Dependencies - Bump `log4j-core` from 2.18.0 to 2.19.0 -- Bump `reactor-netty-http` from 1.0.24 to 1.1.2 - Bump `reactor-netty-http` from 1.0.18 to 1.1.2 - Bump `jettison` from 1.5.0 to 1.5.3 - Bump `forbiddenapis` from 3.3 to 3.4 - Bump `avro` from 1.11.0 to 1.11.1 - Bump `woodstox-core` from 6.3.0 to 6.3.1 - Bump `xmlbeans` from 5.1.0 to 5.1.1 ([#4354](https://github.com/opensearch-project/OpenSearch/pull/4354)) -- Bump `azure-storage-common` from 12.18.0 to 12.18.1 ([#4164](https://github.com/opensearch-project/OpenSearch/pull/4664)) - Bump `org.gradle.test-retry` from 1.4.0 to 1.4.1 ([#4411](https://github.com/opensearch-project/OpenSearch/pull/4411)) - Bump `reactive-streams` from 1.0.3 to 1.0.4 ([#4488](https://github.com/opensearch-project/OpenSearch/pull/4488)) -- Bump `reactor-netty-core` from 1.0.19 to 1.0.22 ([#4447](https://github.com/opensearch-project/OpenSearch/pull/4447)) -- Bump `reactive-streams` from 1.0.3 to 1.0.4 ([#4488](https://github.com/opensearch-project/OpenSearch/pull/4488)) -- Bump `reactor-core` from 3.4.23 to 3.5.1 ([#5604](https://github.com/opensearch-project/OpenSearch/pull/5604)) +- Bump `antlr4` from 4.9.3 to 4.11.1 ([#4546](https://github.com/opensearch-project/OpenSearch/pull/4546)) - Bump `jempbox` from 1.8.16 to 1.8.17 ([#4550](https://github.com/opensearch-project/OpenSearch/pull/4550)) +- Bump `Gradle` to 7.6 and `Java` to JDK-19 ([#4973](https://github.com/opensearch-project/OpenSearch/pull/4973)) - Bump `spock-core` from 2.1-groovy-3.0 to 2.3-groovy-3.0 ([#5315](https://github.com/opensearch-project/OpenSearch/pull/5315)) -- Bump to Gradle 7.6 and JDK-19 ([#4973](https://github.com/opensearch-project/OpenSearch/pull/4973)) -- Bump Apache Lucene to 9.5.0-snapshot-d5cef1c ([#5570](https://github.com/opensearch-project/OpenSearch/pull/5570)) -- Bump antlr4 from 4.9.3 to 4.11.1 ([#4546](https://github.com/opensearch-project/OpenSearch/pull/4546)) +- Bump `Apache Lucene` to 9.5.0-snapshot-d5cef1c ([#5570](https://github.com/opensearch-project/OpenSearch/pull/5570)) - Bump `maven-model` from 3.6.2 to 3.8.6 ([#5599](https://github.com/opensearch-project/OpenSearch/pull/5599)) - Bump `maxmind-db` from 2.1.0 to 3.0.0 ([#5601](https://github.com/opensearch-project/OpenSearch/pull/5601)) -- Bump `protobuf-java` from 3.21.11 to 3.21.12 ([#5603](https://github.com/opensearch-project/OpenSearch/pull/5603)) +- Bump `reactor-core` from 3.4.23 to 3.5.1 ([#5604](https://github.com/opensearch-project/OpenSearch/pull/5604)) - Bump `azure-core-http-netty` from 1.12.7 to 1.12.8 -- Bump `wiremock-jre8-standalone` from 2.33.2 to 2.35.0 - Bump `gson` from 2.10 to 2.10.1 -- Bump `json-schema-validator` from 1.0.73 to 1.0.76 - Bump `jna` from 5.11.0 to 5.13.0 -- Bump `joni` from 2.1.44 to 2.1.45 - Bump `commons-io:commons-io` from 2.7 to 2.11.0 - Bump `org.jruby.joni:joni` from 2.1.45 to 2.1.48 - Bump `org.apache.ant:ant` from 1.10.12 to 1.10.13 - Bump `com.azure:azure-storage-common` from 12.18.1 to 12.19.3 - Bump `wiremock-jre8-standalone` from 2.33.2 to 2.35.0 -- Bump `gson` from 2.10 to 2.10.1 -- Bump `json-schema-validator` from 1.0.73 to 1.0.76 -- Bump `jna` from 5.11.0 to 5.13.0 -- Bump `joni` from 2.1.44 to 2.1.45 -- Bump `commons-io:commons-io` from 2.7 to 2.11.0 -- Bump `org.jruby.joni:joni` from 2.1.45 to 2.1.48 -- Bump `com.google.code.gson:gson` from 2.10 to 2.10.1 - Bump `com.maxmind.geoip2:geoip2` from 4.0.0 to 4.0.1 - Bump `com.networknt:json-schema-validator` from 1.0.76 to 1.0.78 - Bump `com.netflix.nebula:gradle-info-plugin` from 12.0.0 to 12.1.0 @@ -59,13 +44,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Bump `org.apache.commons:commons-configuration2` from 2.8.0 to 2.9.0 - Bump `com.netflix.nebula:nebula-publishing-plugin` from 19.2.0 to 20.2.0 - Bump `com.netflix.nebula.ospackage-base` from 11.0.0 to 11.2.0 -- Bump `org.apache.commons:commons-compress` from 1.22 to 1.23.0 - Bump `com.google.protobuf:protobuf-java` from 3.22.2 to 3.22.3 ### Changed - [CCR] Add getHistoryOperationsFromTranslog method to fetch the history snapshot from translogs ([#3948](https://github.com/opensearch-project/OpenSearch/pull/3948)) -- Relax visibility of the HTTP_CHANNEL_KEY and HTTP_SERVER_CHANNEL_KEY to make it possible for the plugins to access associated Netty4HttpChannel / Netty4HttpServerChannel instance ([#4638](https://github.com/opensearch-project/OpenSearch/pull/4638)) - Migrate client transports to Apache HttpClient / Core 5.x ([#4459](https://github.com/opensearch-project/OpenSearch/pull/4459)) +- Relax visibility of the HTTP_CHANNEL_KEY and HTTP_SERVER_CHANNEL_KEY to make it possible for the plugins to access associated Netty4HttpChannel / Netty4HttpServerChannel instance ([#4638](https://github.com/opensearch-project/OpenSearch/pull/4638)) - Change http code on create index API with bad input raising NotXContentException from 500 to 400 ([#4773](https://github.com/opensearch-project/OpenSearch/pull/4773)) - Change http code for DecommissioningFailedException from 500 to 400 ([#5283](https://github.com/opensearch-project/OpenSearch/pull/5283)) - Require MediaType in Strings.toString API ([#6009](https://github.com/opensearch-project/OpenSearch/pull/6009)) @@ -74,17 +58,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Deprecated ### Removed +- Remove LegacyESVersion.V_7_0_* and V_7_1_* Constants ([#2768](https://github.com/opensearch-project/OpenSearch/pull/2768)) - Remove deprecated code to add node name into log pattern of log4j property file ([#4568](https://github.com/opensearch-project/OpenSearch/pull/4568)) - Unused object and import within TransportClusterAllocationExplainAction ([#4639](https://github.com/opensearch-project/OpenSearch/pull/4639)) -- Remove LegacyESVersion.V_7_0_* and V_7_1_* Constants ([#2768](https://https://github.com/opensearch-project/OpenSearch/pull/2768)) - Remove LegacyESVersion.V_7_2_ and V_7_3_ Constants ([#4702](https://github.com/opensearch-project/OpenSearch/pull/4702)) - Always auto release the flood stage block ([#4703](https://github.com/opensearch-project/OpenSearch/pull/4703)) - Remove LegacyESVersion.V_7_4_ and V_7_5_ Constants ([#4704](https://github.com/opensearch-project/OpenSearch/pull/4704)) - Remove Legacy Version support from Snapshot/Restore Service ([#4728](https://github.com/opensearch-project/OpenSearch/pull/4728)) +- Remove LegacyESVersion.V_7_6_ and V_7_7_ Constants ([#4837](https://github.com/opensearch-project/OpenSearch/pull/4837)) - Remove deprecated serialization logic from pipeline aggs ([#4847](https://github.com/opensearch-project/OpenSearch/pull/4847)) -- Remove unused private methods ([#4926](https://github.com/opensearch-project/OpenSearch/pull/4926)) - Remove LegacyESVersion.V_7_8_ and V_7_9_ Constants ([#4855](https://github.com/opensearch-project/OpenSearch/pull/4855)) -- Remove LegacyESVersion.V_7_6_ and V_7_7_ Constants ([#4837](https://github.com/opensearch-project/OpenSearch/pull/4837)) +- Remove unused private methods ([#4926](https://github.com/opensearch-project/OpenSearch/pull/4926)) - Remove LegacyESVersion.V_7_10_ Constants ([#5018](https://github.com/opensearch-project/OpenSearch/pull/5018)) - Remove Version.V_1_ Constants ([#5021](https://github.com/opensearch-project/OpenSearch/pull/5021)) - Remove custom Map, List and Set collection classes ([#6871](https://github.com/opensearch-project/OpenSearch/pull/6871)) @@ -98,25 +82,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased 2.x] ### Added -- Add index create block when all nodes have breached high disk watermark ([#5852](https://github.com/opensearch-project/OpenSearch/pull/5852)) -- Add cluster manager throttling stats in nodes/stats API ([#5790](https://github.com/opensearch-project/OpenSearch/pull/5790)) + - Add support for feature flags in opensearch.yml ([#4959](https://github.com/opensearch-project/OpenSearch/pull/4959)) -- Add query for initialized extensions ([#5658](https://github.com/opensearch-project/OpenSearch/pull/5658)) -- Add update-index-settings allowlist for searchable snapshot ([#5907](https://github.com/opensearch-project/OpenSearch/pull/5907)) -- Add new cat/segment_replication API to surface Segment Replication metrics ([#5718](https://github.com/opensearch-project/OpenSearch/pull/5718)). -- Replace latches with CompletableFutures for extensions ([#5646](https://github.com/opensearch-project/OpenSearch/pull/5646)) +- Add support to apply index create block ([#4603](https://github.com/opensearch-project/OpenSearch/issues/4603)) +- Add support for ppc64le architecture ([#5459](https://github.com/opensearch-project/OpenSearch/pull/5459)) - Add GeoTile and GeoHash Grid aggregations on GeoShapes. ([#5589](https://github.com/opensearch-project/OpenSearch/pull/5589)) +- Add cancellation of in-flight SearchTasks based on resource consumption ([#5606](https://github.com/opensearch-project/OpenSearch/pull/5605)) +- Replace latches with CompletableFutures for extensions ([#5646](https://github.com/opensearch-project/OpenSearch/pull/5646)) +- Add query for initialized extensions ([#5658](https://github.com/opensearch-project/OpenSearch/pull/5658)) +- Add new cat/segment_replication API to surface Segment Replication metrics ([#5718](https://github.com/opensearch-project/OpenSearch/pull/5718)) +- Add cluster manager throttling stats in nodes/stats API ([#5790](https://github.com/opensearch-project/OpenSearch/pull/5790)) +- Add index create block when all nodes have breached high disk watermark ([#5852](https://github.com/opensearch-project/OpenSearch/pull/5852)) - Add support to disallow search request with preference parameter with strict weighted shard routing([#5874](https://github.com/opensearch-project/OpenSearch/pull/5874)) -- Add support to apply index create block ([#4603](https://github.com/opensearch-project/OpenSearch/issues/4603)) +- Add update-index-settings allowlist for searchable snapshot ([#5907](https://github.com/opensearch-project/OpenSearch/pull/5907)) +- Add identity and access control extension point ([#5925](https://github.com/opensearch-project/OpenSearch/pull/5925)) - Add support for minimum compatible version for extensions ([#6003](https://github.com/opensearch-project/OpenSearch/pull/6003)) -- Add a guardrail to limit maximum number of shard on the cluster ([#6143](https://github.com/opensearch-project/OpenSearch/pull/6143)) -- Add cancellation of in-flight SearchTasks based on resource consumption ([#5606](https://github.com/opensearch-project/OpenSearch/pull/5605)) -- Add support for ppc64le architecture ([#5459](https://github.com/opensearch-project/OpenSearch/pull/5459)) - [Segment Replication] Add primary weight factor for balanced primary distribution ([#6017](https://github.com/opensearch-project/OpenSearch/pull/6017)) -- Add a setting to control auto release of OpenSearch managed index creation block ([#6277](https://github.com/opensearch-project/OpenSearch/pull/6277)) +- Add a guardrail to limit maximum number of shard on the cluster ([#6143](https://github.com/opensearch-project/OpenSearch/pull/6143)) - Fix timeout error when adding a document to an index with extension running ([#6275](https://github.com/opensearch-project/OpenSearch/pull/6275)) -- Clean up temporary files created during segment merge incase segment merge fails ([#6324](https://github.com/opensearch-project/OpenSearch/pull/6324)) -- Add identity and access control extension point ([5925](https://github.com/opensearch-project/OpenSearch/pull/5925)) +- Add a setting to control auto release of OpenSearch managed index creation block ([#6277](https://github.com/opensearch-project/OpenSearch/pull/6277)) +- Clean up temporary files created during segment merge encase segment merge fails ([#6324](https://github.com/opensearch-project/OpenSearch/pull/6324)) - [Extensions] Moving Extensions APIs to protobuf serialization. ([#6960](https://github.com/opensearch-project/OpenSearch/pull/6960)) ### Dependencies @@ -124,8 +109,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Changed - Use ReplicationFailedException instead of OpensearchException in ReplicationTarget ([#4725](https://github.com/opensearch-project/OpenSearch/pull/4725)) - [Refactor] Use local opensearch.common.SetOnce instead of lucene's utility class ([#5947](https://github.com/opensearch-project/OpenSearch/pull/5947)) -- Cluster health call to throw decommissioned exception for local decommissioned node([#6008](https://github.com/opensearch-project/OpenSearch/pull/6008)) - [Refactor] core.common to new opensearch-common library ([#5976](https://github.com/opensearch-project/OpenSearch/pull/5976)) +- Cluster health call to throw decommissioned exception for local decommissioned node([#6008](https://github.com/opensearch-project/OpenSearch/pull/6008)) - Cluster local health call to throw exception if node is decommissioned or weighed away ([#6198](https://github.com/opensearch-project/OpenSearch/pull/6198)) From 3c93f26ec924b2168edc4fed880b0a62ba9f113e Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Mon, 24 Apr 2023 12:30:06 -0400 Subject: [PATCH 20/33] Move to use nomral smoketest Signed-off-by: Stephen Crawford --- modules/identity-shiro/build.gradle | 1 + .../HttpSmokeTestCaseWithIdentity.java | 2 +- qa/smoke-test-http/build.gradle | 4 +- .../http/IdentityAuthenticationIT.java | 88 +++++++++++++++++++ .../org/opensearch/rest/RestController.java | 2 +- 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 qa/smoke-test-http/src/test/java/org/opensearch/http/IdentityAuthenticationIT.java diff --git a/modules/identity-shiro/build.gradle b/modules/identity-shiro/build.gradle index 67e1dbafba043..95a80a2e37a7a 100644 --- a/modules/identity-shiro/build.gradle +++ b/modules/identity-shiro/build.gradle @@ -30,6 +30,7 @@ dependencies { testImplementation project(path: ':modules:transport-netty4') // for http testImplementation project(path: ':plugins:transport-nio') // for http testImplementation "org.mockito:mockito-core:${versions.mockito}" + testImplementation project(path: ':client:rest-high-level') } /* diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java index b39a4a2ef85d7..da7ceaa2406fb 100644 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java +++ b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java @@ -23,7 +23,7 @@ import java.util.Collection; /** - * Abstract Rest Test Case installs and enables ShiroIdentityPlugin and removes mock + * Abstract Rest Test Case installs and enables ShiroIdentityPlugin and removes mock * http transport to enable REST requests against a test cluster * * @opensearch.experimental diff --git a/qa/smoke-test-http/build.gradle b/qa/smoke-test-http/build.gradle index 2402c9b807283..d4cce3f57165c 100644 --- a/qa/smoke-test-http/build.gradle +++ b/qa/smoke-test-http/build.gradle @@ -35,7 +35,9 @@ apply plugin: 'opensearch.test-with-dependencies' dependencies { testImplementation project(path: ':modules:transport-netty4') // for http - testImplementation project(path: ':plugins:transport-nio') // for http + testImplementation project(path: ':plugins:transport-nio') + testImplementation project(path: ':modules:identity-shiro') + testImplementation project(path: ':modules:identity-shiro') // for http } integTest { diff --git a/qa/smoke-test-http/src/test/java/org/opensearch/http/IdentityAuthenticationIT.java b/qa/smoke-test-http/src/test/java/org/opensearch/http/IdentityAuthenticationIT.java new file mode 100644 index 0000000000000..13b9f93f4d0bd --- /dev/null +++ b/qa/smoke-test-http/src/test/java/org/opensearch/http/IdentityAuthenticationIT.java @@ -0,0 +1,88 @@ +/* + * 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.http; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; +import org.opensearch.client.Request; +import org.opensearch.client.RequestOptions; +import org.opensearch.client.Response; +import org.opensearch.client.ResponseException; +import org.opensearch.common.settings.Settings; +import org.opensearch.common.util.FeatureFlags; +import org.opensearch.identity.shiro.ShiroIdentityPlugin; +import org.opensearch.plugins.Plugin; +import org.opensearch.rest.RestStatus; +import org.opensearch.test.OpenSearchIntegTestCase; +import org.opensearch.transport.Netty4ModulePlugin; +import org.opensearch.transport.nio.NioTransportPlugin; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.core.StringContains.containsString; + +@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.SUITE, supportsDedicatedMasters = false, numDataNodes = 1) +public class IdentityAuthenticationIT extends HttpSmokeTestCase { + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.builder() + .put(super.nodeSettings(nodeOrdinal)) + .put(FeatureFlags.IDENTITY, true) + .build(); + } + + @Override + protected Collection> nodePlugins() { + return Arrays.asList(getTestTransportPlugin(), Netty4ModulePlugin.class, NioTransportPlugin.class, ShiroIdentityPlugin.class); + } + + + public void testBasicAuthSuccess() throws Exception { + final Response response = createHealthRequest("Basic YWRtaW46YWRtaW4="); // admin:admin + final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); + + assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); + assertThat(content, containsString("green")); + } + + public void testBasicAuthUnauthorized_invalidHeader() throws Exception { + final Response response = createHealthRequest("Basic aaaa"); // invalid username password + final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); + + assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); + assertThat(content, containsString("Illegally formed basic authorization header")); + } + + public void testBasicAuthUnauthorized_wrongPassword() throws Exception { + final Response response = createHealthRequest("Basic YWRtaW46aW52YWxpZFBhc3N3b3Jk"); // admin:invalidPassword + final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); + + assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); + } + + public void testBasicAuthUnauthorized_unknownUser() throws Exception { + final Response response = createHealthRequest("Basic dXNlcjpkb2VzTm90RXhpc3Q="); // user:doesNotExist + final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); + + assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); + } + + private Response createHealthRequest(final String authorizationHeaderValue) throws Exception { + final Request request = new Request("GET", "/_cluster/health"); + final RequestOptions options = RequestOptions.DEFAULT.toBuilder().addHeader("Authorization", authorizationHeaderValue).build(); + request.setOptions(options); + + try { + final Response response = getRestClient().performRequest(request); + return response; + } catch (final ResponseException re) { + return re.getResponse(); + } + } +} diff --git a/server/src/main/java/org/opensearch/rest/RestController.java b/server/src/main/java/org/opensearch/rest/RestController.java index 638dd7442a891..113f7940de571 100644 --- a/server/src/main/java/org/opensearch/rest/RestController.java +++ b/server/src/main/java/org/opensearch/rest/RestController.java @@ -543,7 +543,7 @@ private boolean handleAuthenticateUser(final RestRequest request, final RestChan ); channel.sendResponse(bytesRestResponse); } catch (final Exception ex) { - final BytesRestResponse bytesRestResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, _ignored.getMessage()); + final BytesRestResponse bytesRestResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, ex.getMessage()); channel.sendResponse(bytesRestResponse); } return false; From c81dca842b22297f805c0191597c630866798804 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Mon, 24 Apr 2023 12:32:18 -0400 Subject: [PATCH 21/33] Remove sub dirs Signed-off-by: Stephen Crawford --- .../identity/BasicAuthenticationIT.java | 66 -------------- .../HttpSmokeTestCaseWithIdentity.java | 90 ------------------- 2 files changed, 156 deletions(-) delete mode 100644 modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java delete mode 100644 modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java deleted file mode 100644 index 7dc9da4c1bf8b..0000000000000 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/BasicAuthenticationIT.java +++ /dev/null @@ -1,66 +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.identity; - -import org.opensearch.client.Request; -import org.opensearch.client.RequestOptions; -import org.opensearch.client.Response; -import org.opensearch.client.ResponseException; -import org.opensearch.rest.RestStatus; - -import java.nio.charset.StandardCharsets; -import static org.hamcrest.Matchers.equalTo; - -import static org.hamcrest.core.StringContains.containsString; - -public class BasicAuthenticationIT extends HttpSmokeTestCaseWithIdentity { - - public void testBasicAuthSuccess() throws Exception { - final Response response = createHealthRequest("Basic YWRtaW46YWRtaW4="); // admin:admin - final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); - - assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); - assertThat(content, containsString("green")); - } - - public void testBasicAuthUnauthorized_invalidHeader() throws Exception { - final Response response = createHealthRequest("Basic aaaa"); // invalid username password - final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); - - assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); - assertThat(content, containsString("Illegally formed basic authorization header")); - } - - public void testBasicAuthUnauthorized_wrongPassword() throws Exception { - final Response response = createHealthRequest("Basic YWRtaW46aW52YWxpZFBhc3N3b3Jk"); // admin:invalidPassword - final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); - - assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); - } - - public void testBasicAuthUnauthorized_unknownUser() throws Exception { - final Response response = createHealthRequest("Basic dXNlcjpkb2VzTm90RXhpc3Q="); // user:doesNotExist - final String content = new String(response.getEntity().getContent().readAllBytes(), StandardCharsets.UTF_8); - - assertThat(content, response.getStatusLine().getStatusCode(), equalTo(RestStatus.UNAUTHORIZED.getStatus())); - } - - private Response createHealthRequest(final String authorizationHeaderValue) throws Exception { - final Request request = new Request("GET", "/_cluster/health"); - final RequestOptions options = RequestOptions.DEFAULT.toBuilder().addHeader("Authorization", authorizationHeaderValue).build(); - request.setOptions(options); - - try { - final Response response = getRestClient().performRequest(request); - return response; - } catch (final ResponseException re) { - return re.getResponse(); - } - } -} diff --git a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java b/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java deleted file mode 100644 index da7ceaa2406fb..0000000000000 --- a/modules/identity-shiro/src/internalClusterTest/java/org/opensearch/identity/HttpSmokeTestCaseWithIdentity.java +++ /dev/null @@ -1,90 +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.identity; - -import org.opensearch.common.network.NetworkModule; -import org.opensearch.common.settings.Settings; -import org.opensearch.identity.shiro.ShiroIdentityPlugin; -import org.opensearch.plugins.Plugin; -import org.opensearch.test.OpenSearchIntegTestCase; -import org.opensearch.transport.Netty4ModulePlugin; -import org.opensearch.transport.nio.MockNioTransportPlugin; -import org.opensearch.transport.nio.NioTransportPlugin; -import org.junit.BeforeClass; -import org.opensearch.common.util.FeatureFlags; - -import java.util.Arrays; -import java.util.Collection; - -/** - * Abstract Rest Test Case installs and enables ShiroIdentityPlugin and removes mock - * http transport to enable REST requests against a test cluster - * - * @opensearch.experimental - */ -@OpenSearchIntegTestCase.ClusterScope(numDataNodes = 0, numClientNodes = 0, scope = OpenSearchIntegTestCase.Scope.TEST) -public abstract class HttpSmokeTestCaseWithIdentity extends OpenSearchIntegTestCase { - - private static String nodeTransportTypeKey; - private static String nodeHttpTypeKey; - private static String clientTypeKey; - - @SuppressWarnings("unchecked") - @BeforeClass - public static void setUpTransport() { - nodeTransportTypeKey = getTypeKey(randomFrom(getTestTransportPlugin(), Netty4ModulePlugin.class, NioTransportPlugin.class)); - nodeHttpTypeKey = getHttpTypeKey(randomFrom(Netty4ModulePlugin.class, NioTransportPlugin.class)); - clientTypeKey = getTypeKey(randomFrom(getTestTransportPlugin(), Netty4ModulePlugin.class, NioTransportPlugin.class)); - } - - private static String getTypeKey(Class clazz) { - if (clazz.equals(MockNioTransportPlugin.class)) { - return MockNioTransportPlugin.MOCK_NIO_TRANSPORT_NAME; - } else if (clazz.equals(NioTransportPlugin.class)) { - return NioTransportPlugin.NIO_TRANSPORT_NAME; - } else { - assert clazz.equals(Netty4ModulePlugin.class); - return Netty4ModulePlugin.NETTY_TRANSPORT_NAME; - } - } - - private static String getHttpTypeKey(Class clazz) { - if (clazz.equals(NioTransportPlugin.class)) { - return NioTransportPlugin.NIO_HTTP_TRANSPORT_NAME; - } else { - assert clazz.equals(Netty4ModulePlugin.class); - return Netty4ModulePlugin.NETTY_HTTP_TRANSPORT_NAME; - } - } - - @Override - protected boolean addMockHttpTransport() { - return false; // enable http - } - - @Override - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.builder() - .put(super.nodeSettings(nodeOrdinal)) - .put(NetworkModule.TRANSPORT_TYPE_KEY, nodeTransportTypeKey) - .put(NetworkModule.HTTP_TYPE_KEY, nodeHttpTypeKey) - .put(FeatureFlags.IDENTITY, true) - .build(); - } - - @Override - protected Collection> nodePlugins() { - return Arrays.asList(getTestTransportPlugin(), Netty4ModulePlugin.class, NioTransportPlugin.class, ShiroIdentityPlugin.class); - } - - @Override - protected boolean ignoreExternalCluster() { - return true; - } -} From b57866221c47766d2be84cbdf2b23ea7ea0a89d0 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Tue, 25 Apr 2023 15:49:35 -0400 Subject: [PATCH 22/33] Peter's feedback Signed-off-by: Stephen Crawford --- CHANGELOG.md | 7 ++++--- gradle/missing-javadoc.gradle | 2 -- .../opensearch/common/settings/FeatureFlagSettings.java | 3 +-- .../main/java/org/opensearch/common/util/FeatureFlags.java | 2 -- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4d479d0c825d..2b21de11ce2d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Bump `woodstox-core` from 6.3.0 to 6.3.1 - Bump `xmlbeans` from 5.1.0 to 5.1.1 ([#4354](https://github.com/opensearch-project/OpenSearch/pull/4354)) - Bump `org.gradle.test-retry` from 1.4.0 to 1.4.1 ([#4411](https://github.com/opensearch-project/OpenSearch/pull/4411)) +- Bump `reactor-netty-core` from 1.0.19 to 1.0.22 ([#4447](https://github.com/opensearch-project/OpenSearch/pull/4447)) - Bump `reactive-streams` from 1.0.3 to 1.0.4 ([#4488](https://github.com/opensearch-project/OpenSearch/pull/4488)) - Bump `antlr4` from 4.9.3 to 4.11.1 ([#4546](https://github.com/opensearch-project/OpenSearch/pull/4546)) - Bump `jempbox` from 1.8.16 to 1.8.17 ([#4550](https://github.com/opensearch-project/OpenSearch/pull/4550)) @@ -32,12 +33,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Bump `gson` from 2.10 to 2.10.1 - Bump `jna` from 5.11.0 to 5.13.0 - Bump `commons-io:commons-io` from 2.7 to 2.11.0 -- Bump `org.jruby.joni:joni` from 2.1.45 to 2.1.48 +- Bump `org.jruby.joni:joni` from 2.1.44 to 2.1.48 - Bump `org.apache.ant:ant` from 1.10.12 to 1.10.13 -- Bump `com.azure:azure-storage-common` from 12.18.1 to 12.19.3 +- Bump `com.azure:azure-storage-common` from 12.18.0 to 12.19.3 - Bump `wiremock-jre8-standalone` from 2.33.2 to 2.35.0 - Bump `com.maxmind.geoip2:geoip2` from 4.0.0 to 4.0.1 -- Bump `com.networknt:json-schema-validator` from 1.0.76 to 1.0.78 +- Bump `com.networknt:json-schema-validator` from 1.0.73 to 1.0.78 - Bump `com.netflix.nebula:gradle-info-plugin` from 12.0.0 to 12.1.0 - Bump `com.avast.gradle:gradle-docker-compose-plugin` from 0.16.11 to 0.16.12 - Bump `org.apache.commons:commons-compress` from 1.22 to 1.23.0 diff --git a/gradle/missing-javadoc.gradle b/gradle/missing-javadoc.gradle index 1e2aa6b4cc839..7f971b2470052 100644 --- a/gradle/missing-javadoc.gradle +++ b/gradle/missing-javadoc.gradle @@ -6,7 +6,6 @@ * compatible open source license. */ -import javax.annotation.Nullable import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.PathSensitivity; import org.gradle.internal.jvm.Jvm @@ -107,7 +106,6 @@ configure([ project(":modules:aggs-matrix-stats"), project(":modules:analysis-common"), project(":modules:geo"), - project(":modules:identity-shiro"), project(":modules:ingest-common"), project(":modules:ingest-geoip"), project(":modules:ingest-user-agent"), diff --git a/server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java b/server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java index 97fb299dc12c3..0f819ad02bf0e 100644 --- a/server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/FeatureFlagSettings.java @@ -37,8 +37,7 @@ protected FeatureFlagSettings( FeatureFlags.SEGMENT_REPLICATION_EXPERIMENTAL_SETTING, FeatureFlags.REMOTE_STORE_SETTING, FeatureFlags.EXTENSIONS_SETTING, - FeatureFlags.SEARCH_PIPELINE_SETTING, - FeatureFlags.IDENTITY_SETTING + FeatureFlags.SEARCH_PIPELINE_SETTING ) ) ); diff --git a/server/src/main/java/org/opensearch/common/util/FeatureFlags.java b/server/src/main/java/org/opensearch/common/util/FeatureFlags.java index 29aa51c8c95e4..ea77f5dcf41f8 100644 --- a/server/src/main/java/org/opensearch/common/util/FeatureFlags.java +++ b/server/src/main/java/org/opensearch/common/util/FeatureFlags.java @@ -96,6 +96,4 @@ public static boolean isEnabled(String featureFlagName) { public static final Setting EXTENSIONS_SETTING = Setting.boolSetting(EXTENSIONS, false, Property.NodeScope); public static final Setting SEARCH_PIPELINE_SETTING = Setting.boolSetting(SEARCH_PIPELINE, false, Property.NodeScope); - - public static final Setting IDENTITY_SETTING = Setting.boolSetting(IDENTITY, false, Property.NodeScope); } From 033d38cae726b1a21085cbe06968e6bb2c551bdf Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Tue, 25 Apr 2023 15:55:35 -0400 Subject: [PATCH 23/33] Peter's feedback fix Signed-off-by: Stephen Crawford --- gradle/missing-javadoc.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle/missing-javadoc.gradle b/gradle/missing-javadoc.gradle index 7f971b2470052..02ae2dbbbea97 100644 --- a/gradle/missing-javadoc.gradle +++ b/gradle/missing-javadoc.gradle @@ -6,6 +6,8 @@ * compatible open source license. */ + +import javax.annotation.Nullable import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.PathSensitivity; import org.gradle.internal.jvm.Jvm From d05dadc2a5ec07263d945838fede41ba662f7ee0 Mon Sep 17 00:00:00 2001 From: Stephen Crawford Date: Wed, 26 Apr 2023 09:38:40 -0400 Subject: [PATCH 24/33] Swap changelog, add javadocs Signed-off-by: Stephen Crawford --- .idea/inspectionProfiles/Project_Default.xml | 3 + CHANGELOG.md | 66 +++++-------------- .../identity/shiro/ShiroIdentityPlugin.java | 10 +++ .../identity/shiro/ShiroSubject.java | 19 ++++++ .../shiro/realm/BCryptPasswordMatcher.java | 6 ++ .../identity/shiro/realm/OpenSearchRealm.java | 33 ++++++++++ .../opensearch/identity/shiro/realm/User.java | 16 +++++ 7 files changed, 105 insertions(+), 48 deletions(-) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 5cf789707c58c..ece87b3eed38a 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,6 +2,9 @@