diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5832378bff..5041f4b625 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @cliu123 @cwperks @DarshitChanpura @davidlago @peternied @RyanL1997 @scrawfor99 @reta +* @cliu123 @cwperks @DarshitChanpura @davidlago @peternied @RyanL1997 @scrawfor99 @reta @willyborankin diff --git a/.github/actions/create-bwc-build/action.yaml b/.github/actions/create-bwc-build/action.yaml index b6ee3d5478..fcfa612a7d 100644 --- a/.github/actions/create-bwc-build/action.yaml +++ b/.github/actions/create-bwc-build/action.yaml @@ -5,7 +5,7 @@ inputs: plugin-branch: description: 'The branch of the plugin that should be built, e.g "2.2", "1.x"' required: true - + outputs: built-version: description: 'The version of OpenSearch that was associated with this branch' diff --git a/.github/actions/start-opensearch-with-one-plugin/action.yml b/.github/actions/start-opensearch-with-one-plugin/action.yml index b562851b0c..fa5681c422 100644 --- a/.github/actions/start-opensearch-with-one-plugin/action.yml +++ b/.github/actions/start-opensearch-with-one-plugin/action.yml @@ -70,7 +70,7 @@ runs: # Run any configuration scripts - name: Run Setup Script for Linux if: ${{ runner.os == 'Linux' && inputs.setup-script-name != '' }} - run: | + run: | echo "running linux setup" chmod +x ./${{ inputs.setup-script-name }}.sh ./${{ inputs.setup-script-name }}.sh diff --git a/.github/workflows/delete_backport_branch.yml b/.github/workflows/delete_backport_branch.yml index 35417b46b3..9964fe1ec8 100644 --- a/.github/workflows/delete_backport_branch.yml +++ b/.github/workflows/delete_backport_branch.yml @@ -1,9 +1,9 @@ name: Delete merged branch of the backport PRs -on: +on: pull_request: types: - closed - + jobs: delete-branch: runs-on: ubuntu-latest diff --git a/.github/workflows/plugin_install.yml b/.github/workflows/plugin_install.yml index 75289d560a..301c193e11 100644 --- a/.github/workflows/plugin_install.yml +++ b/.github/workflows/plugin_install.yml @@ -38,7 +38,7 @@ jobs: if: ${{ runner.os == 'Linux' }} run: | cat > setup.sh <<'EOF' - chmod +x ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/plugins/${{ env.PLUGIN_NAME }}/tools/install_demo_configuration.sh + chmod +x ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/plugins/${{ env.PLUGIN_NAME }}/tools/install_demo_configuration.sh /bin/bash -c "yes | ./opensearch-${{ env.OPENSEARCH_VERSION }}-SNAPSHOT/plugins/${{ env.PLUGIN_NAME }}/tools/install_demo_configuration.sh" EOF diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a7e7d89e9a..371de48a2e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ OpenSearch is a community project that is built and maintained by people just like **you**. [This document](https://github.com/opensearch-project/.github/blob/main/CONTRIBUTING.md) explains how you can contribute to this and related projects. -Visit the following link(s) for more information on specific practices: +Visit the following link(s) for more information on specific practices: - [Triaging](./TRIAGING.md) diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 5168d01a46..358b2eac14 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -48,9 +48,9 @@ The `curl localhost:9200` call should succeed again. Kill the server with `Ctrl+ >Worth noting:\ > The version of OpenSearch and the security plugin must match as there is an explicit version check at startup. This can be a bit confusing as, for example, at the time of writing this guide, the `main` branch of this security plugin builds version `3.0.0.0-SNAPSHOT` compatible with OpenSearch `3.0.0`. Check the expected compatible version in `build.gradle` file [here](https://github.com/opensearch-project/security/blob/main/build.gradle) and make sure you get the correct branch from OpenSearch when building that project. -> +> > The line to look for: `opensearch_version = System.getProperty("opensearch.version", "x")` -> +> > Alternatively, you can find the compatible version of OpenSearch by running in project root folder > ``` > ./gradlew properties -q | grep -E '^version:' | awk '{print $2}' @@ -164,7 +164,7 @@ Checkstyle enforces several rules within this codebase. Sometimes it will be nec *Execute Checkstyle* ``` -./gradlew checkstyleMain checkstyleTest +./gradlew checkstyleMain checkstyleTest ``` *Example violation* diff --git a/DEVELOPING_WITH_DOCKER.md b/DEVELOPING_WITH_DOCKER.md index a0ba045846..6616e11313 100644 --- a/DEVELOPING_WITH_DOCKER.md +++ b/DEVELOPING_WITH_DOCKER.md @@ -1,40 +1,40 @@ # Developing with Docker -Docker is a powerful tool that can be used to quickly spin up an OpenSearch cluster. When you follow the steps to run [OpenSearch with Docker](https://opensearch.org/docs/latest/install-and-configure/install-opensearch/docker/), you will find the Security Plugin already included in the basic distribution. +Docker is a powerful tool that can be used to quickly spin up an OpenSearch cluster. When you follow the steps to run [OpenSearch with Docker](https://opensearch.org/docs/latest/install-and-configure/install-opensearch/docker/), you will find the Security Plugin already included in the basic distribution. - [Developing with Docker](#developing-with-docker) - [Configuring Security](#configuring-security) - [Mounting Local Volumes](#mounting-local-volumes) - [Example docker-compose](#example-docker-compose) - -## Configuring Security -By default, the Docker installation of OpenSearch does not enable the Security plugin. In order to enable Security development, you will need set `DISABLE_SECURITY_PLUGIN=false`, as well as change `DISABLE_INSTALL_DEMO_CONFIG` and `DISABLE_SECURITY_DASHBOARDS_PLUGIN`. This will install the demo certificates, and allow you to develop with realistic Security configurations. An example of a completely configured docker-compose file is shown below. +## Configuring Security + +By default, the Docker installation of OpenSearch does not enable the Security plugin. In order to enable Security development, you will need set `DISABLE_SECURITY_PLUGIN=false`, as well as change `DISABLE_INSTALL_DEMO_CONFIG` and `DISABLE_SECURITY_DASHBOARDS_PLUGIN`. This will install the demo certificates, and allow you to develop with realistic Security configurations. An example of a completely configured docker-compose file is shown below. > Warning: You should never use the demo certificates for a production environment. Instead, you will need to follow the steps on [configuring security](https://opensearch.org/docs/latest/security/configuration/index/) before using the cluster for production. -### Mounting Local Volumes +### Mounting Local Volumes -In order to test development changes with an OpenSearch Docker-installation, you will need to mount the volumes in your docker-compose file. +In order to test development changes with an OpenSearch Docker-installation, you will need to mount the volumes in your docker-compose file. -To update your cluster to have local changes, follow these steps: +To update your cluster to have local changes, follow these steps: 1. First you will need to make changes in your local `opensearch-project/security` repository. For this example, assume your fork is cloned into a directory called `security`. -2. After you make changes to your cloned repository, you will need to run `./gradlew assemble`. This will create a `.jar` file you can mount into the Docker container. The file will be located at `./security/build/distributions/opensearch-security-.0-SNAPSHOT.jar`, where the `` field is simply the OpenSearch distribution. -3. You will then need to navigate to your `docker-compose.yml` file where you are running you OpenSearch cluster from. For this example, let us assume this is in another directory called `opensearch-docker`. -4. Modify the compose file, so that in the `volumes:` section of each node configuration (the default configuration will have `opensearch-node1` and `opensearch-node2`), you have a new line which reads `~/security/build/distributions/opensearch-security-.0-SNAPSHOT.jar:/usr/share/opensearch/plugins/opensearch-security/opensearch-security-.0.jar`. This line should be added to the volumes section of all nodes in the compose file. You will not need to add it to the `opensearch-dashboards` section. -5. You can now restart the Docker container by running `docker-compose down -v` and `docker-compose up`. Your changes will now be live in the OpenSearch cluster instance. +2. After you make changes to your cloned repository, you will need to run `./gradlew assemble`. This will create a `.jar` file you can mount into the Docker container. The file will be located at `./security/build/distributions/opensearch-security-.0-SNAPSHOT.jar`, where the `` field is simply the OpenSearch distribution. +3. You will then need to navigate to your `docker-compose.yml` file where you are running you OpenSearch cluster from. For this example, let us assume this is in another directory called `opensearch-docker`. +4. Modify the compose file, so that in the `volumes:` section of each node configuration (the default configuration will have `opensearch-node1` and `opensearch-node2`), you have a new line which reads `~/security/build/distributions/opensearch-security-.0-SNAPSHOT.jar:/usr/share/opensearch/plugins/opensearch-security/opensearch-security-.0.jar`. This line should be added to the volumes section of all nodes in the compose file. You will not need to add it to the `opensearch-dashboards` section. +5. You can now restart the Docker container by running `docker-compose down -v` and `docker-compose up`. Your changes will now be live in the OpenSearch cluster instance. -### Example docker-compose +### Example docker-compose -This is an example of a completely configured docker-compose file for a local installation of the 2.5.0 version of OpenSearch. +This is an example of a completely configured docker-compose file for a local installation of the 2.5.0 version of OpenSearch. ``` version: '3' services: opensearch-node1: - image: opensearchstaging/opensearch:2.5.0 # This is a image of the 2.5.0 distribution + image: opensearchstaging/opensearch:2.5.0 # This is a image of the 2.5.0 distribution environment: - cluster.name=opensearch-cluster - node.name=opensearch-node1 @@ -58,7 +58,7 @@ services: # - ./config/opensearch.yml:/usr/share/opensearch/config/opensearch.yml # These paths are relative to the location of the docker-compose file # - ./config/esnode.pem:/usr/share/opensearch/config/esnode.pem # - ./config/esnode-key.pem:/usr/share/opensearch/config/esnode-key.pem - # - ./config/root-ca.pem:/usr/share/opensearch/config/root-ca.pem + # - ./config/root-ca.pem:/usr/share/opensearch/config/root-ca.pem # - ./config/opensearch-security/audit.yml:/usr/share/opensearch/config/opensearch-security/audit.yml # - ./config/opensearch-security/tenants.yml:/usr/share/opensearch/config/opensearch-security/tenants.yml # - /OpenSearch-Snapshots:/mnt/snapshots # This is where your snapshots would be stored @@ -86,8 +86,8 @@ services: # - ./config/root-ca.pem:/usr/share/opensearch/config/root-ca.pem # - ./config/opensearch-security/audit.yml:/usr/share/opensearch/config/opensearch-security/audit.yml # - ./config/opensearch-security/tenants.yml:/usr/share/opensearch/config/opensearch-security/tenants.yml - # - /OpenSearch-Snapshots:/mnt/snapshots - # - /security/build/distributions/opensearch-security-2.5.0.0-SNAPSHOT.jar:/usr/share/opensearch/plugins/opensearch-security/opensearch-security-2.5.0.0.jar + # - /OpenSearch-Snapshots:/mnt/snapshots + # - /security/build/distributions/opensearch-security-2.5.0.0-SNAPSHOT.jar:/usr/share/opensearch/plugins/opensearch-security/opensearch-security-2.5.0.0.jar networks: - opensearch-net opensearch-dashboards: diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 4605135a16..f27e192923 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -22,6 +22,7 @@ This document contains a list of maintainers in this repo. See [opensearch-proje | Ryan Liang | [RyanL1997](https://github.com/RyanL1997) | Amazon | | Stephen Crawford | [scrawfor99](https://github.com/scrawfor99) | Amazon | | Andriy Redko | [reta](https://github.com/reta) | Aiven | +| Andrey Pleskach | [willyborankin](https://github.com/willyborankin) | Aiven | ## Practices diff --git a/README.md b/README.md index b9ca3b80da..5c89f5d72d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -[![CI](https://github.com/opensearch-project/security/workflows/CI/badge.svg?branch=main)](https://github.com/opensearch-project/security/actions) [![](https://img.shields.io/github/issues/opensearch-project/security/untriaged?labelColor=red)](https://github.com/opensearch-project/security/issues?q=is%3Aissue+is%3Aopen+label%3A"untriaged") [![](https://img.shields.io/github/issues/opensearch-project/security/security%20vulnerability?labelColor=red)](https://github.com/opensearch-project/security/issues?q=is%3Aissue+is%3Aopen+label%3A"security%20vulnerability") [![](https://img.shields.io/github/issues/opensearch-project/security)](https://github.com/opensearch-project/security/issues) [![](https://img.shields.io/github/issues-pr/opensearch-project/security)](https://github.com/opensearch-project/security/pulls) +[![CI](https://github.com/opensearch-project/security/workflows/CI/badge.svg?branch=main)](https://github.com/opensearch-project/security/actions) [![](https://img.shields.io/github/issues/opensearch-project/security/untriaged?labelColor=red)](https://github.com/opensearch-project/security/issues?q=is%3Aissue+is%3Aopen+label%3A"untriaged") [![](https://img.shields.io/github/issues/opensearch-project/security/security%20vulnerability?labelColor=red)](https://github.com/opensearch-project/security/issues?q=is%3Aissue+is%3Aopen+label%3A"security%20vulnerability") [![](https://img.shields.io/github/issues/opensearch-project/security)](https://github.com/opensearch-project/security/issues) [![](https://img.shields.io/github/issues-pr/opensearch-project/security)](https://github.com/opensearch-project/security/pulls) [![](https://img.shields.io/codecov/c/gh/opensearch-project/security)](https://app.codecov.io/gh/opensearch-project/security) [![](https://img.shields.io/github/issues/opensearch-project/security/v2.4.0)](https://github.com/opensearch-project/security/issues?q=is%3Aissue+is%3Aopen+label%3A"v2.4.0") [![](https://img.shields.io/github/issues/opensearch-project/security/v3.0.0)](https://github.com/opensearch-project/security/issues?q=is%3Aissue+is%3Aopen+label%3A"v3.0.0") [![Slack](https://img.shields.io/badge/Slack-4A154B?&logo=slack&logoColor=white)](https://opensearch.slack.com/archives/C051Y637FKK) -## Announcement: The Slack workspace is live! Please join the [conversation](https://opensearch.slack.com/archives/C051Y637FKK). +## Announcement: The Slack workspace is live! Please join the [conversation](https://opensearch.slack.com/archives/C051Y637FKK). @@ -37,7 +37,7 @@ OpenSearch Security is a plugin for OpenSearch that offers encryption, authentic * Full data in transit encryption * Node-to-node encryption * Certificate revocation lists -* Hot Certificate renewal +* Hot Certificate renewal ### Authentication * Internal user database @@ -60,7 +60,7 @@ OpenSearch Security is a plugin for OpenSearch that offers encryption, authentic * REST management API ### Audit/Compliance logging -* Audit logging +* Audit logging * Compliance logging for GDPR, HIPAA, PCI, SOX and ISO compliance ### OpenSearch Dashboards multi-tenancy @@ -126,7 +126,7 @@ sequenceDiagram participant OpenSearch participant SecurityPlugin participant Cluster as Plugin - + Client->>OpenSearch: Request OpenSearch->>SecurityPlugin: Request SecurityPlugin->>SecurityPlugin: Add Auth information to request context @@ -188,7 +188,7 @@ If you discover a potential security issue in this project we ask that you notif ## License -This code is licensed under the Apache 2.0 License. +This code is licensed under the Apache 2.0 License. ## Copyright diff --git a/TRIAGING.md b/TRIAGING.md index 2c4ea32fdf..bb61779a7c 100644 --- a/TRIAGING.md +++ b/TRIAGING.md @@ -20,7 +20,7 @@ If you have an issue you'd like to bring forth please consider getting a link to ### Is there an agenda for each week? -Meetings are lightly structured as follows: +Meetings are lightly structured as follows: 1. Announcements: If there are any announcements to be made they will happen at the start of the meeting. 2. Review of new issues: The meetings always start with reviewing all untriaged [issues](https://github.com/search?q=label%3Auntriaged+is%3Aopen++repo%3Aopensearch-project%2Fsecurity+repo%3Aopensearch-project%2Fsecurity-dashboards-plugin&type=issues&ref=advsearch&s=created&o=desc) for the security and security-dashboards repositories. @@ -53,7 +53,7 @@ There you can find answers to many common questions as well as speak with implem ### What if my issue is critical to OpenSearch operations, do I have to wait for the weekly meeting for it to be addressed? -All new issues for the [security](https://github.com/opensearch-project/security/issues?q=is%3Aissue+is%3Aopen+label%3Auntriaged) repo and [security-dashboards](https://github.com/opensearch-project/security-dashboards-plugin/issues?q=is%3Aissue+is%3Aopen+-label%3Atriaged) repo are reviewed daily to check for critical issues which require immediate triaging. If an issue relates to a severe concern for OpenSearch operation, it will be triaged by a maintainer mid-week. You can still come to discuss an issue at the following meeting even if it has already been triaged during the week. +All new issues for the [security](https://github.com/opensearch-project/security/issues?q=is%3Aissue+is%3Aopen+label%3Auntriaged) repo and [security-dashboards](https://github.com/opensearch-project/security-dashboards-plugin/issues?q=is%3Aissue+is%3Aopen+-label%3Atriaged) repo are reviewed daily to check for critical issues which require immediate triaging. If an issue relates to a severe concern for OpenSearch operation, it will be triaged by a maintainer mid-week. You can still come to discuss an issue at the following meeting even if it has already been triaged during the week. ### Is this where I should bring up potential security vulnerabilities? diff --git a/build.gradle b/build.gradle index ef187e290f..15eaad0803 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ plugins { id 'idea' id 'jacoco' id 'maven-publish' - id 'com.diffplug.spotless' version '6.18.0' + id 'com.diffplug.spotless' version '6.19.0' id 'checkstyle' id 'com.netflix.nebula.ospackage' version "11.1.0" id "org.gradle.test-retry" version "1.5.2" @@ -70,23 +70,58 @@ apply plugin: 'opensearch.opensearchplugin' apply plugin: 'opensearch.pluginzip' apply plugin: 'opensearch.rest-test' apply plugin: 'opensearch.testclusters' - -licenseFile = rootProject.file('LICENSE.txt') -noticeFile = rootProject.file('NOTICE.txt') +// apply from: 'gradle/formatting.gradle' spotless { java { + // Normally this isn't necessary, but we have Java sources in + // non-standard places + target '**/com/amazon/dlic/**/*.java' + target '**/com/amazon/security/**/*.java' + target '**/test/**/*.java' + + removeUnusedImports() + eclipse().configFile rootProject.file('formatter/formatterConfig.xml') + trimTrailingWhitespace() + endWithNewline(); + // note: you can use an empty string for all the imports you didn't specify explicitly, and '\\#` prefix for static imports importOrder('java', 'javax', '', 'com.amazon', 'org.opensearch', '\\#') - targetExclude('src/integrationTest/**') + + custom 'Refuse wildcard imports', { + // Wildcard imports can't be resolved; fail the build + if (it =~ /\s+import .*\*;/) { + throw new AssertionError("Do not use wildcard imports. 'spotlessApply' cannot resolve this issue.") + } + } + + // See DEVELOPER_GUIDE.md for details of when to enable this. + if (System.getProperty('spotless.paddedcell') != null) { + paddedCell() + } + } + format 'misc', { + target '*.md', '*.gradle', '**/*.json', '**/*.yaml', '**/*.yml', '**/*.svg' + + trimTrailingWhitespace() + endWithNewline() } - format("integrationTest", JavaExtension) { - target('src/integrationTest/java/**/*.java') + format('javaFoo', JavaExtension) { + importOrder('java', 'javax', '', 'com.amazon', 'org.opensearch', '\\#') - indentWithTabs(4) + target '**/*.java' + targetExclude '**/com/amazon/dlic/**/*.java' + targetExclude '**/com/amazon/security/**/*.java' + targetExclude '**/test/**/*.java' + + trimTrailingWhitespace() + endWithNewline(); } } +licenseFile = rootProject.file('LICENSE.txt') +noticeFile = rootProject.file('NOTICE.txt') + spotbugs { includeFilter = file('spotbugs-include.xml') } @@ -301,6 +336,7 @@ configurations { force "io.netty:netty-transport:${versions.netty}" force "io.netty:netty-transport-native-unix-common:${versions.netty}" force "org.apache.bcel:bcel:6.6.0" // This line should be removed once Spotbugs is upgraded to 4.7.4 + force "com.github.luben:zstd-jni:${versions.zstd}" } } @@ -346,7 +382,6 @@ task integrationTest(type: Test) { check.dependsOn integrationTest dependencies { - implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5' implementation "org.opensearch.plugin:transport-netty4-client:${opensearch_version}" implementation "org.opensearch.client:opensearch-rest-high-level-client:${opensearch_version}" implementation "org.apache.httpcomponents.client5:httpclient5-cache:${versions.httpclient5}" @@ -424,7 +459,7 @@ dependencies { runtimeOnly 'com.fasterxml.woodstox:woodstox-core:6.4.0' runtimeOnly 'org.apache.ws.xmlschema:xmlschema-core:2.2.5' runtimeOnly 'org.apache.santuario:xmlsec:2.2.3' - runtimeOnly 'com.github.luben:zstd-jni:1.5.2-1' + runtimeOnly "com.github.luben:zstd-jni:${versions.zstd}" runtimeOnly 'org.checkerframework:checker-qual:3.5.0' runtimeOnly "org.bouncycastle:bcpkix-jdk15on:${versions.bouncycastle}" diff --git a/bwc-test/src/test/java/SecurityBackwardsCompatibilityIT.java b/bwc-test/src/test/java/SecurityBackwardsCompatibilityIT.java index 1afc1b88d5..59c2a26c03 100644 --- a/bwc-test/src/test/java/SecurityBackwardsCompatibilityIT.java +++ b/bwc-test/src/test/java/SecurityBackwardsCompatibilityIT.java @@ -13,15 +13,11 @@ import java.util.stream.Collectors; import org.junit.Assume; -import org.junit.Assert; import org.junit.Before; -import org.opensearch.client.Response; -import org.opensearch.common.settings.Settings; -import org.opensearch.rest.RestStatus; -import org.opensearch.test.rest.OpenSearchRestTestCase; import org.opensearch.Version; -import com.google.common.collect.ImmutableMap; +import org.opensearch.common.settings.Settings; +import org.opensearch.test.rest.OpenSearchRestTestCase; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasItem; @@ -56,14 +52,13 @@ protected boolean preserveTemplatesUponCompletion() { @Override protected final Settings restClientSettings() { - return Settings - .builder() - .put(super.restClientSettings()) - // increase the timeout here to 90 seconds to handle long waits for a green - // cluster health. the waits for green need to be longer than a minute to - // account for delayed shards - .put(OpenSearchRestTestCase.CLIENT_SOCKET_TIMEOUT, "90s") - .build(); + return Settings.builder() + .put(super.restClientSettings()) + // increase the timeout here to 90 seconds to handle long waits for a green + // cluster health. the waits for green need to be longer than a minute to + // account for delayed shards + .put(OpenSearchRestTestCase.CLIENT_SOCKET_TIMEOUT, "90s") + .build(); } public void testBasicBackwardsCompatibility() throws Exception { diff --git a/config/roles.yml b/config/roles.yml index e4eb3ac535..d03b47ab28 100644 --- a/config/roles.yml +++ b/config/roles.yml @@ -205,6 +205,8 @@ index_management_full_access: - "cluster:admin/opendistro/ism/*" - "cluster:admin/opendistro/rollup/*" - "cluster:admin/opendistro/transform/*" + - "cluster:admin/opensearch/controlcenter/lron/*" + - "cluster:admin/opensearch/notifications/channels/get" - "cluster:admin/opensearch/notifications/feature/publish" index_permissions: - index_patterns: diff --git a/formatter/formatterConfig.xml b/formatter/formatterConfig.xml new file mode 100644 index 0000000000..713e55274d --- /dev/null +++ b/formatter/formatterConfig.xml @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gradle/formatting.gradle b/gradle/formatting.gradle new file mode 100644 index 0000000000..40ae51afb1 --- /dev/null +++ b/gradle/formatting.gradle @@ -0,0 +1,95 @@ +/* +* SPDX-License-Identifier: Apache-2.0 +* +* The OpenSearch Contributors require contributions made to +* this file be licensed under the Apache-2.0 license or a +* compatible open source license. +* +* Modifications Copyright OpenSearch Contributors. See +* GitHub history for details. +*/ + +/* + * 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. + */ + +import org.opensearch.gradle.BuildPlugin + +/* + * This script plugin configures formatting for Java source using Spotless + * for Gradle. Since the act of formatting existing source can interfere + * with developers' workflows, we don't automatically format all code + * (yet). Instead, we maintain a list of projects that are excluded from + * formatting, until we reach a point where we can comfortably format them + * in one go without too much disruption. + * + * Any new sub-projects must not be added to the exclusions list! + * + * To perform a reformat, run: + * + * ./gradlew spotlessApply + * + * To check the current format, run: + * + * ./gradlew spotlessJavaCheck + * + * This is also carried out by the `precommit` task. + * + * For more about Spotless, see: + * + * https://github.com/diffplug/spotless/tree/master/plugin-gradle + */ + +org.opensearch.gradle.BuildPlugin { + plugins.withType(BuildPlugin).whenPluginAdded { + project.apply plugin: "com.diffplug.spotless" + + spotless { + java { + // Normally this isn't necessary, but we have Java sources in + // non-standard places + target '**/*.java' + + removeUnusedImports() + eclipse().configFile rootProject.file('buildSrc/formatterConfig.xml') + trimTrailingWhitespace() + endWithNewline() + + custom 'Refuse wildcard imports', { + // Wildcard imports can't be resolved; fail the build + if (it =~ /\s+import .*\*;/) { + throw new AssertionError("Do not use wildcard imports. 'spotlessApply' cannot resolve this issue.") + } + } + + // See DEVELOPER_GUIDE.md for details of when to enable this. + if (System.getProperty('spotless.paddedcell') != null) { + paddedCell() + } + } + format 'misc', { + target '*.md', '*.gradle', '**/*.yaml', '**/*.yml', '**/*.svg' + + trimTrailingWhitespace() + endWithNewline() + } + } + + precommit.dependsOn 'spotlessJavaCheck' + } +} diff --git a/legacy/securityconfig_v6/action_groups.yml b/legacy/securityconfig_v6/action_groups.yml index 14c1b3082f..3faa4c5e31 100644 --- a/legacy/securityconfig_v6/action_groups.yml +++ b/legacy/securityconfig_v6/action_groups.yml @@ -128,7 +128,7 @@ CLUSTER_COMPOSITE_OPS: - "indices:admin/aliases*" - "indices:data/write/reindex" - CLUSTER_COMPOSITE_OPS_RO - + MANAGE_SNAPSHOTS: readonly: true permissions: diff --git a/legacy/securityconfig_v6/config.yml b/legacy/securityconfig_v6/config.yml index 15d5ee9973..d867a72200 100644 --- a/legacy/securityconfig_v6/config.yml +++ b/legacy/securityconfig_v6/config.yml @@ -1,14 +1,14 @@ # This is the main OpenSearch Security configuration file where authentication # and authorization is defined. -# +# # You need to configure at least one authentication domain in the authc of this file. -# An authentication domain is responsible for extracting the user credentials from -# the request and for validating them against an authentication backend like Active Directory for example. +# An authentication domain is responsible for extracting the user credentials from +# the request and for validating them against an authentication backend like Active Directory for example. # -# If more than one authentication domain is configured the first one which succeeds wins. +# If more than one authentication domain is configured the first one which succeeds wins. # If all authentication domains fail then the request is unauthenticated. # In this case an exception is thrown and/or the HTTP status is set to 401. -# +# # After authentication authorization (authz) will be applied. There can be zero or more authorizers which collect # the roles from a given backend for the authenticated user. # @@ -21,18 +21,18 @@ # For HTTP it is possible to allow anonymous authentication. If that is the case then the HTTP authenticators try to # find user credentials in the HTTP request. If credentials are found then the user gets regularly authenticated. # If none can be found the user will be authenticated as an "anonymous" user. This user has always the username "opendistro_security_anonymous" -# and one role named "opendistro_security_anonymous_backendrole". +# and one role named "opendistro_security_anonymous_backendrole". # If you enable anonymous authentication all HTTP authenticators will not challenge. -# +# # # Note: If you define more than one HTTP authenticators make sure to put non-challenging authenticators like "proxy" or "clientcert" -# first and the challenging one last. +# first and the challenging one last. # Because it's not possible to challenge a client with two different authentication methods (for example # Kerberos and Basic) only one can have the challenge flag set to true. You can cope with this situation # by using pre-authentication, e.g. sending a HTTP Basic authentication header in the request. # # Default value of the challenge flag is true. -# +# # # HTTP # basic (challenging) @@ -78,7 +78,7 @@ opendistro_security: ###### and here https://tools.ietf.org/html/rfc7239 ###### and https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Remote_IP_Valve authc: - kerberos_auth_domain: + kerberos_auth_domain: http_enabled: false transport_enabled: false order: 6 @@ -92,7 +92,7 @@ opendistro_security: strip_realm_from_principal: true authentication_backend: type: noop - basic_internal_auth_domain: + basic_internal_auth_domain: http_enabled: true transport_enabled: true order: 4 @@ -164,11 +164,11 @@ opendistro_security: password: null userbase: 'ou=people,dc=example,dc=com' # Filter to search for users (currently in the whole subtree beneath userbase) - # {0} is substituted with the username + # {0} is substituted with the username usersearch: '(sAMAccountName={0})' # Use this attribute from the user as username (if not set then DN is used) username_attribute: null - authz: + authz: roles_from_myldap: http_enabled: false transport_enabled: false @@ -191,8 +191,8 @@ opendistro_security: rolebase: 'ou=groups,dc=example,dc=com' # Filter to search for roles (currently in the whole subtree beneath rolebase) # {0} is substituted with the DN of the user - # {1} is substituted with the username - # {2} is substituted with an attribute value from user's directory entry, of the authenticated user. Use userroleattribute to specify the name of the attribute + # {1} is substituted with the username + # {2} is substituted with an attribute value from user's directory entry, of the authenticated user. Use userroleattribute to specify the name of the attribute rolesearch: '(member={0})' # Specify the name of the attribute which value should be substituted with {2} above userroleattribute: null @@ -206,12 +206,12 @@ opendistro_security: resolve_nested_roles: true userbase: 'ou=people,dc=example,dc=com' # Filter to search for users (currently in the whole subtree beneath userbase) - # {0} is substituted with the username + # {0} is substituted with the username usersearch: '(uid={0})' # Skip users matching a user name, a wildcard or a regex pattern - #skip_users: + #skip_users: # - 'cn=Michael Jackson,ou*people,o=TEST' - # - '/\S*/' + # - '/\S*/' roles_from_another_ldap: http_enabled: false transport_enabled: false diff --git a/legacy/securityconfig_v6/internal_users.yml b/legacy/securityconfig_v6/internal_users.yml index 19c5eff661..c7d177787d 100644 --- a/legacy/securityconfig_v6/internal_users.yml +++ b/legacy/securityconfig_v6/internal_users.yml @@ -19,13 +19,13 @@ logstash: roles: - logstash -#password is: kibanaserver +#password is: kibanaserver kibanaserver: readonly: true hash: $2a$12$4AcgAt3xwOWadA5s5blL6ev39OXDNhmOesEoo33eZtrq2N0YrU3H. #password is: kibanaro -kibanaro: +kibanaro: hash: $2a$12$JJSXNfTowz7Uu5ttXfeYpeYE0arACvcwlPBStB1F.MI7f0U9Z4DGC roles: - kibanauser diff --git a/legacy/securityconfig_v6/roles.yml b/legacy/securityconfig_v6/roles.yml index 68a5bd6f98..c546b85393 100644 --- a/legacy/securityconfig_v6/roles.yml +++ b/legacy/securityconfig_v6/roles.yml @@ -3,7 +3,7 @@ # - '' # indices: # '': -# '': +# '': # - '' # _dls_: '' # _fls_: @@ -15,9 +15,9 @@ # and a type. If a request is executed against all indices (or all types) then the asterix ('*') is needed. # Every role a user has will be examined if it allows the action against an index (or type). At least one role must match # for the request to be successful. If no role match then the request will be denied. Currently a match must happen within -# one single role - that means that permissions can not span multiple roles. +# one single role - that means that permissions can not span multiple roles. -# For , and simple wildcards and regular expressions are possible. +# For , and simple wildcards and regular expressions are possible. # A asterix (*) will match any character sequence (or an empty sequence) # A question mark (?) will match any single character (but NOT empty character) # Example: '*my*index' will match 'my_first_index' as well as 'myindex' but not 'myindex1' @@ -27,7 +27,7 @@ # '//' # Example: '/\S*/' will match any non whitespace characters -# Important: +# Important: # Index, alias or type names can not contain dots (.) in the or expression. # Reason is that we currently parse the config file into a OpenSearch settings object which cannot cope with dots in keys. # Workaround: Just configure something like '?kibana' instead of '.kibana' or 'my?index' instead of 'my.index' @@ -59,7 +59,7 @@ opendistro_security_readall: '*': - READ -# Read all and monitor, but no write permissions +# Read all and monitor, but no write permissions opendistro_security_readall_and_monitor: cluster: - CLUSTER_MONITOR @@ -99,7 +99,7 @@ opendistro_security_kibana_user: - INDICES_ALL '?management-beats': '*': - - INDICES_ALL + - INDICES_ALL '*': '*': - indices:data/read/field_caps* @@ -135,7 +135,7 @@ opendistro_security_kibana_server: - "indices:admin/aliases*" # For logstash and beats -opendistro_security_logstash: +opendistro_security_logstash: cluster: - CLUSTER_MONITOR - CLUSTER_COMPOSITE_OPS diff --git a/legacy/securityconfig_v6/roles_mapping.yml b/legacy/securityconfig_v6/roles_mapping.yml index b3263eb234..588ba13f6e 100644 --- a/legacy/securityconfig_v6/roles_mapping.yml +++ b/legacy/securityconfig_v6/roles_mapping.yml @@ -9,12 +9,12 @@ opendistro_security_all_access: opendistro_security_logstash: backendroles: - logstash - + opendistro_security_kibana_server: readonly: true users: - kibanaserver - + opendistro_security_kibana_user: backendroles: - kibanauser diff --git a/release-notes/opensearch-security.release-notes-2.8.0.0.md b/release-notes/opensearch-security.release-notes-2.8.0.0.md new file mode 100644 index 0000000000..32d33d83f7 --- /dev/null +++ b/release-notes/opensearch-security.release-notes-2.8.0.0.md @@ -0,0 +1,30 @@ +## 2023-06-06 Version 2.8.0.0 + +Compatible with OpenSearch 2.8.0 + +### Features + +* Identify extension Transport requests and permit handshake and extension registration actions ([#2599](https://github.com/opensearch-project/security/pull/2599)) +* Use ExtensionsManager.lookupExtensionSettingsById when verifying extension unique id ([#2749](https://github.com/opensearch-project/security/pull/2749)) +* Generate auth tokens for service accounts ([#2716](https://github.com/opensearch-project/security/pull/2716)) +* Security User Refactor ([#2594](https://github.com/opensearch-project/security/pull/2594)) +* Add score based password verification ([#2557](https://github.com/opensearch-project/security/pull/2557)) +* Usage of JWKS with JWT (w/o OpenID connect) ([#2808](https://github.com/opensearch-project/security/pull/2808)) + +### Bug Fixes + +* `deserializeSafeFromHeader` uses `context.getHeader(headerName)` instead of `context.getHeaders()` ([#2768](https://github.com/opensearch-project/security/pull/2768)) +* Fix multitency config update ([#2758](https://github.com/opensearch-project/security/pull/2758)) + +### Enhancements + +* Add default roles for SQL plugin: PPL and cross-cluster search ([#2729](https://github.com/opensearch-project/security/pull/2729)) +* Update security-analytics roles to add correlation engine apis ([#2732](https://github.com/opensearch-project/security/pull/2732)) +* Changes in role.yml for long-running operation notification feature in Index-Management repo ([#2789](https://github.com/opensearch-project/security/pull/2789)) +* Rest admin permissions ([#2411](https://github.com/opensearch-project/security/pull/2411)) +* Separate config option to enable restapi: permissions ([#2605](https://github.com/opensearch-project/security/pull/2605)) + +### Maintenance + +* Update to Gradle 8.1.1 ([#2738](https://github.com/opensearch-project/security/pull/2738)) +* Upgrade spring-core from 5.3.26 to 5.3.27 ([#2717](https://github.com/opensearch-project/security/pull/2717)) diff --git a/src/integrationTest/java/org/opensearch/node/PluginAwareNode.java b/src/integrationTest/java/org/opensearch/node/PluginAwareNode.java index 1599cd2a37..62b0199824 100644 --- a/src/integrationTest/java/org/opensearch/node/PluginAwareNode.java +++ b/src/integrationTest/java/org/opensearch/node/PluginAwareNode.java @@ -33,7 +33,7 @@ import org.opensearch.plugins.Plugin; public class PluginAwareNode extends Node { - + private final boolean clusterManagerEligible; @SafeVarargs @@ -41,7 +41,7 @@ public PluginAwareNode(boolean clusterManagerEligible, final Settings preparedSe super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, Collections.emptyMap(), null, () -> System.getenv("HOSTNAME")), Arrays.asList(plugins), true); this.clusterManagerEligible = clusterManagerEligible; } - + public boolean isClusterManagerEligible() { return clusterManagerEligible; diff --git a/src/integrationTest/java/org/opensearch/security/SecurityRolesTests.java b/src/integrationTest/java/org/opensearch/security/SecurityRolesTests.java index d93a168341..c25d28ef12 100644 --- a/src/integrationTest/java/org/opensearch/security/SecurityRolesTests.java +++ b/src/integrationTest/java/org/opensearch/security/SecurityRolesTests.java @@ -47,9 +47,9 @@ public void testSecurityRoles() throws Exception { HttpResponse response = client.getAuthInfo(); response.assertStatusCode(HttpStatus.SC_OK); - // Check username + // Check username assertThat(response.getTextFromJsonBody("/user_name"), equalTo("sr_user")); - + // Check security roles assertThat(response.getTextFromJsonBody("/roles/0"), equalTo("user_sr_user__abc_ber")); assertThat(response.getTextFromJsonBody("/roles/1"), equalTo("user_sr_user__def_efg")); diff --git a/src/integrationTest/java/org/opensearch/security/http/CommonProxyAuthenticationTests.java b/src/integrationTest/java/org/opensearch/security/http/CommonProxyAuthenticationTests.java index 244bd6b80e..c17ccb8ea3 100644 --- a/src/integrationTest/java/org/opensearch/security/http/CommonProxyAuthenticationTests.java +++ b/src/integrationTest/java/org/opensearch/security/http/CommonProxyAuthenticationTests.java @@ -36,7 +36,7 @@ abstract class CommonProxyAuthenticationTests { protected static final String ATTRIBUTE_DEPARTMENT = "department"; protected static final String ATTRIBUTE_SKILLS = "skills"; - + protected static final String USER_ATTRIBUTE_DEPARTMENT_NAME = "attr.proxy." + ATTRIBUTE_DEPARTMENT; protected static final String USER_ATTRIBUTE_SKILLS_NAME = "attr.proxy." + ATTRIBUTE_SKILLS; protected static final String USER_ATTRIBUTE_USERNAME_NAME = "attr.proxy.username"; @@ -82,7 +82,7 @@ abstract class CommonProxyAuthenticationTests { protected static final RolesMapping ROLES_MAPPING_FIRST_MATE = new RolesMapping(ROLE_ALL_INDEX_SEARCH) .backendRoles(BACKEND_ROLE_FIRST_MATE); - + protected abstract LocalCluster getCluster(); protected void shouldAuthenticateWithBasicAuthWhenProxyAuthenticationIsConfigured() { diff --git a/src/integrationTest/java/org/opensearch/security/http/JwtAuthenticationTests.java b/src/integrationTest/java/org/opensearch/security/http/JwtAuthenticationTests.java index 5875a120a4..65a4e32d7e 100644 --- a/src/integrationTest/java/org/opensearch/security/http/JwtAuthenticationTests.java +++ b/src/integrationTest/java/org/opensearch/security/http/JwtAuthenticationTests.java @@ -141,7 +141,7 @@ public void shouldAuthenticateWithJwtToken_positive() { response.assertStatusCode(200); String username = response.getTextFromJsonBody(POINTER_USERNAME); - assertThat(username, equalTo(username)); + assertThat(username, equalTo(USER_SUPERHERO)); } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuditCompliance.java b/src/integrationTest/java/org/opensearch/test/framework/AuditCompliance.java index c9d5f8b40a..d75fc0e4e5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuditCompliance.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuditCompliance.java @@ -18,89 +18,90 @@ public class AuditCompliance implements ToXContentObject { - private boolean enabled = false; - - private Boolean writeLogDiffs; - - private List readIgnoreUsers; - - private List writeWatchedIndices; - - private List writeIgnoreUsers; - - private Boolean readMetadataOnly; - - private Boolean writeMetadataOnly; - - private Boolean externalConfig; - - private Boolean internalConfig; - - public AuditCompliance enabled(boolean enabled) { - this.enabled = enabled; - this.writeLogDiffs = false; - this.readIgnoreUsers = Collections.emptyList(); - this.writeWatchedIndices = Collections.emptyList(); - this.writeIgnoreUsers = Collections.emptyList(); - this.readMetadataOnly = false; - this.writeMetadataOnly = false; - this.externalConfig = false; - this.internalConfig = false; - return this; - } - - public AuditCompliance writeLogDiffs(boolean writeLogDiffs) { - this.writeLogDiffs = writeLogDiffs; - return this; - } - - public AuditCompliance readIgnoreUsers(List list) { - this.readIgnoreUsers = list; - return this; - } - - public AuditCompliance writeWatchedIndices(List list) { - this.writeWatchedIndices = list; - return this; - } - - public AuditCompliance writeIgnoreUsers(List list) { - this.writeIgnoreUsers = list; - return this; - } - - public AuditCompliance readMetadataOnly(boolean readMetadataOnly) { - this.readMetadataOnly = readMetadataOnly; - return this; - } - - public AuditCompliance writeMetadataOnly(boolean writeMetadataOnly) { - this.writeMetadataOnly = writeMetadataOnly; - return this; - } - - public AuditCompliance externalConfig(boolean externalConfig) { - this.externalConfig = externalConfig; - return this; - } - - public AuditCompliance internalConfig(boolean internalConfig) { - this.internalConfig = internalConfig; - return this; - } - - @Override public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("enabled", enabled); - xContentBuilder.field("write_log_diffs", writeLogDiffs); - xContentBuilder.field("read_ignore_users", readIgnoreUsers); - xContentBuilder.field("write_watched_indices", writeWatchedIndices); - xContentBuilder.field("write_ignore_users", writeIgnoreUsers); - xContentBuilder.field("read_metadata_only", readMetadataOnly); - xContentBuilder.field("write_metadata_only", writeMetadataOnly); - xContentBuilder.field("external_config", externalConfig); - xContentBuilder.field("internal_config", internalConfig); - xContentBuilder.endObject(); - return xContentBuilder; - } + private boolean enabled = false; + + private Boolean writeLogDiffs; + + private List readIgnoreUsers; + + private List writeWatchedIndices; + + private List writeIgnoreUsers; + + private Boolean readMetadataOnly; + + private Boolean writeMetadataOnly; + + private Boolean externalConfig; + + private Boolean internalConfig; + + public AuditCompliance enabled(boolean enabled) { + this.enabled = enabled; + this.writeLogDiffs = false; + this.readIgnoreUsers = Collections.emptyList(); + this.writeWatchedIndices = Collections.emptyList(); + this.writeIgnoreUsers = Collections.emptyList(); + this.readMetadataOnly = false; + this.writeMetadataOnly = false; + this.externalConfig = false; + this.internalConfig = false; + return this; + } + + public AuditCompliance writeLogDiffs(boolean writeLogDiffs) { + this.writeLogDiffs = writeLogDiffs; + return this; + } + + public AuditCompliance readIgnoreUsers(List list) { + this.readIgnoreUsers = list; + return this; + } + + public AuditCompliance writeWatchedIndices(List list) { + this.writeWatchedIndices = list; + return this; + } + + public AuditCompliance writeIgnoreUsers(List list) { + this.writeIgnoreUsers = list; + return this; + } + + public AuditCompliance readMetadataOnly(boolean readMetadataOnly) { + this.readMetadataOnly = readMetadataOnly; + return this; + } + + public AuditCompliance writeMetadataOnly(boolean writeMetadataOnly) { + this.writeMetadataOnly = writeMetadataOnly; + return this; + } + + public AuditCompliance externalConfig(boolean externalConfig) { + this.externalConfig = externalConfig; + return this; + } + + public AuditCompliance internalConfig(boolean internalConfig) { + this.internalConfig = internalConfig; + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("enabled", enabled); + xContentBuilder.field("write_log_diffs", writeLogDiffs); + xContentBuilder.field("read_ignore_users", readIgnoreUsers); + xContentBuilder.field("write_watched_indices", writeWatchedIndices); + xContentBuilder.field("write_ignore_users", writeIgnoreUsers); + xContentBuilder.field("read_metadata_only", readMetadataOnly); + xContentBuilder.field("write_metadata_only", writeMetadataOnly); + xContentBuilder.field("external_config", externalConfig); + xContentBuilder.field("internal_config", internalConfig); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuditConfiguration.java b/src/integrationTest/java/org/opensearch/test/framework/AuditConfiguration.java index 783fa19af0..1b3f11cc83 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuditConfiguration.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuditConfiguration.java @@ -15,41 +15,42 @@ import org.opensearch.core.xcontent.XContentBuilder; public class AuditConfiguration implements ToXContentObject { - private final boolean enabled; + private final boolean enabled; - private AuditFilters filters; + private AuditFilters filters; - private AuditCompliance compliance; + private AuditCompliance compliance; - public AuditConfiguration(boolean enabled) { - this.filters = new AuditFilters(); - this.compliance = new AuditCompliance(); - this.enabled = enabled; - } + public AuditConfiguration(boolean enabled) { + this.filters = new AuditFilters(); + this.compliance = new AuditCompliance(); + this.enabled = enabled; + } - public boolean isEnabled() { - return enabled; - } + public boolean isEnabled() { + return enabled; + } - public AuditConfiguration filters(AuditFilters filters) { - this.filters = filters; - return this; - } + public AuditConfiguration filters(AuditFilters filters) { + this.filters = filters; + return this; + } - public AuditConfiguration compliance(AuditCompliance auditCompliance) { - this.compliance = auditCompliance; - return this; - } + public AuditConfiguration compliance(AuditCompliance auditCompliance) { + this.compliance = auditCompliance; + return this; + } - @Override public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - // json built here must be deserialized to org.opensearch.security.auditlog.config.AuditConfig - xContentBuilder.startObject(); - xContentBuilder.field("enabled", enabled); + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + // json built here must be deserialized to org.opensearch.security.auditlog.config.AuditConfig + xContentBuilder.startObject(); + xContentBuilder.field("enabled", enabled); - xContentBuilder.field("audit", filters); - xContentBuilder.field("compliance", compliance); + xContentBuilder.field("audit", filters); + xContentBuilder.field("compliance", compliance); - xContentBuilder.endObject(); - return xContentBuilder; - } + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuditFilters.java b/src/integrationTest/java/org/opensearch/test/framework/AuditFilters.java index bc9f972906..f984becefa 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuditFilters.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuditFilters.java @@ -18,104 +18,105 @@ public class AuditFilters implements ToXContentObject { - private Boolean enabledRest; - - private Boolean enabledTransport; - - private Boolean logRequestBody; - - private Boolean resolveIndices; - - private Boolean resolveBulkRequests; - - private Boolean excludeSensitiveHeaders; - - private List ignoreUsers; - - private List ignoreRequests; - - private List disabledRestCategories; - - private List disabledTransportCategories; - - public AuditFilters() { - this.enabledRest = false; - this.enabledTransport = false; - - this.logRequestBody = true; - this.resolveIndices = true; - this.resolveBulkRequests = false; - this.excludeSensitiveHeaders = true; - - this.ignoreUsers = Collections.emptyList(); - this.ignoreRequests = Collections.emptyList(); - this.disabledRestCategories = Collections.emptyList(); - this.disabledTransportCategories = Collections.emptyList(); - } - - public AuditFilters enabledRest(boolean enabled) { - this.enabledRest = enabled; - return this; - } - - public AuditFilters enabledTransport(boolean enabled) { - this.enabledTransport = enabled; - return this; - } - - public AuditFilters logRequestBody(boolean logRequestBody) { - this.logRequestBody = logRequestBody; - return this; - } - - public AuditFilters resolveIndices(boolean resolveIndices) { - this.resolveIndices = resolveIndices; - return this; - } - - public AuditFilters resolveBulkRequests(boolean resolveBulkRequests) { - this.resolveBulkRequests = resolveBulkRequests; - return this; - } - - public AuditFilters excludeSensitiveHeaders(boolean excludeSensitiveHeaders) { - this.excludeSensitiveHeaders = excludeSensitiveHeaders; - return this; - } - - public AuditFilters ignoreUsers(List ignoreUsers) { - this.ignoreUsers = ignoreUsers; - return this; - } - - public AuditFilters ignoreRequests(List ignoreRequests) { - this.ignoreRequests = ignoreRequests; - return this; - } - - public AuditFilters disabledRestCategories(List disabledRestCategories) { - this.disabledRestCategories = disabledRestCategories; - return this; - } - - public AuditFilters disabledTransportCategories(List disabledTransportCategories) { - this.disabledTransportCategories = disabledTransportCategories; - return this; - } - - @Override public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("enable_rest", enabledRest); - xContentBuilder.field("enable_transport", enabledTransport); - xContentBuilder.field("resolve_indices", resolveIndices); - xContentBuilder.field("log_request_body", logRequestBody); - xContentBuilder.field("resolve_bulk_requests", resolveBulkRequests); - xContentBuilder.field("exclude_sensitive_headers", excludeSensitiveHeaders); - xContentBuilder.field("ignore_users", ignoreUsers); - xContentBuilder.field("ignore_requests", ignoreRequests); - xContentBuilder.field("disabled_rest_categories", disabledRestCategories); - xContentBuilder.field("disabled_transport_categories", disabledTransportCategories); - xContentBuilder.endObject(); - return xContentBuilder; - } + private Boolean enabledRest; + + private Boolean enabledTransport; + + private Boolean logRequestBody; + + private Boolean resolveIndices; + + private Boolean resolveBulkRequests; + + private Boolean excludeSensitiveHeaders; + + private List ignoreUsers; + + private List ignoreRequests; + + private List disabledRestCategories; + + private List disabledTransportCategories; + + public AuditFilters() { + this.enabledRest = false; + this.enabledTransport = false; + + this.logRequestBody = true; + this.resolveIndices = true; + this.resolveBulkRequests = false; + this.excludeSensitiveHeaders = true; + + this.ignoreUsers = Collections.emptyList(); + this.ignoreRequests = Collections.emptyList(); + this.disabledRestCategories = Collections.emptyList(); + this.disabledTransportCategories = Collections.emptyList(); + } + + public AuditFilters enabledRest(boolean enabled) { + this.enabledRest = enabled; + return this; + } + + public AuditFilters enabledTransport(boolean enabled) { + this.enabledTransport = enabled; + return this; + } + + public AuditFilters logRequestBody(boolean logRequestBody) { + this.logRequestBody = logRequestBody; + return this; + } + + public AuditFilters resolveIndices(boolean resolveIndices) { + this.resolveIndices = resolveIndices; + return this; + } + + public AuditFilters resolveBulkRequests(boolean resolveBulkRequests) { + this.resolveBulkRequests = resolveBulkRequests; + return this; + } + + public AuditFilters excludeSensitiveHeaders(boolean excludeSensitiveHeaders) { + this.excludeSensitiveHeaders = excludeSensitiveHeaders; + return this; + } + + public AuditFilters ignoreUsers(List ignoreUsers) { + this.ignoreUsers = ignoreUsers; + return this; + } + + public AuditFilters ignoreRequests(List ignoreRequests) { + this.ignoreRequests = ignoreRequests; + return this; + } + + public AuditFilters disabledRestCategories(List disabledRestCategories) { + this.disabledRestCategories = disabledRestCategories; + return this; + } + + public AuditFilters disabledTransportCategories(List disabledTransportCategories) { + this.disabledTransportCategories = disabledTransportCategories; + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("enable_rest", enabledRest); + xContentBuilder.field("enable_transport", enabledTransport); + xContentBuilder.field("resolve_indices", resolveIndices); + xContentBuilder.field("log_request_body", logRequestBody); + xContentBuilder.field("resolve_bulk_requests", resolveBulkRequests); + xContentBuilder.field("exclude_sensitive_headers", excludeSensitiveHeaders); + xContentBuilder.field("ignore_users", ignoreUsers); + xContentBuilder.field("ignore_requests", ignoreRequests); + xContentBuilder.field("disabled_rest_categories", disabledRestCategories); + xContentBuilder.field("disabled_transport_categories", disabledTransportCategories); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuthFailureListeners.java b/src/integrationTest/java/org/opensearch/test/framework/AuthFailureListeners.java index 5d467bd754..472d3d8d08 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuthFailureListeners.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuthFailureListeners.java @@ -19,21 +19,21 @@ public class AuthFailureListeners implements ToXContentObject { - private Map limits = new LinkedHashMap<>(); + private Map limits = new LinkedHashMap<>(); - public AuthFailureListeners addRateLimit(RateLimiting rateLimiting) { - Objects.requireNonNull(rateLimiting, "Rate limiting is required"); - limits.put(rateLimiting.getName(), rateLimiting); - return this; - } + public AuthFailureListeners addRateLimit(RateLimiting rateLimiting) { + Objects.requireNonNull(rateLimiting, "Rate limiting is required"); + limits.put(rateLimiting.getName(), rateLimiting); + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - for(Map.Entry entry : limits.entrySet()) { - xContentBuilder.field(entry.getKey(), entry.getValue()); - } - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + for (Map.Entry entry : limits.entrySet()) { + xContentBuilder.field(entry.getKey(), entry.getValue()); + } + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuthorizationBackend.java b/src/integrationTest/java/org/opensearch/test/framework/AuthorizationBackend.java index 2d9d1c1b66..521d35ed46 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuthorizationBackend.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuthorizationBackend.java @@ -18,28 +18,28 @@ import org.opensearch.core.xcontent.XContentBuilder; public class AuthorizationBackend implements ToXContentObject { - private final String type; - private Supplier> config; + private final String type; + private Supplier> config; - public AuthorizationBackend(String type) { - this.type = type; - } + public AuthorizationBackend(String type) { + this.type = type; + } - public AuthorizationBackend config(Map ldapConfig) { - return config(() -> ldapConfig); - } + public AuthorizationBackend config(Map ldapConfig) { + return config(() -> ldapConfig); + } - public AuthorizationBackend config(Supplier> ldapConfigSupplier) { - this.config = Objects.requireNonNull(ldapConfigSupplier, "Configuration supplier is required"); - return this; - } + public AuthorizationBackend config(Supplier> ldapConfigSupplier) { + this.config = Objects.requireNonNull(ldapConfigSupplier, "Configuration supplier is required"); + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("type", type); - xContentBuilder.field("config", config.get()); - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("type", type); + xContentBuilder.field("config", config.get()); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/AuthzDomain.java b/src/integrationTest/java/org/opensearch/test/framework/AuthzDomain.java index 7d611881e0..5ccf1f9ee0 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/AuthzDomain.java +++ b/src/integrationTest/java/org/opensearch/test/framework/AuthzDomain.java @@ -19,52 +19,52 @@ */ public class AuthzDomain implements ToXContentObject { - private final String id; + private final String id; - private String description; + private String description; - private boolean httpEnabled; + private boolean httpEnabled; - private boolean transportEnabled; + private boolean transportEnabled; - private AuthorizationBackend authorizationBackend; + private AuthorizationBackend authorizationBackend; - public AuthzDomain(String id) { - this.id = id; - } + public AuthzDomain(String id) { + this.id = id; + } - public String getId() { - return id; - } + public String getId() { + return id; + } - public AuthzDomain description(String description) { - this.description = description; - return this; - } + public AuthzDomain description(String description) { + this.description = description; + return this; + } - public AuthzDomain httpEnabled(boolean httpEnabled) { - this.httpEnabled = httpEnabled; - return this; - } + public AuthzDomain httpEnabled(boolean httpEnabled) { + this.httpEnabled = httpEnabled; + return this; + } - public AuthzDomain authorizationBackend(AuthorizationBackend authorizationBackend) { - this.authorizationBackend = authorizationBackend; - return this; - } + public AuthzDomain authorizationBackend(AuthorizationBackend authorizationBackend) { + this.authorizationBackend = authorizationBackend; + return this; + } - public AuthzDomain transportEnabled(boolean transportEnabled) { - this.transportEnabled = transportEnabled; - return this; - } + public AuthzDomain transportEnabled(boolean transportEnabled) { + this.transportEnabled = transportEnabled; + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("description", description); - xContentBuilder.field("http_enabled", httpEnabled); - xContentBuilder.field("transport_enabled", transportEnabled); - xContentBuilder.field("authorization_backend", authorizationBackend); - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("description", description); + xContentBuilder.field("http_enabled", httpEnabled); + xContentBuilder.field("transport_enabled", transportEnabled); + xContentBuilder.field("authorization_backend", authorizationBackend); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/JwtConfigBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/JwtConfigBuilder.java index 5b1ea2c678..48dfa128e0 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/JwtConfigBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/JwtConfigBuilder.java @@ -17,46 +17,46 @@ import static org.apache.commons.lang3.StringUtils.isNoneBlank; public class JwtConfigBuilder { - private String jwtHeader; - private String signingKey; - private String subjectKey; - private String rolesKey; - - public JwtConfigBuilder jwtHeader(String jwtHeader) { - this.jwtHeader = jwtHeader; - return this; - } - - public JwtConfigBuilder signingKey(String signingKey) { - this.signingKey = signingKey; - return this; - } - - public JwtConfigBuilder subjectKey(String subjectKey) { - this.subjectKey = subjectKey; - return this; - } - - public JwtConfigBuilder rolesKey(String rolesKey) { - this.rolesKey = rolesKey; - return this; - } - - public Map build() { - Builder builder = new Builder<>(); - if(Objects.isNull(signingKey)) { - throw new IllegalStateException("Signing key is required."); - } - builder.put("signing_key", signingKey); - if(isNoneBlank(jwtHeader)) { - builder.put("jwt_header", jwtHeader); - } - if(isNoneBlank(subjectKey)) { - builder.put("subject_key", subjectKey); - } - if(isNoneBlank(rolesKey)) { - builder.put("roles_key", rolesKey); - } - return builder.build(); - } + private String jwtHeader; + private String signingKey; + private String subjectKey; + private String rolesKey; + + public JwtConfigBuilder jwtHeader(String jwtHeader) { + this.jwtHeader = jwtHeader; + return this; + } + + public JwtConfigBuilder signingKey(String signingKey) { + this.signingKey = signingKey; + return this; + } + + public JwtConfigBuilder subjectKey(String subjectKey) { + this.subjectKey = subjectKey; + return this; + } + + public JwtConfigBuilder rolesKey(String rolesKey) { + this.rolesKey = rolesKey; + return this; + } + + public Map build() { + Builder builder = new Builder<>(); + if (Objects.isNull(signingKey)) { + throw new IllegalStateException("Signing key is required."); + } + builder.put("signing_key", signingKey); + if (isNoneBlank(jwtHeader)) { + builder.put("jwt_header", jwtHeader); + } + if (isNoneBlank(subjectKey)) { + builder.put("subject_key", subjectKey); + } + if (isNoneBlank(rolesKey)) { + builder.put("roles_key", rolesKey); + } + return builder.build(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/LdapAuthenticationConfigBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/LdapAuthenticationConfigBuilder.java index b6519f7b87..07f1836b59 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/LdapAuthenticationConfigBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/LdapAuthenticationConfigBuilder.java @@ -20,100 +20,100 @@ * {@link LdapAuthorizationConfigBuilder} */ public class LdapAuthenticationConfigBuilder { - private boolean enableSsl = false; - private boolean enableStartTls = false; - private boolean enableSslClientAuth = false; - private boolean verifyHostnames = false; - private List hosts; - private String bindDn; - private String password; - private String userBase; - private String userSearch; - private String usernameAttribute; - - private String penTrustedCasFilePath; - - /** - * Subclass of this - */ - private final T builderSubclass; - - protected LdapAuthenticationConfigBuilder(Function thisCastFunction) { - this.builderSubclass = thisCastFunction.apply(this); - } - - public static LdapAuthenticationConfigBuilder config() { - return new LdapAuthenticationConfigBuilder<>(Function.identity()); - } - - public T enableSsl(boolean enableSsl) { - this.enableSsl = enableSsl; - return builderSubclass; - } - - public T enableStartTls(boolean enableStartTls) { - this.enableStartTls = enableStartTls; - return builderSubclass; - } - - public T enableSslClientAuth(boolean enableSslClientAuth) { - this.enableSslClientAuth = enableSslClientAuth; - return builderSubclass; - } - - public T verifyHostnames(boolean verifyHostnames) { - this.verifyHostnames = verifyHostnames; - return builderSubclass; - } - - public T hosts(List hosts) { - this.hosts = hosts; - return builderSubclass; - } - - public T bindDn(String bindDn) { - this.bindDn = bindDn; - return builderSubclass; - } - - public T password(String password) { - this.password = password; - return builderSubclass; - } - - public T userBase(String userBase) { - this.userBase = userBase; - return builderSubclass; - } - - public T userSearch(String userSearch) { - this.userSearch = userSearch; - return builderSubclass; - } - - public T usernameAttribute(String usernameAttribute) { - this.usernameAttribute = usernameAttribute; - return builderSubclass; - } - - public T penTrustedCasFilePath(String penTrustedCasFilePath) { - this.penTrustedCasFilePath = penTrustedCasFilePath; - return builderSubclass; - } - - public Map build() { - HashMap config = new HashMap<>(); - config.put("enable_ssl", enableSsl); - config.put("enable_start_tls", enableStartTls); - config.put("enable_ssl_client_auth", enableSslClientAuth); - config.put("verify_hostnames", verifyHostnames); - config.put("hosts", hosts); - config.put("bind_dn", bindDn); - config.put("password", password); - config.put("userbase", userBase); - config.put("usersearch", userSearch); - config.put("username_attribute", usernameAttribute); - config.put("pemtrustedcas_filepath", penTrustedCasFilePath); - return config; - } + private boolean enableSsl = false; + private boolean enableStartTls = false; + private boolean enableSslClientAuth = false; + private boolean verifyHostnames = false; + private List hosts; + private String bindDn; + private String password; + private String userBase; + private String userSearch; + private String usernameAttribute; + + private String penTrustedCasFilePath; + + /** + * Subclass of this + */ + private final T builderSubclass; + + protected LdapAuthenticationConfigBuilder(Function thisCastFunction) { + this.builderSubclass = thisCastFunction.apply(this); + } + + public static LdapAuthenticationConfigBuilder config() { + return new LdapAuthenticationConfigBuilder<>(Function.identity()); + } + + public T enableSsl(boolean enableSsl) { + this.enableSsl = enableSsl; + return builderSubclass; + } + + public T enableStartTls(boolean enableStartTls) { + this.enableStartTls = enableStartTls; + return builderSubclass; + } + + public T enableSslClientAuth(boolean enableSslClientAuth) { + this.enableSslClientAuth = enableSslClientAuth; + return builderSubclass; + } + + public T verifyHostnames(boolean verifyHostnames) { + this.verifyHostnames = verifyHostnames; + return builderSubclass; + } + + public T hosts(List hosts) { + this.hosts = hosts; + return builderSubclass; + } + + public T bindDn(String bindDn) { + this.bindDn = bindDn; + return builderSubclass; + } + + public T password(String password) { + this.password = password; + return builderSubclass; + } + + public T userBase(String userBase) { + this.userBase = userBase; + return builderSubclass; + } + + public T userSearch(String userSearch) { + this.userSearch = userSearch; + return builderSubclass; + } + + public T usernameAttribute(String usernameAttribute) { + this.usernameAttribute = usernameAttribute; + return builderSubclass; + } + + public T penTrustedCasFilePath(String penTrustedCasFilePath) { + this.penTrustedCasFilePath = penTrustedCasFilePath; + return builderSubclass; + } + + public Map build() { + HashMap config = new HashMap<>(); + config.put("enable_ssl", enableSsl); + config.put("enable_start_tls", enableStartTls); + config.put("enable_ssl_client_auth", enableSslClientAuth); + config.put("verify_hostnames", verifyHostnames); + config.put("hosts", hosts); + config.put("bind_dn", bindDn); + config.put("password", password); + config.put("userbase", userBase); + config.put("usersearch", userSearch); + config.put("username_attribute", usernameAttribute); + config.put("pemtrustedcas_filepath", penTrustedCasFilePath); + return config; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/LdapAuthorizationConfigBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/LdapAuthorizationConfigBuilder.java index 43611d8d08..9f2a0abd83 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/LdapAuthorizationConfigBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/LdapAuthorizationConfigBuilder.java @@ -13,63 +13,63 @@ import java.util.Map; public class LdapAuthorizationConfigBuilder extends LdapAuthenticationConfigBuilder { - private List skipUsers; - private String roleBase; - private String roleSearch; - private String userRoleAttribute; - private String userRoleName; - private String roleName; - private boolean resolveNestedRoles; + private List skipUsers; + private String roleBase; + private String roleSearch; + private String userRoleAttribute; + private String userRoleName; + private String roleName; + private boolean resolveNestedRoles; - public LdapAuthorizationConfigBuilder() { - super(LdapAuthorizationConfigBuilder.class::cast); - } + public LdapAuthorizationConfigBuilder() { + super(LdapAuthorizationConfigBuilder.class::cast); + } - public LdapAuthorizationConfigBuilder skipUsers(List skipUsers) { - this.skipUsers = skipUsers; - return this; - } + public LdapAuthorizationConfigBuilder skipUsers(List skipUsers) { + this.skipUsers = skipUsers; + return this; + } - public LdapAuthorizationConfigBuilder roleBase(String roleBase) { - this.roleBase = roleBase; - return this; - } + public LdapAuthorizationConfigBuilder roleBase(String roleBase) { + this.roleBase = roleBase; + return this; + } - public LdapAuthorizationConfigBuilder roleSearch(String roleSearch) { - this.roleSearch = roleSearch; - return this; - } + public LdapAuthorizationConfigBuilder roleSearch(String roleSearch) { + this.roleSearch = roleSearch; + return this; + } - public LdapAuthorizationConfigBuilder userRoleAttribute(String userRoleAttribute) { - this.userRoleAttribute = userRoleAttribute; - return this; - } + public LdapAuthorizationConfigBuilder userRoleAttribute(String userRoleAttribute) { + this.userRoleAttribute = userRoleAttribute; + return this; + } - public LdapAuthorizationConfigBuilder userRoleName(String userRoleName) { - this.userRoleName = userRoleName; - return this; - } + public LdapAuthorizationConfigBuilder userRoleName(String userRoleName) { + this.userRoleName = userRoleName; + return this; + } - public LdapAuthorizationConfigBuilder roleName(String roleName) { - this.roleName = roleName; - return this; - } + public LdapAuthorizationConfigBuilder roleName(String roleName) { + this.roleName = roleName; + return this; + } - public LdapAuthorizationConfigBuilder resolveNestedRoles(boolean resolveNestedRoles) { - this.resolveNestedRoles = resolveNestedRoles; - return this; - } + public LdapAuthorizationConfigBuilder resolveNestedRoles(boolean resolveNestedRoles) { + this.resolveNestedRoles = resolveNestedRoles; + return this; + } - @Override - public Map build() { - Map map = super.build(); - map.put("skip_users", skipUsers); - map.put("rolebase", roleBase); - map.put("rolesearch", roleSearch); - map.put("userroleattribute", userRoleAttribute); - map.put("userrolename", userRoleName); - map.put("rolename", roleName); - map.put("resolve_nested_roles", resolveNestedRoles); - return map; - } + @Override + public Map build() { + Map map = super.build(); + map.put("skip_users", skipUsers); + map.put("rolebase", roleBase); + map.put("rolesearch", roleSearch); + map.put("userroleattribute", userRoleAttribute); + map.put("userrolename", userRoleName); + map.put("rolename", roleName); + map.put("resolve_nested_roles", resolveNestedRoles); + return map; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/RateLimiting.java b/src/integrationTest/java/org/opensearch/test/framework/RateLimiting.java index b41c6f8f1d..bd38aac1e5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/RateLimiting.java +++ b/src/integrationTest/java/org/opensearch/test/framework/RateLimiting.java @@ -17,69 +17,69 @@ public class RateLimiting implements ToXContentObject { - private final String name; - private String type; - private String authenticationBackend; - private Integer allowedTries; - private Integer timeWindowSeconds; - private Integer blockExpirySeconds; - private Integer maxBlockedClients; - private Integer maxTrackedClients; + private final String name; + private String type; + private String authenticationBackend; + private Integer allowedTries; + private Integer timeWindowSeconds; + private Integer blockExpirySeconds; + private Integer maxBlockedClients; + private Integer maxTrackedClients; - public String getName() { - return name; - } + public String getName() { + return name; + } - public RateLimiting(String name) { - this.name = Objects.requireNonNull(name, "Rate limit name is required."); - } + public RateLimiting(String name) { + this.name = Objects.requireNonNull(name, "Rate limit name is required."); + } - public RateLimiting type(String type) { - this.type = type; - return this; - } + public RateLimiting type(String type) { + this.type = type; + return this; + } - public RateLimiting authenticationBackend(String authenticationBackend) { - this.authenticationBackend = authenticationBackend; - return this; - } + public RateLimiting authenticationBackend(String authenticationBackend) { + this.authenticationBackend = authenticationBackend; + return this; + } - public RateLimiting allowedTries(Integer allowedTries) { - this.allowedTries = allowedTries; - return this; - } + public RateLimiting allowedTries(Integer allowedTries) { + this.allowedTries = allowedTries; + return this; + } - public RateLimiting timeWindowSeconds(Integer timeWindowSeconds) { - this.timeWindowSeconds = timeWindowSeconds; - return this; - } + public RateLimiting timeWindowSeconds(Integer timeWindowSeconds) { + this.timeWindowSeconds = timeWindowSeconds; + return this; + } - public RateLimiting blockExpirySeconds(Integer blockExpirySeconds) { - this.blockExpirySeconds = blockExpirySeconds; - return this; - } + public RateLimiting blockExpirySeconds(Integer blockExpirySeconds) { + this.blockExpirySeconds = blockExpirySeconds; + return this; + } - public RateLimiting maxBlockedClients(Integer maxBlockedClients) { - this.maxBlockedClients = maxBlockedClients; - return this; - } + public RateLimiting maxBlockedClients(Integer maxBlockedClients) { + this.maxBlockedClients = maxBlockedClients; + return this; + } - public RateLimiting maxTrackedClients(Integer maxTrackedClients) { - this.maxTrackedClients = maxTrackedClients; - return this; - } + public RateLimiting maxTrackedClients(Integer maxTrackedClients) { + this.maxTrackedClients = maxTrackedClients; + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("type", type); - xContentBuilder.field("authentication_backend", authenticationBackend); - xContentBuilder.field("allowed_tries", allowedTries); - xContentBuilder.field("time_window_seconds", timeWindowSeconds); - xContentBuilder.field("block_expiry_seconds", blockExpirySeconds); - xContentBuilder.field("max_blocked_clients", maxBlockedClients); - xContentBuilder.field("max_tracked_clients", maxTrackedClients); - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("type", type); + xContentBuilder.field("authentication_backend", authenticationBackend); + xContentBuilder.field("allowed_tries", allowedTries); + xContentBuilder.field("time_window_seconds", timeWindowSeconds); + xContentBuilder.field("block_expiry_seconds", blockExpirySeconds); + xContentBuilder.field("max_blocked_clients", maxBlockedClients); + xContentBuilder.field("max_tracked_clients", maxTrackedClients); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/RolesMapping.java b/src/integrationTest/java/org/opensearch/test/framework/RolesMapping.java index a0f048f953..75c0325474 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/RolesMapping.java +++ b/src/integrationTest/java/org/opensearch/test/framework/RolesMapping.java @@ -27,71 +27,69 @@ */ public class RolesMapping implements ToXContentObject { - /** - * OpenSearch role name - */ - private String roleName; + /** + * OpenSearch role name + */ + private String roleName; - /** - * Backend role names - */ - private List backendRoles; + /** + * Backend role names + */ + private List backendRoles; - private boolean reserved = false; + private boolean reserved = false; - /** - * Creates roles mapping to OpenSearch role defined by parameter role - * @param role OpenSearch role, must not be null. - */ - public RolesMapping(Role role) { - requireNonNull(role); - this.roleName = requireNonNull(role.getName()); - this.backendRoles = new ArrayList<>(); - } + /** + * Creates roles mapping to OpenSearch role defined by parameter role + * @param role OpenSearch role, must not be null. + */ + public RolesMapping(Role role) { + requireNonNull(role); + this.roleName = requireNonNull(role.getName()); + this.backendRoles = new ArrayList<>(); + } + /** + * Defines backend role names + * @param backendRoles backend roles names + * @return current {@link RolesMapping} instance + */ + public RolesMapping backendRoles(String... backendRoles) { + this.backendRoles.addAll(Arrays.asList(backendRoles)); + return this; + } - /** - * Defines backend role names - * @param backendRoles backend roles names - * @return current {@link RolesMapping} instance - */ - public RolesMapping backendRoles(String...backendRoles) { - this.backendRoles.addAll(Arrays.asList(backendRoles)); - return this; - } + /** + * Determines if role is reserved + * @param reserved true for reserved roles + * @return current {@link RolesMapping} instance + */ + public RolesMapping reserved(boolean reserved) { + this.reserved = reserved; + return this; + } - /** - * Determines if role is reserved - * @param reserved true for reserved roles - * @return current {@link RolesMapping} instance - */ - public RolesMapping reserved(boolean reserved) { - this.reserved = reserved; - return this; - } + /** + * Returns OpenSearch role name + * @return role name + */ + public String getRoleName() { + return roleName; + } - - /** - * Returns OpenSearch role name - * @return role name - */ - public String getRoleName() { - return roleName; - } - - /** - * Controls serialization to JSON - * @param xContentBuilder must not be null - * @param params not used parameter, but required by the interface {@link ToXContentObject} - * @return builder form parameter xContentBuilder - * @throws IOException denotes error during serialization to JSON - */ - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("reserved", reserved); - xContentBuilder.field("backend_roles", backendRoles); - xContentBuilder.endObject(); - return xContentBuilder; - } + /** + * Controls serialization to JSON + * @param xContentBuilder must not be null + * @param params not used parameter, but required by the interface {@link ToXContentObject} + * @return builder form parameter xContentBuilder + * @throws IOException denotes error during serialization to JSON + */ + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("reserved", reserved); + xContentBuilder.field("backend_roles", backendRoles); + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/TestIndex.java b/src/integrationTest/java/org/opensearch/test/framework/TestIndex.java index 9d5feb9eee..6f6bd935a5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/TestIndex.java +++ b/src/integrationTest/java/org/opensearch/test/framework/TestIndex.java @@ -34,51 +34,50 @@ public class TestIndex { - private final String name; - private final Settings settings; - - public TestIndex(String name, Settings settings) { - this.name = name; - this.settings = settings; - - } - - public void create(Client client) { - client.admin().indices().create(new CreateIndexRequest(name).settings(settings)).actionGet(); - } - - public String getName() { - return name; - } - - - public static Builder name(String name) { - return new Builder().name(name); - } - - public static class Builder { - private String name; - private Settings.Builder settings = Settings.builder(); - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder setting(String name, int value) { - settings.put(name, value); - return this; - } - - public Builder shards(int value) { - settings.put("index.number_of_shards", 5); - return this; - } - - public TestIndex build() { - return new TestIndex(name, settings.build()); - } - - } + private final String name; + private final Settings settings; + + public TestIndex(String name, Settings settings) { + this.name = name; + this.settings = settings; + + } + + public void create(Client client) { + client.admin().indices().create(new CreateIndexRequest(name).settings(settings)).actionGet(); + } + + public String getName() { + return name; + } + + public static Builder name(String name) { + return new Builder().name(name); + } + + public static class Builder { + private String name; + private Settings.Builder settings = Settings.builder(); + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder setting(String name, int value) { + settings.put(name, value); + return this; + } + + public Builder shards(int value) { + settings.put("index.number_of_shards", 5); + return this; + } + + public TestIndex build() { + return new TestIndex(name, settings.build()); + } + + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java b/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java index 43b98b02ce..a702102e6b 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java +++ b/src/integrationTest/java/org/opensearch/test/framework/TestSecurityConfig.java @@ -76,630 +76,642 @@ */ public class TestSecurityConfig { - private static final Logger log = LogManager.getLogger(TestSecurityConfig.class); - - private Config config = new Config(); - private Map internalUsers = new LinkedHashMap<>(); - private Map roles = new LinkedHashMap<>(); - private AuditConfiguration auditConfiguration; - private Map rolesMapping = new LinkedHashMap<>(); - - private String indexName = ".opendistro_security"; - - public TestSecurityConfig() { - - } - - public TestSecurityConfig configIndexName(String configIndexName) { - this.indexName = configIndexName; - return this; - } - - public TestSecurityConfig authFailureListeners(AuthFailureListeners listener) { - config.authFailureListeners(listener); - return this; - } - - public TestSecurityConfig anonymousAuth(boolean anonymousAuthEnabled) { - config.anonymousAuth(anonymousAuthEnabled); - return this; - } - - public TestSecurityConfig doNotFailOnForbidden(boolean doNotFailOnForbidden) { - config.doNotFailOnForbidden(doNotFailOnForbidden); - return this; - } - - public TestSecurityConfig xff(XffConfig xffConfig) { - config.xffConfig(xffConfig); - return this; - } - - public TestSecurityConfig authc(AuthcDomain authcDomain) { - config.authc(authcDomain); - return this; - } - - public TestSecurityConfig authz(AuthzDomain authzDomain) { - config.authz(authzDomain); - return this; - } - public TestSecurityConfig user(User user) { - this.internalUsers.put(user.name, user); - - for (Role role : user.roles) { - this.roles.put(role.name, role); - } - - return this; - } - - public List getUsers() { - return new ArrayList<>(internalUsers.values()); - } - - public TestSecurityConfig roles(Role... roles) { - for (Role role : roles) { - if(this.roles.containsKey(role.name)) { - throw new IllegalStateException("Role with name " + role.name + " is already defined"); - } - this.roles.put(role.name, role); - } - - return this; - } - - public TestSecurityConfig audit(AuditConfiguration auditConfiguration) { - this.auditConfiguration = auditConfiguration; - return this; - } - - public TestSecurityConfig rolesMapping(RolesMapping...mappings) { - for (RolesMapping mapping : mappings) { - String roleName = mapping.getRoleName(); - if(rolesMapping.containsKey(roleName)) { - throw new IllegalArgumentException("Role mapping " + roleName + " already exists"); - } - this.rolesMapping.put(roleName, mapping); - } - return this; - } - - public static class Config implements ToXContentObject { - private boolean anonymousAuth; - - private Boolean doNotFailOnForbidden; - private XffConfig xffConfig; - private Map authcDomainMap = new LinkedHashMap<>(); - - private AuthFailureListeners authFailureListeners; - private Map authzDomainMap = new LinkedHashMap<>(); - - public Config anonymousAuth(boolean anonymousAuth) { - this.anonymousAuth = anonymousAuth; - return this; - } - - public Config doNotFailOnForbidden(Boolean doNotFailOnForbidden) { - this.doNotFailOnForbidden = doNotFailOnForbidden; - return this; - } - - public Config xffConfig(XffConfig xffConfig) { - this.xffConfig = xffConfig; - return this; - } - - public Config authc(AuthcDomain authcDomain) { - authcDomainMap.put(authcDomain.id, authcDomain); - return this; - } - - public Config authFailureListeners(AuthFailureListeners authFailureListeners) { - this.authFailureListeners = authFailureListeners; - return this; - } - - public Config authz(AuthzDomain authzDomain) { - authzDomainMap.put(authzDomain.getId(), authzDomain); - return this; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.startObject("dynamic"); - - if (anonymousAuth || (xffConfig != null)) { - xContentBuilder.startObject("http"); - xContentBuilder.field("anonymous_auth_enabled", anonymousAuth); - if(xffConfig != null) { - xContentBuilder.field("xff", xffConfig); - } - xContentBuilder.endObject(); - } - if(doNotFailOnForbidden != null) { - xContentBuilder.field("do_not_fail_on_forbidden", doNotFailOnForbidden); - } - - xContentBuilder.field("authc", authcDomainMap); - if(authzDomainMap.isEmpty() == false) { - xContentBuilder.field("authz", authzDomainMap); - } - - if(authFailureListeners != null) { - xContentBuilder.field("auth_failure_listeners", authFailureListeners); - } - - xContentBuilder.endObject(); - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class User implements UserCredentialsHolder, ToXContentObject { - - public final static TestSecurityConfig.User USER_ADMIN = new TestSecurityConfig.User("admin") - .roles(new Role("allaccess").indexPermissions("*").on("*").clusterPermissions("*")); - - String name; - private String password; - List roles = new ArrayList<>(); - private Map attributes = new HashMap<>(); - - public User(String name) { - this.name = name; - this.password = "secret"; - } - - public User password(String password) { - this.password = password; - return this; - } - - public User roles(Role... roles) { - // We scope the role names by user to keep tests free of potential side effects - String roleNamePrefix = "user_" + this.getName() + "__"; - this.roles.addAll(Arrays.asList(roles).stream().map((r) -> r.clone().name(roleNamePrefix + r.getName())).collect(Collectors.toSet())); - return this; - } - - public User attr(String key, Object value) { - this.attributes.put(key, value); - return this; - } - - public String getName() { - return name; - } - - public String getPassword() { - return password; - } - - public Set getRoleNames() { - return roles.stream().map(Role::getName).collect(Collectors.toSet()); - } - - public Object getAttribute(String attributeName) { - return attributes.get(attributeName); - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("hash", hash(password.toCharArray())); - - Set roleNames = getRoleNames(); - - if (!roleNames.isEmpty()) { - xContentBuilder.field("opendistro_security_roles", roleNames); - } - - if (attributes != null && attributes.size() != 0) { - xContentBuilder.field("attributes", attributes); - } - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class Role implements ToXContentObject { - public static Role ALL_ACCESS = new Role("all_access").clusterPermissions("*").indexPermissions("*").on("*"); - - private String name; - private List clusterPermissions = new ArrayList<>(); - - private List indexPermissions = new ArrayList<>(); - - public Role(String name) { - this.name = name; - } - - public Role clusterPermissions(String... clusterPermissions) { - this.clusterPermissions.addAll(Arrays.asList(clusterPermissions)); - return this; - } - - public IndexPermission indexPermissions(String... indexPermissions) { - return new IndexPermission(this, indexPermissions); - } - - public Role name(String name) { - this.name = name; - return this; - } - - public String getName() { - return name; - } - - public Role clone() { - Role role = new Role(this.name); - role.clusterPermissions.addAll(this.clusterPermissions); - role.indexPermissions.addAll(this.indexPermissions); - return role; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - if (!clusterPermissions.isEmpty()) { - xContentBuilder.field("cluster_permissions", clusterPermissions); - } - - if (!indexPermissions.isEmpty()) { - xContentBuilder.field("index_permissions", indexPermissions); - } - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class IndexPermission implements ToXContentObject { - private List allowedActions; - private List indexPatterns; - private Role role; - private String dlsQuery; - private List fls; - private List maskedFields; - - IndexPermission(Role role, String... allowedActions) { - this.allowedActions = Arrays.asList(allowedActions); - this.role = role; - } - - public IndexPermission dls(String dlsQuery) { - this.dlsQuery = dlsQuery; - return this; - } - - public IndexPermission fls(String... fls) { - this.fls = Arrays.asList(fls); - return this; - } - - public IndexPermission maskedFields(String... maskedFields) { - this.maskedFields = Arrays.asList(maskedFields); - return this; - } - - public Role on(String... indexPatterns) { - this.indexPatterns = Arrays.asList(indexPatterns); - this.role.indexPermissions.add(this); - return this.role; - } - - public Role on(TestIndex... testindices) { - this.indexPatterns = Arrays.asList(testindices).stream().map(TestIndex::getName).collect(Collectors.toList()); - this.role.indexPermissions.add(this); - return this.role; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("index_patterns", indexPatterns); - xContentBuilder.field("allowed_actions", allowedActions); - - if (dlsQuery != null) { - xContentBuilder.field("dls", dlsQuery); - } - - if (fls != null) { - xContentBuilder.field("fls", fls); - } - - if (maskedFields != null) { - xContentBuilder.field("masked_fields", maskedFields); - } - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class AuthcDomain implements ToXContentObject { - - private static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoqZbjLUAWc+DZTkinQAdvy1GFjPHPnxheU89hSiWoDD3NOW76H3u3T7cCDdOah2msdxSlBmCBH6wik8qLYkcV8owWukQg3PQmbEhrdPaKo0QCgomWs4nLgtmEYqcZ+QQldd82MdTlQ1QmoQmI9Uxqs1SuaKZASp3Gy19y8su5CV+FZ6BruUw9HELK055sAwl3X7j5ouabXGbcib2goBF3P52LkvbJLuWr5HDZEOeSkwIeqSeMojASM96K5SdotD+HwEyjaTjzRPL2Aa1BEQFWOQ6CFJLyLH7ZStDuPM1mJU1VxIVfMbZrhsUBjAnIhRynmWxML7YlNqkP9j6jyOIYQIDAQAB"; - - public static final int BASIC_AUTH_DOMAIN_ORDER = 0; - public final static AuthcDomain AUTHC_HTTPBASIC_INTERNAL = new TestSecurityConfig.AuthcDomain("basic", BASIC_AUTH_DOMAIN_ORDER) - .httpAuthenticatorWithChallenge("basic").backend("internal"); - - public final static AuthcDomain AUTHC_HTTPBASIC_INTERNAL_WITHOUT_CHALLENGE = new TestSecurityConfig.AuthcDomain("basic", - BASIC_AUTH_DOMAIN_ORDER) - .httpAuthenticator("basic").backend("internal"); - - public final static AuthcDomain DISABLED_AUTHC_HTTPBASIC_INTERNAL = new TestSecurityConfig - .AuthcDomain("basic", BASIC_AUTH_DOMAIN_ORDER, false).httpAuthenticator("basic").backend("internal"); - - public final static AuthcDomain JWT_AUTH_DOMAIN = new TestSecurityConfig - .AuthcDomain("jwt", 1) - .jwtHttpAuthenticator(new JwtConfigBuilder().jwtHeader(AUTHORIZATION).signingKey(PUBLIC_KEY)).backend("noop"); - - private final String id; - private boolean enabled = true; - private int order; - private List skipUsers = new ArrayList<>(); - private HttpAuthenticator httpAuthenticator; - private AuthenticationBackend authenticationBackend; - - public AuthcDomain(String id, int order, boolean enabled) { - this.id = id; - this.order = order; - this.enabled = enabled; - } - - public AuthcDomain(String id, int order) { - this(id, order, true); - } - - public AuthcDomain httpAuthenticator(String type) { - this.httpAuthenticator = new HttpAuthenticator(type); - return this; - } - - public AuthcDomain jwtHttpAuthenticator(JwtConfigBuilder builder) { - this.httpAuthenticator = new HttpAuthenticator("jwt") - .challenge(false).config(builder.build()); - return this; - } - - public AuthcDomain httpAuthenticatorWithChallenge(String type) { - this.httpAuthenticator = new HttpAuthenticator(type).challenge(true); - return this; - } - - public AuthcDomain httpAuthenticator(HttpAuthenticator httpAuthenticator) { - this.httpAuthenticator = httpAuthenticator; - return this; - } - - public AuthcDomain backend(String type) { - this.authenticationBackend = new AuthenticationBackend(type); - return this; - } - - public AuthcDomain backend(AuthenticationBackend authenticationBackend) { - this.authenticationBackend = authenticationBackend; - return this; - } - - public AuthcDomain skipUsers(String... users) { - this.skipUsers.addAll(Arrays.asList(users)); - return this; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("http_enabled", enabled); - xContentBuilder.field("order", order); - - if (httpAuthenticator != null) { - xContentBuilder.field("http_authenticator", httpAuthenticator); - } - - if (authenticationBackend != null) { - xContentBuilder.field("authentication_backend", authenticationBackend); - } - - if (skipUsers != null && skipUsers.size() > 0) { - xContentBuilder.field("skip_users", skipUsers); - } - - xContentBuilder.endObject(); - return xContentBuilder; - } - - public static class HttpAuthenticator implements ToXContentObject { - private final String type; - private boolean challenge; - private Map config = new HashMap(); - - public HttpAuthenticator(String type) { - this.type = type; - } - - public HttpAuthenticator challenge(boolean challenge) { - this.challenge = challenge; - return this; - } - - public HttpAuthenticator config(Map config) { - this.config.putAll(config); - return this; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("type", type); - xContentBuilder.field("challenge", challenge); - xContentBuilder.field("config", config); - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - - public static class AuthenticationBackend implements ToXContentObject { - private final String type; - private Supplier> config = () -> new HashMap(); - - public AuthenticationBackend(String type) { - this.type = type; - } - - public AuthenticationBackend config(Map config) { - Map configCopy = new HashMap<>(config); - this.config = () -> configCopy; - return this; - } - - public AuthenticationBackend config(Supplier> configSupplier) { - this.config = configSupplier; - return this; - } - - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - - xContentBuilder.field("type", type); - xContentBuilder.field("config", config.get()); - - xContentBuilder.endObject(); - return xContentBuilder; - } - } - } - - public void initIndex(Client client) { - Map settings = new HashMap<>(); - if (indexName.startsWith(".")) { - settings.put("index.hidden", true); - } - client.admin().indices().create(new CreateIndexRequest(indexName).settings(settings)).actionGet(); - - writeSingleEntryConfigToIndex(client, CType.CONFIG, config); - if(auditConfiguration != null) { - writeSingleEntryConfigToIndex(client, CType.AUDIT, "config", auditConfiguration); - } - writeConfigToIndex(client, CType.ROLES, roles); - writeConfigToIndex(client, CType.INTERNALUSERS, internalUsers); - writeConfigToIndex(client, CType.ROLESMAPPING, rolesMapping); - writeEmptyConfigToIndex(client, CType.ACTIONGROUPS); - writeEmptyConfigToIndex(client, CType.TENANTS); - } - - public void updateInternalUsersConfiguration(Client client, List users) { - Map userMap = new HashMap<>(); - for(User user : users) { - userMap.put(user.getName(), user); - } - updateConfigInIndex(client, CType.INTERNALUSERS, userMap); - } - - - static String hash(final char[] clearTextPassword) { - final byte[] salt = new byte[16]; - new SecureRandom().nextBytes(salt); - final String hash = OpenBSDBCrypt.generate((Objects.requireNonNull(clearTextPassword)), salt, 12); - Arrays.fill(salt, (byte) 0); - Arrays.fill(clearTextPassword, '\0'); - return hash; - } - - private void writeEmptyConfigToIndex(Client client, CType configType) { - writeConfigToIndex(client, configType, Collections.emptyMap()); - } - - private void writeConfigToIndex(Client client, CType configType, Map config) { - try { - String json = configToJson(configType, config); - - log.info("Writing security configuration into index " + configType + ":\n" + json); - - BytesReference bytesReference = toByteReference(json); - client.index(new IndexRequest(indexName).id(configType.toLCString()) - .setRefreshPolicy(IMMEDIATE).source(configType.toLCString(), bytesReference)) - .actionGet(); - } catch (Exception e) { - throw new RuntimeException("Error while initializing config for " + indexName, e); - } - } - - private static BytesReference toByteReference(String string) throws UnsupportedEncodingException { - return BytesReference.fromByteBuffer(ByteBuffer.wrap(string.getBytes("utf-8"))); - } - - private void updateConfigInIndex(Client client, CType configType, Map config) { - try { - String json = configToJson(configType, config); - BytesReference bytesReference = toByteReference(json); - log.info("Update configuration of type '{}' in index '{}', new value '{}'.", configType, indexName, json); - UpdateRequest upsert = new UpdateRequest(indexName, configType.toLCString()).doc(configType.toLCString(), bytesReference) - .setRefreshPolicy(IMMEDIATE); - client.update(upsert).actionGet(); - } catch (Exception e) { - throw new RuntimeException("Error while updating config for " + indexName, e); - } - } - - private static String configToJson(CType configType, Map config) throws IOException { - XContentBuilder builder = XContentFactory.jsonBuilder(); - - builder.startObject(); - builder.startObject("_meta"); - builder.field("type", configType.toLCString()); - builder.field("config_version", 2); - builder.endObject(); - - for (Map.Entry entry : config.entrySet()) { - builder.field(entry.getKey(), entry.getValue()); - } - - builder.endObject(); - - return Strings.toString(builder); - } - - private void writeSingleEntryConfigToIndex(Client client, CType configType, ToXContentObject config) { - writeSingleEntryConfigToIndex(client, configType, configType.toLCString(), config); - } - - private void writeSingleEntryConfigToIndex(Client client, CType configType, String configurationRoot, ToXContentObject config) { - try { - XContentBuilder builder = XContentFactory.jsonBuilder(); - - builder.startObject(); - builder.startObject("_meta"); - builder.field("type", configType.toLCString()); - builder.field("config_version", 2); - builder.endObject(); - - builder.field(configurationRoot, config); - - builder.endObject(); - - String json = Strings.toString(builder); - - log.info("Writing security plugin configuration into index " + configType + ":\n" + json); - - client.index(new IndexRequest(indexName).id(configType.toLCString()) - .setRefreshPolicy(IMMEDIATE).source(configType.toLCString(), toByteReference(json))) - .actionGet(); - } catch (Exception e) { - throw new RuntimeException("Error while initializing config for " + indexName, e); - } - } + private static final Logger log = LogManager.getLogger(TestSecurityConfig.class); + + private Config config = new Config(); + private Map internalUsers = new LinkedHashMap<>(); + private Map roles = new LinkedHashMap<>(); + private AuditConfiguration auditConfiguration; + private Map rolesMapping = new LinkedHashMap<>(); + + private String indexName = ".opendistro_security"; + + public TestSecurityConfig() { + + } + + public TestSecurityConfig configIndexName(String configIndexName) { + this.indexName = configIndexName; + return this; + } + + public TestSecurityConfig authFailureListeners(AuthFailureListeners listener) { + config.authFailureListeners(listener); + return this; + } + + public TestSecurityConfig anonymousAuth(boolean anonymousAuthEnabled) { + config.anonymousAuth(anonymousAuthEnabled); + return this; + } + + public TestSecurityConfig doNotFailOnForbidden(boolean doNotFailOnForbidden) { + config.doNotFailOnForbidden(doNotFailOnForbidden); + return this; + } + + public TestSecurityConfig xff(XffConfig xffConfig) { + config.xffConfig(xffConfig); + return this; + } + + public TestSecurityConfig authc(AuthcDomain authcDomain) { + config.authc(authcDomain); + return this; + } + + public TestSecurityConfig authz(AuthzDomain authzDomain) { + config.authz(authzDomain); + return this; + } + + public TestSecurityConfig user(User user) { + this.internalUsers.put(user.name, user); + + for (Role role : user.roles) { + this.roles.put(role.name, role); + } + + return this; + } + + public List getUsers() { + return new ArrayList<>(internalUsers.values()); + } + + public TestSecurityConfig roles(Role... roles) { + for (Role role : roles) { + if (this.roles.containsKey(role.name)) { + throw new IllegalStateException("Role with name " + role.name + " is already defined"); + } + this.roles.put(role.name, role); + } + + return this; + } + + public TestSecurityConfig audit(AuditConfiguration auditConfiguration) { + this.auditConfiguration = auditConfiguration; + return this; + } + + public TestSecurityConfig rolesMapping(RolesMapping... mappings) { + for (RolesMapping mapping : mappings) { + String roleName = mapping.getRoleName(); + if (rolesMapping.containsKey(roleName)) { + throw new IllegalArgumentException("Role mapping " + roleName + " already exists"); + } + this.rolesMapping.put(roleName, mapping); + } + return this; + } + + public static class Config implements ToXContentObject { + private boolean anonymousAuth; + + private Boolean doNotFailOnForbidden; + private XffConfig xffConfig; + private Map authcDomainMap = new LinkedHashMap<>(); + + private AuthFailureListeners authFailureListeners; + private Map authzDomainMap = new LinkedHashMap<>(); + + public Config anonymousAuth(boolean anonymousAuth) { + this.anonymousAuth = anonymousAuth; + return this; + } + + public Config doNotFailOnForbidden(Boolean doNotFailOnForbidden) { + this.doNotFailOnForbidden = doNotFailOnForbidden; + return this; + } + + public Config xffConfig(XffConfig xffConfig) { + this.xffConfig = xffConfig; + return this; + } + + public Config authc(AuthcDomain authcDomain) { + authcDomainMap.put(authcDomain.id, authcDomain); + return this; + } + + public Config authFailureListeners(AuthFailureListeners authFailureListeners) { + this.authFailureListeners = authFailureListeners; + return this; + } + + public Config authz(AuthzDomain authzDomain) { + authzDomainMap.put(authzDomain.getId(), authzDomain); + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.startObject("dynamic"); + + if (anonymousAuth || (xffConfig != null)) { + xContentBuilder.startObject("http"); + xContentBuilder.field("anonymous_auth_enabled", anonymousAuth); + if (xffConfig != null) { + xContentBuilder.field("xff", xffConfig); + } + xContentBuilder.endObject(); + } + if (doNotFailOnForbidden != null) { + xContentBuilder.field("do_not_fail_on_forbidden", doNotFailOnForbidden); + } + + xContentBuilder.field("authc", authcDomainMap); + if (authzDomainMap.isEmpty() == false) { + xContentBuilder.field("authz", authzDomainMap); + } + + if (authFailureListeners != null) { + xContentBuilder.field("auth_failure_listeners", authFailureListeners); + } + + xContentBuilder.endObject(); + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class User implements UserCredentialsHolder, ToXContentObject { + + public final static TestSecurityConfig.User USER_ADMIN = new TestSecurityConfig.User("admin").roles( + new Role("allaccess").indexPermissions("*").on("*").clusterPermissions("*") + ); + + String name; + private String password; + List roles = new ArrayList<>(); + private Map attributes = new HashMap<>(); + + public User(String name) { + this.name = name; + this.password = "secret"; + } + + public User password(String password) { + this.password = password; + return this; + } + + public User roles(Role... roles) { + // We scope the role names by user to keep tests free of potential side effects + String roleNamePrefix = "user_" + this.getName() + "__"; + this.roles.addAll( + Arrays.asList(roles).stream().map((r) -> r.clone().name(roleNamePrefix + r.getName())).collect(Collectors.toSet()) + ); + return this; + } + + public User attr(String key, Object value) { + this.attributes.put(key, value); + return this; + } + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public Set getRoleNames() { + return roles.stream().map(Role::getName).collect(Collectors.toSet()); + } + + public Object getAttribute(String attributeName) { + return attributes.get(attributeName); + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("hash", hash(password.toCharArray())); + + Set roleNames = getRoleNames(); + + if (!roleNames.isEmpty()) { + xContentBuilder.field("opendistro_security_roles", roleNames); + } + + if (attributes != null && attributes.size() != 0) { + xContentBuilder.field("attributes", attributes); + } + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class Role implements ToXContentObject { + public static Role ALL_ACCESS = new Role("all_access").clusterPermissions("*").indexPermissions("*").on("*"); + + private String name; + private List clusterPermissions = new ArrayList<>(); + + private List indexPermissions = new ArrayList<>(); + + public Role(String name) { + this.name = name; + } + + public Role clusterPermissions(String... clusterPermissions) { + this.clusterPermissions.addAll(Arrays.asList(clusterPermissions)); + return this; + } + + public IndexPermission indexPermissions(String... indexPermissions) { + return new IndexPermission(this, indexPermissions); + } + + public Role name(String name) { + this.name = name; + return this; + } + + public String getName() { + return name; + } + + public Role clone() { + Role role = new Role(this.name); + role.clusterPermissions.addAll(this.clusterPermissions); + role.indexPermissions.addAll(this.indexPermissions); + return role; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + if (!clusterPermissions.isEmpty()) { + xContentBuilder.field("cluster_permissions", clusterPermissions); + } + + if (!indexPermissions.isEmpty()) { + xContentBuilder.field("index_permissions", indexPermissions); + } + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class IndexPermission implements ToXContentObject { + private List allowedActions; + private List indexPatterns; + private Role role; + private String dlsQuery; + private List fls; + private List maskedFields; + + IndexPermission(Role role, String... allowedActions) { + this.allowedActions = Arrays.asList(allowedActions); + this.role = role; + } + + public IndexPermission dls(String dlsQuery) { + this.dlsQuery = dlsQuery; + return this; + } + + public IndexPermission fls(String... fls) { + this.fls = Arrays.asList(fls); + return this; + } + + public IndexPermission maskedFields(String... maskedFields) { + this.maskedFields = Arrays.asList(maskedFields); + return this; + } + + public Role on(String... indexPatterns) { + this.indexPatterns = Arrays.asList(indexPatterns); + this.role.indexPermissions.add(this); + return this.role; + } + + public Role on(TestIndex... testindices) { + this.indexPatterns = Arrays.asList(testindices).stream().map(TestIndex::getName).collect(Collectors.toList()); + this.role.indexPermissions.add(this); + return this.role; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("index_patterns", indexPatterns); + xContentBuilder.field("allowed_actions", allowedActions); + + if (dlsQuery != null) { + xContentBuilder.field("dls", dlsQuery); + } + + if (fls != null) { + xContentBuilder.field("fls", fls); + } + + if (maskedFields != null) { + xContentBuilder.field("masked_fields", maskedFields); + } + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class AuthcDomain implements ToXContentObject { + + private static String PUBLIC_KEY = + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoqZbjLUAWc+DZTkinQAdvy1GFjPHPnxheU89hSiWoDD3NOW76H3u3T7cCDdOah2msdxSlBmCBH6wik8qLYkcV8owWukQg3PQmbEhrdPaKo0QCgomWs4nLgtmEYqcZ+QQldd82MdTlQ1QmoQmI9Uxqs1SuaKZASp3Gy19y8su5CV+FZ6BruUw9HELK055sAwl3X7j5ouabXGbcib2goBF3P52LkvbJLuWr5HDZEOeSkwIeqSeMojASM96K5SdotD+HwEyjaTjzRPL2Aa1BEQFWOQ6CFJLyLH7ZStDuPM1mJU1VxIVfMbZrhsUBjAnIhRynmWxML7YlNqkP9j6jyOIYQIDAQAB"; + + public static final int BASIC_AUTH_DOMAIN_ORDER = 0; + public final static AuthcDomain AUTHC_HTTPBASIC_INTERNAL = new TestSecurityConfig.AuthcDomain("basic", BASIC_AUTH_DOMAIN_ORDER) + .httpAuthenticatorWithChallenge("basic") + .backend("internal"); + + public final static AuthcDomain AUTHC_HTTPBASIC_INTERNAL_WITHOUT_CHALLENGE = new TestSecurityConfig.AuthcDomain( + "basic", + BASIC_AUTH_DOMAIN_ORDER + ).httpAuthenticator("basic").backend("internal"); + + public final static AuthcDomain DISABLED_AUTHC_HTTPBASIC_INTERNAL = new TestSecurityConfig.AuthcDomain( + "basic", + BASIC_AUTH_DOMAIN_ORDER, + false + ).httpAuthenticator("basic").backend("internal"); + + public final static AuthcDomain JWT_AUTH_DOMAIN = new TestSecurityConfig.AuthcDomain("jwt", 1).jwtHttpAuthenticator( + new JwtConfigBuilder().jwtHeader(AUTHORIZATION).signingKey(PUBLIC_KEY) + ).backend("noop"); + + private final String id; + private boolean enabled = true; + private int order; + private List skipUsers = new ArrayList<>(); + private HttpAuthenticator httpAuthenticator; + private AuthenticationBackend authenticationBackend; + + public AuthcDomain(String id, int order, boolean enabled) { + this.id = id; + this.order = order; + this.enabled = enabled; + } + + public AuthcDomain(String id, int order) { + this(id, order, true); + } + + public AuthcDomain httpAuthenticator(String type) { + this.httpAuthenticator = new HttpAuthenticator(type); + return this; + } + + public AuthcDomain jwtHttpAuthenticator(JwtConfigBuilder builder) { + this.httpAuthenticator = new HttpAuthenticator("jwt").challenge(false).config(builder.build()); + return this; + } + + public AuthcDomain httpAuthenticatorWithChallenge(String type) { + this.httpAuthenticator = new HttpAuthenticator(type).challenge(true); + return this; + } + + public AuthcDomain httpAuthenticator(HttpAuthenticator httpAuthenticator) { + this.httpAuthenticator = httpAuthenticator; + return this; + } + + public AuthcDomain backend(String type) { + this.authenticationBackend = new AuthenticationBackend(type); + return this; + } + + public AuthcDomain backend(AuthenticationBackend authenticationBackend) { + this.authenticationBackend = authenticationBackend; + return this; + } + + public AuthcDomain skipUsers(String... users) { + this.skipUsers.addAll(Arrays.asList(users)); + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("http_enabled", enabled); + xContentBuilder.field("order", order); + + if (httpAuthenticator != null) { + xContentBuilder.field("http_authenticator", httpAuthenticator); + } + + if (authenticationBackend != null) { + xContentBuilder.field("authentication_backend", authenticationBackend); + } + + if (skipUsers != null && skipUsers.size() > 0) { + xContentBuilder.field("skip_users", skipUsers); + } + + xContentBuilder.endObject(); + return xContentBuilder; + } + + public static class HttpAuthenticator implements ToXContentObject { + private final String type; + private boolean challenge; + private Map config = new HashMap(); + + public HttpAuthenticator(String type) { + this.type = type; + } + + public HttpAuthenticator challenge(boolean challenge) { + this.challenge = challenge; + return this; + } + + public HttpAuthenticator config(Map config) { + this.config.putAll(config); + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("type", type); + xContentBuilder.field("challenge", challenge); + xContentBuilder.field("config", config); + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + + public static class AuthenticationBackend implements ToXContentObject { + private final String type; + private Supplier> config = () -> new HashMap(); + + public AuthenticationBackend(String type) { + this.type = type; + } + + public AuthenticationBackend config(Map config) { + Map configCopy = new HashMap<>(config); + this.config = () -> configCopy; + return this; + } + + public AuthenticationBackend config(Supplier> configSupplier) { + this.config = configSupplier; + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + + xContentBuilder.field("type", type); + xContentBuilder.field("config", config.get()); + + xContentBuilder.endObject(); + return xContentBuilder; + } + } + } + + public void initIndex(Client client) { + Map settings = new HashMap<>(); + if (indexName.startsWith(".")) { + settings.put("index.hidden", true); + } + client.admin().indices().create(new CreateIndexRequest(indexName).settings(settings)).actionGet(); + + writeSingleEntryConfigToIndex(client, CType.CONFIG, config); + if (auditConfiguration != null) { + writeSingleEntryConfigToIndex(client, CType.AUDIT, "config", auditConfiguration); + } + writeConfigToIndex(client, CType.ROLES, roles); + writeConfigToIndex(client, CType.INTERNALUSERS, internalUsers); + writeConfigToIndex(client, CType.ROLESMAPPING, rolesMapping); + writeEmptyConfigToIndex(client, CType.ACTIONGROUPS); + writeEmptyConfigToIndex(client, CType.TENANTS); + } + + public void updateInternalUsersConfiguration(Client client, List users) { + Map userMap = new HashMap<>(); + for (User user : users) { + userMap.put(user.getName(), user); + } + updateConfigInIndex(client, CType.INTERNALUSERS, userMap); + } + + static String hash(final char[] clearTextPassword) { + final byte[] salt = new byte[16]; + new SecureRandom().nextBytes(salt); + final String hash = OpenBSDBCrypt.generate((Objects.requireNonNull(clearTextPassword)), salt, 12); + Arrays.fill(salt, (byte) 0); + Arrays.fill(clearTextPassword, '\0'); + return hash; + } + + private void writeEmptyConfigToIndex(Client client, CType configType) { + writeConfigToIndex(client, configType, Collections.emptyMap()); + } + + private void writeConfigToIndex(Client client, CType configType, Map config) { + try { + String json = configToJson(configType, config); + + log.info("Writing security configuration into index " + configType + ":\n" + json); + + BytesReference bytesReference = toByteReference(json); + client.index( + new IndexRequest(indexName).id(configType.toLCString()) + .setRefreshPolicy(IMMEDIATE) + .source(configType.toLCString(), bytesReference) + ).actionGet(); + } catch (Exception e) { + throw new RuntimeException("Error while initializing config for " + indexName, e); + } + } + + private static BytesReference toByteReference(String string) throws UnsupportedEncodingException { + return BytesReference.fromByteBuffer(ByteBuffer.wrap(string.getBytes("utf-8"))); + } + + private void updateConfigInIndex(Client client, CType configType, Map config) { + try { + String json = configToJson(configType, config); + BytesReference bytesReference = toByteReference(json); + log.info("Update configuration of type '{}' in index '{}', new value '{}'.", configType, indexName, json); + UpdateRequest upsert = new UpdateRequest(indexName, configType.toLCString()).doc(configType.toLCString(), bytesReference) + .setRefreshPolicy(IMMEDIATE); + client.update(upsert).actionGet(); + } catch (Exception e) { + throw new RuntimeException("Error while updating config for " + indexName, e); + } + } + + private static String configToJson(CType configType, Map config) throws IOException { + XContentBuilder builder = XContentFactory.jsonBuilder(); + + builder.startObject(); + builder.startObject("_meta"); + builder.field("type", configType.toLCString()); + builder.field("config_version", 2); + builder.endObject(); + + for (Map.Entry entry : config.entrySet()) { + builder.field(entry.getKey(), entry.getValue()); + } + + builder.endObject(); + + return Strings.toString(builder); + } + + private void writeSingleEntryConfigToIndex(Client client, CType configType, ToXContentObject config) { + writeSingleEntryConfigToIndex(client, configType, configType.toLCString(), config); + } + + private void writeSingleEntryConfigToIndex(Client client, CType configType, String configurationRoot, ToXContentObject config) { + try { + XContentBuilder builder = XContentFactory.jsonBuilder(); + + builder.startObject(); + builder.startObject("_meta"); + builder.field("type", configType.toLCString()); + builder.field("config_version", 2); + builder.endObject(); + + builder.field(configurationRoot, config); + + builder.endObject(); + + String json = Strings.toString(builder); + + log.info("Writing security plugin configuration into index " + configType + ":\n" + json); + + client.index( + new IndexRequest(indexName).id(configType.toLCString()) + .setRefreshPolicy(IMMEDIATE) + .source(configType.toLCString(), toByteReference(json)) + ).actionGet(); + } catch (Exception e) { + throw new RuntimeException("Error while initializing config for " + indexName, e); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/XffConfig.java b/src/integrationTest/java/org/opensearch/test/framework/XffConfig.java index fa4ec5d849..b1c10bfd73 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/XffConfig.java +++ b/src/integrationTest/java/org/opensearch/test/framework/XffConfig.java @@ -39,44 +39,44 @@ */ public class XffConfig implements ToXContentObject { - private final boolean enabled; + private final boolean enabled; - /** - * Regular expression used to determine if HTTP proxy is trusted or not. IP address of trusted proxies must match the regular - * expression defined by the below field. - */ - private String internalProxiesRegexp; + /** + * Regular expression used to determine if HTTP proxy is trusted or not. IP address of trusted proxies must match the regular + * expression defined by the below field. + */ + private String internalProxiesRegexp; - private String remoteIpHeader; + private String remoteIpHeader; - public XffConfig(boolean enabled) { - this.enabled = enabled; - } + public XffConfig(boolean enabled) { + this.enabled = enabled; + } - /** - * Builder-like method used to set value of the field {@link #internalProxiesRegexp} - * @param internalProxiesRegexp regular expression which matches IP address of a HTTP proxies if the proxies are trusted. - * @return builder - */ - public XffConfig internalProxiesRegexp(String internalProxiesRegexp) { - this.internalProxiesRegexp = internalProxiesRegexp; - return this; - } + /** + * Builder-like method used to set value of the field {@link #internalProxiesRegexp} + * @param internalProxiesRegexp regular expression which matches IP address of a HTTP proxies if the proxies are trusted. + * @return builder + */ + public XffConfig internalProxiesRegexp(String internalProxiesRegexp) { + this.internalProxiesRegexp = internalProxiesRegexp; + return this; + } - public XffConfig remoteIpHeader(String remoteIpHeader) { - this.remoteIpHeader = remoteIpHeader; - return this; - } + public XffConfig remoteIpHeader(String remoteIpHeader) { + this.remoteIpHeader = remoteIpHeader; + return this; + } - @Override - public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { - xContentBuilder.startObject(); - xContentBuilder.field("enabled", enabled); - xContentBuilder.field("internalProxies", internalProxiesRegexp); - if(StringUtils.isNoneBlank(remoteIpHeader)) { - xContentBuilder.field("remoteIpHeader", remoteIpHeader); - } - xContentBuilder.endObject(); - return xContentBuilder; - } + @Override + public XContentBuilder toXContent(XContentBuilder xContentBuilder, Params params) throws IOException { + xContentBuilder.startObject(); + xContentBuilder.field("enabled", enabled); + xContentBuilder.field("internalProxies", internalProxiesRegexp); + if (StringUtils.isNoneBlank(remoteIpHeader)) { + xContentBuilder.field("remoteIpHeader", remoteIpHeader); + } + xContentBuilder.endObject(); + return xContentBuilder; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/audit/AuditLogsRule.java b/src/integrationTest/java/org/opensearch/test/framework/audit/AuditLogsRule.java index 9f19b4e5db..911173e14a 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/audit/AuditLogsRule.java +++ b/src/integrationTest/java/org/opensearch/test/framework/audit/AuditLogsRule.java @@ -36,94 +36,98 @@ public class AuditLogsRule implements TestRule { - private static final Logger log = LogManager.getLogger(AuditLogsRule.class); - - private List currentTestAuditMessages; - - public void waitForAuditLogs() { - try { - TimeUnit.SECONDS.sleep(3); - afterWaitingForAuditLogs(); - } catch (InterruptedException e) { - throw new RuntimeException("Waiting for audit logs interrupted.", e); - } - } - - private void afterWaitingForAuditLogs() { - if(log.isDebugEnabled()) { - log.debug("Audit records captured during test:\n{}", auditMessagesToString(currentTestAuditMessages)); - } - } - - public void assertExactlyOne(Predicate predicate) { - assertExactly(1, predicate); - } - - public void assertAuditLogsCount(int from, int to) { - int actualCount = currentTestAuditMessages.size(); - String message = "Expected audit log count is between " + from + " and " + to + " but was " + actualCount; - assertThat(message, actualCount, allOf(greaterThanOrEqualTo(from), lessThanOrEqualTo(to))); - } - - public void assertExactly(long expectedNumberOfAuditMessages, Predicate predicate) { - assertExactly(exactNumberOfAuditsFulfillPredicate(expectedNumberOfAuditMessages, predicate)); - } - - private void assertExactly(Matcher> matcher) { - //pollDelay - initial delay before first evaluation - Awaitility.await("Await for audit logs") - .atMost(3, TimeUnit.SECONDS).pollDelay(0, TimeUnit.MICROSECONDS) - .until(() -> new ArrayList<>(currentTestAuditMessages), matcher); - } - - public void assertAtLeast(long minCount, Predicate predicate) { - assertExactly(atLeastCertainNumberOfAuditsFulfillPredicate(minCount, predicate)); - } - - private static String auditMessagesToString(List audits) { - return audits.stream().map(AuditMessage::toString).collect(Collectors.joining(",\n")); - } - - @Override - public Statement apply(Statement statement, Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - String methodName = description.getMethodName(); - beforeTest(methodName); - try { - statement.evaluate(); - } catch (ConditionTimeoutException ex) { - whenTimeoutOccurs(methodName); - throw ex; - } - finally { - afterTest(); - } - } - }; - } - - private void whenTimeoutOccurs(String methodName) { - List copy = new ArrayList<>(currentTestAuditMessages); - String auditMessages = auditMessagesToString(copy); - log.error("Timeout occured due to insufficient number ('{}') of captured audit messages during test '{}'\n{}", - copy.size(), methodName, auditMessages); - } - - private void afterTest() { - TestRuleAuditLogSink.unregisterListener(); - this.currentTestAuditMessages = null; - } - - private void beforeTest(String methodName) { - log.info("Start collecting audit logs before test {}", methodName); - this.currentTestAuditMessages = synchronizedList(new ArrayList<>()); - TestRuleAuditLogSink.registerListener(this); - } - - public void onAuditMessage(AuditMessage auditMessage) { - currentTestAuditMessages.add(auditMessage); - log.debug("New audit message received '{}', total number of audit messages '{}'.", auditMessage, currentTestAuditMessages.size()); - } + private static final Logger log = LogManager.getLogger(AuditLogsRule.class); + + private List currentTestAuditMessages; + + public void waitForAuditLogs() { + try { + TimeUnit.SECONDS.sleep(3); + afterWaitingForAuditLogs(); + } catch (InterruptedException e) { + throw new RuntimeException("Waiting for audit logs interrupted.", e); + } + } + + private void afterWaitingForAuditLogs() { + if (log.isDebugEnabled()) { + log.debug("Audit records captured during test:\n{}", auditMessagesToString(currentTestAuditMessages)); + } + } + + public void assertExactlyOne(Predicate predicate) { + assertExactly(1, predicate); + } + + public void assertAuditLogsCount(int from, int to) { + int actualCount = currentTestAuditMessages.size(); + String message = "Expected audit log count is between " + from + " and " + to + " but was " + actualCount; + assertThat(message, actualCount, allOf(greaterThanOrEqualTo(from), lessThanOrEqualTo(to))); + } + + public void assertExactly(long expectedNumberOfAuditMessages, Predicate predicate) { + assertExactly(exactNumberOfAuditsFulfillPredicate(expectedNumberOfAuditMessages, predicate)); + } + + private void assertExactly(Matcher> matcher) { + // pollDelay - initial delay before first evaluation + Awaitility.await("Await for audit logs") + .atMost(3, TimeUnit.SECONDS) + .pollDelay(0, TimeUnit.MICROSECONDS) + .until(() -> new ArrayList<>(currentTestAuditMessages), matcher); + } + + public void assertAtLeast(long minCount, Predicate predicate) { + assertExactly(atLeastCertainNumberOfAuditsFulfillPredicate(minCount, predicate)); + } + + private static String auditMessagesToString(List audits) { + return audits.stream().map(AuditMessage::toString).collect(Collectors.joining(",\n")); + } + + @Override + public Statement apply(Statement statement, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + String methodName = description.getMethodName(); + beforeTest(methodName); + try { + statement.evaluate(); + } catch (ConditionTimeoutException ex) { + whenTimeoutOccurs(methodName); + throw ex; + } finally { + afterTest(); + } + } + }; + } + + private void whenTimeoutOccurs(String methodName) { + List copy = new ArrayList<>(currentTestAuditMessages); + String auditMessages = auditMessagesToString(copy); + log.error( + "Timeout occured due to insufficient number ('{}') of captured audit messages during test '{}'\n{}", + copy.size(), + methodName, + auditMessages + ); + } + + private void afterTest() { + TestRuleAuditLogSink.unregisterListener(); + this.currentTestAuditMessages = null; + } + + private void beforeTest(String methodName) { + log.info("Start collecting audit logs before test {}", methodName); + this.currentTestAuditMessages = synchronizedList(new ArrayList<>()); + TestRuleAuditLogSink.registerListener(this); + } + + public void onAuditMessage(AuditMessage auditMessage) { + currentTestAuditMessages.add(auditMessage); + log.debug("New audit message received '{}', total number of audit messages '{}'.", auditMessage, currentTestAuditMessages.size()); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/audit/AuditMessagePredicate.java b/src/integrationTest/java/org/opensearch/test/framework/audit/AuditMessagePredicate.java index 940294b938..922f2d54aa 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/audit/AuditMessagePredicate.java +++ b/src/integrationTest/java/org/opensearch/test/framework/audit/AuditMessagePredicate.java @@ -33,122 +33,201 @@ public class AuditMessagePredicate implements Predicate { - private final AuditCategory category; - private final Origin requestLayer; - private final String restRequestPath; - private final String initiatingUser; - private final Method requestMethod; - private final String transportRequestType; - private final String effectiveUser; - private final String index; - - private AuditMessagePredicate(AuditCategory category, Origin requestLayer, String restRequestPath, - String initiatingUser, Method requestMethod, String transportRequestType, String effectiveUser, String index) { - this.category = category; - this.requestLayer = requestLayer; - this.restRequestPath = restRequestPath; - this.initiatingUser = initiatingUser; - this.requestMethod = requestMethod; - this.transportRequestType = transportRequestType; - this.effectiveUser = effectiveUser; - this.index = index; - } - - private AuditMessagePredicate(AuditCategory category) { - this(category, null, null, null, null, null, null, null); - } - - public static AuditMessagePredicate auditPredicate(AuditCategory category) { - return new AuditMessagePredicate(category); - } - - public static AuditMessagePredicate userAuthenticated(User user) { - return auditPredicate(AUTHENTICATED).withInitiatingUser(user); - } - - public static AuditMessagePredicate grantedPrivilege(User user, String requestType) { - return auditPredicate(GRANTED_PRIVILEGES).withLayer(Origin.TRANSPORT).withEffectiveUser(user) - .withTransportRequestType(requestType); - } - - public static AuditMessagePredicate missingPrivilege(User user, String requestType) { - return auditPredicate(MISSING_PRIVILEGES).withLayer(Origin.TRANSPORT).withEffectiveUser(user) - .withTransportRequestType(requestType); - } - - public AuditMessagePredicate withLayer(Origin layer) { - return new AuditMessagePredicate(category, layer, restRequestPath, initiatingUser, requestMethod, - transportRequestType, effectiveUser, index); - } - - public AuditMessagePredicate withRequestPath(String path) { - return new AuditMessagePredicate(category, requestLayer, path, initiatingUser, requestMethod, transportRequestType, effectiveUser, - index); - } - - public AuditMessagePredicate withInitiatingUser(String user) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, user, requestMethod, transportRequestType, effectiveUser, - index); - } - - public AuditMessagePredicate withInitiatingUser(User user) { - return withInitiatingUser(user.getName()); - } - - public AuditMessagePredicate withRestMethod(Method method) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, initiatingUser, method, - transportRequestType, effectiveUser, index); - } - - public AuditMessagePredicate withTransportRequestType(String type) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, initiatingUser, requestMethod, type, effectiveUser, index); - } - - public AuditMessagePredicate withEffectiveUser(String user) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, initiatingUser, requestMethod, transportRequestType, user, - index); - } - - public AuditMessagePredicate withEffectiveUser(User user) { - return withEffectiveUser(user.getName()); - } - - public AuditMessagePredicate withRestRequest(Method method, String path) { - return this.withLayer(Origin.REST).withRestMethod(method).withRequestPath(path); - } - - public AuditMessagePredicate withIndex(String indexName) { - return new AuditMessagePredicate(category, requestLayer, restRequestPath, initiatingUser, requestMethod, transportRequestType, - effectiveUser, indexName); - } - - @Override - public boolean test(AuditMessage auditMessage) { - List> predicates = new ArrayList<>(); - predicates.add(audit -> Objects.isNull(category) || category.equals(audit.getCategory())); - predicates.add(audit -> Objects.isNull(requestLayer) || requestLayer.equals(audit.getAsMap().get(REQUEST_LAYER))); - predicates.add(audit -> Objects.isNull(restRequestPath) || restRequestPath.equals(audit.getAsMap().get(REST_REQUEST_PATH))); - predicates.add(audit -> Objects.isNull(initiatingUser) || initiatingUser.equals(audit.getInitiatingUser())); - predicates.add(audit -> Objects.isNull(requestMethod) || requestMethod.equals(audit.getRequestMethod())); - predicates.add(audit -> Objects.isNull(transportRequestType) || transportRequestType.equals(audit.getRequestType())); - predicates.add(audit -> Objects.isNull(effectiveUser) || effectiveUser.equals(audit.getEffectiveUser())); - predicates.add(audit -> Objects.isNull(index) || containIndex(audit, index)); - return predicates.stream().reduce(Predicate::and).orElseThrow().test(auditMessage); - } - - private boolean containIndex(AuditMessage auditMessage, String indexName) { - Map audit = auditMessage.getAsMap(); - return Optional.ofNullable(audit.get(RESOLVED_INDICES)) - .filter(String[].class::isInstance) - .map(String[].class::cast) - .stream() - .flatMap(Arrays::stream) - .collect(Collectors.toSet()) - .contains(indexName); - } - - @Override - public String toString() { - return "AuditMessagePredicate{" + "category=" + category + ", requestLayer=" + requestLayer + ", restRequestPath='" + restRequestPath + '\'' + ", requestInitiatingUser='" + initiatingUser + '\'' + ", requestMethod=" + requestMethod + ", transportRequestType='" + transportRequestType + '\'' + '}'; - } + private final AuditCategory category; + private final Origin requestLayer; + private final String restRequestPath; + private final String initiatingUser; + private final Method requestMethod; + private final String transportRequestType; + private final String effectiveUser; + private final String index; + + private AuditMessagePredicate( + AuditCategory category, + Origin requestLayer, + String restRequestPath, + String initiatingUser, + Method requestMethod, + String transportRequestType, + String effectiveUser, + String index + ) { + this.category = category; + this.requestLayer = requestLayer; + this.restRequestPath = restRequestPath; + this.initiatingUser = initiatingUser; + this.requestMethod = requestMethod; + this.transportRequestType = transportRequestType; + this.effectiveUser = effectiveUser; + this.index = index; + } + + private AuditMessagePredicate(AuditCategory category) { + this(category, null, null, null, null, null, null, null); + } + + public static AuditMessagePredicate auditPredicate(AuditCategory category) { + return new AuditMessagePredicate(category); + } + + public static AuditMessagePredicate userAuthenticated(User user) { + return auditPredicate(AUTHENTICATED).withInitiatingUser(user); + } + + public static AuditMessagePredicate grantedPrivilege(User user, String requestType) { + return auditPredicate(GRANTED_PRIVILEGES).withLayer(Origin.TRANSPORT).withEffectiveUser(user).withTransportRequestType(requestType); + } + + public static AuditMessagePredicate missingPrivilege(User user, String requestType) { + return auditPredicate(MISSING_PRIVILEGES).withLayer(Origin.TRANSPORT).withEffectiveUser(user).withTransportRequestType(requestType); + } + + public AuditMessagePredicate withLayer(Origin layer) { + return new AuditMessagePredicate( + category, + layer, + restRequestPath, + initiatingUser, + requestMethod, + transportRequestType, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withRequestPath(String path) { + return new AuditMessagePredicate( + category, + requestLayer, + path, + initiatingUser, + requestMethod, + transportRequestType, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withInitiatingUser(String user) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + user, + requestMethod, + transportRequestType, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withInitiatingUser(User user) { + return withInitiatingUser(user.getName()); + } + + public AuditMessagePredicate withRestMethod(Method method) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + initiatingUser, + method, + transportRequestType, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withTransportRequestType(String type) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + initiatingUser, + requestMethod, + type, + effectiveUser, + index + ); + } + + public AuditMessagePredicate withEffectiveUser(String user) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + initiatingUser, + requestMethod, + transportRequestType, + user, + index + ); + } + + public AuditMessagePredicate withEffectiveUser(User user) { + return withEffectiveUser(user.getName()); + } + + public AuditMessagePredicate withRestRequest(Method method, String path) { + return this.withLayer(Origin.REST).withRestMethod(method).withRequestPath(path); + } + + public AuditMessagePredicate withIndex(String indexName) { + return new AuditMessagePredicate( + category, + requestLayer, + restRequestPath, + initiatingUser, + requestMethod, + transportRequestType, + effectiveUser, + indexName + ); + } + + @Override + public boolean test(AuditMessage auditMessage) { + List> predicates = new ArrayList<>(); + predicates.add(audit -> Objects.isNull(category) || category.equals(audit.getCategory())); + predicates.add(audit -> Objects.isNull(requestLayer) || requestLayer.equals(audit.getAsMap().get(REQUEST_LAYER))); + predicates.add(audit -> Objects.isNull(restRequestPath) || restRequestPath.equals(audit.getAsMap().get(REST_REQUEST_PATH))); + predicates.add(audit -> Objects.isNull(initiatingUser) || initiatingUser.equals(audit.getInitiatingUser())); + predicates.add(audit -> Objects.isNull(requestMethod) || requestMethod.equals(audit.getRequestMethod())); + predicates.add(audit -> Objects.isNull(transportRequestType) || transportRequestType.equals(audit.getRequestType())); + predicates.add(audit -> Objects.isNull(effectiveUser) || effectiveUser.equals(audit.getEffectiveUser())); + predicates.add(audit -> Objects.isNull(index) || containIndex(audit, index)); + return predicates.stream().reduce(Predicate::and).orElseThrow().test(auditMessage); + } + + private boolean containIndex(AuditMessage auditMessage, String indexName) { + Map audit = auditMessage.getAsMap(); + return Optional.ofNullable(audit.get(RESOLVED_INDICES)) + .filter(String[].class::isInstance) + .map(String[].class::cast) + .stream() + .flatMap(Arrays::stream) + .collect(Collectors.toSet()) + .contains(indexName); + } + + @Override + public String toString() { + return "AuditMessagePredicate{" + + "category=" + + category + + ", requestLayer=" + + requestLayer + + ", restRequestPath='" + + restRequestPath + + '\'' + + ", requestInitiatingUser='" + + initiatingUser + + '\'' + + ", requestMethod=" + + requestMethod + + ", transportRequestType='" + + transportRequestType + + '\'' + + '}'; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/audit/TestRuleAuditLogSink.java b/src/integrationTest/java/org/opensearch/test/framework/audit/TestRuleAuditLogSink.java index 0a9abaeb0d..c73d57d23c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/audit/TestRuleAuditLogSink.java +++ b/src/integrationTest/java/org/opensearch/test/framework/audit/TestRuleAuditLogSink.java @@ -17,35 +17,35 @@ import org.opensearch.security.auditlog.sink.AuditLogSink; public class TestRuleAuditLogSink extends AuditLogSink { - private static final Logger log = LogManager.getLogger(TestRuleAuditLogSink.class); - - private static volatile AuditLogsRule listener; - - public TestRuleAuditLogSink(String name, Settings settings, String settingsPrefix, AuditLogSink fallbackSink) { - super(name, settings, settingsPrefix, fallbackSink); - log.info("Test rule audit log sink created"); - } - - @Override - protected boolean doStore(AuditMessage auditMessage) { - log.debug("New audit message received '{}'.", auditMessage); - AuditLogsRule currentListener = listener; - if(currentListener != null) { - currentListener.onAuditMessage(auditMessage); - } - return true; - } - - public static void registerListener(AuditLogsRule auditLogsRule) { - listener = auditLogsRule; - } - - public static void unregisterListener() { - listener = null; - } - - @Override - public boolean isHandlingBackpressure() { - return true; - } + private static final Logger log = LogManager.getLogger(TestRuleAuditLogSink.class); + + private static volatile AuditLogsRule listener; + + public TestRuleAuditLogSink(String name, Settings settings, String settingsPrefix, AuditLogSink fallbackSink) { + super(name, settings, settingsPrefix, fallbackSink); + log.info("Test rule audit log sink created"); + } + + @Override + protected boolean doStore(AuditMessage auditMessage) { + log.debug("New audit message received '{}'.", auditMessage); + AuditLogsRule currentListener = listener; + if (currentListener != null) { + currentListener.onAuditMessage(auditMessage); + } + return true; + } + + public static void registerListener(AuditLogsRule auditLogsRule) { + listener = auditLogsRule; + } + + public static void unregisterListener() { + listener = null; + } + + @Override + public boolean isHandlingBackpressure() { + return true; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/AlgorithmKit.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/AlgorithmKit.java index 270a2bad6f..60ae56410c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/AlgorithmKit.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/AlgorithmKit.java @@ -48,99 +48,100 @@ */ class AlgorithmKit { - private static final Logger log = LogManager.getLogger(AlgorithmKit.class); - public static final String SIGNATURE_ALGORITHM_SHA_256_WITH_RSA = "SHA256withRSA"; - public static final String SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA = "SHA256withECDSA"; - - private final String signatureAlgorithmName; - private final Supplier keyPairSupplier; - - private AlgorithmKit(String signatureAlgorithmName, Supplier keyPairSupplier) { - notEmptyAlgorithmName(signatureAlgorithmName); - this.signatureAlgorithmName = signatureAlgorithmName; - this.keyPairSupplier = requireNonNull(keyPairSupplier, "Key pair supplier is required."); - } - - private static void notEmptyAlgorithmName(String signatureAlgorithmName) { - if(Strings.isNullOrEmpty(signatureAlgorithmName)){ - throw new RuntimeException("Algorithm name is required."); - } - } - - /** - * Static factory method. ECDSA algorithm used for key pair creation. Signature algorithm is defined by field - * {@link #SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA} - * - * @param securityProvider determines cryptographic algorithm implementation - * @param ellipticCurve - * @return new instance of class {@link AlgorithmKit} - */ - public static AlgorithmKit ecdsaSha256withEcdsa(Provider securityProvider, String ellipticCurve) { - notEmptyAlgorithmName(ellipticCurve); - Supplier supplier = ecdsaKeyPairSupplier(requireNonNull(securityProvider, "Security provider is required"), ellipticCurve); - return new AlgorithmKit(SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA, supplier); - } - - /** - * Static factory method. It creates object of {@link AlgorithmKit} which enforces usage of RSA algorithm for key pair generation. - * Signature algorithm is defined by {@link #SIGNATURE_ALGORITHM_SHA_256_WITH_RSA} - * - * @param securityProvider determines cryptographic algorithm implementation - * @param keySize defines key size for RSA algorithm - * @return new instance of class {@link AlgorithmKit} - */ - public static AlgorithmKit rsaSha256withRsa(Provider securityProvider, int keySize) { - positiveKeySize(keySize); - Supplier supplier = rsaKeyPairSupplier(securityProvider, keySize); - return new AlgorithmKit(SIGNATURE_ALGORITHM_SHA_256_WITH_RSA, supplier); - } - - private static void positiveKeySize(int keySize) { - if(keySize <= 0) { - throw new RuntimeException("Key size must be a positive integer value, provided: " + keySize); - } - } - - /** - * It determines algorithm used for digital signature - * @return algorithm name - */ - public String getSignatureAlgorithmName(){ - return signatureAlgorithmName; - } - - /** - * It creates new private and public key pair - * @return new pair of keys - */ - public KeyPair generateKeyPair(){ - return keyPairSupplier.get(); - } - private static Supplier rsaKeyPairSupplier(Provider securityProvider, int keySize) { - try { - KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", securityProvider); - log.info("Initialize key pair generator with keySize: {}", keySize); - generator.initialize(keySize); - return generator::generateKeyPair; - } catch (NoSuchAlgorithmException e) { - String message = "Error while initializing RSA asymmetric key generator."; - log.error(message, e); - throw new RuntimeException(message, e); - } - } - - private static Supplier ecdsaKeyPairSupplier(Provider securityProvider, String ellipticCurve) { - try { - KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", securityProvider); - log.info("Initialize key pair generator with elliptic curve: {}", ellipticCurve); - ECGenParameterSpec ecsp = new ECGenParameterSpec(ellipticCurve); - generator.initialize(ecsp); - return generator::generateKeyPair; - } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { - String message = "Error while initializing ECDSA asymmetric key generator."; - log.error(message, e); - throw new RuntimeException(message, e); - } - } + private static final Logger log = LogManager.getLogger(AlgorithmKit.class); + public static final String SIGNATURE_ALGORITHM_SHA_256_WITH_RSA = "SHA256withRSA"; + public static final String SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA = "SHA256withECDSA"; + + private final String signatureAlgorithmName; + private final Supplier keyPairSupplier; + + private AlgorithmKit(String signatureAlgorithmName, Supplier keyPairSupplier) { + notEmptyAlgorithmName(signatureAlgorithmName); + this.signatureAlgorithmName = signatureAlgorithmName; + this.keyPairSupplier = requireNonNull(keyPairSupplier, "Key pair supplier is required."); + } + + private static void notEmptyAlgorithmName(String signatureAlgorithmName) { + if (Strings.isNullOrEmpty(signatureAlgorithmName)) { + throw new RuntimeException("Algorithm name is required."); + } + } + + /** + * Static factory method. ECDSA algorithm used for key pair creation. Signature algorithm is defined by field + * {@link #SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA} + * + * @param securityProvider determines cryptographic algorithm implementation + * @param ellipticCurve + * @return new instance of class {@link AlgorithmKit} + */ + public static AlgorithmKit ecdsaSha256withEcdsa(Provider securityProvider, String ellipticCurve) { + notEmptyAlgorithmName(ellipticCurve); + Supplier supplier = ecdsaKeyPairSupplier(requireNonNull(securityProvider, "Security provider is required"), ellipticCurve); + return new AlgorithmKit(SIGNATURE_ALGORITHM_SHA_256_WITH_ECDSA, supplier); + } + + /** + * Static factory method. It creates object of {@link AlgorithmKit} which enforces usage of RSA algorithm for key pair generation. + * Signature algorithm is defined by {@link #SIGNATURE_ALGORITHM_SHA_256_WITH_RSA} + * + * @param securityProvider determines cryptographic algorithm implementation + * @param keySize defines key size for RSA algorithm + * @return new instance of class {@link AlgorithmKit} + */ + public static AlgorithmKit rsaSha256withRsa(Provider securityProvider, int keySize) { + positiveKeySize(keySize); + Supplier supplier = rsaKeyPairSupplier(securityProvider, keySize); + return new AlgorithmKit(SIGNATURE_ALGORITHM_SHA_256_WITH_RSA, supplier); + } + + private static void positiveKeySize(int keySize) { + if (keySize <= 0) { + throw new RuntimeException("Key size must be a positive integer value, provided: " + keySize); + } + } + + /** + * It determines algorithm used for digital signature + * @return algorithm name + */ + public String getSignatureAlgorithmName() { + return signatureAlgorithmName; + } + + /** + * It creates new private and public key pair + * @return new pair of keys + */ + public KeyPair generateKeyPair() { + return keyPairSupplier.get(); + } + + private static Supplier rsaKeyPairSupplier(Provider securityProvider, int keySize) { + try { + KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", securityProvider); + log.info("Initialize key pair generator with keySize: {}", keySize); + generator.initialize(keySize); + return generator::generateKeyPair; + } catch (NoSuchAlgorithmException e) { + String message = "Error while initializing RSA asymmetric key generator."; + log.error(message, e); + throw new RuntimeException(message, e); + } + } + + private static Supplier ecdsaKeyPairSupplier(Provider securityProvider, String ellipticCurve) { + try { + KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", securityProvider); + log.info("Initialize key pair generator with elliptic curve: {}", ellipticCurve); + ECGenParameterSpec ecsp = new ECGenParameterSpec(ellipticCurve); + generator.initialize(ecsp); + return generator::generateKeyPair; + } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { + String message = "Error while initializing ECDSA asymmetric key generator."; + log.error(message, e); + throw new RuntimeException(message, e); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateData.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateData.java index 3712bd1763..09d0f931e6 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateData.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateData.java @@ -40,50 +40,50 @@ */ public class CertificateData { - private final X509CertificateHolder certificate; - private final KeyPair keyPair; + private final X509CertificateHolder certificate; + private final KeyPair keyPair; - public CertificateData(X509CertificateHolder certificate, KeyPair keyPair) { - this.certificate = certificate; - this.keyPair = keyPair; - } + public CertificateData(X509CertificateHolder certificate, KeyPair keyPair) { + this.certificate = certificate; + this.keyPair = keyPair; + } - /** - * The method returns X.509 certificate encoded in PEM format. PEM format is defined by - * RFC 1421. - * @return Certificate in PEM format - */ - public String certificateInPemFormat() { - return PemConverter.toPem(certificate); - } + /** + * The method returns X.509 certificate encoded in PEM format. PEM format is defined by + * RFC 1421. + * @return Certificate in PEM format + */ + public String certificateInPemFormat() { + return PemConverter.toPem(certificate); + } - public X509Certificate certificate() { - try { - return new JcaX509CertificateConverter().getCertificate(certificate); - } catch (CertificateException e) { - throw new RuntimeException("Cannot retrieve certificate", e); - } - } + public X509Certificate certificate() { + try { + return new JcaX509CertificateConverter().getCertificate(certificate); + } catch (CertificateException e) { + throw new RuntimeException("Cannot retrieve certificate", e); + } + } - /** - * It returns the private key associated with certificate encoded in PEM format. PEM format is defined by - * RFC 1421. - * @param privateKeyPassword password used for private key encryption. null for unencrypted key. - * @return private key encoded in PEM format - */ - public String privateKeyInPemFormat(String privateKeyPassword) { - return PemConverter.toPem(keyPair.getPrivate(), privateKeyPassword); - } + /** + * It returns the private key associated with certificate encoded in PEM format. PEM format is defined by + * RFC 1421. + * @param privateKeyPassword password used for private key encryption. null for unencrypted key. + * @return private key encoded in PEM format + */ + public String privateKeyInPemFormat(String privateKeyPassword) { + return PemConverter.toPem(keyPair.getPrivate(), privateKeyPassword); + } - X500Name getCertificateSubject() { - return certificate.getSubject(); - } + X500Name getCertificateSubject() { + return certificate.getSubject(); + } - KeyPair getKeyPair() { - return keyPair; - } + KeyPair getKeyPair() { + return keyPair; + } - public Key getKey() { - return keyPair.getPrivate(); - } + public Key getKey() { + return keyPair.getPrivate(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateMetadata.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateMetadata.java index fbd2c1f8e8..cc94621f72 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateMetadata.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificateMetadata.java @@ -42,180 +42,179 @@ * */ class CertificateMetadata { - /** - * Certification subject (person, company, web server, IoT device). The subject of certificate is an owner of the certificate - * (simplification). The format of this field must adhere to RFC 4514. - * @see RFC 4514 - */ - private final String subject; - - /** - * It describes certificate expiration date - */ - private final int validityDays; - - /** - * Optionally used by Open Search to indicate that the certificate can be used by Open Search node to confirm the node identity. The - * value becomes a part of - * SAN (Subject Alternative Name) extension - * - * @see #dnsNames - * @see SAN (Subject Alternative Name) extension - */ - private final String nodeOid; - - /** - * The certificate contains only one {@link #subject}. This is a common limitation when a certificate is used by a web server which is - * associated with a few domains. To overcome this limitation SAN (Subject Alternative Name) extension was introduced. - * The field contains additional subject names which enables creation of so called multi-domain certificates. The extension is defined - * in section 4.2.1.6 of RFC 5280 - * - * @see RFC 5280 - */ - private final List dnsNames; - - /** - * Similar to {@link #dnsNames} but contains IP addresses instead of domains. - */ - private final List ipAddresses; - - /** - * If a private key associated with certificate is used to sign other certificate then this field has to be true. - */ - private final boolean basicConstrainIsCa; - - /** - * Allowed usages for public key associated with certificate - */ - private final Set keyUsages; - - - private CertificateMetadata(String subject, - int validityDays, - String nodeOid, - List dnsNames, - List ipAddresses, - boolean basicConstrainIsCa, - Set keyUsages) { - this.subject = subject; - this.validityDays = validityDays; - this.nodeOid = nodeOid; - this.dnsNames = requireNonNull(dnsNames, "List of dns names must not be null."); - this.ipAddresses = requireNonNull(ipAddresses, "List of IP addresses must not be null"); - this.basicConstrainIsCa = basicConstrainIsCa; - this.keyUsages = requireNonNull(keyUsages, "Key usage set must not be null."); - } - - /** - * Static factory method. It creates metadata which contains only basic information. - * @param subjectName please see {@link #subject} - * @param validityDays please see {@link #validityDays} - * @return new instance of {@link CertificateMetadata} - */ - public static CertificateMetadata basicMetadata(String subjectName, int validityDays) { - return new CertificateMetadata(subjectName, validityDays, null, emptyList(), emptyList(), false, emptySet()); - } - - /** - * It is related to private key associated with certificate. It specifies metadata related to allowed private key usage. - * @param basicConstrainIsCa {@link #basicConstrainIsCa} - * @param keyUsages {@link #keyUsages} - * @return returns newly created instance of {@link CertificateData} - */ - public CertificateMetadata withKeyUsage(boolean basicConstrainIsCa, PublicKeyUsage...keyUsages){ - Set usages = arrayToEnumSet(keyUsages); - return new CertificateMetadata(subject, validityDays, nodeOid, dnsNames, ipAddresses, basicConstrainIsCa, usages); - } - - private > Set arrayToEnumSet(T[] enumArray) { - if((enumArray == null) || (enumArray.length == 0)){ - return Collections.emptySet(); - } - return EnumSet.copyOf(asList(enumArray)); - } - - /** - * The method defines metadata related to SAN (Subject Alternative Name) extension. - * @param nodeOid {@link #nodeOid} - * @param dnsNames {@link #dnsNames} - * @param ipAddresses {@link #ipAddresses} - * @return new instance of {@link CertificateMetadata} - * @see SAN (Subject Alternative Name) extension - */ - public CertificateMetadata withSubjectAlternativeName(String nodeOid, List dnsNames, String...ipAddresses) { - return new CertificateMetadata(subject, validityDays, nodeOid, dnsNames, asList(ipAddresses), basicConstrainIsCa, keyUsages); - } - - /** - * {@link #subject} - * @return Subject name - */ - public String getSubject() { - return subject; - } - - /** - * {@link #validityDays} - * @return determines certificate expiration date - */ - public int getValidityDays() { - return validityDays; - } - - /** - * {@link #basicConstrainIsCa} - * @return Determines if another certificate can be derived from certificate. - */ - public boolean isBasicConstrainIsCa() { - return basicConstrainIsCa; - } - - KeyUsage asKeyUsage() { - Integer keyUsageBitMask = keyUsages - .stream() - .filter(PublicKeyUsage::isNotExtendedUsage) - .map(PublicKeyUsage::asInt) - .reduce(0, (accumulator, currentValue) -> accumulator | currentValue); - return new KeyUsage(keyUsageBitMask); - } - - boolean hasSubjectAlternativeNameExtension() { - return ((ipAddresses.size() + dnsNames.size()) > 0) || (Strings.isNullOrEmpty(nodeOid) == false); - } - - DERSequence createSubjectAlternativeNames() { - List subjectAlternativeNameList = new ArrayList<>(); - if (!Strings.isNullOrEmpty(nodeOid)) { - subjectAlternativeNameList.add(new GeneralName(GeneralName.registeredID, nodeOid)); - } - if (isNotEmpty(dnsNames)) { - for (String dnsName : dnsNames) { - subjectAlternativeNameList.add(new GeneralName(GeneralName.dNSName, dnsName)); - } - } - if (isNotEmpty(ipAddresses)) { - for (String ip : ipAddresses) { - subjectAlternativeNameList.add(new GeneralName(GeneralName.iPAddress, ip)); - } - } - return new DERSequence(subjectAlternativeNameList.toArray(ASN1Encodable[]::new)); - } - - private static boolean isNotEmpty(Collection collection) { - return (collection != null) && (!collection.isEmpty()); - } - - boolean hasExtendedKeyUsage() { - return keyUsages.stream().anyMatch(PublicKeyUsage::isNotExtendedUsage); - } - - ExtendedKeyUsage getExtendedKeyUsage() { - KeyPurposeId[] usages = keyUsages - .stream() - .filter(PublicKeyUsage::isExtendedUsage) - .map(PublicKeyUsage::getKeyPurposeId) - .toArray(KeyPurposeId[]::new); - return new ExtendedKeyUsage(usages); - } + /** + * Certification subject (person, company, web server, IoT device). The subject of certificate is an owner of the certificate + * (simplification). The format of this field must adhere to RFC 4514. + * @see RFC 4514 + */ + private final String subject; + + /** + * It describes certificate expiration date + */ + private final int validityDays; + + /** + * Optionally used by Open Search to indicate that the certificate can be used by Open Search node to confirm the node identity. The + * value becomes a part of + * SAN (Subject Alternative Name) extension + * + * @see #dnsNames + * @see SAN (Subject Alternative Name) extension + */ + private final String nodeOid; + + /** + * The certificate contains only one {@link #subject}. This is a common limitation when a certificate is used by a web server which is + * associated with a few domains. To overcome this limitation SAN (Subject Alternative Name) extension was introduced. + * The field contains additional subject names which enables creation of so called multi-domain certificates. The extension is defined + * in section 4.2.1.6 of RFC 5280 + * + * @see RFC 5280 + */ + private final List dnsNames; + + /** + * Similar to {@link #dnsNames} but contains IP addresses instead of domains. + */ + private final List ipAddresses; + + /** + * If a private key associated with certificate is used to sign other certificate then this field has to be true. + */ + private final boolean basicConstrainIsCa; + + /** + * Allowed usages for public key associated with certificate + */ + private final Set keyUsages; + + private CertificateMetadata( + String subject, + int validityDays, + String nodeOid, + List dnsNames, + List ipAddresses, + boolean basicConstrainIsCa, + Set keyUsages + ) { + this.subject = subject; + this.validityDays = validityDays; + this.nodeOid = nodeOid; + this.dnsNames = requireNonNull(dnsNames, "List of dns names must not be null."); + this.ipAddresses = requireNonNull(ipAddresses, "List of IP addresses must not be null"); + this.basicConstrainIsCa = basicConstrainIsCa; + this.keyUsages = requireNonNull(keyUsages, "Key usage set must not be null."); + } + + /** + * Static factory method. It creates metadata which contains only basic information. + * @param subjectName please see {@link #subject} + * @param validityDays please see {@link #validityDays} + * @return new instance of {@link CertificateMetadata} + */ + public static CertificateMetadata basicMetadata(String subjectName, int validityDays) { + return new CertificateMetadata(subjectName, validityDays, null, emptyList(), emptyList(), false, emptySet()); + } + + /** + * It is related to private key associated with certificate. It specifies metadata related to allowed private key usage. + * @param basicConstrainIsCa {@link #basicConstrainIsCa} + * @param keyUsages {@link #keyUsages} + * @return returns newly created instance of {@link CertificateData} + */ + public CertificateMetadata withKeyUsage(boolean basicConstrainIsCa, PublicKeyUsage... keyUsages) { + Set usages = arrayToEnumSet(keyUsages); + return new CertificateMetadata(subject, validityDays, nodeOid, dnsNames, ipAddresses, basicConstrainIsCa, usages); + } + + private > Set arrayToEnumSet(T[] enumArray) { + if ((enumArray == null) || (enumArray.length == 0)) { + return Collections.emptySet(); + } + return EnumSet.copyOf(asList(enumArray)); + } + + /** + * The method defines metadata related to SAN (Subject Alternative Name) extension. + * @param nodeOid {@link #nodeOid} + * @param dnsNames {@link #dnsNames} + * @param ipAddresses {@link #ipAddresses} + * @return new instance of {@link CertificateMetadata} + * @see SAN (Subject Alternative Name) extension + */ + public CertificateMetadata withSubjectAlternativeName(String nodeOid, List dnsNames, String... ipAddresses) { + return new CertificateMetadata(subject, validityDays, nodeOid, dnsNames, asList(ipAddresses), basicConstrainIsCa, keyUsages); + } + + /** + * {@link #subject} + * @return Subject name + */ + public String getSubject() { + return subject; + } + + /** + * {@link #validityDays} + * @return determines certificate expiration date + */ + public int getValidityDays() { + return validityDays; + } + + /** + * {@link #basicConstrainIsCa} + * @return Determines if another certificate can be derived from certificate. + */ + public boolean isBasicConstrainIsCa() { + return basicConstrainIsCa; + } + + KeyUsage asKeyUsage() { + Integer keyUsageBitMask = keyUsages.stream() + .filter(PublicKeyUsage::isNotExtendedUsage) + .map(PublicKeyUsage::asInt) + .reduce(0, (accumulator, currentValue) -> accumulator | currentValue); + return new KeyUsage(keyUsageBitMask); + } + + boolean hasSubjectAlternativeNameExtension() { + return ((ipAddresses.size() + dnsNames.size()) > 0) || (Strings.isNullOrEmpty(nodeOid) == false); + } + + DERSequence createSubjectAlternativeNames() { + List subjectAlternativeNameList = new ArrayList<>(); + if (!Strings.isNullOrEmpty(nodeOid)) { + subjectAlternativeNameList.add(new GeneralName(GeneralName.registeredID, nodeOid)); + } + if (isNotEmpty(dnsNames)) { + for (String dnsName : dnsNames) { + subjectAlternativeNameList.add(new GeneralName(GeneralName.dNSName, dnsName)); + } + } + if (isNotEmpty(ipAddresses)) { + for (String ip : ipAddresses) { + subjectAlternativeNameList.add(new GeneralName(GeneralName.iPAddress, ip)); + } + } + return new DERSequence(subjectAlternativeNameList.toArray(ASN1Encodable[]::new)); + } + + private static boolean isNotEmpty(Collection collection) { + return (collection != null) && (!collection.isEmpty()); + } + + boolean hasExtendedKeyUsage() { + return keyUsages.stream().anyMatch(PublicKeyUsage::isNotExtendedUsage); + } + + ExtendedKeyUsage getExtendedKeyUsage() { + KeyPurposeId[] usages = keyUsages.stream() + .filter(PublicKeyUsage::isExtendedUsage) + .map(PublicKeyUsage::getKeyPurposeId) + .toArray(KeyPurposeId[]::new); + return new ExtendedKeyUsage(usages); + } } // CS-ENFORCE-SINGLE diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuer.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuer.java index 8d821a4571..6facf5f2ac 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuer.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuer.java @@ -83,144 +83,159 @@ */ class CertificatesIssuer { - private static final Logger log = LogManager.getLogger(CertificatesIssuer.class); - - private static final AtomicLong ID_COUNTER = new AtomicLong(System.currentTimeMillis()); - - private final Provider securityProvider; - private final AlgorithmKit algorithmKit; - private final JcaX509ExtensionUtils extUtils; - - CertificatesIssuer(Provider securityProvider, AlgorithmKit algorithmKit) { - this.securityProvider = securityProvider; - this.algorithmKit = algorithmKit; - this.extUtils = getExtUtils(); - } - - /** - * The method creates a certificate with provided metadata and public key obtained from {@link #algorithmKit}. The result of invocation - * contains required data to use a certificate by its owner. - * - * @param certificateMetadata metadata which should be embedded into created certificate - * @return {@link CertificateData} which contain certificate and private key associated with the certificate. - */ - public CertificateData issueSelfSignedCertificate(CertificateMetadata certificateMetadata) { - try { - KeyPair publicAndPrivateKey = algorithmKit.generateKeyPair(); - X500Name issuerName = stringToX500Name(requireNonNull(certificateMetadata.getSubject(), "Certificate metadata are required.")); - X509CertificateHolder x509CertificateHolder = buildCertificateHolder( - certificateMetadata, - issuerName, - publicAndPrivateKey.getPublic(), - publicAndPrivateKey); - return new CertificateData(x509CertificateHolder, publicAndPrivateKey); - } catch (OperatorCreationException | CertIOException e) { - log.error("Error while generating certificate", e); - throw new RuntimeException("Error while generating self signed certificate", e); - } - } - - /** - * The method is similar to {@link #issueSignedCertificate(CertificateMetadata, CertificateData)} but additionally it signs created - * certificate using data from parentCertificateData. - * - * @param metadata metadata which should be embedded into created certificate - * @param parentCertificateData data required to signe a newly issued certificate (private key among others things). - * @return {@link CertificateData} which contain certificate and private key associated with the certificate. - */ - public CertificateData issueSignedCertificate(CertificateMetadata metadata, CertificateData parentCertificateData) { - try { - KeyPair publicAndPrivateKey = algorithmKit.generateKeyPair(); - KeyPair parentKeyPair = requireNonNull(parentCertificateData, "Issuer certificate data are required") - .getKeyPair(); - X500Name issuerName = parentCertificateData.getCertificateSubject(); - var x509CertificateHolder = buildCertificateHolder(requireNonNull(metadata, "Certificate metadata are required"), - issuerName, - publicAndPrivateKey.getPublic(), - parentKeyPair); - return new CertificateData(x509CertificateHolder, publicAndPrivateKey); - } catch (OperatorCreationException | CertIOException e) { - log.error("Error while generating signed certificate", e); - throw new RuntimeException("Error while generating signed certificate", e); - } - } - - private X509CertificateHolder buildCertificateHolder(CertificateMetadata certificateMetadata, - X500Name issuerName, - PublicKey certificatePublicKey, - KeyPair parentKeyPair) throws CertIOException, OperatorCreationException { - X509v3CertificateBuilder builder = builderWithBasicExtensions(certificateMetadata, issuerName, certificatePublicKey, parentKeyPair.getPublic()); - addSubjectAlternativeNameExtension(builder, certificateMetadata); - addExtendedKeyUsageExtension(builder, certificateMetadata); - return builder.build(createContentSigner(parentKeyPair.getPrivate())); - } - - private ContentSigner createContentSigner(PrivateKey privateKey) throws OperatorCreationException { - return new JcaContentSignerBuilder(algorithmKit.getSignatureAlgorithmName()) - .setProvider(securityProvider) - .build(privateKey); - } - - private void addExtendedKeyUsageExtension(X509v3CertificateBuilder builder, CertificateMetadata certificateMetadata) throws CertIOException { - if(certificateMetadata.hasExtendedKeyUsage()) { - builder.addExtension(Extension.extendedKeyUsage, true, certificateMetadata.getExtendedKeyUsage()); - } - } - - private X509v3CertificateBuilder builderWithBasicExtensions(CertificateMetadata certificateMetadata, - X500Name issuerName, - PublicKey certificatePublicKey, - PublicKey parentPublicKey) throws CertIOException { - X500Name subjectName = stringToX500Name(certificateMetadata.getSubject()); - Date validityStartDate = new Date(System.currentTimeMillis() - (24 * 3600 * 1000)); - Date validityEndDate = getEndDate(validityStartDate, certificateMetadata.getValidityDays()); - - BigInteger certificateSerialNumber = generateNextCertificateSerialNumber(); - return new X509v3CertificateBuilder(issuerName, certificateSerialNumber, validityStartDate, - validityEndDate, subjectName, SubjectPublicKeyInfo.getInstance(certificatePublicKey.getEncoded())) - .addExtension(Extension.basicConstraints, true, new BasicConstraints(certificateMetadata.isBasicConstrainIsCa())) - .addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(parentPublicKey)) - .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certificatePublicKey)) - .addExtension(Extension.keyUsage, true, certificateMetadata.asKeyUsage()); - } - - private void addSubjectAlternativeNameExtension(X509v3CertificateBuilder builder, CertificateMetadata metadata) throws CertIOException { - if(metadata.hasSubjectAlternativeNameExtension()){ - DERSequence subjectAlternativeNames = metadata.createSubjectAlternativeNames(); - builder.addExtension(Extension.subjectAlternativeName, false, subjectAlternativeNames); - } - } - - private Date getEndDate(Date startDate, int validityDays) { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(startDate); - calendar.add(Calendar.DATE, validityDays); - return calendar.getTime(); - } - - private static JcaX509ExtensionUtils getExtUtils() { - try { - return new JcaX509ExtensionUtils(); - } catch (NoSuchAlgorithmException e) { - log.error("Getting certificate extension utils failed", e); - throw new RuntimeException("Getting certificate extension utils failed", e); - } - } - - private X500Name stringToX500Name(String distinguishedName) { - if (Strings.isNullOrEmpty(distinguishedName)) { - throw new RuntimeException("No DN (distinguished name) must not be null or empty"); - } - try { - return new X500Name(RFC4519Style.INSTANCE, distinguishedName); - } catch (IllegalArgumentException e) { - String message = String.format("Invalid DN (distinguished name) specified for %s certificate.", distinguishedName); - throw new RuntimeException(message, e); - } - } - - private BigInteger generateNextCertificateSerialNumber() { - return BigInteger.valueOf(ID_COUNTER.incrementAndGet()); - } + private static final Logger log = LogManager.getLogger(CertificatesIssuer.class); + + private static final AtomicLong ID_COUNTER = new AtomicLong(System.currentTimeMillis()); + + private final Provider securityProvider; + private final AlgorithmKit algorithmKit; + private final JcaX509ExtensionUtils extUtils; + + CertificatesIssuer(Provider securityProvider, AlgorithmKit algorithmKit) { + this.securityProvider = securityProvider; + this.algorithmKit = algorithmKit; + this.extUtils = getExtUtils(); + } + + /** + * The method creates a certificate with provided metadata and public key obtained from {@link #algorithmKit}. The result of invocation + * contains required data to use a certificate by its owner. + * + * @param certificateMetadata metadata which should be embedded into created certificate + * @return {@link CertificateData} which contain certificate and private key associated with the certificate. + */ + public CertificateData issueSelfSignedCertificate(CertificateMetadata certificateMetadata) { + try { + KeyPair publicAndPrivateKey = algorithmKit.generateKeyPair(); + X500Name issuerName = stringToX500Name(requireNonNull(certificateMetadata.getSubject(), "Certificate metadata are required.")); + X509CertificateHolder x509CertificateHolder = buildCertificateHolder( + certificateMetadata, + issuerName, + publicAndPrivateKey.getPublic(), + publicAndPrivateKey + ); + return new CertificateData(x509CertificateHolder, publicAndPrivateKey); + } catch (OperatorCreationException | CertIOException e) { + log.error("Error while generating certificate", e); + throw new RuntimeException("Error while generating self signed certificate", e); + } + } + + /** + * The method is similar to {@link #issueSignedCertificate(CertificateMetadata, CertificateData)} but additionally it signs created + * certificate using data from parentCertificateData. + * + * @param metadata metadata which should be embedded into created certificate + * @param parentCertificateData data required to signe a newly issued certificate (private key among others things). + * @return {@link CertificateData} which contain certificate and private key associated with the certificate. + */ + public CertificateData issueSignedCertificate(CertificateMetadata metadata, CertificateData parentCertificateData) { + try { + KeyPair publicAndPrivateKey = algorithmKit.generateKeyPair(); + KeyPair parentKeyPair = requireNonNull(parentCertificateData, "Issuer certificate data are required").getKeyPair(); + X500Name issuerName = parentCertificateData.getCertificateSubject(); + var x509CertificateHolder = buildCertificateHolder( + requireNonNull(metadata, "Certificate metadata are required"), + issuerName, + publicAndPrivateKey.getPublic(), + parentKeyPair + ); + return new CertificateData(x509CertificateHolder, publicAndPrivateKey); + } catch (OperatorCreationException | CertIOException e) { + log.error("Error while generating signed certificate", e); + throw new RuntimeException("Error while generating signed certificate", e); + } + } + + private X509CertificateHolder buildCertificateHolder( + CertificateMetadata certificateMetadata, + X500Name issuerName, + PublicKey certificatePublicKey, + KeyPair parentKeyPair + ) throws CertIOException, OperatorCreationException { + X509v3CertificateBuilder builder = builderWithBasicExtensions( + certificateMetadata, + issuerName, + certificatePublicKey, + parentKeyPair.getPublic() + ); + addSubjectAlternativeNameExtension(builder, certificateMetadata); + addExtendedKeyUsageExtension(builder, certificateMetadata); + return builder.build(createContentSigner(parentKeyPair.getPrivate())); + } + + private ContentSigner createContentSigner(PrivateKey privateKey) throws OperatorCreationException { + return new JcaContentSignerBuilder(algorithmKit.getSignatureAlgorithmName()).setProvider(securityProvider).build(privateKey); + } + + private void addExtendedKeyUsageExtension(X509v3CertificateBuilder builder, CertificateMetadata certificateMetadata) + throws CertIOException { + if (certificateMetadata.hasExtendedKeyUsage()) { + builder.addExtension(Extension.extendedKeyUsage, true, certificateMetadata.getExtendedKeyUsage()); + } + } + + private X509v3CertificateBuilder builderWithBasicExtensions( + CertificateMetadata certificateMetadata, + X500Name issuerName, + PublicKey certificatePublicKey, + PublicKey parentPublicKey + ) throws CertIOException { + X500Name subjectName = stringToX500Name(certificateMetadata.getSubject()); + Date validityStartDate = new Date(System.currentTimeMillis() - (24 * 3600 * 1000)); + Date validityEndDate = getEndDate(validityStartDate, certificateMetadata.getValidityDays()); + + BigInteger certificateSerialNumber = generateNextCertificateSerialNumber(); + return new X509v3CertificateBuilder( + issuerName, + certificateSerialNumber, + validityStartDate, + validityEndDate, + subjectName, + SubjectPublicKeyInfo.getInstance(certificatePublicKey.getEncoded()) + ).addExtension(Extension.basicConstraints, true, new BasicConstraints(certificateMetadata.isBasicConstrainIsCa())) + .addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(parentPublicKey)) + .addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(certificatePublicKey)) + .addExtension(Extension.keyUsage, true, certificateMetadata.asKeyUsage()); + } + + private void addSubjectAlternativeNameExtension(X509v3CertificateBuilder builder, CertificateMetadata metadata) throws CertIOException { + if (metadata.hasSubjectAlternativeNameExtension()) { + DERSequence subjectAlternativeNames = metadata.createSubjectAlternativeNames(); + builder.addExtension(Extension.subjectAlternativeName, false, subjectAlternativeNames); + } + } + + private Date getEndDate(Date startDate, int validityDays) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(startDate); + calendar.add(Calendar.DATE, validityDays); + return calendar.getTime(); + } + + private static JcaX509ExtensionUtils getExtUtils() { + try { + return new JcaX509ExtensionUtils(); + } catch (NoSuchAlgorithmException e) { + log.error("Getting certificate extension utils failed", e); + throw new RuntimeException("Getting certificate extension utils failed", e); + } + } + + private X500Name stringToX500Name(String distinguishedName) { + if (Strings.isNullOrEmpty(distinguishedName)) { + throw new RuntimeException("No DN (distinguished name) must not be null or empty"); + } + try { + return new X500Name(RFC4519Style.INSTANCE, distinguishedName); + } catch (IllegalArgumentException e) { + String message = String.format("Invalid DN (distinguished name) specified for %s certificate.", distinguishedName); + throw new RuntimeException(message, e); + } + } + + private BigInteger generateNextCertificateSerialNumber() { + return BigInteger.valueOf(ID_COUNTER.incrementAndGet()); + } } // CS-ENFORCE-SINGLE diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuerFactory.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuerFactory.java index 823a0c04ca..f68ccf6022 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuerFactory.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/CertificatesIssuerFactory.java @@ -24,45 +24,45 @@ */ class CertificatesIssuerFactory { - private static final int KEY_SIZE = 2048; + private static final int KEY_SIZE = 2048; - private CertificatesIssuerFactory() { + private CertificatesIssuerFactory() { - } + } - private static final Provider DEFAULT_SECURITY_PROVIDER = new BouncyCastleProvider(); + private static final Provider DEFAULT_SECURITY_PROVIDER = new BouncyCastleProvider(); - /** - * @see {@link #rsaBaseCertificateIssuer(Provider)} - */ - public static CertificatesIssuer rsaBaseCertificateIssuer() { - return rsaBaseCertificateIssuer(null); - } + /** + * @see {@link #rsaBaseCertificateIssuer(Provider)} + */ + public static CertificatesIssuer rsaBaseCertificateIssuer() { + return rsaBaseCertificateIssuer(null); + } - /** - * The method creates {@link CertificatesIssuer} which uses RSA algorithm for certificate creation. - * @param securityProvider determines cryptographic algorithm implementation, can be null. - * @return new instance of {@link CertificatesIssuer} - */ - public static CertificatesIssuer rsaBaseCertificateIssuer(Provider securityProvider) { - Provider provider = Optional.ofNullable(securityProvider).orElse(DEFAULT_SECURITY_PROVIDER); - return new CertificatesIssuer(provider, rsaSha256withRsa(provider, KEY_SIZE)); - } + /** + * The method creates {@link CertificatesIssuer} which uses RSA algorithm for certificate creation. + * @param securityProvider determines cryptographic algorithm implementation, can be null. + * @return new instance of {@link CertificatesIssuer} + */ + public static CertificatesIssuer rsaBaseCertificateIssuer(Provider securityProvider) { + Provider provider = Optional.ofNullable(securityProvider).orElse(DEFAULT_SECURITY_PROVIDER); + return new CertificatesIssuer(provider, rsaSha256withRsa(provider, KEY_SIZE)); + } - /** - * {@link #rsaBaseCertificateIssuer(Provider)} - */ - public static CertificatesIssuer ecdsaBaseCertificatesIssuer() { - return ecdsaBaseCertificatesIssuer(null); - } + /** + * {@link #rsaBaseCertificateIssuer(Provider)} + */ + public static CertificatesIssuer ecdsaBaseCertificatesIssuer() { + return ecdsaBaseCertificatesIssuer(null); + } - /** - * It creates {@link CertificatesIssuer} which uses asymmetric cryptography algorithm which relays on elliptic curves. - * @param securityProvider determines cryptographic algorithm implementation, can be null. - * @return new instance of {@link CertificatesIssuer} - */ - public static CertificatesIssuer ecdsaBaseCertificatesIssuer(Provider securityProvider) { - Provider provider = Optional.ofNullable(securityProvider).orElse(DEFAULT_SECURITY_PROVIDER); - return new CertificatesIssuer(provider, ecdsaSha256withEcdsa(securityProvider, "P-384")); - } + /** + * It creates {@link CertificatesIssuer} which uses asymmetric cryptography algorithm which relays on elliptic curves. + * @param securityProvider determines cryptographic algorithm implementation, can be null. + * @return new instance of {@link CertificatesIssuer} + */ + public static CertificatesIssuer ecdsaBaseCertificatesIssuer(Provider securityProvider) { + Provider provider = Optional.ofNullable(securityProvider).orElse(DEFAULT_SECURITY_PROVIDER); + return new CertificatesIssuer(provider, ecdsaSha256withEcdsa(securityProvider, "P-384")); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/PemConverter.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/PemConverter.java index a92e2036d7..749ab232bc 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/PemConverter.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/PemConverter.java @@ -53,68 +53,67 @@ */ class PemConverter { - private PemConverter() { - } + private PemConverter() {} - private static final Logger log = LogManager.getLogger(PemConverter.class); - private static final SecureRandom secureRandom = new SecureRandom(); + private static final Logger log = LogManager.getLogger(PemConverter.class); + private static final SecureRandom secureRandom = new SecureRandom(); - /** - * It converts certificate represented by {@link X509CertificateHolder} object to PEM format - * @param certificate is a certificate to convert - * @return {@link String} which contains PEM encoded certificate - */ - public static String toPem(X509CertificateHolder certificate) { - StringWriter stringWriter = new StringWriter(); - try (JcaPEMWriter writer = new JcaPEMWriter(stringWriter)) { - writer.writeObject(requireNonNull(certificate, "Certificate is required.")); - } catch (Exception e) { - throw new RuntimeException("Cannot write certificate in PEM format", e); - } - return stringWriter.toString(); - } + /** + * It converts certificate represented by {@link X509CertificateHolder} object to PEM format + * @param certificate is a certificate to convert + * @return {@link String} which contains PEM encoded certificate + */ + public static String toPem(X509CertificateHolder certificate) { + StringWriter stringWriter = new StringWriter(); + try (JcaPEMWriter writer = new JcaPEMWriter(stringWriter)) { + writer.writeObject(requireNonNull(certificate, "Certificate is required.")); + } catch (Exception e) { + throw new RuntimeException("Cannot write certificate in PEM format", e); + } + return stringWriter.toString(); + } - /** - * It converts private key represented by class {@link PrivateKey} to PEM format. - * @param privateKey is a private key, cannot be null - * @param privateKeyPassword is a password used to encode private key, null for unencrypted private key - * @return {@link String} which contains PEM encoded private key - */ - public static String toPem(PrivateKey privateKey, String privateKeyPassword) { - try(StringWriter stringWriter = new StringWriter()){ - savePrivateKey(stringWriter, requireNonNull(privateKey, "Private key is required."), privateKeyPassword); - return stringWriter.toString(); - } catch (IOException e) { - throw new RuntimeException("Cannot convert private key into PEM format.", e); - } - } + /** + * It converts private key represented by class {@link PrivateKey} to PEM format. + * @param privateKey is a private key, cannot be null + * @param privateKeyPassword is a password used to encode private key, null for unencrypted private key + * @return {@link String} which contains PEM encoded private key + */ + public static String toPem(PrivateKey privateKey, String privateKeyPassword) { + try (StringWriter stringWriter = new StringWriter()) { + savePrivateKey(stringWriter, requireNonNull(privateKey, "Private key is required."), privateKeyPassword); + return stringWriter.toString(); + } catch (IOException e) { + throw new RuntimeException("Cannot convert private key into PEM format.", e); + } + } - private static void savePrivateKey(Writer out, PrivateKey privateKey, String privateKeyPassword) { - try (JcaPEMWriter writer = new JcaPEMWriter(out)) { - writer.writeObject(createPkcs8PrivateKeyPem(privateKey, privateKeyPassword)); - } catch (Exception e) { - log.error("Error while writing private key.", e); - throw new RuntimeException("Error while writing private key ", e); - } - } + private static void savePrivateKey(Writer out, PrivateKey privateKey, String privateKeyPassword) { + try (JcaPEMWriter writer = new JcaPEMWriter(out)) { + writer.writeObject(createPkcs8PrivateKeyPem(privateKey, privateKeyPassword)); + } catch (Exception e) { + log.error("Error while writing private key.", e); + throw new RuntimeException("Error while writing private key ", e); + } + } - private static PemObject createPkcs8PrivateKeyPem(PrivateKey privateKey, String password) { - try { - OutputEncryptor outputEncryptor = password == null ? null : getPasswordEncryptor(password); - return new PKCS8Generator(PrivateKeyInfo.getInstance(privateKey.getEncoded()), outputEncryptor).generate(); - } catch (PemGenerationException | OperatorCreationException e) { - log.error("Creating PKCS8 private key failed", e); - throw new RuntimeException("Creating PKCS8 private key failed", e); - } - } + private static PemObject createPkcs8PrivateKeyPem(PrivateKey privateKey, String password) { + try { + OutputEncryptor outputEncryptor = password == null ? null : getPasswordEncryptor(password); + return new PKCS8Generator(PrivateKeyInfo.getInstance(privateKey.getEncoded()), outputEncryptor).generate(); + } catch (PemGenerationException | OperatorCreationException e) { + log.error("Creating PKCS8 private key failed", e); + throw new RuntimeException("Creating PKCS8 private key failed", e); + } + } - private static OutputEncryptor getPasswordEncryptor(String password) throws OperatorCreationException { - if (!Strings.isNullOrEmpty(password)) { - JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.PBE_SHA1_3DES); - encryptorBuilder.setRandom(secureRandom); - encryptorBuilder.setPassword(password.toCharArray()); - return encryptorBuilder.build(); - } - return null; - } + private static OutputEncryptor getPasswordEncryptor(String password) throws OperatorCreationException { + if (!Strings.isNullOrEmpty(password)) { + JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.PBE_SHA1_3DES); + encryptorBuilder.setRandom(secureRandom); + encryptorBuilder.setPassword(password.toCharArray()); + return encryptorBuilder.build(); + } + return null; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/PublicKeyUsage.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/PublicKeyUsage.java index 9ee2ec8a02..af37c66001 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/PublicKeyUsage.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/PublicKeyUsage.java @@ -28,47 +28,48 @@ */ // CS-ENFORCE-SINGLE enum PublicKeyUsage { - DIGITAL_SIGNATURE(KeyUsage.digitalSignature), - KEY_CERT_SIGN(KeyUsage.keyCertSign), - CRL_SIGN(KeyUsage.cRLSign), - NON_REPUDIATION(KeyUsage.nonRepudiation), - KEY_ENCIPHERMENT(KeyUsage.keyEncipherment), + DIGITAL_SIGNATURE(KeyUsage.digitalSignature), + KEY_CERT_SIGN(KeyUsage.keyCertSign), + CRL_SIGN(KeyUsage.cRLSign), + NON_REPUDIATION(KeyUsage.nonRepudiation), + KEY_ENCIPHERMENT(KeyUsage.keyEncipherment), - SERVER_AUTH(KeyPurposeId.id_kp_serverAuth), + SERVER_AUTH(KeyPurposeId.id_kp_serverAuth), - CLIENT_AUTH(KeyPurposeId.id_kp_clientAuth); + CLIENT_AUTH(KeyPurposeId.id_kp_clientAuth); - private final int keyUsage; - private final KeyPurposeId id; + private final int keyUsage; + private final KeyPurposeId id; - PublicKeyUsage(int keyUsage) { - this.keyUsage = keyUsage; - this.id = null; - } + PublicKeyUsage(int keyUsage) { + this.keyUsage = keyUsage; + this.id = null; + } - PublicKeyUsage(KeyPurposeId id) { - this.id = Objects.requireNonNull(id, "Key purpose id is required."); - this.keyUsage = 0; - } + PublicKeyUsage(KeyPurposeId id) { + this.id = Objects.requireNonNull(id, "Key purpose id is required."); + this.keyUsage = 0; + } - boolean isExtendedUsage() { - return this.id != null; - } + boolean isExtendedUsage() { + return this.id != null; + } - boolean isNotExtendedUsage() { - return this.id == null; - } + boolean isNotExtendedUsage() { + return this.id == null; + } - int asInt(){ - if(isExtendedUsage()) { - throw new RuntimeException("Integer value is not available for extended key usage"); - } - return keyUsage; - } - KeyPurposeId getKeyPurposeId() { - if(isExtendedUsage() == false){ - throw new RuntimeException("Key purpose id is not available."); - } - return id; - } + int asInt() { + if (isExtendedUsage()) { + throw new RuntimeException("Integer value is not available for extended key usage"); + } + return keyUsage; + } + + KeyPurposeId getKeyPurposeId() { + if (isExtendedUsage() == false) { + throw new RuntimeException("Key purpose id is not available."); + } + return id; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java b/src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java index bc5f5f267d..2dd1dd5eea 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java +++ b/src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java @@ -53,169 +53,162 @@ */ public class TestCertificates { - private static final Logger log = LogManager.getLogger(TestCertificates.class); - - public static final Integer MAX_NUMBER_OF_NODE_CERTIFICATES = 3; - - private static final String CA_SUBJECT = "DC=com,DC=example,O=Example Com Inc.,OU=Example Com Inc. Root CA,CN=Example Com Inc. Root CA"; - private static final String ADMIN_DN = "CN=kirk,OU=client,O=client,L=test,C=de"; - private static final int CERTIFICATE_VALIDITY_DAYS = 365; - private static final String CERTIFICATE_FILE_EXT = ".cert"; - private static final String KEY_FILE_EXT = ".key"; - private final CertificateData caCertificate; - private final CertificateData adminCertificate; - private final List nodeCertificates; - - private final CertificateData ldapCertificate; - - public TestCertificates() { - this.caCertificate = createCaCertificate(); - this.nodeCertificates = IntStream.range(0, MAX_NUMBER_OF_NODE_CERTIFICATES) - .mapToObj(this::createNodeCertificate) - .collect(Collectors.toList()); - this.ldapCertificate = createLdapCertificate(); - this.adminCertificate = createAdminCertificate(ADMIN_DN); - log.info("Test certificates successfully generated"); - } - - private CertificateData createCaCertificate() { - CertificateMetadata metadata = CertificateMetadata.basicMetadata(CA_SUBJECT, CERTIFICATE_VALIDITY_DAYS) - .withKeyUsage(true, DIGITAL_SIGNATURE, KEY_CERT_SIGN, CRL_SIGN); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSelfSignedCertificate(metadata); - } - - public CertificateData createAdminCertificate(String adminDn) { - CertificateMetadata metadata = CertificateMetadata.basicMetadata(adminDn, CERTIFICATE_VALIDITY_DAYS) - .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSignedCertificate(metadata, caCertificate); - } - - public CertificateData createSelfSignedCertificate(String distinguishedName) { - CertificateMetadata metadata = CertificateMetadata.basicMetadata(distinguishedName, CERTIFICATE_VALIDITY_DAYS); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSelfSignedCertificate(metadata); - } - - /** - * It returns the most trusted certificate. Certificates for nodes and users are derived from this certificate. - * @return file which contains certificate in PEM format, defined by RFC 1421 - */ - public File getRootCertificate() { - return createTempFile("root", CERTIFICATE_FILE_EXT, caCertificate.certificateInPemFormat()); - } - - public CertificateData getRootCertificateData() { - return caCertificate; - } - - /** - * Certificate for Open Search node. The certificate is derived from root certificate, returned by method {@link #getRootCertificate()} - * @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES} - * @return file which contains certificate in PEM format, defined by RFC 1421 - */ - public File getNodeCertificate(int node) { - CertificateData certificateData = getNodeCertificateData(node); - return createTempFile("node-" + node, CERTIFICATE_FILE_EXT, certificateData.certificateInPemFormat()); - } - - public CertificateData getNodeCertificateData(int node) { - isCorrectNodeNumber(node); - return nodeCertificates.get(node); - } - - private void isCorrectNodeNumber(int node) { - if (node >= MAX_NUMBER_OF_NODE_CERTIFICATES) { - String message = String.format("Cannot get certificate for node %d, number of created certificates for nodes is %d", node, - MAX_NUMBER_OF_NODE_CERTIFICATES); - throw new RuntimeException(message); - } - } - - private CertificateData createNodeCertificate(Integer node) { - String subject = String.format("DC=de,L=test,O=node,OU=node,CN=node-%d.example.com", node); - String domain = String.format("node-%d.example.com", node); - CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) - .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH) - .withSubjectAlternativeName("1.2.3.4.5.5", List.of(domain, "localhost"), "127.0.0.1"); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSignedCertificate(metadata, caCertificate); - } - - public CertificateData issueUserCertificate(String organizationUnit, String username) { - String subject = String.format("DC=de,L=test,O=users,OU=%s,CN=%s", organizationUnit, username); - CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS).withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH); - return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); - } - - private CertificateData createLdapCertificate() { - String subject = "DC=de,L=test,O=node,OU=node,CN=ldap.example.com"; - CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) - .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH) - .withSubjectAlternativeName(null, List.of("localhost"), "127.0.0.1"); - return CertificatesIssuerFactory - .rsaBaseCertificateIssuer() - .issueSignedCertificate(metadata, caCertificate); - } - - - public CertificateData getLdapCertificateData() { - return ldapCertificate; - } - - /** - * It returns private key associated with node certificate returned by method {@link #getNodeCertificate(int)} - * - * @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES} - * @param privateKeyPassword is a password used to encode private key, can be null to retrieve unencrypted key. - * @return file which contains private key encoded in PEM format, defined - * by RFC 1421 - */ - public File getNodeKey(int node, String privateKeyPassword) { - CertificateData certificateData = nodeCertificates.get(node); - return createTempFile("node-" + node, KEY_FILE_EXT, certificateData.privateKeyInPemFormat(privateKeyPassword)); - } - - /** - * Certificate which proofs admin user identity. Certificate is derived from root certificate returned by - * method {@link #getRootCertificate()} - * @return file which contains certificate in PEM format, defined by RFC 1421 - */ - public File getAdminCertificate() { - return createTempFile("admin", CERTIFICATE_FILE_EXT, adminCertificate.certificateInPemFormat()); - } - - public CertificateData getAdminCertificateData() { - return adminCertificate; - } - - /** - * It returns private key associated with admin certificate returned by {@link #getAdminCertificate()}. - * - * @param privateKeyPassword is a password used to encode private key, can be null to retrieve unencrypted key. - * @return file which contains private key encoded in PEM format, defined - * by RFC 1421 - */ - public File getAdminKey(String privateKeyPassword) { - return createTempFile("admin", KEY_FILE_EXT, adminCertificate.privateKeyInPemFormat(privateKeyPassword)); - } - - public String[] getAdminDNs() { - return new String[] {ADMIN_DN}; - } - - private File createTempFile(String name, String suffix, String contents) { - try { - Path path = Files.createTempFile(name, suffix); - Files.writeString(path, contents); - return path.toFile(); - } catch (IOException ex) { - throw new RuntimeException("Cannot create temp file with name " + name + " and suffix " + suffix); - } - } + private static final Logger log = LogManager.getLogger(TestCertificates.class); + + public static final Integer MAX_NUMBER_OF_NODE_CERTIFICATES = 3; + + private static final String CA_SUBJECT = "DC=com,DC=example,O=Example Com Inc.,OU=Example Com Inc. Root CA,CN=Example Com Inc. Root CA"; + private static final String ADMIN_DN = "CN=kirk,OU=client,O=client,L=test,C=de"; + private static final int CERTIFICATE_VALIDITY_DAYS = 365; + private static final String CERTIFICATE_FILE_EXT = ".cert"; + private static final String KEY_FILE_EXT = ".key"; + private final CertificateData caCertificate; + private final CertificateData adminCertificate; + private final List nodeCertificates; + + private final CertificateData ldapCertificate; + + public TestCertificates() { + this.caCertificate = createCaCertificate(); + this.nodeCertificates = IntStream.range(0, MAX_NUMBER_OF_NODE_CERTIFICATES) + .mapToObj(this::createNodeCertificate) + .collect(Collectors.toList()); + this.ldapCertificate = createLdapCertificate(); + this.adminCertificate = createAdminCertificate(ADMIN_DN); + log.info("Test certificates successfully generated"); + } + + private CertificateData createCaCertificate() { + CertificateMetadata metadata = CertificateMetadata.basicMetadata(CA_SUBJECT, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(true, DIGITAL_SIGNATURE, KEY_CERT_SIGN, CRL_SIGN); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSelfSignedCertificate(metadata); + } + + public CertificateData createAdminCertificate(String adminDn) { + CertificateMetadata metadata = CertificateMetadata.basicMetadata(adminDn, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); + } + + public CertificateData createSelfSignedCertificate(String distinguishedName) { + CertificateMetadata metadata = CertificateMetadata.basicMetadata(distinguishedName, CERTIFICATE_VALIDITY_DAYS); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSelfSignedCertificate(metadata); + } + + /** + * It returns the most trusted certificate. Certificates for nodes and users are derived from this certificate. + * @return file which contains certificate in PEM format, defined by RFC 1421 + */ + public File getRootCertificate() { + return createTempFile("root", CERTIFICATE_FILE_EXT, caCertificate.certificateInPemFormat()); + } + + public CertificateData getRootCertificateData() { + return caCertificate; + } + + /** + * Certificate for Open Search node. The certificate is derived from root certificate, returned by method {@link #getRootCertificate()} + * @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES} + * @return file which contains certificate in PEM format, defined by RFC 1421 + */ + public File getNodeCertificate(int node) { + CertificateData certificateData = getNodeCertificateData(node); + return createTempFile("node-" + node, CERTIFICATE_FILE_EXT, certificateData.certificateInPemFormat()); + } + + public CertificateData getNodeCertificateData(int node) { + isCorrectNodeNumber(node); + return nodeCertificates.get(node); + } + + private void isCorrectNodeNumber(int node) { + if (node >= MAX_NUMBER_OF_NODE_CERTIFICATES) { + String message = String.format( + "Cannot get certificate for node %d, number of created certificates for nodes is %d", + node, + MAX_NUMBER_OF_NODE_CERTIFICATES + ); + throw new RuntimeException(message); + } + } + + private CertificateData createNodeCertificate(Integer node) { + String subject = String.format("DC=de,L=test,O=node,OU=node,CN=node-%d.example.com", node); + String domain = String.format("node-%d.example.com", node); + CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH) + .withSubjectAlternativeName("1.2.3.4.5.5", List.of(domain, "localhost"), "127.0.0.1"); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); + } + + public CertificateData issueUserCertificate(String organizationUnit, String username) { + String subject = String.format("DC=de,L=test,O=users,OU=%s,CN=%s", organizationUnit, username); + CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); + } + + private CertificateData createLdapCertificate() { + String subject = "DC=de,L=test,O=node,OU=node,CN=ldap.example.com"; + CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS) + .withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH) + .withSubjectAlternativeName(null, List.of("localhost"), "127.0.0.1"); + return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate); + } + + public CertificateData getLdapCertificateData() { + return ldapCertificate; + } + + /** + * It returns private key associated with node certificate returned by method {@link #getNodeCertificate(int)} + * + * @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES} + * @param privateKeyPassword is a password used to encode private key, can be null to retrieve unencrypted key. + * @return file which contains private key encoded in PEM format, defined + * by RFC 1421 + */ + public File getNodeKey(int node, String privateKeyPassword) { + CertificateData certificateData = nodeCertificates.get(node); + return createTempFile("node-" + node, KEY_FILE_EXT, certificateData.privateKeyInPemFormat(privateKeyPassword)); + } + + /** + * Certificate which proofs admin user identity. Certificate is derived from root certificate returned by + * method {@link #getRootCertificate()} + * @return file which contains certificate in PEM format, defined by RFC 1421 + */ + public File getAdminCertificate() { + return createTempFile("admin", CERTIFICATE_FILE_EXT, adminCertificate.certificateInPemFormat()); + } + + public CertificateData getAdminCertificateData() { + return adminCertificate; + } + + /** + * It returns private key associated with admin certificate returned by {@link #getAdminCertificate()}. + * + * @param privateKeyPassword is a password used to encode private key, can be null to retrieve unencrypted key. + * @return file which contains private key encoded in PEM format, defined + * by RFC 1421 + */ + public File getAdminKey(String privateKeyPassword) { + return createTempFile("admin", KEY_FILE_EXT, adminCertificate.privateKeyInPemFormat(privateKeyPassword)); + } + + public String[] getAdminDNs() { + return new String[] { ADMIN_DN }; + } + + private File createTempFile(String name, String suffix, String contents) { + try { + Path path = Files.createTempFile(name, suffix); + Files.writeString(path, contents); + return path.toFile(); + } catch (IOException ex) { + throw new RuntimeException("Cannot create temp file with name " + name + " and suffix " + suffix); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/CloseableHttpClientFactory.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/CloseableHttpClientFactory.java index e0e57d2ef1..ed236dcd0c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/CloseableHttpClientFactory.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/CloseableHttpClientFactory.java @@ -27,44 +27,50 @@ class CloseableHttpClientFactory { - private final SSLContext sslContext; + private final SSLContext sslContext; - private final RequestConfig requestConfig; + private final RequestConfig requestConfig; - private final HttpRoutePlanner routePlanner; + private final HttpRoutePlanner routePlanner; - private final String[] supportedCipherSuit; + private final String[] supportedCipherSuit; - public CloseableHttpClientFactory(SSLContext sslContext, - RequestConfig requestConfig, - HttpRoutePlanner routePlanner, - String[] supportedCipherSuit) { - this.sslContext = Objects.requireNonNull(sslContext, "SSL context is required."); - this.requestConfig = requestConfig; - this.routePlanner = routePlanner; - this.supportedCipherSuit = supportedCipherSuit; - } + public CloseableHttpClientFactory( + SSLContext sslContext, + RequestConfig requestConfig, + HttpRoutePlanner routePlanner, + String[] supportedCipherSuit + ) { + this.sslContext = Objects.requireNonNull(sslContext, "SSL context is required."); + this.requestConfig = requestConfig; + this.routePlanner = routePlanner; + this.supportedCipherSuit = supportedCipherSuit; + } - public CloseableHttpClient getHTTPClient() { + public CloseableHttpClient getHTTPClient() { - final HttpClientBuilder hcb = HttpClients.custom(); + final HttpClientBuilder hcb = HttpClients.custom(); - final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(this.sslContext, null, supportedCipherSuit, - NoopHostnameVerifier.INSTANCE); + final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( + this.sslContext, + null, + supportedCipherSuit, + NoopHostnameVerifier.INSTANCE + ); - final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(sslsf) - .setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(60, TimeUnit.SECONDS).build()) - .build(); - hcb.setConnectionManager(cm); - if(routePlanner != null) { - hcb.setRoutePlanner(routePlanner); - } + final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() + .setSSLSocketFactory(sslsf) + .setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(60, TimeUnit.SECONDS).build()) + .build(); + hcb.setConnectionManager(cm); + if (routePlanner != null) { + hcb.setRoutePlanner(routePlanner); + } - if (requestConfig != null) { - hcb.setDefaultRequestConfig(requestConfig); - } + if (requestConfig != null) { + hcb.setDefaultRequestConfig(requestConfig); + } - return hcb.build(); - } + return hcb.build(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/ClusterManager.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/ClusterManager.java index 35c5229bfb..dff40e395c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/ClusterManager.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/ClusterManager.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH -* +* * 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 @@ -12,7 +12,7 @@ * 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. -* +* */ /* @@ -52,105 +52,121 @@ import static org.opensearch.test.framework.cluster.NodeType.DATA; public enum ClusterManager { - //3 nodes (1m, 2d) - DEFAULT(new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.DATA), new NodeSettings(NodeRole.DATA)), - - //1 node (1md) - SINGLENODE(new NodeSettings(NodeRole.CLUSTER_MANAGER, NodeRole.DATA)), - - SINGLE_REMOTE_CLIENT(new NodeSettings(NodeRole.CLUSTER_MANAGER, NodeRole.DATA, NodeRole.REMOTE_CLUSTER_CLIENT)), - - //4 node (1m, 2d, 1c) - CLIENTNODE(new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.DATA), new NodeSettings(NodeRole.DATA), new NodeSettings()), - - THREE_CLUSTER_MANAGERS(new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.DATA), new NodeSettings(NodeRole.DATA)); - - private List nodeSettings = new LinkedList<>(); - - private ClusterManager(NodeSettings... settings) { - nodeSettings.addAll(Arrays.asList(settings)); - } - - public List getNodeSettings() { - return unmodifiableList(nodeSettings); - } - - public List getClusterManagerNodeSettings() { - return unmodifiableList(nodeSettings.stream().filter(a -> a.containRole(NodeRole.CLUSTER_MANAGER)).collect(Collectors.toList())); - } - - public List getNonClusterManagerNodeSettings() { - return unmodifiableList(nodeSettings.stream().filter(a -> !a.containRole(NodeRole.CLUSTER_MANAGER)).collect(Collectors.toList())); - } - - public int getNodes() { - return nodeSettings.size(); - } - - public int getClusterManagerNodes() { - return (int) nodeSettings.stream().filter(a -> a.containRole(NodeRole.CLUSTER_MANAGER)).count(); - } - - public int getDataNodes() { - return (int) nodeSettings.stream().filter(a -> a.containRole(NodeRole.DATA)).count(); - } - - public int getClientNodes() { - return (int) nodeSettings.stream().filter(a -> a.isClientNode()).count(); - } - - - public static class NodeSettings { - - private final static List> DEFAULT_PLUGINS = List.of(Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, - MatrixAggregationModulePlugin.class, ParentJoinModulePlugin.class, PercolatorModulePlugin.class, ReindexModulePlugin.class); - - private final Set roles; - public final List> plugins; - - public NodeSettings(NodeRole...roles) { - this(roles.length == 0 ? Collections.emptySet() : EnumSet.copyOf(Arrays.asList(roles)), Collections.emptyList()); - } - - public NodeSettings(Set roles, List> additionalPlugins) { - super(); - this.roles = Objects.requireNonNull(roles, "Node roles set must not be null"); - this.plugins = mergePlugins(additionalPlugins, DEFAULT_PLUGINS); - } - - public boolean containRole(NodeRole nodeRole) { - return roles.contains(nodeRole); - } - - public boolean isClientNode() { - return (roles.contains(NodeRole.DATA) == false) && (roles.contains(NodeRole.CLUSTER_MANAGER)); - } - - NodeType recognizeNodeType() { - if (roles.contains(NodeRole.CLUSTER_MANAGER)) { - return CLUSTER_MANAGER; - } else if (roles.contains(NodeRole.DATA)) { - return DATA; - } else { - return CLIENT; - } - } - - private List> mergePlugins(Collection>...plugins) { - List> mergedPlugins = Arrays.stream(plugins) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - return unmodifiableList(mergedPlugins); - } - - @SuppressWarnings("unchecked") - public Class[] getPlugins() { - return plugins.toArray(new Class[0]); - } - - public Class[] pluginsWithAddition(List> additionalPlugins) { - return mergePlugins(plugins, additionalPlugins).toArray(Class[]::new); - } - } + // 3 nodes (1m, 2d) + DEFAULT(new NodeSettings(NodeRole.CLUSTER_MANAGER), new NodeSettings(NodeRole.DATA), new NodeSettings(NodeRole.DATA)), + + // 1 node (1md) + SINGLENODE(new NodeSettings(NodeRole.CLUSTER_MANAGER, NodeRole.DATA)), + + SINGLE_REMOTE_CLIENT(new NodeSettings(NodeRole.CLUSTER_MANAGER, NodeRole.DATA, NodeRole.REMOTE_CLUSTER_CLIENT)), + + // 4 node (1m, 2d, 1c) + CLIENTNODE( + new NodeSettings(NodeRole.CLUSTER_MANAGER), + new NodeSettings(NodeRole.DATA), + new NodeSettings(NodeRole.DATA), + new NodeSettings() + ), + + THREE_CLUSTER_MANAGERS( + new NodeSettings(NodeRole.CLUSTER_MANAGER), + new NodeSettings(NodeRole.CLUSTER_MANAGER), + new NodeSettings(NodeRole.CLUSTER_MANAGER), + new NodeSettings(NodeRole.DATA), + new NodeSettings(NodeRole.DATA) + ); + + private List nodeSettings = new LinkedList<>(); + + private ClusterManager(NodeSettings... settings) { + nodeSettings.addAll(Arrays.asList(settings)); + } + + public List getNodeSettings() { + return unmodifiableList(nodeSettings); + } + + public List getClusterManagerNodeSettings() { + return unmodifiableList(nodeSettings.stream().filter(a -> a.containRole(NodeRole.CLUSTER_MANAGER)).collect(Collectors.toList())); + } + + public List getNonClusterManagerNodeSettings() { + return unmodifiableList(nodeSettings.stream().filter(a -> !a.containRole(NodeRole.CLUSTER_MANAGER)).collect(Collectors.toList())); + } + + public int getNodes() { + return nodeSettings.size(); + } + + public int getClusterManagerNodes() { + return (int) nodeSettings.stream().filter(a -> a.containRole(NodeRole.CLUSTER_MANAGER)).count(); + } + + public int getDataNodes() { + return (int) nodeSettings.stream().filter(a -> a.containRole(NodeRole.DATA)).count(); + } + + public int getClientNodes() { + return (int) nodeSettings.stream().filter(a -> a.isClientNode()).count(); + } + + public static class NodeSettings { + + private final static List> DEFAULT_PLUGINS = List.of( + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + MatrixAggregationModulePlugin.class, + ParentJoinModulePlugin.class, + PercolatorModulePlugin.class, + ReindexModulePlugin.class + ); + + private final Set roles; + public final List> plugins; + + public NodeSettings(NodeRole... roles) { + this(roles.length == 0 ? Collections.emptySet() : EnumSet.copyOf(Arrays.asList(roles)), Collections.emptyList()); + } + + public NodeSettings(Set roles, List> additionalPlugins) { + super(); + this.roles = Objects.requireNonNull(roles, "Node roles set must not be null"); + this.plugins = mergePlugins(additionalPlugins, DEFAULT_PLUGINS); + } + + public boolean containRole(NodeRole nodeRole) { + return roles.contains(nodeRole); + } + + public boolean isClientNode() { + return (roles.contains(NodeRole.DATA) == false) && (roles.contains(NodeRole.CLUSTER_MANAGER)); + } + + NodeType recognizeNodeType() { + if (roles.contains(NodeRole.CLUSTER_MANAGER)) { + return CLUSTER_MANAGER; + } else if (roles.contains(NodeRole.DATA)) { + return DATA; + } else { + return CLIENT; + } + } + + private List> mergePlugins(Collection>... plugins) { + List> mergedPlugins = Arrays.stream(plugins) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + return unmodifiableList(mergedPlugins); + } + + @SuppressWarnings("unchecked") + public Class[] getPlugins() { + return plugins.toArray(new Class[0]); + } + + public Class[] pluginsWithAddition(List> additionalPlugins) { + return mergePlugins(plugins, additionalPlugins).toArray(Class[]::new); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/ContextHeaderDecoratorClient.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/ContextHeaderDecoratorClient.java index 890de49ed7..2b05807fa2 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/ContextHeaderDecoratorClient.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/ContextHeaderDecoratorClient.java @@ -27,23 +27,29 @@ */ public class ContextHeaderDecoratorClient extends FilterClient { - private Map headers; - - public ContextHeaderDecoratorClient(Client in, Map headers) { - super(in); - this.headers = headers != null ? headers : Collections.emptyMap(); - } - - @Override - protected void doExecute(ActionType action, Request request, - ActionListener listener) { - - ThreadContext threadContext = threadPool().getThreadContext(); - ContextPreservingActionListener wrappedListener = new ContextPreservingActionListener<>(threadContext.newRestorableContext(true), listener); - - try (StoredContext ctx = threadContext.stashContext()) { - threadContext.putHeader(this.headers); - super.doExecute(action, request, wrappedListener); - } - } + private Map headers; + + public ContextHeaderDecoratorClient(Client in, Map headers) { + super(in); + this.headers = headers != null ? headers : Collections.emptyMap(); + } + + @Override + protected void doExecute( + ActionType action, + Request request, + ActionListener listener + ) { + + ThreadContext threadContext = threadPool().getThreadContext(); + ContextPreservingActionListener wrappedListener = new ContextPreservingActionListener<>( + threadContext.newRestorableContext(true), + listener + ); + + try (StoredContext ctx = threadContext.stashContext()) { + threadContext.putHeader(this.headers); + super.doExecute(action, request, wrappedListener); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalAddressRoutePlanner.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalAddressRoutePlanner.java index ab29d3206e..9181186f52 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalAddressRoutePlanner.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalAddressRoutePlanner.java @@ -23,26 +23,26 @@ */ class LocalAddressRoutePlanner extends DefaultRoutePlanner { - /** - * IP address of one of the local network interfaces. - */ - private final InetAddress localAddress; + /** + * IP address of one of the local network interfaces. + */ + private final InetAddress localAddress; - /** - * Creates {@link LocalAddressRoutePlanner} - * @param localAddress IP address of one of the local network interfaces. Client socket used by Apache HTTP client will be bind to - * address from this parameter. The parameter must not be null. - */ - public LocalAddressRoutePlanner(InetAddress localAddress) { - super(DefaultSchemePortResolver.INSTANCE); - this.localAddress = Objects.requireNonNull(localAddress); - } + /** + * Creates {@link LocalAddressRoutePlanner} + * @param localAddress IP address of one of the local network interfaces. Client socket used by Apache HTTP client will be bind to + * address from this parameter. The parameter must not be null. + */ + public LocalAddressRoutePlanner(InetAddress localAddress) { + super(DefaultSchemePortResolver.INSTANCE); + this.localAddress = Objects.requireNonNull(localAddress); + } - /** - * Determines IP address used by the client socket of Apache HTTP client - */ - @Override - protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) { - return localAddress; - } + /** + * Determines IP address used by the client socket of Apache HTTP client + */ + @Override + protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) { + return localAddress; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java index e9bb7b5be5..539e15fb57 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java @@ -74,414 +74,455 @@ */ public class LocalCluster extends ExternalResource implements AutoCloseable, OpenSearchClientProvider { - private static final Logger log = LogManager.getLogger(LocalCluster.class); - - public static final String INIT_CONFIGURATION_DIR = "security.default_init.dir"; - - protected static final AtomicLong num = new AtomicLong(); - - private boolean sslOnly; - - private final List> plugins; - private final ClusterManager clusterManager; - private final TestSecurityConfig testSecurityConfig; - private Settings nodeOverride; - private final String clusterName; - private final MinimumSecuritySettingsSupplierFactory minimumOpenSearchSettingsSupplierFactory; - private final TestCertificates testCertificates; - private final List clusterDependencies; - private final Map remotes; - private volatile LocalOpenSearchCluster localOpenSearchCluster; - private final List testIndices; - - private boolean loadConfigurationIntoIndex; - - private LocalCluster(String clusterName, TestSecurityConfig testSgConfig, boolean sslOnly, Settings nodeOverride, - ClusterManager clusterManager, List> plugins, TestCertificates testCertificates, - List clusterDependencies, Map remotes, List testIndices, - boolean loadConfigurationIntoIndex, String defaultConfigurationInitDirectory) { - this.plugins = plugins; - this.testCertificates = testCertificates; - this.clusterManager = clusterManager; - this.testSecurityConfig = testSgConfig; - this.sslOnly = sslOnly; - this.nodeOverride = nodeOverride; - this.clusterName = clusterName; - this.minimumOpenSearchSettingsSupplierFactory = new MinimumSecuritySettingsSupplierFactory(testCertificates); - this.remotes = remotes; - this.clusterDependencies = clusterDependencies; - this.testIndices = testIndices; - this.loadConfigurationIntoIndex = loadConfigurationIntoIndex; - if(StringUtils.isNoneBlank(defaultConfigurationInitDirectory)) { - System.setProperty(INIT_CONFIGURATION_DIR, defaultConfigurationInitDirectory); - } - } - - public String getSnapshotDirPath() { - return localOpenSearchCluster.getSnapshotDirPath(); - } - - @Override - public void before() throws Throwable { - if (localOpenSearchCluster == null) { - for (LocalCluster dependency : clusterDependencies) { - if (!dependency.isStarted()) { - dependency.before(); - } - } - - for (Map.Entry entry : remotes.entrySet()) { - @SuppressWarnings("resource") - InetSocketAddress transportAddress = entry.getValue().localOpenSearchCluster.clusterManagerNode().getTransportAddress(); - String key = "cluster.remote." + entry.getKey() + ".seeds"; - String value = transportAddress.getHostString() + ":" + transportAddress.getPort(); - log.info("Remote cluster '{}' added to configuration with the following seed '{}'", key, value); - nodeOverride = Settings.builder().put(nodeOverride) - .putList(key, value) - .build(); - } - start(); - } - } - - @Override - protected void after() { - System.clearProperty(INIT_CONFIGURATION_DIR); - close(); - } - - @Override - public void close() { - if (localOpenSearchCluster != null && localOpenSearchCluster.isStarted()) { - try { - localOpenSearchCluster.destroy(); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - localOpenSearchCluster = null; - } - } - } - - @Override - public String getClusterName() { - return clusterName; - } - - @Override - public InetSocketAddress getHttpAddress() { - return localOpenSearchCluster.clientNode().getHttpAddress(); - } - - public int getHttpPort() { - return getHttpAddress().getPort(); - } - - @Override - public InetSocketAddress getTransportAddress() { - return localOpenSearchCluster.clientNode().getTransportAddress(); - } - - /** - * Returns a Client object that performs cluster-internal requests. As these requests are regard as cluster-internal, - * no authentication is performed and no user-information is attached to these requests. Thus, this client should - * be only used for preparing test environments, but not as a test subject. - */ - public Client getInternalNodeClient() { - return localOpenSearchCluster.clientNode().getInternalNodeClient(); - } - - /** - * Returns a random node of this cluster. - */ - public PluginAwareNode node() { - return this.localOpenSearchCluster.clusterManagerNode().esNode(); - } - - /** - * Returns all nodes of this cluster. - */ - public List nodes() { - return this.localOpenSearchCluster.getNodes(); - } - - public LocalOpenSearchCluster.Node getNodeByName(String name) { - return this.localOpenSearchCluster.getNodeByName(name); - } - - public boolean isStarted() { - return localOpenSearchCluster != null; - } - - public List getConfiguredUsers() { - return testSecurityConfig.getUsers(); - } - - public Random getRandom() { - return localOpenSearchCluster.getRandom(); - } - - private void start() { - try { - NodeSettingsSupplier nodeSettingsSupplier = minimumOpenSearchSettingsSupplierFactory.minimumOpenSearchSettings(sslOnly, nodeOverride); - localOpenSearchCluster = new LocalOpenSearchCluster(clusterName, clusterManager, nodeSettingsSupplier, plugins, testCertificates); - - localOpenSearchCluster.start(); - - - if (loadConfigurationIntoIndex) { - initSecurityIndex(testSecurityConfig); - } - - try (Client client = getInternalNodeClient()) { - for (TestIndex index : this.testIndices) { - index.create(client); - } - } - - } catch (Exception e) { - log.error("Local ES cluster start failed", e); - throw new RuntimeException(e); - } - } - - private void initSecurityIndex(TestSecurityConfig testSecurityConfig) { - log.info("Initializing OpenSearch Security index"); - try(Client client = new ContextHeaderDecoratorClient(this.getInternalNodeClient(), Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER , "true"))) { - testSecurityConfig.initIndex(client); - triggerConfigurationReload(client); - } - } - - public void updateUserConfiguration(List users) { - try(Client client = new ContextHeaderDecoratorClient(this.getInternalNodeClient(), Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER , "true"))) { - testSecurityConfig.updateInternalUsersConfiguration(client, users); - triggerConfigurationReload(client); - } - } - - private static void triggerConfigurationReload(Client client) { - ConfigUpdateResponse configUpdateResponse = client.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(CType.lcStringValues().toArray(new String[0]))).actionGet(); - if (configUpdateResponse.hasFailures()) { - throw new RuntimeException("ConfigUpdateResponse produced failures: " + configUpdateResponse.failures()); - } - } - - public CertificateData getAdminCertificate() { - return testCertificates.getAdminCertificateData(); - } - - public static class Builder { - - private final Settings.Builder nodeOverrideSettingsBuilder = Settings.builder(); - - private boolean sslOnly = false; - private final List> plugins = new ArrayList<>(); - private Map remoteClusters = new HashMap<>(); - private List clusterDependencies = new ArrayList<>(); - private List testIndices = new ArrayList<>(); - private ClusterManager clusterManager = ClusterManager.DEFAULT; - private TestSecurityConfig testSecurityConfig = new TestSecurityConfig(); - private String clusterName = "local_cluster"; - private TestCertificates testCertificates; - - private boolean loadConfigurationIntoIndex = true; - - private String defaultConfigurationInitDirectory = null; - - public Builder() { - } - - public Builder dependsOn(Object object) { - // We just want to make sure that the object is already done - if (object == null) { - throw new IllegalStateException("Dependency not fulfilled"); - } - return this; - } - - public Builder clusterManager(ClusterManager clusterManager) { - this.clusterManager = clusterManager; - return this; - } - - /** - * Starts a cluster with only one node and thus saves some resources during startup. This shall be only used - * for tests where the node interactions are not relevant to the test. An example for this would be - * authentication tests, as authentication is always done on the directly connected node. - */ - public Builder singleNode() { - this.clusterManager = ClusterManager.SINGLENODE; - return this; - } - - /** - * Specifies the configuration of the security plugin that shall be used by this cluster. - */ - public Builder config(TestSecurityConfig testSecurityConfig) { - this.testSecurityConfig = testSecurityConfig; - return this; - } - - public Builder sslOnly(boolean sslOnly) { - this.sslOnly = sslOnly; - return this; - } - - public Builder nodeSettings(Map settings) { - settings.forEach((key, value) -> { - if (value instanceof List) { - List values = ((List) value).stream().map(String::valueOf).collect(Collectors.toList()); - nodeOverrideSettingsBuilder.putList(key, values); - } else { - nodeOverrideSettingsBuilder.put(key, String.valueOf(value)); - } - }); - - return this; - } - - /** - * Adds additional plugins to the cluster - */ - public Builder plugin(Class plugin) { - this.plugins.add(plugin); - - return this; - } - - public Builder authFailureListeners(AuthFailureListeners listener) { - testSecurityConfig.authFailureListeners(listener); - return this; - } - - /** - * Specifies a remote cluster and its name. The remote cluster can be then used in Cross Cluster Search - * operations with the specified name. - */ - public Builder remote(String name, LocalCluster anotherCluster) { - remoteClusters.put(name, anotherCluster); - - clusterDependencies.add(anotherCluster); - - return this; - } - - /** - * Specifies test indices that shall be created upon startup of the cluster. - */ - public Builder indices(TestIndex... indices) { - this.testIndices.addAll(Arrays.asList(indices)); - return this; - } - - public Builder users(TestSecurityConfig.User... users) { - for (TestSecurityConfig.User user : users) { - testSecurityConfig.user(user); - } - return this; - } - - public Builder audit(AuditConfiguration auditConfiguration) { - if (auditConfiguration != null) { - testSecurityConfig.audit(auditConfiguration); - } - if (auditConfiguration.isEnabled()) { - nodeOverrideSettingsBuilder.put("plugins.security.audit.type", TestRuleAuditLogSink.class.getName()); - } else { - nodeOverrideSettingsBuilder.put("plugins.security.audit.type", "noop"); - } - return this; - } - - public List getUsers() { - return testSecurityConfig.getUsers(); - } - - public Builder roles(Role... roles) { - testSecurityConfig.roles(roles); - return this; - } - - public Builder rolesMapping(RolesMapping...mappings) { - testSecurityConfig.rolesMapping(mappings); - return this; - } - - public Builder authc(TestSecurityConfig.AuthcDomain authc) { - testSecurityConfig.authc(authc); - return this; - } - - public Builder authz(AuthzDomain authzDomain) { - testSecurityConfig.authz(authzDomain); - return this; - } - - public Builder clusterName(String clusterName) { - this.clusterName = clusterName; - return this; - } - - public Builder configIndexName(String configIndexName) { - testSecurityConfig.configIndexName(configIndexName); - return this; - } - - public Builder testCertificates(TestCertificates certificates) { - this.testCertificates = certificates; - return this; - } - - public Builder anonymousAuth(boolean anonAuthEnabled) { - testSecurityConfig.anonymousAuth(anonAuthEnabled); - return this; - } - - public Builder xff(XffConfig xffConfig){ - testSecurityConfig.xff(xffConfig); - return this; - } - - public Builder loadConfigurationIntoIndex(boolean loadConfigurationIntoIndex) { - this.loadConfigurationIntoIndex = loadConfigurationIntoIndex; - return this; - } - public Builder certificates(TestCertificates certificates) { - this.testCertificates = certificates; - return this; - } - - public Builder doNotFailOnForbidden(boolean doNotFailOnForbidden) { - testSecurityConfig.doNotFailOnForbidden(doNotFailOnForbidden); - return this; - } - - public Builder defaultConfigurationInitDirectory(String defaultConfigurationInitDirectory){ - this.defaultConfigurationInitDirectory = defaultConfigurationInitDirectory; - return this; - } - - public LocalCluster build() { - try { - if(testCertificates == null) { - testCertificates = new TestCertificates(); - } - clusterName += "_" + num.incrementAndGet(); - Settings settings = nodeOverrideSettingsBuilder.build(); - return new LocalCluster(clusterName, testSecurityConfig, sslOnly, settings, clusterManager, plugins, testCertificates, - clusterDependencies, remoteClusters, testIndices, loadConfigurationIntoIndex, defaultConfigurationInitDirectory); - } catch (Exception e) { - log.error("Failed to build LocalCluster", e); - throw new RuntimeException(e); - } - } - - } - - @Override - public TestCertificates getTestCertificates() { - return testCertificates; - } + private static final Logger log = LogManager.getLogger(LocalCluster.class); + + public static final String INIT_CONFIGURATION_DIR = "security.default_init.dir"; + + protected static final AtomicLong num = new AtomicLong(); + + private boolean sslOnly; + + private final List> plugins; + private final ClusterManager clusterManager; + private final TestSecurityConfig testSecurityConfig; + private Settings nodeOverride; + private final String clusterName; + private final MinimumSecuritySettingsSupplierFactory minimumOpenSearchSettingsSupplierFactory; + private final TestCertificates testCertificates; + private final List clusterDependencies; + private final Map remotes; + private volatile LocalOpenSearchCluster localOpenSearchCluster; + private final List testIndices; + + private boolean loadConfigurationIntoIndex; + + private LocalCluster( + String clusterName, + TestSecurityConfig testSgConfig, + boolean sslOnly, + Settings nodeOverride, + ClusterManager clusterManager, + List> plugins, + TestCertificates testCertificates, + List clusterDependencies, + Map remotes, + List testIndices, + boolean loadConfigurationIntoIndex, + String defaultConfigurationInitDirectory + ) { + this.plugins = plugins; + this.testCertificates = testCertificates; + this.clusterManager = clusterManager; + this.testSecurityConfig = testSgConfig; + this.sslOnly = sslOnly; + this.nodeOverride = nodeOverride; + this.clusterName = clusterName; + this.minimumOpenSearchSettingsSupplierFactory = new MinimumSecuritySettingsSupplierFactory(testCertificates); + this.remotes = remotes; + this.clusterDependencies = clusterDependencies; + this.testIndices = testIndices; + this.loadConfigurationIntoIndex = loadConfigurationIntoIndex; + if (StringUtils.isNoneBlank(defaultConfigurationInitDirectory)) { + System.setProperty(INIT_CONFIGURATION_DIR, defaultConfigurationInitDirectory); + } + } + + public String getSnapshotDirPath() { + return localOpenSearchCluster.getSnapshotDirPath(); + } + + @Override + public void before() throws Throwable { + if (localOpenSearchCluster == null) { + for (LocalCluster dependency : clusterDependencies) { + if (!dependency.isStarted()) { + dependency.before(); + } + } + + for (Map.Entry entry : remotes.entrySet()) { + @SuppressWarnings("resource") + InetSocketAddress transportAddress = entry.getValue().localOpenSearchCluster.clusterManagerNode().getTransportAddress(); + String key = "cluster.remote." + entry.getKey() + ".seeds"; + String value = transportAddress.getHostString() + ":" + transportAddress.getPort(); + log.info("Remote cluster '{}' added to configuration with the following seed '{}'", key, value); + nodeOverride = Settings.builder().put(nodeOverride).putList(key, value).build(); + } + start(); + } + } + + @Override + protected void after() { + System.clearProperty(INIT_CONFIGURATION_DIR); + close(); + } + + @Override + public void close() { + if (localOpenSearchCluster != null && localOpenSearchCluster.isStarted()) { + try { + localOpenSearchCluster.destroy(); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + localOpenSearchCluster = null; + } + } + } + + @Override + public String getClusterName() { + return clusterName; + } + + @Override + public InetSocketAddress getHttpAddress() { + return localOpenSearchCluster.clientNode().getHttpAddress(); + } + + public int getHttpPort() { + return getHttpAddress().getPort(); + } + + @Override + public InetSocketAddress getTransportAddress() { + return localOpenSearchCluster.clientNode().getTransportAddress(); + } + + /** + * Returns a Client object that performs cluster-internal requests. As these requests are regard as cluster-internal, + * no authentication is performed and no user-information is attached to these requests. Thus, this client should + * be only used for preparing test environments, but not as a test subject. + */ + public Client getInternalNodeClient() { + return localOpenSearchCluster.clientNode().getInternalNodeClient(); + } + + /** + * Returns a random node of this cluster. + */ + public PluginAwareNode node() { + return this.localOpenSearchCluster.clusterManagerNode().esNode(); + } + + /** + * Returns all nodes of this cluster. + */ + public List nodes() { + return this.localOpenSearchCluster.getNodes(); + } + + public LocalOpenSearchCluster.Node getNodeByName(String name) { + return this.localOpenSearchCluster.getNodeByName(name); + } + + public boolean isStarted() { + return localOpenSearchCluster != null; + } + + public List getConfiguredUsers() { + return testSecurityConfig.getUsers(); + } + + public Random getRandom() { + return localOpenSearchCluster.getRandom(); + } + + private void start() { + try { + NodeSettingsSupplier nodeSettingsSupplier = minimumOpenSearchSettingsSupplierFactory.minimumOpenSearchSettings( + sslOnly, + nodeOverride + ); + localOpenSearchCluster = new LocalOpenSearchCluster( + clusterName, + clusterManager, + nodeSettingsSupplier, + plugins, + testCertificates + ); + + localOpenSearchCluster.start(); + + if (loadConfigurationIntoIndex) { + initSecurityIndex(testSecurityConfig); + } + + try (Client client = getInternalNodeClient()) { + for (TestIndex index : this.testIndices) { + index.create(client); + } + } + + } catch (Exception e) { + log.error("Local ES cluster start failed", e); + throw new RuntimeException(e); + } + } + + private void initSecurityIndex(TestSecurityConfig testSecurityConfig) { + log.info("Initializing OpenSearch Security index"); + try ( + Client client = new ContextHeaderDecoratorClient( + this.getInternalNodeClient(), + Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER, "true") + ) + ) { + testSecurityConfig.initIndex(client); + triggerConfigurationReload(client); + } + } + + public void updateUserConfiguration(List users) { + try ( + Client client = new ContextHeaderDecoratorClient( + this.getInternalNodeClient(), + Map.of(ConfigConstants.OPENDISTRO_SECURITY_CONF_REQUEST_HEADER, "true") + ) + ) { + testSecurityConfig.updateInternalUsersConfiguration(client, users); + triggerConfigurationReload(client); + } + } + + private static void triggerConfigurationReload(Client client) { + ConfigUpdateResponse configUpdateResponse = client.execute( + ConfigUpdateAction.INSTANCE, + new ConfigUpdateRequest(CType.lcStringValues().toArray(new String[0])) + ).actionGet(); + if (configUpdateResponse.hasFailures()) { + throw new RuntimeException("ConfigUpdateResponse produced failures: " + configUpdateResponse.failures()); + } + } + + public CertificateData getAdminCertificate() { + return testCertificates.getAdminCertificateData(); + } + + public static class Builder { + + private final Settings.Builder nodeOverrideSettingsBuilder = Settings.builder(); + + private boolean sslOnly = false; + private final List> plugins = new ArrayList<>(); + private Map remoteClusters = new HashMap<>(); + private List clusterDependencies = new ArrayList<>(); + private List testIndices = new ArrayList<>(); + private ClusterManager clusterManager = ClusterManager.DEFAULT; + private TestSecurityConfig testSecurityConfig = new TestSecurityConfig(); + private String clusterName = "local_cluster"; + private TestCertificates testCertificates; + + private boolean loadConfigurationIntoIndex = true; + + private String defaultConfigurationInitDirectory = null; + + public Builder() {} + + public Builder dependsOn(Object object) { + // We just want to make sure that the object is already done + if (object == null) { + throw new IllegalStateException("Dependency not fulfilled"); + } + return this; + } + + public Builder clusterManager(ClusterManager clusterManager) { + this.clusterManager = clusterManager; + return this; + } + + /** + * Starts a cluster with only one node and thus saves some resources during startup. This shall be only used + * for tests where the node interactions are not relevant to the test. An example for this would be + * authentication tests, as authentication is always done on the directly connected node. + */ + public Builder singleNode() { + this.clusterManager = ClusterManager.SINGLENODE; + return this; + } + + /** + * Specifies the configuration of the security plugin that shall be used by this cluster. + */ + public Builder config(TestSecurityConfig testSecurityConfig) { + this.testSecurityConfig = testSecurityConfig; + return this; + } + + public Builder sslOnly(boolean sslOnly) { + this.sslOnly = sslOnly; + return this; + } + + public Builder nodeSettings(Map settings) { + settings.forEach((key, value) -> { + if (value instanceof List) { + List values = ((List) value).stream().map(String::valueOf).collect(Collectors.toList()); + nodeOverrideSettingsBuilder.putList(key, values); + } else { + nodeOverrideSettingsBuilder.put(key, String.valueOf(value)); + } + }); + + return this; + } + + /** + * Adds additional plugins to the cluster + */ + public Builder plugin(Class plugin) { + this.plugins.add(plugin); + + return this; + } + + public Builder authFailureListeners(AuthFailureListeners listener) { + testSecurityConfig.authFailureListeners(listener); + return this; + } + + /** + * Specifies a remote cluster and its name. The remote cluster can be then used in Cross Cluster Search + * operations with the specified name. + */ + public Builder remote(String name, LocalCluster anotherCluster) { + remoteClusters.put(name, anotherCluster); + + clusterDependencies.add(anotherCluster); + + return this; + } + + /** + * Specifies test indices that shall be created upon startup of the cluster. + */ + public Builder indices(TestIndex... indices) { + this.testIndices.addAll(Arrays.asList(indices)); + return this; + } + + public Builder users(TestSecurityConfig.User... users) { + for (TestSecurityConfig.User user : users) { + testSecurityConfig.user(user); + } + return this; + } + + public Builder audit(AuditConfiguration auditConfiguration) { + if (auditConfiguration != null) { + testSecurityConfig.audit(auditConfiguration); + } + if (auditConfiguration.isEnabled()) { + nodeOverrideSettingsBuilder.put("plugins.security.audit.type", TestRuleAuditLogSink.class.getName()); + } else { + nodeOverrideSettingsBuilder.put("plugins.security.audit.type", "noop"); + } + return this; + } + + public List getUsers() { + return testSecurityConfig.getUsers(); + } + + public Builder roles(Role... roles) { + testSecurityConfig.roles(roles); + return this; + } + + public Builder rolesMapping(RolesMapping... mappings) { + testSecurityConfig.rolesMapping(mappings); + return this; + } + + public Builder authc(TestSecurityConfig.AuthcDomain authc) { + testSecurityConfig.authc(authc); + return this; + } + + public Builder authz(AuthzDomain authzDomain) { + testSecurityConfig.authz(authzDomain); + return this; + } + + public Builder clusterName(String clusterName) { + this.clusterName = clusterName; + return this; + } + + public Builder configIndexName(String configIndexName) { + testSecurityConfig.configIndexName(configIndexName); + return this; + } + + public Builder testCertificates(TestCertificates certificates) { + this.testCertificates = certificates; + return this; + } + + public Builder anonymousAuth(boolean anonAuthEnabled) { + testSecurityConfig.anonymousAuth(anonAuthEnabled); + return this; + } + + public Builder xff(XffConfig xffConfig) { + testSecurityConfig.xff(xffConfig); + return this; + } + + public Builder loadConfigurationIntoIndex(boolean loadConfigurationIntoIndex) { + this.loadConfigurationIntoIndex = loadConfigurationIntoIndex; + return this; + } + + public Builder certificates(TestCertificates certificates) { + this.testCertificates = certificates; + return this; + } + + public Builder doNotFailOnForbidden(boolean doNotFailOnForbidden) { + testSecurityConfig.doNotFailOnForbidden(doNotFailOnForbidden); + return this; + } + + public Builder defaultConfigurationInitDirectory(String defaultConfigurationInitDirectory) { + this.defaultConfigurationInitDirectory = defaultConfigurationInitDirectory; + return this; + } + + public LocalCluster build() { + try { + if (testCertificates == null) { + testCertificates = new TestCertificates(); + } + clusterName += "_" + num.incrementAndGet(); + Settings settings = nodeOverrideSettingsBuilder.build(); + return new LocalCluster( + clusterName, + testSecurityConfig, + sslOnly, + settings, + clusterManager, + plugins, + testCertificates, + clusterDependencies, + remoteClusters, + testIndices, + loadConfigurationIntoIndex, + defaultConfigurationInitDirectory + ); + } catch (Exception e) { + log.error("Failed to build LocalCluster", e); + throw new RuntimeException(e); + } + } + + } + + @Override + public TestCertificates getTestCertificates() { + return testCertificates; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java index 1b7befbcfc..2a4b417145 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java @@ -83,444 +83,491 @@ */ public class LocalOpenSearchCluster { - static { - System.setProperty("opensearch.enforce.bootstrap.checks", "true"); - } - - private static final Logger log = LogManager.getLogger(LocalOpenSearchCluster.class); - - private final String clusterName; - private final ClusterManager clusterManager; - private final NodeSettingsSupplier nodeSettingsSupplier; - private final List> additionalPlugins; - private final List nodes = new ArrayList<>(); - private final TestCertificates testCertificates; - - private File clusterHomeDir; - private List seedHosts; - private List initialClusterManagerHosts; - private int retry = 0; - private boolean started; - private Random random = new Random(); - - private File snapshotDir; - - public LocalOpenSearchCluster(String clusterName, ClusterManager clusterManager, NodeSettingsSupplier nodeSettingsSupplier, - List> additionalPlugins, TestCertificates testCertificates) { - this.clusterName = clusterName; - this.clusterManager = clusterManager; - this.nodeSettingsSupplier = nodeSettingsSupplier; - this.additionalPlugins = additionalPlugins; - this.testCertificates = testCertificates; - try { - createClusterDirectory(clusterName); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - public String getSnapshotDirPath() { - return snapshotDir.getAbsolutePath(); - } - - private void createClusterDirectory(String clusterName) throws IOException { - this.clusterHomeDir = Files.createTempDirectory("local_cluster_" + clusterName).toFile(); - log.debug("Cluster home directory '{}'.", clusterHomeDir.getAbsolutePath()); - this.snapshotDir = new File(this.clusterHomeDir, "snapshots"); - this.snapshotDir.mkdir(); - } - - private List getNodesByType(NodeType nodeType) { - return nodes.stream() - .filter(currentNode -> currentNode.hasAssignedType(nodeType)) - .collect(Collectors.toList()); - } - - private long countNodesByType(NodeType nodeType) { - return getNodesByType(nodeType).stream().count(); - } - - public void start() throws Exception { - log.info("Starting {}", clusterName); - - int clusterManagerNodeCount = clusterManager.getClusterManagerNodes(); - int nonClusterManagerNodeCount = clusterManager.getDataNodes() + clusterManager.getClientNodes(); - - SortedSet clusterManagerNodeTransportPorts = TCP.allocate(clusterName, Math.max(clusterManagerNodeCount, 4), 5000 + 42 * 1000 + 300); - SortedSet clusterManagerNodeHttpPorts = TCP.allocate(clusterName, clusterManagerNodeCount, 5000 + 42 * 1000 + 200); - - this.seedHosts = toHostList(clusterManagerNodeTransportPorts); - Set clusterManagerPorts = clusterManagerNodeTransportPorts - .stream().limit(clusterManagerNodeCount).collect(Collectors.toSet()); - this.initialClusterManagerHosts = toHostList(clusterManagerPorts); - - started = true; - - CompletableFuture clusterManagerNodeFuture = startNodes( - clusterManager.getClusterManagerNodeSettings(), clusterManagerNodeTransportPorts, - clusterManagerNodeHttpPorts); - - SortedSet nonClusterManagerNodeTransportPorts = TCP.allocate(clusterName, nonClusterManagerNodeCount, 5000 + 42 * 1000 + 310); - SortedSet nonClusterManagerNodeHttpPorts = TCP.allocate(clusterName, nonClusterManagerNodeCount, 5000 + 42 * 1000 + 210); - - CompletableFuture nonClusterManagerNodeFuture = startNodes( - clusterManager.getNonClusterManagerNodeSettings(), nonClusterManagerNodeTransportPorts, - nonClusterManagerNodeHttpPorts); - - CompletableFuture.allOf(clusterManagerNodeFuture, nonClusterManagerNodeFuture).join(); - - if (isNodeFailedWithPortCollision()) { - log.info("Detected port collision for cluster manager node. Retrying."); - - retry(); - return; - } - - log.info("Startup finished. Waiting for GREEN"); - - waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10), nodes.size()); - - log.info("Started: {}", this); - - } - - public String getClusterName() { - return clusterName; - } - - public boolean isStarted() { - return started; - } - - public void stop() { - List> stopFutures = new ArrayList<>(); - for (Node node : nodes) { - stopFutures.add(node.stop(2, TimeUnit.SECONDS)); - } - CompletableFuture.allOf(stopFutures.toArray(size -> new CompletableFuture[size])).join(); - } - - public void destroy() { - stop(); - nodes.clear(); - - try { - FileUtils.deleteDirectory(clusterHomeDir); - } catch (IOException e) { - log.warn("Error while deleting " + clusterHomeDir, e); - } - } - - public Node clientNode() { - return findRunningNode(getNodesByType(CLIENT), getNodesByType(DATA), getNodesByType(CLUSTER_MANAGER)); - } - - public Node clusterManagerNode() { - return findRunningNode(getNodesByType(CLUSTER_MANAGER)); - } - - public List getNodes() { - return Collections.unmodifiableList(nodes); - } - - public Node getNodeByName(String name) { - return nodes.stream().filter(node -> node.getNodeName().equals(name)).findAny().orElseThrow(() -> new RuntimeException( - "No such node with name: " + name + "; available: " + nodes.stream().map(Node::getNodeName).collect(Collectors.toList()))); - } - - private boolean isNodeFailedWithPortCollision() { - return nodes.stream().anyMatch(Node::isPortCollision); - } - - private void retry() throws Exception { - retry++; - - if (retry > 10) { - throw new RuntimeException("Detected port collisions for cluster manager node. Giving up."); - } - - stop(); - - this.nodes.clear(); - this.seedHosts = null; - this.initialClusterManagerHosts = null; - createClusterDirectory("local_cluster_" + clusterName + "_retry_" + retry); - start(); - } - - @SafeVarargs - private final Node findRunningNode(List nodes, List... moreNodes) { - for (Node node : nodes) { - if (node.isRunning()) { - return node; - } - } - - if (moreNodes != null && moreNodes.length > 0) { - for (List nodesList : moreNodes) { - for (Node node : nodesList) { - if (node.isRunning()) { - return node; - } - } - } - } - - return null; - } - - private CompletableFuture startNodes(List nodeSettingList, SortedSet transportPorts, SortedSet httpPorts) { - Iterator transportPortIterator = transportPorts.iterator(); - Iterator httpPortIterator = httpPorts.iterator(); - List> futures = new ArrayList<>(); - - for (NodeSettings nodeSettings : nodeSettingList) { - Node node = new Node(nodeSettings, transportPortIterator.next(), httpPortIterator.next()); - futures.add(node.start()); - } - - return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); - } - - public void waitForCluster(ClusterHealthStatus status, TimeValue timeout, int expectedNodeCount) throws IOException { - Client client = clientNode().getInternalNodeClient(); - - - log.debug("waiting for cluster state {} and {} nodes", status.name(), expectedNodeCount); - AdminClient adminClient = client.admin(); - - final ClusterHealthResponse healthResponse = adminClient.cluster().prepareHealth().setWaitForStatus(status).setTimeout(timeout) - .setClusterManagerNodeTimeout(timeout).setWaitForNodes("" + expectedNodeCount).execute().actionGet(); - - if (log.isDebugEnabled()) { - log.debug("Current ClusterState:\n{}", Strings.toString(XContentType.JSON,healthResponse)); - } - - if (healthResponse.isTimedOut()) { - throw new IOException( - "cluster state is " + healthResponse.getStatus().name() + " with " + healthResponse.getNumberOfNodes() + " nodes"); - } else { - log.debug("... cluster state ok {} with {} nodes", healthResponse.getStatus().name(), healthResponse.getNumberOfNodes()); - } - - assertEquals(expectedNodeCount, healthResponse.getNumberOfNodes()); - - } - - @Override - public String toString() { - String clusterManagerNodes = nodeByTypeToString(CLUSTER_MANAGER); - String dataNodes = nodeByTypeToString(DATA); - String clientNodes = nodeByTypeToString(CLIENT); - return "\nES Cluster " + clusterName - + "\ncluster manager nodes: " + clusterManagerNodes - + "\n data nodes: " + dataNodes - + "\nclient nodes: " + clientNodes + "\n"; - } - - private String nodeByTypeToString(NodeType type) { - return getNodesByType(type).stream().map(Objects::toString).collect(Collectors.joining(", ")); - } - - private static List toHostList(Collection ports) { - return ports.stream().map(port -> "127.0.0.1:" + port).collect(Collectors.toList()); - } - - private String createNextNodeName(NodeSettings nodeSettings) { - NodeType type = nodeSettings.recognizeNodeType(); - long nodeTypeCount = countNodesByType(type); - String nodeType = type.name().toLowerCase(Locale.ROOT); - return nodeType + "_" + nodeTypeCount; - } - - public class Node implements OpenSearchClientProvider { - private final NodeType nodeType; - private final String nodeName; - private final NodeSettings nodeSettings; - private final File nodeHomeDir; - private final File dataDir; - private final File logsDir; - private final int transportPort; - private final int httpPort; - private final InetSocketAddress httpAddress; - private final InetSocketAddress transportAddress; - private PluginAwareNode node; - private boolean running = false; - private boolean portCollision = false; - - Node(NodeSettings nodeSettings, int transportPort, int httpPort) { - this.nodeName = createNextNodeName(requireNonNull(nodeSettings, "Node settings are required.")); - this.nodeSettings = nodeSettings; - this.nodeHomeDir = new File(clusterHomeDir, nodeName); - this.dataDir = new File(this.nodeHomeDir, "data"); - this.logsDir = new File(this.nodeHomeDir, "logs"); - this.transportPort = transportPort; - this.httpPort = httpPort; - InetAddress hostAddress = InetAddresses.forString("127.0.0.1"); - this.httpAddress = new InetSocketAddress(hostAddress, httpPort); - this.transportAddress = new InetSocketAddress(hostAddress, transportPort); - - this.nodeType = nodeSettings.recognizeNodeType(); - nodes.add(this); - } - - boolean hasAssignedType(NodeType type) { - return requireNonNull(type, "Node type is required.").equals(this.nodeType); - } - - CompletableFuture start() { - CompletableFuture completableFuture = new CompletableFuture<>(); - Class[] mergedPlugins = nodeSettings.pluginsWithAddition(additionalPlugins); - this.node = new PluginAwareNode(nodeSettings.containRole(NodeRole.CLUSTER_MANAGER), getOpenSearchSettings(), mergedPlugins); - - new Thread(new Runnable() { - - @Override - public void run() { - try { - node.start(); - running = true; - completableFuture.complete(StartStage.INITIALIZED); - } catch (BindTransportException | BindHttpException e) { - log.warn("Port collision detected for {}", this, e); - portCollision = true; - try { - node.close(); - } catch (IOException e1) { - log.error(e1); - } - - node = null; - TCP.reserve(transportPort, httpPort); - - completableFuture.complete(StartStage.RETRY); - - } catch (Throwable e) { - log.error("Unable to start {}", this, e); - node = null; - completableFuture.completeExceptionally(e); - } - } - }).start(); - - return completableFuture; - } - - public Client getInternalNodeClient() { - return node.client(); - } - - public PluginAwareNode esNode() { - return node; - } - - public boolean isRunning() { - return running; - } - - public X getInjectable(Class clazz) { - return node.injector().getInstance(clazz); - } - - public CompletableFuture stop(long timeout, TimeUnit timeUnit) { - return CompletableFuture.supplyAsync(() -> { - try { - log.info("Stopping {}", this); - - running = false; - - if (node != null) { - node.close(); - boolean stopped = node.awaitClose(timeout, timeUnit); - node = null; - return stopped; - } else { - return false; - } - } catch (Throwable e) { - String message = "Error while stopping " + this; - log.warn(message, e); - throw new RuntimeException(message, e); - } - }); - } - - @Override - public String toString() { - String state = running ? "RUNNING" : node != null ? "INITIALIZING" : "STOPPED"; - - return nodeName + " " + state + " [" + transportPort + ", " + httpPort + "]"; - } - - public boolean isPortCollision() { - return portCollision; - } - - public String getNodeName() { - return nodeName; - } - - @Override - public InetSocketAddress getHttpAddress() { - return httpAddress; - } - - @Override - public InetSocketAddress getTransportAddress() { - return transportAddress; - } - - private Settings getOpenSearchSettings() { - Settings settings = Settings.builder() - .put(getMinimalOpenSearchSettings()) - .putList("path.repo", List.of(getSnapshotDirPath())) - .build(); - - if (nodeSettingsSupplier != null) { - // TODO node number - return Settings.builder().put(settings).put(nodeSettingsSupplier.get(0)).build(); - } - return settings; - } - - private Settings getMinimalOpenSearchSettings() { - return Settings.builder().put("node.name", nodeName).putList("node.roles", createNodeRolesSettings()) - .put("cluster.name", clusterName).put("path.home", nodeHomeDir.toPath()).put("path.data", dataDir.toPath()) - .put("path.logs", logsDir.toPath()).putList("cluster.initial_cluster_manager_nodes", initialClusterManagerHosts) - .put("discovery.initial_state_timeout", "8s").putList("discovery.seed_hosts", seedHosts).put("transport.tcp.port", transportPort) - .put("http.port", httpPort).put("cluster.routing.allocation.disk.threshold_enabled", false) - .put("discovery.probe.connect_timeout", "10s").put("discovery.probe.handshake_timeout", "10s").put("http.cors.enabled", true) - .put("gateway.auto_import_dangling_indices", "true") - .build(); - } - - private List createNodeRolesSettings() { - final ImmutableList.Builder nodeRolesBuilder = ImmutableList.builder(); - if (nodeSettings.containRole(NodeRole.DATA)) { - nodeRolesBuilder.add("data"); - } - if (nodeSettings.containRole(NodeRole.CLUSTER_MANAGER)) { - nodeRolesBuilder.add("cluster_manager"); - } - if(nodeSettings.containRole(NodeRole.REMOTE_CLUSTER_CLIENT)) { - nodeRolesBuilder.add("remote_cluster_client"); - } - return nodeRolesBuilder.build(); - } - - @Override - public String getClusterName() { - return clusterName; - } - - @Override - public TestCertificates getTestCertificates() { - return testCertificates; - } - } - - public Random getRandom() { - return random; - } + static { + System.setProperty("opensearch.enforce.bootstrap.checks", "true"); + } + + private static final Logger log = LogManager.getLogger(LocalOpenSearchCluster.class); + + private final String clusterName; + private final ClusterManager clusterManager; + private final NodeSettingsSupplier nodeSettingsSupplier; + private final List> additionalPlugins; + private final List nodes = new ArrayList<>(); + private final TestCertificates testCertificates; + + private File clusterHomeDir; + private List seedHosts; + private List initialClusterManagerHosts; + private int retry = 0; + private boolean started; + private Random random = new Random(); + + private File snapshotDir; + + public LocalOpenSearchCluster( + String clusterName, + ClusterManager clusterManager, + NodeSettingsSupplier nodeSettingsSupplier, + List> additionalPlugins, + TestCertificates testCertificates + ) { + this.clusterName = clusterName; + this.clusterManager = clusterManager; + this.nodeSettingsSupplier = nodeSettingsSupplier; + this.additionalPlugins = additionalPlugins; + this.testCertificates = testCertificates; + try { + createClusterDirectory(clusterName); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public String getSnapshotDirPath() { + return snapshotDir.getAbsolutePath(); + } + + private void createClusterDirectory(String clusterName) throws IOException { + this.clusterHomeDir = Files.createTempDirectory("local_cluster_" + clusterName).toFile(); + log.debug("Cluster home directory '{}'.", clusterHomeDir.getAbsolutePath()); + this.snapshotDir = new File(this.clusterHomeDir, "snapshots"); + this.snapshotDir.mkdir(); + } + + private List getNodesByType(NodeType nodeType) { + return nodes.stream().filter(currentNode -> currentNode.hasAssignedType(nodeType)).collect(Collectors.toList()); + } + + private long countNodesByType(NodeType nodeType) { + return getNodesByType(nodeType).stream().count(); + } + + public void start() throws Exception { + log.info("Starting {}", clusterName); + + int clusterManagerNodeCount = clusterManager.getClusterManagerNodes(); + int nonClusterManagerNodeCount = clusterManager.getDataNodes() + clusterManager.getClientNodes(); + + SortedSet clusterManagerNodeTransportPorts = TCP.allocate( + clusterName, + Math.max(clusterManagerNodeCount, 4), + 5000 + 42 * 1000 + 300 + ); + SortedSet clusterManagerNodeHttpPorts = TCP.allocate(clusterName, clusterManagerNodeCount, 5000 + 42 * 1000 + 200); + + this.seedHosts = toHostList(clusterManagerNodeTransportPorts); + Set clusterManagerPorts = clusterManagerNodeTransportPorts.stream() + .limit(clusterManagerNodeCount) + .collect(Collectors.toSet()); + this.initialClusterManagerHosts = toHostList(clusterManagerPorts); + + started = true; + + CompletableFuture clusterManagerNodeFuture = startNodes( + clusterManager.getClusterManagerNodeSettings(), + clusterManagerNodeTransportPorts, + clusterManagerNodeHttpPorts + ); + + SortedSet nonClusterManagerNodeTransportPorts = TCP.allocate( + clusterName, + nonClusterManagerNodeCount, + 5000 + 42 * 1000 + 310 + ); + SortedSet nonClusterManagerNodeHttpPorts = TCP.allocate(clusterName, nonClusterManagerNodeCount, 5000 + 42 * 1000 + 210); + + CompletableFuture nonClusterManagerNodeFuture = startNodes( + clusterManager.getNonClusterManagerNodeSettings(), + nonClusterManagerNodeTransportPorts, + nonClusterManagerNodeHttpPorts + ); + + CompletableFuture.allOf(clusterManagerNodeFuture, nonClusterManagerNodeFuture).join(); + + if (isNodeFailedWithPortCollision()) { + log.info("Detected port collision for cluster manager node. Retrying."); + + retry(); + return; + } + + log.info("Startup finished. Waiting for GREEN"); + + waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10), nodes.size()); + + log.info("Started: {}", this); + + } + + public String getClusterName() { + return clusterName; + } + + public boolean isStarted() { + return started; + } + + public void stop() { + List> stopFutures = new ArrayList<>(); + for (Node node : nodes) { + stopFutures.add(node.stop(2, TimeUnit.SECONDS)); + } + CompletableFuture.allOf(stopFutures.toArray(size -> new CompletableFuture[size])).join(); + } + + public void destroy() { + stop(); + nodes.clear(); + + try { + FileUtils.deleteDirectory(clusterHomeDir); + } catch (IOException e) { + log.warn("Error while deleting " + clusterHomeDir, e); + } + } + + public Node clientNode() { + return findRunningNode(getNodesByType(CLIENT), getNodesByType(DATA), getNodesByType(CLUSTER_MANAGER)); + } + + public Node clusterManagerNode() { + return findRunningNode(getNodesByType(CLUSTER_MANAGER)); + } + + public List getNodes() { + return Collections.unmodifiableList(nodes); + } + + public Node getNodeByName(String name) { + return nodes.stream() + .filter(node -> node.getNodeName().equals(name)) + .findAny() + .orElseThrow( + () -> new RuntimeException( + "No such node with name: " + name + "; available: " + nodes.stream().map(Node::getNodeName).collect(Collectors.toList()) + ) + ); + } + + private boolean isNodeFailedWithPortCollision() { + return nodes.stream().anyMatch(Node::isPortCollision); + } + + private void retry() throws Exception { + retry++; + + if (retry > 10) { + throw new RuntimeException("Detected port collisions for cluster manager node. Giving up."); + } + + stop(); + + this.nodes.clear(); + this.seedHosts = null; + this.initialClusterManagerHosts = null; + createClusterDirectory("local_cluster_" + clusterName + "_retry_" + retry); + start(); + } + + @SafeVarargs + private final Node findRunningNode(List nodes, List... moreNodes) { + for (Node node : nodes) { + if (node.isRunning()) { + return node; + } + } + + if (moreNodes != null && moreNodes.length > 0) { + for (List nodesList : moreNodes) { + for (Node node : nodesList) { + if (node.isRunning()) { + return node; + } + } + } + } + + return null; + } + + private CompletableFuture startNodes( + List nodeSettingList, + SortedSet transportPorts, + SortedSet httpPorts + ) { + Iterator transportPortIterator = transportPorts.iterator(); + Iterator httpPortIterator = httpPorts.iterator(); + List> futures = new ArrayList<>(); + + for (NodeSettings nodeSettings : nodeSettingList) { + Node node = new Node(nodeSettings, transportPortIterator.next(), httpPortIterator.next()); + futures.add(node.start()); + } + + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + } + + public void waitForCluster(ClusterHealthStatus status, TimeValue timeout, int expectedNodeCount) throws IOException { + Client client = clientNode().getInternalNodeClient(); + + log.debug("waiting for cluster state {} and {} nodes", status.name(), expectedNodeCount); + AdminClient adminClient = client.admin(); + + final ClusterHealthResponse healthResponse = adminClient.cluster() + .prepareHealth() + .setWaitForStatus(status) + .setTimeout(timeout) + .setClusterManagerNodeTimeout(timeout) + .setWaitForNodes("" + expectedNodeCount) + .execute() + .actionGet(); + + if (log.isDebugEnabled()) { + log.debug("Current ClusterState:\n{}", Strings.toString(XContentType.JSON, healthResponse)); + } + + if (healthResponse.isTimedOut()) { + throw new IOException( + "cluster state is " + healthResponse.getStatus().name() + " with " + healthResponse.getNumberOfNodes() + " nodes" + ); + } else { + log.debug("... cluster state ok {} with {} nodes", healthResponse.getStatus().name(), healthResponse.getNumberOfNodes()); + } + + assertEquals(expectedNodeCount, healthResponse.getNumberOfNodes()); + + } + + @Override + public String toString() { + String clusterManagerNodes = nodeByTypeToString(CLUSTER_MANAGER); + String dataNodes = nodeByTypeToString(DATA); + String clientNodes = nodeByTypeToString(CLIENT); + return "\nES Cluster " + + clusterName + + "\ncluster manager nodes: " + + clusterManagerNodes + + "\n data nodes: " + + dataNodes + + "\nclient nodes: " + + clientNodes + + "\n"; + } + + private String nodeByTypeToString(NodeType type) { + return getNodesByType(type).stream().map(Objects::toString).collect(Collectors.joining(", ")); + } + + private static List toHostList(Collection ports) { + return ports.stream().map(port -> "127.0.0.1:" + port).collect(Collectors.toList()); + } + + private String createNextNodeName(NodeSettings nodeSettings) { + NodeType type = nodeSettings.recognizeNodeType(); + long nodeTypeCount = countNodesByType(type); + String nodeType = type.name().toLowerCase(Locale.ROOT); + return nodeType + "_" + nodeTypeCount; + } + + public class Node implements OpenSearchClientProvider { + private final NodeType nodeType; + private final String nodeName; + private final NodeSettings nodeSettings; + private final File nodeHomeDir; + private final File dataDir; + private final File logsDir; + private final int transportPort; + private final int httpPort; + private final InetSocketAddress httpAddress; + private final InetSocketAddress transportAddress; + private PluginAwareNode node; + private boolean running = false; + private boolean portCollision = false; + + Node(NodeSettings nodeSettings, int transportPort, int httpPort) { + this.nodeName = createNextNodeName(requireNonNull(nodeSettings, "Node settings are required.")); + this.nodeSettings = nodeSettings; + this.nodeHomeDir = new File(clusterHomeDir, nodeName); + this.dataDir = new File(this.nodeHomeDir, "data"); + this.logsDir = new File(this.nodeHomeDir, "logs"); + this.transportPort = transportPort; + this.httpPort = httpPort; + InetAddress hostAddress = InetAddresses.forString("127.0.0.1"); + this.httpAddress = new InetSocketAddress(hostAddress, httpPort); + this.transportAddress = new InetSocketAddress(hostAddress, transportPort); + + this.nodeType = nodeSettings.recognizeNodeType(); + nodes.add(this); + } + + boolean hasAssignedType(NodeType type) { + return requireNonNull(type, "Node type is required.").equals(this.nodeType); + } + + CompletableFuture start() { + CompletableFuture completableFuture = new CompletableFuture<>(); + Class[] mergedPlugins = nodeSettings.pluginsWithAddition(additionalPlugins); + this.node = new PluginAwareNode(nodeSettings.containRole(NodeRole.CLUSTER_MANAGER), getOpenSearchSettings(), mergedPlugins); + + new Thread(new Runnable() { + + @Override + public void run() { + try { + node.start(); + running = true; + completableFuture.complete(StartStage.INITIALIZED); + } catch (BindTransportException | BindHttpException e) { + log.warn("Port collision detected for {}", this, e); + portCollision = true; + try { + node.close(); + } catch (IOException e1) { + log.error(e1); + } + + node = null; + TCP.reserve(transportPort, httpPort); + + completableFuture.complete(StartStage.RETRY); + + } catch (Throwable e) { + log.error("Unable to start {}", this, e); + node = null; + completableFuture.completeExceptionally(e); + } + } + }).start(); + + return completableFuture; + } + + public Client getInternalNodeClient() { + return node.client(); + } + + public PluginAwareNode esNode() { + return node; + } + + public boolean isRunning() { + return running; + } + + public X getInjectable(Class clazz) { + return node.injector().getInstance(clazz); + } + + public CompletableFuture stop(long timeout, TimeUnit timeUnit) { + return CompletableFuture.supplyAsync(() -> { + try { + log.info("Stopping {}", this); + + running = false; + + if (node != null) { + node.close(); + boolean stopped = node.awaitClose(timeout, timeUnit); + node = null; + return stopped; + } else { + return false; + } + } catch (Throwable e) { + String message = "Error while stopping " + this; + log.warn(message, e); + throw new RuntimeException(message, e); + } + }); + } + + @Override + public String toString() { + String state = running ? "RUNNING" : node != null ? "INITIALIZING" : "STOPPED"; + + return nodeName + " " + state + " [" + transportPort + ", " + httpPort + "]"; + } + + public boolean isPortCollision() { + return portCollision; + } + + public String getNodeName() { + return nodeName; + } + + @Override + public InetSocketAddress getHttpAddress() { + return httpAddress; + } + + @Override + public InetSocketAddress getTransportAddress() { + return transportAddress; + } + + private Settings getOpenSearchSettings() { + Settings settings = Settings.builder() + .put(getMinimalOpenSearchSettings()) + .putList("path.repo", List.of(getSnapshotDirPath())) + .build(); + + if (nodeSettingsSupplier != null) { + // TODO node number + return Settings.builder().put(settings).put(nodeSettingsSupplier.get(0)).build(); + } + return settings; + } + + private Settings getMinimalOpenSearchSettings() { + return Settings.builder() + .put("node.name", nodeName) + .putList("node.roles", createNodeRolesSettings()) + .put("cluster.name", clusterName) + .put("path.home", nodeHomeDir.toPath()) + .put("path.data", dataDir.toPath()) + .put("path.logs", logsDir.toPath()) + .putList("cluster.initial_cluster_manager_nodes", initialClusterManagerHosts) + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.seed_hosts", seedHosts) + .put("transport.tcp.port", transportPort) + .put("http.port", httpPort) + .put("cluster.routing.allocation.disk.threshold_enabled", false) + .put("discovery.probe.connect_timeout", "10s") + .put("discovery.probe.handshake_timeout", "10s") + .put("http.cors.enabled", true) + .put("gateway.auto_import_dangling_indices", "true") + .build(); + } + + private List createNodeRolesSettings() { + final ImmutableList.Builder nodeRolesBuilder = ImmutableList.builder(); + if (nodeSettings.containRole(NodeRole.DATA)) { + nodeRolesBuilder.add("data"); + } + if (nodeSettings.containRole(NodeRole.CLUSTER_MANAGER)) { + nodeRolesBuilder.add("cluster_manager"); + } + if (nodeSettings.containRole(NodeRole.REMOTE_CLUSTER_CLIENT)) { + nodeRolesBuilder.add("remote_cluster_client"); + } + return nodeRolesBuilder.build(); + } + + @Override + public String getClusterName() { + return clusterName; + } + + @Override + public TestCertificates getTestCertificates() { + return testCertificates; + } + } + + public Random getRandom() { + return random; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/MinimumSecuritySettingsSupplierFactory.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/MinimumSecuritySettingsSupplierFactory.java index 318dce63d6..4ad5f8420e 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/MinimumSecuritySettingsSupplierFactory.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/MinimumSecuritySettingsSupplierFactory.java @@ -34,45 +34,51 @@ public class MinimumSecuritySettingsSupplierFactory { - private final String PRIVATE_KEY_HTTP_PASSWORD = "aWVV63OJ4qzZyPrBwl2MFny4ZV8lQRZchjL"; - private final String PRIVATE_KEY_TRANSPORT_PASSWORD = "iWbUv9w79sbd5tcxvSJNfHXS9GhcPCvdw9x"; + private final String PRIVATE_KEY_HTTP_PASSWORD = "aWVV63OJ4qzZyPrBwl2MFny4ZV8lQRZchjL"; + private final String PRIVATE_KEY_TRANSPORT_PASSWORD = "iWbUv9w79sbd5tcxvSJNfHXS9GhcPCvdw9x"; - private TestCertificates testCertificates; + private TestCertificates testCertificates; - public MinimumSecuritySettingsSupplierFactory(TestCertificates testCertificates) { - if (testCertificates == null) { - throw new IllegalArgumentException("certificates must not be null"); - } - this.testCertificates = testCertificates; + public MinimumSecuritySettingsSupplierFactory(TestCertificates testCertificates) { + if (testCertificates == null) { + throw new IllegalArgumentException("certificates must not be null"); + } + this.testCertificates = testCertificates; - } + } - public NodeSettingsSupplier minimumOpenSearchSettings(boolean sslOnly, Settings other) { - return i -> minimumOpenSearchSettingsBuilder(i, sslOnly).put(other).build(); - } + public NodeSettingsSupplier minimumOpenSearchSettings(boolean sslOnly, Settings other) { + return i -> minimumOpenSearchSettingsBuilder(i, sslOnly).put(other).build(); + } - private Settings.Builder minimumOpenSearchSettingsBuilder(int node, boolean sslOnly) { + private Settings.Builder minimumOpenSearchSettingsBuilder(int node, boolean sslOnly) { - Settings.Builder builder = Settings.builder(); + Settings.Builder builder = Settings.builder(); - builder.put("plugins.security.ssl.transport.pemtrustedcas_filepath", testCertificates.getRootCertificate().getAbsolutePath()); - builder.put("plugins.security.ssl.transport.pemcert_filepath", testCertificates.getNodeCertificate(node).getAbsolutePath()); - builder.put("plugins.security.ssl.transport.pemkey_filepath", testCertificates.getNodeKey(node, PRIVATE_KEY_TRANSPORT_PASSWORD).getAbsolutePath()); - builder.put("plugins.security.ssl.transport.pemkey_password", PRIVATE_KEY_TRANSPORT_PASSWORD); + builder.put("plugins.security.ssl.transport.pemtrustedcas_filepath", testCertificates.getRootCertificate().getAbsolutePath()); + builder.put("plugins.security.ssl.transport.pemcert_filepath", testCertificates.getNodeCertificate(node).getAbsolutePath()); + builder.put( + "plugins.security.ssl.transport.pemkey_filepath", + testCertificates.getNodeKey(node, PRIVATE_KEY_TRANSPORT_PASSWORD).getAbsolutePath() + ); + builder.put("plugins.security.ssl.transport.pemkey_password", PRIVATE_KEY_TRANSPORT_PASSWORD); - builder.put("plugins.security.ssl.http.enabled", true); - builder.put("plugins.security.ssl.http.pemtrustedcas_filepath", testCertificates.getRootCertificate().getAbsolutePath()); - builder.put("plugins.security.ssl.http.pemcert_filepath", testCertificates.getNodeCertificate(node).getAbsolutePath()); - builder.put("plugins.security.ssl.http.pemkey_filepath", testCertificates.getNodeKey(node, PRIVATE_KEY_HTTP_PASSWORD).getAbsolutePath()); - builder.put("plugins.security.ssl.http.pemkey_password", PRIVATE_KEY_HTTP_PASSWORD); - if(sslOnly == false) { - builder.put(ConfigConstants.SECURITY_BACKGROUND_INIT_IF_SECURITYINDEX_NOT_EXIST, false); - builder.putList("plugins.security.authcz.admin_dn", testCertificates.getAdminDNs()); - builder.put("plugins.security.compliance.salt", "1234567890123456"); - builder.put("plugins.security.audit.type", "noop"); - builder.put("plugins.security.background_init_if_securityindex_not_exist", "false"); - } - return builder; + builder.put("plugins.security.ssl.http.enabled", true); + builder.put("plugins.security.ssl.http.pemtrustedcas_filepath", testCertificates.getRootCertificate().getAbsolutePath()); + builder.put("plugins.security.ssl.http.pemcert_filepath", testCertificates.getNodeCertificate(node).getAbsolutePath()); + builder.put( + "plugins.security.ssl.http.pemkey_filepath", + testCertificates.getNodeKey(node, PRIVATE_KEY_HTTP_PASSWORD).getAbsolutePath() + ); + builder.put("plugins.security.ssl.http.pemkey_password", PRIVATE_KEY_HTTP_PASSWORD); + if (sslOnly == false) { + builder.put(ConfigConstants.SECURITY_BACKGROUND_INIT_IF_SECURITYINDEX_NOT_EXIST, false); + builder.putList("plugins.security.authcz.admin_dn", testCertificates.getAdminDNs()); + builder.put("plugins.security.compliance.salt", "1234567890123456"); + builder.put("plugins.security.audit.type", "noop"); + builder.put("plugins.security.background_init_if_securityindex_not_exist", "false"); + } + return builder; - } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeRole.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeRole.java index 7dc77ef37e..0d465fa119 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeRole.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeRole.java @@ -10,5 +10,7 @@ package org.opensearch.test.framework.cluster; enum NodeRole { - DATA, CLUSTER_MANAGER, REMOTE_CLUSTER_CLIENT + DATA, + CLUSTER_MANAGER, + REMOTE_CLUSTER_CLIENT } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeSettingsSupplier.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeSettingsSupplier.java index 75c728287b..cab3a760ca 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeSettingsSupplier.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeSettingsSupplier.java @@ -30,5 +30,5 @@ @FunctionalInterface public interface NodeSettingsSupplier { - Settings get(int i); + Settings get(int i); } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeType.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeType.java index 915f99daa8..8ae8941e8d 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeType.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/NodeType.java @@ -11,5 +11,7 @@ package org.opensearch.test.framework.cluster; enum NodeType { - CLIENT, DATA, CLUSTER_MANAGER + CLIENT, + DATA, + CLUSTER_MANAGER } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/OpenSearchClientProvider.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/OpenSearchClientProvider.java index e395bfceda..45a68994f8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/OpenSearchClientProvider.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/OpenSearchClientProvider.java @@ -79,197 +79,203 @@ */ public interface OpenSearchClientProvider { - String getClusterName(); - - TestCertificates getTestCertificates(); - - InetSocketAddress getHttpAddress(); - - InetSocketAddress getTransportAddress(); - - default URI getHttpAddressAsURI() { - InetSocketAddress address = getHttpAddress(); - return URI.create("https://" + address.getHostString() + ":" + address.getPort()); - } - - /** - * Returns a REST client that sends requests with basic authentication for the specified User object. Optionally, - * additional HTTP headers can be specified which will be sent with each request. - * - * This method should be usually preferred. The other getRestClient() methods shall be only used for specific - * situations. - */ - default TestRestClient getRestClient(UserCredentialsHolder user, CertificateData useCertificateData, Header... headers) { - return getRestClient(user.getName(), user.getPassword(), useCertificateData, headers); - } - - default TestRestClient getRestClient(UserCredentialsHolder user, Header... headers) { - return getRestClient(user.getName(), user.getPassword(), null, headers); - } - - default RestHighLevelClient getRestHighLevelClient(String username, String password, Header... headers) { - return getRestHighLevelClient(new UserCredentialsHolder() { - @Override - public String getName() { - return username; - } - - @Override - public String getPassword() { - return password; - } - }, Arrays.asList(headers)); - } - - - default RestHighLevelClient getRestHighLevelClient(UserCredentialsHolder user) { - return getRestHighLevelClient(user, Collections.emptySet()); - } - - default RestHighLevelClient getRestHighLevelClient(UserCredentialsHolder user, Collection defaultHeaders) { - - BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(user.getName(), user.getPassword().toCharArray())); - - return getRestHighLevelClient(credentialsProvider, defaultHeaders); - } - - default RestHighLevelClient getRestHighLevelClient(Collection defaultHeaders) { - return getRestHighLevelClient((BasicCredentialsProvider)null, defaultHeaders); - } - - default RestHighLevelClient getRestHighLevelClient(BasicCredentialsProvider credentialsProvider, Collection defaultHeaders) { - RestClientBuilder.HttpClientConfigCallback configCallback = httpClientBuilder -> { - TlsStrategy tlsStrategy = ClientTlsStrategyBuilder - .create() - .setSslContext(getSSLContext()) - .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) - // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 - .setTlsDetailsFactory(new Factory() { - @Override - public TlsDetails create(final SSLEngine sslEngine) { - return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); - } - }) - .build(); - - final AsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(tlsStrategy) - .build(); - - if(credentialsProvider != null) { - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); - } - httpClientBuilder.setDefaultHeaders(defaultHeaders); - httpClientBuilder.setConnectionManager(cm); - httpClientBuilder.setDefaultHeaders(defaultHeaders); - return httpClientBuilder; - }; - - InetSocketAddress httpAddress = getHttpAddress(); - RestClientBuilder builder = RestClient.builder(new HttpHost("https", httpAddress.getHostString(), httpAddress.getPort())) - .setHttpClientConfigCallback(configCallback); - - - return new RestHighLevelClient(builder); - } - - default CloseableHttpClient getClosableHttpClient(String[] supportedCipherSuit) { - CloseableHttpClientFactory factory = new CloseableHttpClientFactory(getSSLContext(), null, null, supportedCipherSuit); - return factory.getHTTPClient(); - } - - /** - * Returns a REST client that sends requests with basic authentication for the specified user name and password. Optionally, - * additional HTTP headers can be specified which will be sent with each request. - * - * Normally, you should use the method with the User object argument instead. Use this only if you need more - * control over username and password - for example, when you want to send a wrong password. - */ - default TestRestClient getRestClient(String user, String password, Header... headers) { - return createGenericClientRestClient(new TestRestClientConfiguration().username(user).password(password).headers(headers)); - } - default TestRestClient getRestClient(String user, String password, CertificateData useCertificateData, Header... headers) { - Header basicAuthHeader = getBasicAuthHeader(user, password); - if (headers != null && headers.length > 0) { - List
concatenatedHeaders = Stream.concat(Stream.of(basicAuthHeader), Stream.of(headers)).collect(Collectors.toList()); - return getRestClient(concatenatedHeaders, useCertificateData); - } - return getRestClient(useCertificateData, basicAuthHeader); - } - /** - * Returns a REST client. You can specify additional HTTP headers that will be sent with each request. Use this - * method to test non-basic authentication, such as JWT bearer authentication. - */ - default TestRestClient getRestClient(CertificateData useCertificateData, Header... headers) { - return getRestClient(Arrays.asList(headers), useCertificateData); - } - - default TestRestClient getRestClient(Header... headers) { - return getRestClient((CertificateData) null, headers); - } - - - default TestRestClient getRestClient(List
headers) { - return createGenericClientRestClient(new TestRestClientConfiguration().headers(headers)); - - } - - default TestRestClient getRestClient(List
headers, CertificateData useCertificateData) { - return createGenericClientRestClient(headers, useCertificateData, null); - } - - default TestRestClient createGenericClientRestClient(List
headers, CertificateData useCertificateData, - InetAddress sourceInetAddress) { - return new TestRestClient(getHttpAddress(), headers, getSSLContext(useCertificateData), sourceInetAddress); - } - - default TestRestClient createGenericClientRestClient(TestRestClientConfiguration configuration) { - return new TestRestClient(getHttpAddress(), configuration.getHeaders(), getSSLContext(), configuration.getSourceInetAddress()); - } - - private SSLContext getSSLContext() { - return getSSLContext(null); - } - - private SSLContext getSSLContext(CertificateData useCertificateData) { - X509Certificate[] trustCertificates; - - try { - trustCertificates = PemKeyReader.loadCertificatesFromFile(getTestCertificates().getRootCertificate() ); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - - ks.load(null); - - for (int i = 0; i < trustCertificates.length; i++) { - ks.setCertificateEntry("caCert-" + i, trustCertificates[i]); - } - KeyManager[] keyManagers = null; - if(useCertificateData != null) { - Certificate[] chainOfTrust = {useCertificateData.certificate()}; - ks.setKeyEntry("admin-certificate", useCertificateData.getKey(), null, chainOfTrust); - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(ks, null); - keyManagers = keyManagerFactory.getKeyManagers(); - } - - tmf.init(ks); - - SSLContext sslContext = SSLContext.getInstance("TLS"); - - sslContext.init(keyManagers, tmf.getTrustManagers(), null); - return sslContext; - - } catch (Exception e) { - throw new RuntimeException("Error loading root CA ", e); - } - } - - public interface UserCredentialsHolder { - String getName(); - String getPassword(); - } + String getClusterName(); + + TestCertificates getTestCertificates(); + + InetSocketAddress getHttpAddress(); + + InetSocketAddress getTransportAddress(); + + default URI getHttpAddressAsURI() { + InetSocketAddress address = getHttpAddress(); + return URI.create("https://" + address.getHostString() + ":" + address.getPort()); + } + + /** + * Returns a REST client that sends requests with basic authentication for the specified User object. Optionally, + * additional HTTP headers can be specified which will be sent with each request. + * + * This method should be usually preferred. The other getRestClient() methods shall be only used for specific + * situations. + */ + default TestRestClient getRestClient(UserCredentialsHolder user, CertificateData useCertificateData, Header... headers) { + return getRestClient(user.getName(), user.getPassword(), useCertificateData, headers); + } + + default TestRestClient getRestClient(UserCredentialsHolder user, Header... headers) { + return getRestClient(user.getName(), user.getPassword(), null, headers); + } + + default RestHighLevelClient getRestHighLevelClient(String username, String password, Header... headers) { + return getRestHighLevelClient(new UserCredentialsHolder() { + @Override + public String getName() { + return username; + } + + @Override + public String getPassword() { + return password; + } + }, Arrays.asList(headers)); + } + + default RestHighLevelClient getRestHighLevelClient(UserCredentialsHolder user) { + return getRestHighLevelClient(user, Collections.emptySet()); + } + + default RestHighLevelClient getRestHighLevelClient(UserCredentialsHolder user, Collection defaultHeaders) { + + BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials( + new AuthScope(null, -1), + new UsernamePasswordCredentials(user.getName(), user.getPassword().toCharArray()) + ); + + return getRestHighLevelClient(credentialsProvider, defaultHeaders); + } + + default RestHighLevelClient getRestHighLevelClient(Collection defaultHeaders) { + return getRestHighLevelClient((BasicCredentialsProvider) null, defaultHeaders); + } + + default RestHighLevelClient getRestHighLevelClient( + BasicCredentialsProvider credentialsProvider, + Collection defaultHeaders + ) { + RestClientBuilder.HttpClientConfigCallback configCallback = httpClientBuilder -> { + TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() + .setSslContext(getSSLContext()) + .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) + // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 + .setTlsDetailsFactory(new Factory() { + @Override + public TlsDetails create(final SSLEngine sslEngine) { + return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); + } + }) + .build(); + + final AsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(tlsStrategy).build(); + + if (credentialsProvider != null) { + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } + httpClientBuilder.setDefaultHeaders(defaultHeaders); + httpClientBuilder.setConnectionManager(cm); + httpClientBuilder.setDefaultHeaders(defaultHeaders); + return httpClientBuilder; + }; + + InetSocketAddress httpAddress = getHttpAddress(); + RestClientBuilder builder = RestClient.builder(new HttpHost("https", httpAddress.getHostString(), httpAddress.getPort())) + .setHttpClientConfigCallback(configCallback); + + return new RestHighLevelClient(builder); + } + + default CloseableHttpClient getClosableHttpClient(String[] supportedCipherSuit) { + CloseableHttpClientFactory factory = new CloseableHttpClientFactory(getSSLContext(), null, null, supportedCipherSuit); + return factory.getHTTPClient(); + } + + /** + * Returns a REST client that sends requests with basic authentication for the specified user name and password. Optionally, + * additional HTTP headers can be specified which will be sent with each request. + * + * Normally, you should use the method with the User object argument instead. Use this only if you need more + * control over username and password - for example, when you want to send a wrong password. + */ + default TestRestClient getRestClient(String user, String password, Header... headers) { + return createGenericClientRestClient(new TestRestClientConfiguration().username(user).password(password).headers(headers)); + } + + default TestRestClient getRestClient(String user, String password, CertificateData useCertificateData, Header... headers) { + Header basicAuthHeader = getBasicAuthHeader(user, password); + if (headers != null && headers.length > 0) { + List
concatenatedHeaders = Stream.concat(Stream.of(basicAuthHeader), Stream.of(headers)).collect(Collectors.toList()); + return getRestClient(concatenatedHeaders, useCertificateData); + } + return getRestClient(useCertificateData, basicAuthHeader); + } + + /** + * Returns a REST client. You can specify additional HTTP headers that will be sent with each request. Use this + * method to test non-basic authentication, such as JWT bearer authentication. + */ + default TestRestClient getRestClient(CertificateData useCertificateData, Header... headers) { + return getRestClient(Arrays.asList(headers), useCertificateData); + } + + default TestRestClient getRestClient(Header... headers) { + return getRestClient((CertificateData) null, headers); + } + + default TestRestClient getRestClient(List
headers) { + return createGenericClientRestClient(new TestRestClientConfiguration().headers(headers)); + + } + + default TestRestClient getRestClient(List
headers, CertificateData useCertificateData) { + return createGenericClientRestClient(headers, useCertificateData, null); + } + + default TestRestClient createGenericClientRestClient( + List
headers, + CertificateData useCertificateData, + InetAddress sourceInetAddress + ) { + return new TestRestClient(getHttpAddress(), headers, getSSLContext(useCertificateData), sourceInetAddress); + } + + default TestRestClient createGenericClientRestClient(TestRestClientConfiguration configuration) { + return new TestRestClient(getHttpAddress(), configuration.getHeaders(), getSSLContext(), configuration.getSourceInetAddress()); + } + + private SSLContext getSSLContext() { + return getSSLContext(null); + } + + private SSLContext getSSLContext(CertificateData useCertificateData) { + X509Certificate[] trustCertificates; + + try { + trustCertificates = PemKeyReader.loadCertificatesFromFile(getTestCertificates().getRootCertificate()); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + + ks.load(null); + + for (int i = 0; i < trustCertificates.length; i++) { + ks.setCertificateEntry("caCert-" + i, trustCertificates[i]); + } + KeyManager[] keyManagers = null; + if (useCertificateData != null) { + Certificate[] chainOfTrust = { useCertificateData.certificate() }; + ks.setKeyEntry("admin-certificate", useCertificateData.getKey(), null, chainOfTrust); + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(ks, null); + keyManagers = keyManagerFactory.getKeyManagers(); + } + + tmf.init(ks); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + + sslContext.init(keyManagers, tmf.getTrustManagers(), null); + return sslContext; + + } catch (Exception e) { + throw new RuntimeException("Error loading root CA ", e); + } + } + + public interface UserCredentialsHolder { + String getName(); + + String getPassword(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/PortAllocator.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/PortAllocator.java index ed72fae91f..139378fd22 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/PortAllocator.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/PortAllocator.java @@ -47,118 +47,119 @@ */ public class PortAllocator { - public static final PortAllocator TCP = new PortAllocator(SocketType.TCP, Duration.ofSeconds(100)); - public static final PortAllocator UDP = new PortAllocator(SocketType.UDP, Duration.ofSeconds(100)); + public static final PortAllocator TCP = new PortAllocator(SocketType.TCP, Duration.ofSeconds(100)); + public static final PortAllocator UDP = new PortAllocator(SocketType.UDP, Duration.ofSeconds(100)); - private final SocketType socketType; - private final Duration timeoutDuration; - private final Map allocatedPorts = new HashMap<>(); + private final SocketType socketType; + private final Duration timeoutDuration; + private final Map allocatedPorts = new HashMap<>(); - PortAllocator(SocketType socketType, Duration timeoutDuration) { - this.socketType = socketType; - this.timeoutDuration = timeoutDuration; - } + PortAllocator(SocketType socketType, Duration timeoutDuration) { + this.socketType = socketType; + this.timeoutDuration = timeoutDuration; + } - public SortedSet allocate(String clientName, int numRequested, int minPort) { + public SortedSet allocate(String clientName, int numRequested, int minPort) { - int startPort = minPort; + int startPort = minPort; - while (!isAvailable(startPort)) { - startPort += 10; - } + while (!isAvailable(startPort)) { + startPort += 10; + } - SortedSet foundPorts = new TreeSet<>(); + SortedSet foundPorts = new TreeSet<>(); - for (int currentPort = startPort; foundPorts.size() < numRequested && currentPort < SocketUtils.PORT_RANGE_MAX - && (currentPort - startPort) < 10000; currentPort++) { - if (allocate(clientName, currentPort)) { - foundPorts.add(currentPort); - } - } + for (int currentPort = startPort; foundPorts.size() < numRequested + && currentPort < SocketUtils.PORT_RANGE_MAX + && (currentPort - startPort) < 10000; currentPort++) { + if (allocate(clientName, currentPort)) { + foundPorts.add(currentPort); + } + } - if (foundPorts.size() < numRequested) { - throw new IllegalStateException("Could not find " + numRequested + " free ports starting at " + minPort + " for " + clientName); - } + if (foundPorts.size() < numRequested) { + throw new IllegalStateException("Could not find " + numRequested + " free ports starting at " + minPort + " for " + clientName); + } - return foundPorts; - } + return foundPorts; + } - public int allocateSingle(String clientName, int minPort) { + public int allocateSingle(String clientName, int minPort) { - int startPort = minPort; + int startPort = minPort; - for (int currentPort = startPort; currentPort < SocketUtils.PORT_RANGE_MAX && (currentPort - startPort) < 10000; currentPort++) { - if (allocate(clientName, currentPort)) { - return currentPort; - } - } + for (int currentPort = startPort; currentPort < SocketUtils.PORT_RANGE_MAX && (currentPort - startPort) < 10000; currentPort++) { + if (allocate(clientName, currentPort)) { + return currentPort; + } + } - throw new IllegalStateException("Could not find free port starting at " + minPort + " for " + clientName); + throw new IllegalStateException("Could not find free port starting at " + minPort + " for " + clientName); - } + } - public void reserve(int... ports) { + public void reserve(int... ports) { - for (int port : ports) { - allocate("reserved", port); - } - } + for (int port : ports) { + allocate("reserved", port); + } + } - private boolean isInUse(int port) { - boolean result = !this.socketType.isPortAvailable(port); + private boolean isInUse(int port) { + boolean result = !this.socketType.isPortAvailable(port); - if (result) { - synchronized (this) { - allocatedPorts.put(port, new AllocatedPort("external")); - } - } + if (result) { + synchronized (this) { + allocatedPorts.put(port, new AllocatedPort("external")); + } + } - return result; - } + return result; + } - private boolean isAvailable(int port) { - return !isAllocated(port) && !isInUse(port); - } + private boolean isAvailable(int port) { + return !isAllocated(port) && !isInUse(port); + } - private synchronized boolean isAllocated(int port) { - AllocatedPort allocatedPort = this.allocatedPorts.get(port); + private synchronized boolean isAllocated(int port) { + AllocatedPort allocatedPort = this.allocatedPorts.get(port); - return allocatedPort != null && !allocatedPort.isTimedOut(); - } + return allocatedPort != null && !allocatedPort.isTimedOut(); + } - private synchronized boolean allocate(String clientName, int port) { + private synchronized boolean allocate(String clientName, int port) { - AllocatedPort allocatedPort = allocatedPorts.get(port); + AllocatedPort allocatedPort = allocatedPorts.get(port); - if (allocatedPort != null && allocatedPort.isTimedOut()) { - allocatedPort = null; - allocatedPorts.remove(port); - } + if (allocatedPort != null && allocatedPort.isTimedOut()) { + allocatedPort = null; + allocatedPorts.remove(port); + } - if (allocatedPort == null && !isInUse(port)) { - allocatedPorts.put(port, new AllocatedPort(clientName)); - return true; - } else { - return false; - } - } + if (allocatedPort == null && !isInUse(port)) { + allocatedPorts.put(port, new AllocatedPort(clientName)); + return true; + } else { + return false; + } + } - private class AllocatedPort { - final String client; - final Instant allocatedAt; + private class AllocatedPort { + final String client; + final Instant allocatedAt; - AllocatedPort(String client) { - this.client = client; - this.allocatedAt = Instant.now(); - } + AllocatedPort(String client) { + this.client = client; + this.allocatedAt = Instant.now(); + } - boolean isTimedOut() { - return allocatedAt.plus(timeoutDuration).isBefore(Instant.now()); - } + boolean isTimedOut() { + return allocatedAt.plus(timeoutDuration).isBefore(Instant.now()); + } - @Override - public String toString() { - return "AllocatedPort [client=" + client + ", allocatedAt=" + allocatedAt + "]"; - } - } + @Override + public String toString() { + return "AllocatedPort [client=" + client + ", allocatedAt=" + allocatedAt + "]"; + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/RestClientException.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/RestClientException.java index d53258f020..0023d65e98 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/RestClientException.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/RestClientException.java @@ -10,7 +10,7 @@ package org.opensearch.test.framework.cluster; public class RestClientException extends RuntimeException { - RestClientException(String message, Throwable cause) { - super(message, cause); - } + RestClientException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/SearchRequestFactory.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/SearchRequestFactory.java index 781ad4505c..b40aa9cfcb 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/SearchRequestFactory.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/SearchRequestFactory.java @@ -23,82 +23,82 @@ public final class SearchRequestFactory { - private SearchRequestFactory() { + private SearchRequestFactory() { - } + } - public static SearchRequest queryByIdsRequest(String indexName, String... ids) { - SearchRequest searchRequest = new SearchRequest(indexName); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.idsQuery().addIds(ids)); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest queryByIdsRequest(String indexName, String... ids) { + SearchRequest searchRequest = new SearchRequest(indexName); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.idsQuery().addIds(ids)); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest queryStringQueryRequest(String indexName, String queryString) { - SearchRequest searchRequest = new SearchRequest(indexName); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest queryStringQueryRequest(String indexName, String queryString) { + SearchRequest searchRequest = new SearchRequest(indexName); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest queryStringQueryRequest(String[] indicesNames, String queryString) { - SearchRequest searchRequest = new SearchRequest(indicesNames); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest queryStringQueryRequest(String[] indicesNames, String queryString) { + SearchRequest searchRequest = new SearchRequest(indicesNames); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest queryStringQueryRequest(String queryString) { - SearchRequest searchRequest = new SearchRequest(); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest queryStringQueryRequest(String queryString) { + SearchRequest searchRequest = new SearchRequest(); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.queryStringQuery(queryString)); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest searchRequestWithScroll(String indexName, int pageSize) { - SearchRequest searchRequest = new SearchRequest(indexName); - searchRequest.scroll(new TimeValue(1, MINUTES)); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.matchAllQuery()); - searchSourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC)); - searchSourceBuilder.size(pageSize); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest searchRequestWithScroll(String indexName, int pageSize) { + SearchRequest searchRequest = new SearchRequest(indexName); + searchRequest.scroll(new TimeValue(1, MINUTES)); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.matchAllQuery()); + searchSourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC)); + searchSourceBuilder.size(pageSize); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest searchAll(String...indexNames) { - SearchRequest searchRequest = new SearchRequest(indexNames); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.query(QueryBuilders.matchAllQuery()); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest searchAll(String... indexNames) { + SearchRequest searchRequest = new SearchRequest(indexNames); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(QueryBuilders.matchAllQuery()); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchScrollRequest getSearchScrollRequest(SearchResponse searchResponse) { - SearchScrollRequest scrollRequest = new SearchScrollRequest(searchResponse.getScrollId()); - scrollRequest.scroll(new TimeValue(1, MINUTES)); - return scrollRequest; - } + public static SearchScrollRequest getSearchScrollRequest(SearchResponse searchResponse) { + SearchScrollRequest scrollRequest = new SearchScrollRequest(searchResponse.getScrollId()); + scrollRequest.scroll(new TimeValue(1, MINUTES)); + return scrollRequest; + } - public static SearchRequest averageAggregationRequest(String indexName, String aggregationName, String fieldName) { - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.aggregation(AggregationBuilders.avg(aggregationName).field(fieldName)); - searchSourceBuilder.size(0); - SearchRequest searchRequest = new SearchRequest(indexName); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest averageAggregationRequest(String indexName, String aggregationName, String fieldName) { + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.aggregation(AggregationBuilders.avg(aggregationName).field(fieldName)); + searchSourceBuilder.size(0); + SearchRequest searchRequest = new SearchRequest(indexName); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } - public static SearchRequest statsAggregationRequest(String indexName, String aggregationName, String fieldName) { - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.aggregation(AggregationBuilders.stats(aggregationName).field(fieldName)); - searchSourceBuilder.size(0); - SearchRequest searchRequest = new SearchRequest(indexName); - searchRequest.source(searchSourceBuilder); - return searchRequest; - } + public static SearchRequest statsAggregationRequest(String indexName, String aggregationName, String fieldName) { + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.aggregation(AggregationBuilders.stats(aggregationName).field(fieldName)); + searchSourceBuilder.size(0); + SearchRequest searchRequest = new SearchRequest(indexName); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtils.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtils.java index 92ec47d658..5895829243 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtils.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtils.java @@ -52,261 +52,260 @@ */ public class SocketUtils { - /** - * The default minimum value for port ranges used when finding an available - * socket port. - */ - public static final int PORT_RANGE_MIN = 1024; - - /** - * The default maximum value for port ranges used when finding an available - * socket port. - */ - public static final int PORT_RANGE_MAX = 65535; - - - private static final Random random = new Random(System.currentTimeMillis()); - - - /** - * Although {@code SocketUtils} consists solely of static utility methods, - * this constructor is intentionally {@code public}. - *

Rationale

- *

Static methods from this class may be invoked from within XML - * configuration files using the Spring Expression Language (SpEL) and the - * following syntax. - *

<bean id="bean1" ... p:port="#{T(org.springframework.util.SocketUtils).findAvailableTcpPort(12000)}" />
- * If this constructor were {@code private}, you would be required to supply - * the fully qualified class name to SpEL's {@code T()} function for each usage. - * Thus, the fact that this constructor is {@code public} allows you to reduce - * boilerplate configuration with SpEL as can be seen in the following example. - *
<bean id="socketUtils" class="org.springframework.util.SocketUtils" />
-	* <bean id="bean1" ... p:port="#{socketUtils.findAvailableTcpPort(12000)}" />
-	* <bean id="bean2" ... p:port="#{socketUtils.findAvailableTcpPort(30000)}" />
- */ - public SocketUtils() { - /* no-op */ - } - - - /** - * Find an available TCP port randomly selected from the range - * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. - * @return an available TCP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableTcpPort() { - return findAvailableTcpPort(PORT_RANGE_MIN); - } - - /** - * Find an available TCP port randomly selected from the range - * [{@code minPort}, {@value #PORT_RANGE_MAX}]. - * @param minPort the minimum port number - * @return an available TCP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableTcpPort(int minPort) { - return findAvailableTcpPort(minPort, PORT_RANGE_MAX); - } - - /** - * Find an available TCP port randomly selected from the range - * [{@code minPort}, {@code maxPort}]. - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return an available TCP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableTcpPort(int minPort, int maxPort) { - return SocketType.TCP.findAvailablePort(minPort, maxPort); - } - - /** - * Find the requested number of available TCP ports, each randomly selected - * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. - * @param numRequested the number of available ports to find - * @return a sorted set of available TCP port numbers - * @throws IllegalStateException if the requested number of available ports could not be found - */ - public static SortedSet findAvailableTcpPorts(int numRequested) { - return findAvailableTcpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - /** - * Find the requested number of available TCP ports, each randomly selected - * from the range [{@code minPort}, {@code maxPort}]. - * @param numRequested the number of available ports to find - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return a sorted set of available TCP port numbers - * @throws IllegalStateException if the requested number of available ports could not be found - */ - public static SortedSet findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { - return SocketType.TCP.findAvailablePorts(numRequested, minPort, maxPort); - } - - /** - * Find an available UDP port randomly selected from the range - * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. - * @return an available UDP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableUdpPort() { - return findAvailableUdpPort(PORT_RANGE_MIN); - } - - /** - * Find an available UDP port randomly selected from the range - * [{@code minPort}, {@value #PORT_RANGE_MAX}]. - * @param minPort the minimum port number - * @return an available UDP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableUdpPort(int minPort) { - return findAvailableUdpPort(minPort, PORT_RANGE_MAX); - } - - /** - * Find an available UDP port randomly selected from the range - * [{@code minPort}, {@code maxPort}]. - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return an available UDP port number - * @throws IllegalStateException if no available port could be found - */ - public static int findAvailableUdpPort(int minPort, int maxPort) { - return SocketType.UDP.findAvailablePort(minPort, maxPort); - } - - /** - * Find the requested number of available UDP ports, each randomly selected - * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. - * @param numRequested the number of available ports to find - * @return a sorted set of available UDP port numbers - * @throws IllegalStateException if the requested number of available ports could not be found - */ - public static SortedSet findAvailableUdpPorts(int numRequested) { - return findAvailableUdpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - /** - * Find the requested number of available UDP ports, each randomly selected - * from the range [{@code minPort}, {@code maxPort}]. - * @param numRequested the number of available ports to find - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return a sorted set of available UDP port numbers - * @throws IllegalStateException if the requested number of available ports could not be found - */ - public static SortedSet findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { - return SocketType.UDP.findAvailablePorts(numRequested, minPort, maxPort); - } - - - public enum SocketType { - - TCP { - @Override - protected boolean isPortAvailable(int port) { - try { - ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket( - port, 1, InetAddress.getByName("localhost")); - serverSocket.close(); - return true; - } - catch (Exception ex) { - return false; - } - } - }, - - UDP { - @Override - protected boolean isPortAvailable(int port) { - try { - DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost")); - socket.close(); - return true; - } - catch (Exception ex) { - return false; - } - } - }; - - /** - * Determine if the specified port for this {@code SocketType} is - * currently available on {@code localhost}. - */ - protected abstract boolean isPortAvailable(int port); - - /** - * Find a pseudo-random port number within the range - * [{@code minPort}, {@code maxPort}]. - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return a random port number within the specified range - */ - private int findRandomPort(int minPort, int maxPort) { - int portRange = maxPort - minPort; - return minPort + random.nextInt(portRange + 1); - } - - /** - * Find an available port for this {@code SocketType}, randomly selected - * from the range [{@code minPort}, {@code maxPort}]. - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return an available port number for this socket type - * @throws IllegalStateException if no available port could be found - */ - int findAvailablePort(int minPort, int maxPort) { - //Assert.assertTrue(minPort > 0, "'minPort' must be greater than 0"); - //Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equal to 'minPort'"); - //Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); - - int portRange = maxPort - minPort; - int candidatePort; - int searchCounter = 0; - do { - if (searchCounter > portRange) { - throw new IllegalStateException(String.format( - "Could not find an available %s port in the range [%d, %d] after %d attempts", - name(), minPort, maxPort, searchCounter)); - } - candidatePort = findRandomPort(minPort, maxPort); - searchCounter++; - } - while (!isPortAvailable(candidatePort)); - - return candidatePort; - } - - /** - * Find the requested number of available ports for this {@code SocketType}, - * each randomly selected from the range [{@code minPort}, {@code maxPort}]. - * @param numRequested the number of available ports to find - * @param minPort the minimum port number - * @param maxPort the maximum port number - * @return a sorted set of available port numbers for this socket type - * @throws IllegalStateException if the requested number of available ports could not be found - */ - SortedSet findAvailablePorts(int numRequested, int minPort, int maxPort) { - SortedSet availablePorts = new TreeSet<>(); - int attemptCount = 0; - while ((++attemptCount <= numRequested + 100) && availablePorts.size() < numRequested) { - availablePorts.add(findAvailablePort(minPort, maxPort)); - } - - if (availablePorts.size() != numRequested) { - throw new IllegalStateException(String.format( - "Could not find %d available %s ports in the range [%d, %d]", - numRequested, name(), minPort, maxPort)); - } - - return availablePorts; - } - } + /** + * The default minimum value for port ranges used when finding an available + * socket port. + */ + public static final int PORT_RANGE_MIN = 1024; + + /** + * The default maximum value for port ranges used when finding an available + * socket port. + */ + public static final int PORT_RANGE_MAX = 65535; + + private static final Random random = new Random(System.currentTimeMillis()); + + /** + * Although {@code SocketUtils} consists solely of static utility methods, + * this constructor is intentionally {@code public}. + *

Rationale

+ *

Static methods from this class may be invoked from within XML + * configuration files using the Spring Expression Language (SpEL) and the + * following syntax. + *

<bean id="bean1" ... p:port="#{T(org.springframework.util.SocketUtils).findAvailableTcpPort(12000)}" />
+ * If this constructor were {@code private}, you would be required to supply + * the fully qualified class name to SpEL's {@code T()} function for each usage. + * Thus, the fact that this constructor is {@code public} allows you to reduce + * boilerplate configuration with SpEL as can be seen in the following example. + *
<bean id="socketUtils" class="org.springframework.util.SocketUtils" />
+    * <bean id="bean1" ... p:port="#{socketUtils.findAvailableTcpPort(12000)}" />
+    * <bean id="bean2" ... p:port="#{socketUtils.findAvailableTcpPort(30000)}" />
+ */ + public SocketUtils() { + /* no-op */ + } + + /** + * Find an available TCP port randomly selected from the range + * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableTcpPort() { + return findAvailableTcpPort(PORT_RANGE_MIN); + } + + /** + * Find an available TCP port randomly selected from the range + * [{@code minPort}, {@value #PORT_RANGE_MAX}]. + * @param minPort the minimum port number + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableTcpPort(int minPort) { + return findAvailableTcpPort(minPort, PORT_RANGE_MAX); + } + + /** + * Find an available TCP port randomly selected from the range + * [{@code minPort}, {@code maxPort}]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableTcpPort(int minPort, int maxPort) { + return SocketType.TCP.findAvailablePort(minPort, maxPort); + } + + /** + * Find the requested number of available TCP ports, each randomly selected + * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @param numRequested the number of available ports to find + * @return a sorted set of available TCP port numbers + * @throws IllegalStateException if the requested number of available ports could not be found + */ + public static SortedSet findAvailableTcpPorts(int numRequested) { + return findAvailableTcpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + /** + * Find the requested number of available TCP ports, each randomly selected + * from the range [{@code minPort}, {@code maxPort}]. + * @param numRequested the number of available ports to find + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a sorted set of available TCP port numbers + * @throws IllegalStateException if the requested number of available ports could not be found + */ + public static SortedSet findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { + return SocketType.TCP.findAvailablePorts(numRequested, minPort, maxPort); + } + + /** + * Find an available UDP port randomly selected from the range + * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @return an available UDP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableUdpPort() { + return findAvailableUdpPort(PORT_RANGE_MIN); + } + + /** + * Find an available UDP port randomly selected from the range + * [{@code minPort}, {@value #PORT_RANGE_MAX}]. + * @param minPort the minimum port number + * @return an available UDP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableUdpPort(int minPort) { + return findAvailableUdpPort(minPort, PORT_RANGE_MAX); + } + + /** + * Find an available UDP port randomly selected from the range + * [{@code minPort}, {@code maxPort}]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return an available UDP port number + * @throws IllegalStateException if no available port could be found + */ + public static int findAvailableUdpPort(int minPort, int maxPort) { + return SocketType.UDP.findAvailablePort(minPort, maxPort); + } + + /** + * Find the requested number of available UDP ports, each randomly selected + * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @param numRequested the number of available ports to find + * @return a sorted set of available UDP port numbers + * @throws IllegalStateException if the requested number of available ports could not be found + */ + public static SortedSet findAvailableUdpPorts(int numRequested) { + return findAvailableUdpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + /** + * Find the requested number of available UDP ports, each randomly selected + * from the range [{@code minPort}, {@code maxPort}]. + * @param numRequested the number of available ports to find + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a sorted set of available UDP port numbers + * @throws IllegalStateException if the requested number of available ports could not be found + */ + public static SortedSet findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { + return SocketType.UDP.findAvailablePorts(numRequested, minPort, maxPort); + } + + public enum SocketType { + + TCP { + @Override + protected boolean isPortAvailable(int port) { + try { + ServerSocket serverSocket = ServerSocketFactory.getDefault() + .createServerSocket(port, 1, InetAddress.getByName("localhost")); + serverSocket.close(); + return true; + } catch (Exception ex) { + return false; + } + } + }, + + UDP { + @Override + protected boolean isPortAvailable(int port) { + try { + DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost")); + socket.close(); + return true; + } catch (Exception ex) { + return false; + } + } + }; + + /** + * Determine if the specified port for this {@code SocketType} is + * currently available on {@code localhost}. + */ + protected abstract boolean isPortAvailable(int port); + + /** + * Find a pseudo-random port number within the range + * [{@code minPort}, {@code maxPort}]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a random port number within the specified range + */ + private int findRandomPort(int minPort, int maxPort) { + int portRange = maxPort - minPort; + return minPort + random.nextInt(portRange + 1); + } + + /** + * Find an available port for this {@code SocketType}, randomly selected + * from the range [{@code minPort}, {@code maxPort}]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return an available port number for this socket type + * @throws IllegalStateException if no available port could be found + */ + int findAvailablePort(int minPort, int maxPort) { + // Assert.assertTrue(minPort > 0, "'minPort' must be greater than 0"); + // Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equal to 'minPort'"); + // Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); + + int portRange = maxPort - minPort; + int candidatePort; + int searchCounter = 0; + do { + if (searchCounter > portRange) { + throw new IllegalStateException( + String.format( + "Could not find an available %s port in the range [%d, %d] after %d attempts", + name(), + minPort, + maxPort, + searchCounter + ) + ); + } + candidatePort = findRandomPort(minPort, maxPort); + searchCounter++; + } while (!isPortAvailable(candidatePort)); + + return candidatePort; + } + + /** + * Find the requested number of available ports for this {@code SocketType}, + * each randomly selected from the range [{@code minPort}, {@code maxPort}]. + * @param numRequested the number of available ports to find + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a sorted set of available port numbers for this socket type + * @throws IllegalStateException if the requested number of available ports could not be found + */ + SortedSet findAvailablePorts(int numRequested, int minPort, int maxPort) { + SortedSet availablePorts = new TreeSet<>(); + int attemptCount = 0; + while ((++attemptCount <= numRequested + 100) && availablePorts.size() < numRequested) { + availablePorts.add(findAvailablePort(minPort, maxPort)); + } + + if (availablePorts.size() != numRequested) { + throw new IllegalStateException( + String.format("Could not find %d available %s ports in the range [%d, %d]", numRequested, name(), minPort, maxPort) + ); + } + + return availablePorts; + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtilsTests.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtilsTests.java index 548bedbfa6..fb298c5283 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtilsTests.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/SocketUtilsTests.java @@ -55,158 +55,153 @@ */ public class SocketUtilsTests { - // TCP - - @Test - public void findAvailableTcpPort() { - int port = SocketUtils.findAvailableTcpPort(); - assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - @Test - public void findAvailableTcpPortWithMinPortEqualToMaxPort() { - int minMaxPort = SocketUtils.findAvailableTcpPort(); - int port = SocketUtils.findAvailableTcpPort(minMaxPort, minMaxPort); - assertThat(port, equalTo(minMaxPort)); - } - - @Test - public void findAvailableTcpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { - int port = SocketUtils.findAvailableTcpPort(); - try (ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("localhost"))) { - assertThat(socket, notNullValue()); - // will only look for the exact port - IllegalStateException exception = assertThrows( - IllegalStateException.class, - () -> SocketUtils.findAvailableTcpPort(port, port) - ); - assertThat(exception.getMessage(), startsWith("Could not find an available TCP port")); - assertThat(exception.getMessage(), endsWith("after 1 attempts")); - } - } - - @Test - public void findAvailableTcpPortWithMin() { - int port = SocketUtils.findAvailableTcpPort(50000); - assertPortInRange(port, 50000, PORT_RANGE_MAX); - } - - @Test - public void findAvailableTcpPortInRange() { - int minPort = 20000; - int maxPort = minPort + 1000; - int port = SocketUtils.findAvailableTcpPort(minPort, maxPort); - assertPortInRange(port, minPort, maxPort); - } - - @Test - public void find4AvailableTcpPorts() { - findAvailableTcpPorts(4); - } - - @Test - public void find50AvailableTcpPorts() { - findAvailableTcpPorts(50); - } - - @Test - public void find4AvailableTcpPortsInRange() { - findAvailableTcpPorts(4, 30000, 35000); - } - - @Test - public void find50AvailableTcpPortsInRange() { - findAvailableTcpPorts(50, 40000, 45000); - } - - // UDP - - @Test - public void findAvailableUdpPort() { - int port = SocketUtils.findAvailableUdpPort(); - assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - @Test - public void findAvailableUdpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { - int port = SocketUtils.findAvailableUdpPort(); - try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost"))) { - assertThat(socket, notNullValue()); - // will only look for the exact port - IllegalStateException exception = assertThrows( - IllegalStateException.class, - () -> SocketUtils.findAvailableUdpPort(port, port) - ); - assertThat(exception.getMessage(), startsWith("Could not find an available UDP port")); - assertThat(exception.getMessage(), endsWith("after 1 attempts")); - } - } - - @Test - public void findAvailableUdpPortWithMin() { - int port = SocketUtils.findAvailableUdpPort(50000); - assertPortInRange(port, 50000, PORT_RANGE_MAX); - } - - @Test - public void findAvailableUdpPortInRange() { - int minPort = 20000; - int maxPort = minPort + 1000; - int port = SocketUtils.findAvailableUdpPort(minPort, maxPort); - assertPortInRange(port, minPort, maxPort); - } - - @Test - public void find4AvailableUdpPorts() { - findAvailableUdpPorts(4); - } - - @Test - public void find50AvailableUdpPorts() { - findAvailableUdpPorts(50); - } - - @Test - public void find4AvailableUdpPortsInRange() { - findAvailableUdpPorts(4, 30000, 35000); - } - - @Test - public void find50AvailableUdpPortsInRange() { - findAvailableUdpPorts(50, 40000, 45000); - } - - // Helpers - - private void findAvailableTcpPorts(int numRequested) { - SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested); - assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - private void findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { - SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort); - assertAvailablePorts(ports, numRequested, minPort, maxPort); - } - - private void findAvailableUdpPorts(int numRequested) { - SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested); - assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - - private void findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { - SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested, minPort, maxPort); - assertAvailablePorts(ports, numRequested, minPort, maxPort); - } - private void assertPortInRange(int port, int minPort, int maxPort) { - assertThat("port [" + port + "] >= " + minPort, port, greaterThanOrEqualTo(minPort)); - assertThat("port [" + port + "] <= " + maxPort, port, lessThanOrEqualTo(maxPort)); - } - - private void assertAvailablePorts(SortedSet ports, int numRequested, int minPort, int maxPort) { - assertThat("number of ports requested", ports.size(), equalTo(numRequested)); - for (int port : ports) { - assertPortInRange(port, minPort, maxPort); - } - } + // TCP + + @Test + public void findAvailableTcpPort() { + int port = SocketUtils.findAvailableTcpPort(); + assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + @Test + public void findAvailableTcpPortWithMinPortEqualToMaxPort() { + int minMaxPort = SocketUtils.findAvailableTcpPort(); + int port = SocketUtils.findAvailableTcpPort(minMaxPort, minMaxPort); + assertThat(port, equalTo(minMaxPort)); + } + + @Test + public void findAvailableTcpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { + int port = SocketUtils.findAvailableTcpPort(); + try (ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("localhost"))) { + assertThat(socket, notNullValue()); + // will only look for the exact port + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> SocketUtils.findAvailableTcpPort(port, port)); + assertThat(exception.getMessage(), startsWith("Could not find an available TCP port")); + assertThat(exception.getMessage(), endsWith("after 1 attempts")); + } + } + + @Test + public void findAvailableTcpPortWithMin() { + int port = SocketUtils.findAvailableTcpPort(50000); + assertPortInRange(port, 50000, PORT_RANGE_MAX); + } + + @Test + public void findAvailableTcpPortInRange() { + int minPort = 20000; + int maxPort = minPort + 1000; + int port = SocketUtils.findAvailableTcpPort(minPort, maxPort); + assertPortInRange(port, minPort, maxPort); + } + + @Test + public void find4AvailableTcpPorts() { + findAvailableTcpPorts(4); + } + + @Test + public void find50AvailableTcpPorts() { + findAvailableTcpPorts(50); + } + + @Test + public void find4AvailableTcpPortsInRange() { + findAvailableTcpPorts(4, 30000, 35000); + } + + @Test + public void find50AvailableTcpPortsInRange() { + findAvailableTcpPorts(50, 40000, 45000); + } + + // UDP + + @Test + public void findAvailableUdpPort() { + int port = SocketUtils.findAvailableUdpPort(); + assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + @Test + public void findAvailableUdpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { + int port = SocketUtils.findAvailableUdpPort(); + try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost"))) { + assertThat(socket, notNullValue()); + // will only look for the exact port + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> SocketUtils.findAvailableUdpPort(port, port)); + assertThat(exception.getMessage(), startsWith("Could not find an available UDP port")); + assertThat(exception.getMessage(), endsWith("after 1 attempts")); + } + } + + @Test + public void findAvailableUdpPortWithMin() { + int port = SocketUtils.findAvailableUdpPort(50000); + assertPortInRange(port, 50000, PORT_RANGE_MAX); + } + + @Test + public void findAvailableUdpPortInRange() { + int minPort = 20000; + int maxPort = minPort + 1000; + int port = SocketUtils.findAvailableUdpPort(minPort, maxPort); + assertPortInRange(port, minPort, maxPort); + } + + @Test + public void find4AvailableUdpPorts() { + findAvailableUdpPorts(4); + } + + @Test + public void find50AvailableUdpPorts() { + findAvailableUdpPorts(50); + } + + @Test + public void find4AvailableUdpPortsInRange() { + findAvailableUdpPorts(4, 30000, 35000); + } + + @Test + public void find50AvailableUdpPortsInRange() { + findAvailableUdpPorts(50, 40000, 45000); + } + + // Helpers + + private void findAvailableTcpPorts(int numRequested) { + SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested); + assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + private void findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { + SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort); + assertAvailablePorts(ports, numRequested, minPort, maxPort); + } + + private void findAvailableUdpPorts(int numRequested) { + SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested); + assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + private void findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { + SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested, minPort, maxPort); + assertAvailablePorts(ports, numRequested, minPort, maxPort); + } + + private void assertPortInRange(int port, int minPort, int maxPort) { + assertThat("port [" + port + "] >= " + minPort, port, greaterThanOrEqualTo(minPort)); + assertThat("port [" + port + "] <= " + maxPort, port, lessThanOrEqualTo(maxPort)); + } + + private void assertAvailablePorts(SortedSet ports, int numRequested, int minPort, int maxPort) { + assertThat("number of ports requested", ports.size(), equalTo(numRequested)); + for (int port : ports) { + assertPortInRange(port, minPort, maxPort); + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/StartStage.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/StartStage.java index 80db4ba87a..d5dce0056a 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/StartStage.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/StartStage.java @@ -10,6 +10,6 @@ package org.opensearch.test.framework.cluster; enum StartStage { - INITIALIZED, - RETRY + INITIALIZED, + RETRY } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java index 864b8db3f1..f446cac933 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClient.java @@ -88,347 +88,353 @@ * instance from OpenSearchClientProvider. */ public class TestRestClient implements AutoCloseable { - - private static final Logger log = LogManager.getLogger(TestRestClient.class); - - private boolean enableHTTPClientSSL = true; - private boolean sendHTTPClientCertificate = false; - private InetSocketAddress nodeHttpAddress; - private RequestConfig requestConfig; - private List
headers = new ArrayList<>(); - private Header CONTENT_TYPE_JSON = new BasicHeader("Content-Type", "application/json"); - private SSLContext sslContext; - - private final InetAddress sourceInetAddress; - - public TestRestClient(InetSocketAddress nodeHttpAddress, List
headers, SSLContext sslContext, InetAddress sourceInetAddress) { - this.nodeHttpAddress = nodeHttpAddress; - this.headers.addAll(headers); - this.sslContext = sslContext; - this.sourceInetAddress = sourceInetAddress; - } - - public HttpResponse get(String path, List queryParameters, Header... headers) { - try { - URI uri = new URIBuilder(getHttpServerUri()).setPath(path).addParameters(queryParameters).build(); - return executeRequest(new HttpGet(uri), headers); - } catch (URISyntaxException ex) { - throw new RuntimeException("Incorrect URI syntax", ex); - } - } - - public HttpResponse get(String path, Header... headers) { - return get(path, Collections.emptyList(), headers); - } - - public HttpResponse getWithJsonBody(String path, String body, Header... headers) { - try { - HttpGet httpGet = new HttpGet( new URIBuilder(getHttpServerUri()).setPath(path).build()); - httpGet.setEntity(toStringEntity(body)); - return executeRequest(httpGet, mergeHeaders(CONTENT_TYPE_JSON, headers)); - } catch (URISyntaxException ex) { - throw new RuntimeException("Incorrect URI syntax", ex); - } - } - - public HttpResponse getAuthInfo( Header... headers) { - return executeRequest(new HttpGet(getHttpServerUri() + "/_opendistro/_security/authinfo?pretty"), headers); - } - - public void assertCorrectCredentials(String expectedUserName) { - HttpResponse response = getAuthInfo(); - assertThat(response, notNullValue()); - response.assertStatusCode(200); - String username = response.getTextFromJsonBody("/user_name"); - String message = String.format("Expected user name is '%s', but was '%s'", expectedUserName, username); - assertThat(message, username, equalTo(expectedUserName)); - } - - public HttpResponse head(String path, Header... headers) { - return executeRequest(new HttpHead(getHttpServerUri() + "/" + path), headers); - } - - public HttpResponse options(String path, Header... headers) { - return executeRequest(new HttpOptions(getHttpServerUri() + "/" + path), headers); - } - - public HttpResponse putJson(String path, String body, Header... headers) { - HttpPut uriRequest = new HttpPut(getHttpServerUri() + "/" + path); - uriRequest.setEntity(toStringEntity(body)); - return executeRequest(uriRequest, mergeHeaders(CONTENT_TYPE_JSON, headers)); - } - - private StringEntity toStringEntity(String body) { - return new StringEntity(body); - } - - public HttpResponse putJson(String path, ToXContentObject body) { - return putJson(path, Strings.toString(XContentType.JSON, body)); - } - - public HttpResponse put(String path) { - HttpPut uriRequest = new HttpPut(getHttpServerUri() + "/" + path); - return executeRequest(uriRequest); - } - - public HttpResponse delete(String path, Header... headers) { - return executeRequest(new HttpDelete(getHttpServerUri() + "/" + path), headers); - } - - public HttpResponse postJson(String path, String body, Header... headers) { - HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + path); - uriRequest.setEntity(toStringEntity(body)); - return executeRequest(uriRequest, mergeHeaders(CONTENT_TYPE_JSON, headers)); - } - - public HttpResponse postJson(String path, ToXContentObject body) { - return postJson(path, Strings.toString(XContentType.JSON, body)); - } - - public HttpResponse post(String path) { - HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + path); - return executeRequest(uriRequest); - } - - public HttpResponse patch(String path, String body) { - HttpPatch uriRequest = new HttpPatch(getHttpServerUri() + "/" + path); - uriRequest.setEntity(toStringEntity(body)); - return executeRequest(uriRequest, CONTENT_TYPE_JSON); - } - - public HttpResponse assignRoleToUser(String username, String roleName) { - Objects.requireNonNull(roleName, "Role name is required"); - Objects.requireNonNull(username, "User name is required"); - String body = String.format("[{\"op\":\"add\",\"path\":\"/opendistro_security_roles\",\"value\":[\"%s\"]}]", roleName); - return patch("_plugins/_security/api/internalusers/" + username, body); - } - - public HttpResponse createRole(String roleName, ToXContentObject role) { - Objects.requireNonNull(roleName, "Role name is required"); - Objects.requireNonNull(role, "Role is required"); - return putJson("_plugins/_security/api/roles/" + roleName, role); - } - - public HttpResponse createUser(String userName, ToXContentObject user) { - Objects.requireNonNull(userName, "User name is required"); - Objects.requireNonNull(user, "User is required"); - return putJson("_plugins/_security/api/internalusers/" + userName, user); - } - - public HttpResponse executeRequest(HttpUriRequest uriRequest, Header... requestSpecificHeaders) { - try(CloseableHttpClient httpClient = getHTTPClient()) { - - - if (requestSpecificHeaders != null && requestSpecificHeaders.length > 0) { - for (int i = 0; i < requestSpecificHeaders.length; i++) { - Header h = requestSpecificHeaders[i]; - uriRequest.addHeader(h); - } - } - - for (Header header : headers) { - uriRequest.addHeader(header); - } - - HttpResponse res = new HttpResponse(httpClient.execute(uriRequest)); - log.debug(res.getBody()); - return res; - } catch (IOException e) { - throw new RestClientException("Error occured during HTTP request execution", e); - } - } - - public void createRoleMapping(String backendRoleName, String roleName) { - requireNonNull(backendRoleName, "Backend role name is required"); - requireNonNull(roleName, "Role name is required"); - String path = "_plugins/_security/api/rolesmapping/" + roleName; - String body = String.format("{\"backend_roles\": [\"%s\"]}", backendRoleName); - HttpResponse response = putJson(path, body); - response.assertStatusCode(201); - } - - protected final String getHttpServerUri() { - return "http" + (enableHTTPClientSSL ? "s" : "") + "://" + nodeHttpAddress.getHostString() + ":" + nodeHttpAddress.getPort(); - } - - protected final CloseableHttpClient getHTTPClient() { - HttpRoutePlanner routePlanner = Optional.ofNullable(sourceInetAddress).map(LocalAddressRoutePlanner::new).orElse(null); - var factory = new CloseableHttpClientFactory(sslContext, requestConfig, routePlanner, null); - return factory.getHTTPClient(); - } - - private Header[] mergeHeaders(Header header, Header... headers) { - - if (headers == null || headers.length == 0) { - return new Header[] { header }; - } else { - Header[] result = new Header[headers.length + 1]; - result[0] = header; - System.arraycopy(headers, 0, result, 1, headers.length); - return result; - } - } - - public static class HttpResponse { - private final CloseableHttpResponse inner; - private final String body; - private final Header[] header; - private final int statusCode; - private final String statusReason; - - public HttpResponse(CloseableHttpResponse inner) throws IllegalStateException, IOException { - super(); - this.inner = inner; - final HttpEntity entity = inner.getEntity(); - if (entity == null) { //head request does not have a entity - this.body = ""; - } else { - this.body = IOUtils.toString(entity.getContent(), StandardCharsets.UTF_8); - } - this.header = inner.getHeaders(); - this.statusCode = inner.getCode(); - this.statusReason = inner.getReasonPhrase(); - inner.close(); - } - - public String getContentType() { - Header h = getInner().getFirstHeader("content-type"); - if (h != null) { - return h.getValue(); - } - return null; - } - - public boolean isJsonContentType() { - String ct = getContentType(); - if (ct == null) { - return false; - } - return ct.contains("application/json"); - } - - public CloseableHttpResponse getInner() { - return inner; - } - - public String getBody() { - return body; - } - - public Header[] getHeader() { - return header; - } - - public Optional
findHeader(String name) { - return Arrays.stream(header) - .filter(header -> requireNonNull(name, "Header name is mandatory.").equalsIgnoreCase(header.getName())) - .findFirst(); - } - - public Header getHeader(String name) { - return findHeader(name).orElseThrow(); - } - - public boolean containHeader(String name) { - return findHeader(name).isPresent(); - } - - public int getStatusCode() { - return statusCode; - } - - public String getStatusReason() { - return statusReason; - } - - public List
getHeaders() { - return header == null ? Collections.emptyList() : Arrays.asList(header); - } - - public String getTextFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asText(); - } - - public List getTextArrayFromJsonBody(String jsonPointer) { - return StreamSupport.stream(getJsonNodeAt(jsonPointer).spliterator(), false) - .map(JsonNode::textValue) - .collect(Collectors.toList()); - } - - public int getIntFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asInt(); - } - - public Boolean getBooleanFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asBoolean(); - } - - public Double getDoubleFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asDouble(); - } - - public Long getLongFromJsonBody(String jsonPointer) { - return getJsonNodeAt(jsonPointer).asLong(); - } - - private JsonNode getJsonNodeAt(String jsonPointer) { - try { - return toJsonNode().at(jsonPointer); - } catch (IOException e) { - throw new IllegalArgumentException("Cound not convert response body to JSON node ",e); - } - } - - private JsonNode toJsonNode() throws JsonProcessingException, IOException { - return DefaultObjectMapper.objectMapper.readTree(getBody()); - } - - - - @Override - public String toString() { - return "HttpResponse [inner=" + inner + ", body=" + body + ", header=" + Arrays.toString(header) + ", statusCode=" + statusCode - + ", statusReason=" + statusReason + "]"; - } - - public T getBodyAs(Class authInfoClass) { - try { - return DefaultObjectMapper.readValue(getBody(), authInfoClass); - } catch (IOException e) { - throw new RuntimeException("Cannot parse response body", e); - } - } - - public void assertStatusCode(int expectedHttpStatus) { - String reason = format("Expected status code is '%d', but was '%d'. Response body '%s'.", expectedHttpStatus, statusCode, body); - assertThat(reason, statusCode, equalTo(expectedHttpStatus)); - } - } - - @Override - public String toString() { - return "TestRestClient [server=" + getHttpServerUri() + ", node=" + nodeHttpAddress + "]"; - } - - public RequestConfig getRequestConfig() { - return requestConfig; - } - - public void setRequestConfig(RequestConfig requestConfig) { - this.requestConfig = requestConfig; - } - - public boolean isSendHTTPClientCertificate() { - return sendHTTPClientCertificate; - } - - public void setSendHTTPClientCertificate(boolean sendHTTPClientCertificate) { - this.sendHTTPClientCertificate = sendHTTPClientCertificate; - } - - @Override - public void close() { - // TODO: Is there anything to clean up here? - } + + private static final Logger log = LogManager.getLogger(TestRestClient.class); + + private boolean enableHTTPClientSSL = true; + private boolean sendHTTPClientCertificate = false; + private InetSocketAddress nodeHttpAddress; + private RequestConfig requestConfig; + private List
headers = new ArrayList<>(); + private Header CONTENT_TYPE_JSON = new BasicHeader("Content-Type", "application/json"); + private SSLContext sslContext; + + private final InetAddress sourceInetAddress; + + public TestRestClient(InetSocketAddress nodeHttpAddress, List
headers, SSLContext sslContext, InetAddress sourceInetAddress) { + this.nodeHttpAddress = nodeHttpAddress; + this.headers.addAll(headers); + this.sslContext = sslContext; + this.sourceInetAddress = sourceInetAddress; + } + + public HttpResponse get(String path, List queryParameters, Header... headers) { + try { + URI uri = new URIBuilder(getHttpServerUri()).setPath(path).addParameters(queryParameters).build(); + return executeRequest(new HttpGet(uri), headers); + } catch (URISyntaxException ex) { + throw new RuntimeException("Incorrect URI syntax", ex); + } + } + + public HttpResponse get(String path, Header... headers) { + return get(path, Collections.emptyList(), headers); + } + + public HttpResponse getWithJsonBody(String path, String body, Header... headers) { + try { + HttpGet httpGet = new HttpGet(new URIBuilder(getHttpServerUri()).setPath(path).build()); + httpGet.setEntity(toStringEntity(body)); + return executeRequest(httpGet, mergeHeaders(CONTENT_TYPE_JSON, headers)); + } catch (URISyntaxException ex) { + throw new RuntimeException("Incorrect URI syntax", ex); + } + } + + public HttpResponse getAuthInfo(Header... headers) { + return executeRequest(new HttpGet(getHttpServerUri() + "/_opendistro/_security/authinfo?pretty"), headers); + } + + public void assertCorrectCredentials(String expectedUserName) { + HttpResponse response = getAuthInfo(); + assertThat(response, notNullValue()); + response.assertStatusCode(200); + String username = response.getTextFromJsonBody("/user_name"); + String message = String.format("Expected user name is '%s', but was '%s'", expectedUserName, username); + assertThat(message, username, equalTo(expectedUserName)); + } + + public HttpResponse head(String path, Header... headers) { + return executeRequest(new HttpHead(getHttpServerUri() + "/" + path), headers); + } + + public HttpResponse options(String path, Header... headers) { + return executeRequest(new HttpOptions(getHttpServerUri() + "/" + path), headers); + } + + public HttpResponse putJson(String path, String body, Header... headers) { + HttpPut uriRequest = new HttpPut(getHttpServerUri() + "/" + path); + uriRequest.setEntity(toStringEntity(body)); + return executeRequest(uriRequest, mergeHeaders(CONTENT_TYPE_JSON, headers)); + } + + private StringEntity toStringEntity(String body) { + return new StringEntity(body); + } + + public HttpResponse putJson(String path, ToXContentObject body) { + return putJson(path, Strings.toString(XContentType.JSON, body)); + } + + public HttpResponse put(String path) { + HttpPut uriRequest = new HttpPut(getHttpServerUri() + "/" + path); + return executeRequest(uriRequest); + } + + public HttpResponse delete(String path, Header... headers) { + return executeRequest(new HttpDelete(getHttpServerUri() + "/" + path), headers); + } + + public HttpResponse postJson(String path, String body, Header... headers) { + HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + path); + uriRequest.setEntity(toStringEntity(body)); + return executeRequest(uriRequest, mergeHeaders(CONTENT_TYPE_JSON, headers)); + } + + public HttpResponse postJson(String path, ToXContentObject body) { + return postJson(path, Strings.toString(XContentType.JSON, body)); + } + + public HttpResponse post(String path) { + HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + path); + return executeRequest(uriRequest); + } + + public HttpResponse patch(String path, String body) { + HttpPatch uriRequest = new HttpPatch(getHttpServerUri() + "/" + path); + uriRequest.setEntity(toStringEntity(body)); + return executeRequest(uriRequest, CONTENT_TYPE_JSON); + } + + public HttpResponse assignRoleToUser(String username, String roleName) { + Objects.requireNonNull(roleName, "Role name is required"); + Objects.requireNonNull(username, "User name is required"); + String body = String.format("[{\"op\":\"add\",\"path\":\"/opendistro_security_roles\",\"value\":[\"%s\"]}]", roleName); + return patch("_plugins/_security/api/internalusers/" + username, body); + } + + public HttpResponse createRole(String roleName, ToXContentObject role) { + Objects.requireNonNull(roleName, "Role name is required"); + Objects.requireNonNull(role, "Role is required"); + return putJson("_plugins/_security/api/roles/" + roleName, role); + } + + public HttpResponse createUser(String userName, ToXContentObject user) { + Objects.requireNonNull(userName, "User name is required"); + Objects.requireNonNull(user, "User is required"); + return putJson("_plugins/_security/api/internalusers/" + userName, user); + } + + public HttpResponse executeRequest(HttpUriRequest uriRequest, Header... requestSpecificHeaders) { + try (CloseableHttpClient httpClient = getHTTPClient()) { + + if (requestSpecificHeaders != null && requestSpecificHeaders.length > 0) { + for (int i = 0; i < requestSpecificHeaders.length; i++) { + Header h = requestSpecificHeaders[i]; + uriRequest.addHeader(h); + } + } + + for (Header header : headers) { + uriRequest.addHeader(header); + } + + HttpResponse res = new HttpResponse(httpClient.execute(uriRequest)); + log.debug(res.getBody()); + return res; + } catch (IOException e) { + throw new RestClientException("Error occured during HTTP request execution", e); + } + } + + public void createRoleMapping(String backendRoleName, String roleName) { + requireNonNull(backendRoleName, "Backend role name is required"); + requireNonNull(roleName, "Role name is required"); + String path = "_plugins/_security/api/rolesmapping/" + roleName; + String body = String.format("{\"backend_roles\": [\"%s\"]}", backendRoleName); + HttpResponse response = putJson(path, body); + response.assertStatusCode(201); + } + + protected final String getHttpServerUri() { + return "http" + (enableHTTPClientSSL ? "s" : "") + "://" + nodeHttpAddress.getHostString() + ":" + nodeHttpAddress.getPort(); + } + + protected final CloseableHttpClient getHTTPClient() { + HttpRoutePlanner routePlanner = Optional.ofNullable(sourceInetAddress).map(LocalAddressRoutePlanner::new).orElse(null); + var factory = new CloseableHttpClientFactory(sslContext, requestConfig, routePlanner, null); + return factory.getHTTPClient(); + } + + private Header[] mergeHeaders(Header header, Header... headers) { + + if (headers == null || headers.length == 0) { + return new Header[] { header }; + } else { + Header[] result = new Header[headers.length + 1]; + result[0] = header; + System.arraycopy(headers, 0, result, 1, headers.length); + return result; + } + } + + public static class HttpResponse { + private final CloseableHttpResponse inner; + private final String body; + private final Header[] header; + private final int statusCode; + private final String statusReason; + + public HttpResponse(CloseableHttpResponse inner) throws IllegalStateException, IOException { + super(); + this.inner = inner; + final HttpEntity entity = inner.getEntity(); + if (entity == null) { // head request does not have a entity + this.body = ""; + } else { + this.body = IOUtils.toString(entity.getContent(), StandardCharsets.UTF_8); + } + this.header = inner.getHeaders(); + this.statusCode = inner.getCode(); + this.statusReason = inner.getReasonPhrase(); + inner.close(); + } + + public String getContentType() { + Header h = getInner().getFirstHeader("content-type"); + if (h != null) { + return h.getValue(); + } + return null; + } + + public boolean isJsonContentType() { + String ct = getContentType(); + if (ct == null) { + return false; + } + return ct.contains("application/json"); + } + + public CloseableHttpResponse getInner() { + return inner; + } + + public String getBody() { + return body; + } + + public Header[] getHeader() { + return header; + } + + public Optional
findHeader(String name) { + return Arrays.stream(header) + .filter(header -> requireNonNull(name, "Header name is mandatory.").equalsIgnoreCase(header.getName())) + .findFirst(); + } + + public Header getHeader(String name) { + return findHeader(name).orElseThrow(); + } + + public boolean containHeader(String name) { + return findHeader(name).isPresent(); + } + + public int getStatusCode() { + return statusCode; + } + + public String getStatusReason() { + return statusReason; + } + + public List
getHeaders() { + return header == null ? Collections.emptyList() : Arrays.asList(header); + } + + public String getTextFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asText(); + } + + public List getTextArrayFromJsonBody(String jsonPointer) { + return StreamSupport.stream(getJsonNodeAt(jsonPointer).spliterator(), false) + .map(JsonNode::textValue) + .collect(Collectors.toList()); + } + + public int getIntFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asInt(); + } + + public Boolean getBooleanFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asBoolean(); + } + + public Double getDoubleFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asDouble(); + } + + public Long getLongFromJsonBody(String jsonPointer) { + return getJsonNodeAt(jsonPointer).asLong(); + } + + private JsonNode getJsonNodeAt(String jsonPointer) { + try { + return toJsonNode().at(jsonPointer); + } catch (IOException e) { + throw new IllegalArgumentException("Cound not convert response body to JSON node ", e); + } + } + + private JsonNode toJsonNode() throws JsonProcessingException, IOException { + return DefaultObjectMapper.objectMapper.readTree(getBody()); + } + + @Override + public String toString() { + return "HttpResponse [inner=" + + inner + + ", body=" + + body + + ", header=" + + Arrays.toString(header) + + ", statusCode=" + + statusCode + + ", statusReason=" + + statusReason + + "]"; + } + + public T getBodyAs(Class authInfoClass) { + try { + return DefaultObjectMapper.readValue(getBody(), authInfoClass); + } catch (IOException e) { + throw new RuntimeException("Cannot parse response body", e); + } + } + + public void assertStatusCode(int expectedHttpStatus) { + String reason = format("Expected status code is '%d', but was '%d'. Response body '%s'.", expectedHttpStatus, statusCode, body); + assertThat(reason, statusCode, equalTo(expectedHttpStatus)); + } + } + + @Override + public String toString() { + return "TestRestClient [server=" + getHttpServerUri() + ", node=" + nodeHttpAddress + "]"; + } + + public RequestConfig getRequestConfig() { + return requestConfig; + } + + public void setRequestConfig(RequestConfig requestConfig) { + this.requestConfig = requestConfig; + } + + public boolean isSendHTTPClientCertificate() { + return sendHTTPClientCertificate; + } + + public void setSendHTTPClientCertificate(boolean sendHTTPClientCertificate) { + this.sendHTTPClientCertificate = sendHTTPClientCertificate; + } + + @Override + public void close() { + // TODO: Is there anything to clean up here? + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClientConfiguration.java b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClientConfiguration.java index c1f7a7a737..3b75730303 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClientConfiguration.java +++ b/src/integrationTest/java/org/opensearch/test/framework/cluster/TestRestClientConfiguration.java @@ -36,134 +36,134 @@ */ public class TestRestClientConfiguration { - /** - * Username - */ - private String username; - /** - * Password - */ - private String password; - /** - * HTTP headers which should be attached to each HTTP request which is sent by {@link TestRestClient} - */ - private final List
headers = new ArrayList<>(); - /** - * IP address of client socket of {@link TestRestClient} - */ - private InetAddress sourceInetAddress; - - /** - * Set username - * @param username username - * @return builder - */ - public TestRestClientConfiguration username(String username) { - this.username = username; - return this; - } - - /** - * Set user's password - * @param password password - * @return builder - */ - public TestRestClientConfiguration password(String password) { - this.password = password; - return this; - } - - /** - * The method sets username and password read form userCredentialsHolder - * @param userCredentialsHolder source of credentials - * @return builder - */ - public TestRestClientConfiguration credentials(UserCredentialsHolder userCredentialsHolder) { - Objects.requireNonNull(userCredentialsHolder, "User credential holder is required."); - this.username = userCredentialsHolder.getName(); - this.password = userCredentialsHolder.getPassword(); - return this; - } - - /** - * Add HTTP headers which are attached to each HTTP request - * @param headers headers - * @return builder - */ - public TestRestClientConfiguration headers(Header...headers) { - this.headers.addAll(Arrays.asList(Objects.requireNonNull(headers, "Headers are required"))); - return this; - } - /** - * Add HTTP headers which are attached to each HTTP request - * @param headers list of headers - * @return builder - */ - public TestRestClientConfiguration headers(List
headers) { - this.headers.addAll(Objects.requireNonNull(headers, "Cannot add null headers")); - return this; - } - - /** - * Add HTTP header to each request - * @param name header name - * @param value header value - * @return builder - */ - public TestRestClientConfiguration header(String name, Object value) { - return headers(new BasicHeader(name, value)); - } - - /** - * Set IP address of client socket used by {@link TestRestClient} - * @param sourceInetAddress IP address - * @return builder - */ - public TestRestClientConfiguration sourceInetAddress(InetAddress sourceInetAddress) { - this.sourceInetAddress = sourceInetAddress; - return this; - } - - public TestRestClientConfiguration sourceInetAddress(String sourceInetAddress) { - try { - this.sourceInetAddress = InetAddress.getByName(sourceInetAddress); - return this; - } catch (UnknownHostException e) { - throw new RuntimeException("Cannot get IP address for string " + sourceInetAddress, e); - } - } - - public static TestRestClientConfiguration userWithSourceIp(UserCredentialsHolder credentials, String sourceIpAddress) { - return new TestRestClientConfiguration().credentials(credentials).sourceInetAddress(sourceIpAddress); - } - - /** - * Return complete header list. Basic authentication header is created using fields {@link #username} and {@link #password} - * @return header list - */ - List
getHeaders() { - return Stream.concat(createBasicAuthHeader().stream(), headers.stream()).collect(Collectors.toList()); - } - - private Optional
createBasicAuthHeader() { - if(containsCredentials()) { - return Optional.of(getBasicAuthHeader(username, password)); - } - return Optional.empty(); - } - - private boolean containsCredentials() { - return StringUtils.isNoneBlank(username) && StringUtils.isNoneBlank(password); - } - - InetAddress getSourceInetAddress() { - return sourceInetAddress; - } - - public static Header getBasicAuthHeader(String user, String password) { - String value ="Basic " + Base64.getEncoder() - .encodeToString((user + ":" + requireNonNull(password)) - .getBytes(StandardCharsets.UTF_8)); - return new BasicHeader("Authorization", value); - } + /** + * Username + */ + private String username; + /** + * Password + */ + private String password; + /** + * HTTP headers which should be attached to each HTTP request which is sent by {@link TestRestClient} + */ + private final List
headers = new ArrayList<>(); + /** + * IP address of client socket of {@link TestRestClient} + */ + private InetAddress sourceInetAddress; + + /** + * Set username + * @param username username + * @return builder + */ + public TestRestClientConfiguration username(String username) { + this.username = username; + return this; + } + + /** + * Set user's password + * @param password password + * @return builder + */ + public TestRestClientConfiguration password(String password) { + this.password = password; + return this; + } + + /** + * The method sets username and password read form userCredentialsHolder + * @param userCredentialsHolder source of credentials + * @return builder + */ + public TestRestClientConfiguration credentials(UserCredentialsHolder userCredentialsHolder) { + Objects.requireNonNull(userCredentialsHolder, "User credential holder is required."); + this.username = userCredentialsHolder.getName(); + this.password = userCredentialsHolder.getPassword(); + return this; + } + + /** + * Add HTTP headers which are attached to each HTTP request + * @param headers headers + * @return builder + */ + public TestRestClientConfiguration headers(Header... headers) { + this.headers.addAll(Arrays.asList(Objects.requireNonNull(headers, "Headers are required"))); + return this; + } + + /** + * Add HTTP headers which are attached to each HTTP request + * @param headers list of headers + * @return builder + */ + public TestRestClientConfiguration headers(List
headers) { + this.headers.addAll(Objects.requireNonNull(headers, "Cannot add null headers")); + return this; + } + + /** + * Add HTTP header to each request + * @param name header name + * @param value header value + * @return builder + */ + public TestRestClientConfiguration header(String name, Object value) { + return headers(new BasicHeader(name, value)); + } + + /** + * Set IP address of client socket used by {@link TestRestClient} + * @param sourceInetAddress IP address + * @return builder + */ + public TestRestClientConfiguration sourceInetAddress(InetAddress sourceInetAddress) { + this.sourceInetAddress = sourceInetAddress; + return this; + } + + public TestRestClientConfiguration sourceInetAddress(String sourceInetAddress) { + try { + this.sourceInetAddress = InetAddress.getByName(sourceInetAddress); + return this; + } catch (UnknownHostException e) { + throw new RuntimeException("Cannot get IP address for string " + sourceInetAddress, e); + } + } + + public static TestRestClientConfiguration userWithSourceIp(UserCredentialsHolder credentials, String sourceIpAddress) { + return new TestRestClientConfiguration().credentials(credentials).sourceInetAddress(sourceIpAddress); + } + + /** + * Return complete header list. Basic authentication header is created using fields {@link #username} and {@link #password} + * @return header list + */ + List
getHeaders() { + return Stream.concat(createBasicAuthHeader().stream(), headers.stream()).collect(Collectors.toList()); + } + + private Optional
createBasicAuthHeader() { + if (containsCredentials()) { + return Optional.of(getBasicAuthHeader(username, password)); + } + return Optional.empty(); + } + + private boolean containsCredentials() { + return StringUtils.isNoneBlank(username) && StringUtils.isNoneBlank(password); + } + + InetAddress getSourceInetAddress() { + return sourceInetAddress; + } + + public static Header getBasicAuthHeader(String user, String password) { + String value = "Basic " + + Base64.getEncoder().encodeToString((user + ":" + requireNonNull(password)).getBytes(StandardCharsets.UTF_8)); + return new BasicHeader("Authorization", value); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/EmbeddedLDAPServer.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/EmbeddedLDAPServer.java index fd40a85292..583a0cdaeb 100755 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/EmbeddedLDAPServer.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/EmbeddedLDAPServer.java @@ -19,38 +19,38 @@ public class EmbeddedLDAPServer extends ExternalResource { - private final LdapServer server; - - private final LdifData ldifData; - - public EmbeddedLDAPServer(CertificateData trustAnchor, CertificateData ldapCertificate, LdifData ldifData) { - this.ldifData = Objects.requireNonNull(ldifData, "Ldif data is required"); - this.server = new LdapServer(trustAnchor, ldapCertificate); - } - - @Override - protected void before() { - try { - server.start(ldifData); - } catch (Exception e) { - throw new RuntimeException("Cannot start ldap server", e); - } - } - - @Override - protected void after() { - try { - server.stop(); - } catch (InterruptedException e) { - throw new RuntimeException("Cannot stop LDAP server.", e); - } - } - - public int getLdapNonTlsPort() { - return server.getLdapNonTlsPort(); - } - - public int getLdapTlsPort() { - return server.getLdapsTlsPort(); - } + private final LdapServer server; + + private final LdifData ldifData; + + public EmbeddedLDAPServer(CertificateData trustAnchor, CertificateData ldapCertificate, LdifData ldifData) { + this.ldifData = Objects.requireNonNull(ldifData, "Ldif data is required"); + this.server = new LdapServer(trustAnchor, ldapCertificate); + } + + @Override + protected void before() { + try { + server.start(ldifData); + } catch (Exception e) { + throw new RuntimeException("Cannot start ldap server", e); + } + } + + @Override + protected void after() { + try { + server.stop(); + } catch (InterruptedException e) { + throw new RuntimeException("Cannot stop LDAP server.", e); + } + } + + public int getLdapNonTlsPort() { + return server.getLdapNonTlsPort(); + } + + public int getLdapTlsPort() { + return server.getLdapsTlsPort(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdapServer.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdapServer.java index 13add742e4..18a14242cc 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdapServer.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdapServer.java @@ -52,173 +52,175 @@ * Based on class com.amazon.dlic.auth.ldap.srv.LdapServer from older tests */ final class LdapServer { - private static final Logger log = LogManager.getLogger(LdapServer.class); - - private static final int LOCK_TIMEOUT = 60; - private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; - - private static final String LOCK_TIMEOUT_MSG = "Unable to obtain lock due to timeout after " + LOCK_TIMEOUT + " " + TIME_UNIT.toString(); - private static final String SERVER_NOT_STARTED = "The LDAP server is not started."; - private static final String SERVER_ALREADY_STARTED = "The LDAP server is already started."; - - private final CertificateData trustAnchor; - - private final CertificateData ldapCertificate; - - private InMemoryDirectoryServer server; - private final AtomicBoolean isStarted = new AtomicBoolean(Boolean.FALSE); - private final ReentrantLock serverStateLock = new ReentrantLock(); - - private int ldapNonTlsPort = -1; - private int ldapTlsPort = -1; - - - public LdapServer(CertificateData trustAnchor, CertificateData ldapCertificate) { - this.trustAnchor = trustAnchor; - this.ldapCertificate = ldapCertificate; - } - - public boolean isStarted() { - return this.isStarted.get(); - } - - public int getLdapNonTlsPort() { - return ldapNonTlsPort; - } - - public int getLdapsTlsPort() { - return ldapTlsPort; - } - - public void start(LdifData ldifData) throws Exception { - Objects.requireNonNull(ldifData, "Ldif data is required"); - boolean hasLock = false; - try { - hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); - if (hasLock) { - doStart(ldifData); - this.isStarted.set(Boolean.TRUE); - } else { - throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); - } - } catch (InterruptedException ioe) { - //lock interrupted - log.error("LDAP server start lock interrupted", ioe); - throw ioe; - } finally { - if (hasLock) { - serverStateLock.unlock(); - } - } - } - - private void doStart(LdifData ldifData) throws Exception { - if (isStarted.get()) { - throw new IllegalStateException(LdapServer.SERVER_ALREADY_STARTED); - } - configureAndStartServer(ldifData); - } - - private Collection getInMemoryListenerConfigs() throws Exception { - KeyStore keyStore = createEmptyKeyStore(); - addLdapCertificatesToKeystore(keyStore); - final SSLUtil sslUtil = new SSLUtil(createKeyManager(keyStore), createTrustManagers(keyStore)); - - ldapNonTlsPort = SocketUtils.findAvailableTcpPort(); - ldapTlsPort = SocketUtils.findAvailableTcpPort(); - - Collection listenerConfigs = new ArrayList<>(); - listenerConfigs.add(InMemoryListenerConfig.createLDAPConfig("ldap", null, ldapNonTlsPort, sslUtil.createSSLSocketFactory())); - listenerConfigs.add(InMemoryListenerConfig.createLDAPSConfig("ldaps", ldapTlsPort, sslUtil.createSSLServerSocketFactory())); - return listenerConfigs; - } - - private static KeyManager[] createKeyManager(KeyStore keyStore) - throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException { - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(keyStore, null); - return keyManagerFactory.getKeyManagers(); - } - - private static TrustManager[] createTrustManagers(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException { - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(keyStore); - return trustManagerFactory.getTrustManagers(); - } - - private void addLdapCertificatesToKeystore(KeyStore keyStore) throws KeyStoreException { - keyStore.setCertificateEntry("trustAnchor", trustAnchor.certificate()); - keyStore.setKeyEntry("ldap-key", ldapCertificate.getKey(), null, new Certificate[]{ ldapCertificate.certificate()}); - } - - private static KeyStore createEmptyKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null); - return keyStore; - } - - private synchronized void configureAndStartServer(LdifData ldifData) throws Exception { - Collection listenerConfigs = getInMemoryListenerConfigs(); - - Schema schema = Schema.getDefaultStandardSchema(); - - final String rootObjectDN = ldifData.getRootDistinguishedName(); - InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(new DN(rootObjectDN)); - - config.setSchema(schema); //schema can be set on the rootDN too, per javadoc. - config.setListenerConfigs(listenerConfigs); - config.setEnforceAttributeSyntaxCompliance(false); - config.setEnforceSingleStructuralObjectClass(false); - - server = new InMemoryDirectoryServer(config); - - try { - /* Clear entries from server. */ - server.clear(); - server.startListening(); - loadLdifData(ldifData); - } catch (LDAPException ldape) { - if (ldape.getMessage().contains("java.net.BindException")) { - throw new BindException(ldape.getMessage()); - } - throw ldape; - } - - } - - public void stop() throws InterruptedException { - boolean hasLock = false; - try { - hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); - if (hasLock) { - if (!isStarted.get()) { - throw new IllegalStateException(LdapServer.SERVER_NOT_STARTED); - } - log.info("Shutting down in-Memory Ldap Server."); - server.shutDown(true); - } else { - throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); - } - } catch (InterruptedException ioe) { - //lock interrupted - log.error("Canot stop LDAP server due to interruption", ioe); - throw ioe; - } finally { - if (hasLock) { - serverStateLock.unlock(); - } - } - } - - private void loadLdifData(LdifData ldifData) throws Exception { - try (LDIFReader r = new LDIFReader(new BufferedReader(new StringReader(ldifData.getContent())))){ - Entry entry; - while ((entry = r.readEntry()) != null) { - server.add(entry); - } - } catch(Exception e) { - log.error("Cannot load data into LDAP server", e); - throw e; - } - } + private static final Logger log = LogManager.getLogger(LdapServer.class); + + private static final int LOCK_TIMEOUT = 60; + private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; + + private static final String LOCK_TIMEOUT_MSG = "Unable to obtain lock due to timeout after " + + LOCK_TIMEOUT + + " " + + TIME_UNIT.toString(); + private static final String SERVER_NOT_STARTED = "The LDAP server is not started."; + private static final String SERVER_ALREADY_STARTED = "The LDAP server is already started."; + + private final CertificateData trustAnchor; + + private final CertificateData ldapCertificate; + + private InMemoryDirectoryServer server; + private final AtomicBoolean isStarted = new AtomicBoolean(Boolean.FALSE); + private final ReentrantLock serverStateLock = new ReentrantLock(); + + private int ldapNonTlsPort = -1; + private int ldapTlsPort = -1; + + public LdapServer(CertificateData trustAnchor, CertificateData ldapCertificate) { + this.trustAnchor = trustAnchor; + this.ldapCertificate = ldapCertificate; + } + + public boolean isStarted() { + return this.isStarted.get(); + } + + public int getLdapNonTlsPort() { + return ldapNonTlsPort; + } + + public int getLdapsTlsPort() { + return ldapTlsPort; + } + + public void start(LdifData ldifData) throws Exception { + Objects.requireNonNull(ldifData, "Ldif data is required"); + boolean hasLock = false; + try { + hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); + if (hasLock) { + doStart(ldifData); + this.isStarted.set(Boolean.TRUE); + } else { + throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); + } + } catch (InterruptedException ioe) { + // lock interrupted + log.error("LDAP server start lock interrupted", ioe); + throw ioe; + } finally { + if (hasLock) { + serverStateLock.unlock(); + } + } + } + + private void doStart(LdifData ldifData) throws Exception { + if (isStarted.get()) { + throw new IllegalStateException(LdapServer.SERVER_ALREADY_STARTED); + } + configureAndStartServer(ldifData); + } + + private Collection getInMemoryListenerConfigs() throws Exception { + KeyStore keyStore = createEmptyKeyStore(); + addLdapCertificatesToKeystore(keyStore); + final SSLUtil sslUtil = new SSLUtil(createKeyManager(keyStore), createTrustManagers(keyStore)); + + ldapNonTlsPort = SocketUtils.findAvailableTcpPort(); + ldapTlsPort = SocketUtils.findAvailableTcpPort(); + + Collection listenerConfigs = new ArrayList<>(); + listenerConfigs.add(InMemoryListenerConfig.createLDAPConfig("ldap", null, ldapNonTlsPort, sslUtil.createSSLSocketFactory())); + listenerConfigs.add(InMemoryListenerConfig.createLDAPSConfig("ldaps", ldapTlsPort, sslUtil.createSSLServerSocketFactory())); + return listenerConfigs; + } + + private static KeyManager[] createKeyManager(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException, + UnrecoverableKeyException { + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, null); + return keyManagerFactory.getKeyManagers(); + } + + private static TrustManager[] createTrustManagers(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(keyStore); + return trustManagerFactory.getTrustManagers(); + } + + private void addLdapCertificatesToKeystore(KeyStore keyStore) throws KeyStoreException { + keyStore.setCertificateEntry("trustAnchor", trustAnchor.certificate()); + keyStore.setKeyEntry("ldap-key", ldapCertificate.getKey(), null, new Certificate[] { ldapCertificate.certificate() }); + } + + private static KeyStore createEmptyKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null); + return keyStore; + } + + private synchronized void configureAndStartServer(LdifData ldifData) throws Exception { + Collection listenerConfigs = getInMemoryListenerConfigs(); + + Schema schema = Schema.getDefaultStandardSchema(); + + final String rootObjectDN = ldifData.getRootDistinguishedName(); + InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(new DN(rootObjectDN)); + + config.setSchema(schema); // schema can be set on the rootDN too, per javadoc. + config.setListenerConfigs(listenerConfigs); + config.setEnforceAttributeSyntaxCompliance(false); + config.setEnforceSingleStructuralObjectClass(false); + + server = new InMemoryDirectoryServer(config); + + try { + /* Clear entries from server. */ + server.clear(); + server.startListening(); + loadLdifData(ldifData); + } catch (LDAPException ldape) { + if (ldape.getMessage().contains("java.net.BindException")) { + throw new BindException(ldape.getMessage()); + } + throw ldape; + } + + } + + public void stop() throws InterruptedException { + boolean hasLock = false; + try { + hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); + if (hasLock) { + if (!isStarted.get()) { + throw new IllegalStateException(LdapServer.SERVER_NOT_STARTED); + } + log.info("Shutting down in-Memory Ldap Server."); + server.shutDown(true); + } else { + throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); + } + } catch (InterruptedException ioe) { + // lock interrupted + log.error("Canot stop LDAP server due to interruption", ioe); + throw ioe; + } finally { + if (hasLock) { + serverStateLock.unlock(); + } + } + } + + private void loadLdifData(LdifData ldifData) throws Exception { + try (LDIFReader r = new LDIFReader(new BufferedReader(new StringReader(ldifData.getContent())))) { + Entry entry; + while ((entry = r.readEntry()) != null) { + server.add(entry); + } + } catch (Exception e) { + log.error("Cannot load data into LDAP server", e); + throw e; + } + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifBuilder.java index cea53a92f3..87f01a2bbc 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifBuilder.java @@ -19,50 +19,48 @@ public class LdifBuilder { - private static final Logger log = LogManager.getLogger(LdifBuilder.class); + private static final Logger log = LogManager.getLogger(LdifBuilder.class); - private final List records; + private final List records; - private Record root; + private Record root; - public LdifBuilder() { - this.records = new ArrayList<>(); - } + public LdifBuilder() { + this.records = new ArrayList<>(); + } - public RecordBuilder root(String distinguishedName) { - if(root != null) { - throw new IllegalStateException("Root object is already defined"); - } - return new RecordBuilder(this, distinguishedName); - } + public RecordBuilder root(String distinguishedName) { + if (root != null) { + throw new IllegalStateException("Root object is already defined"); + } + return new RecordBuilder(this, distinguishedName); + } - RecordBuilder newRecord(String distinguishedName) { - if(root == null) { - throw new IllegalStateException("Define root object first"); - } - return new RecordBuilder(this, distinguishedName); - } + RecordBuilder newRecord(String distinguishedName) { + if (root == null) { + throw new IllegalStateException("Define root object first"); + } + return new RecordBuilder(this, distinguishedName); + } - void addRecord(Record record) { - Objects.requireNonNull(record, "Cannot add null record"); - if(records.isEmpty()) { - this.root = record; - } - records.add(Objects.requireNonNull(record, "Cannot add null record")); - } + void addRecord(Record record) { + Objects.requireNonNull(record, "Cannot add null record"); + if (records.isEmpty()) { + this.root = record; + } + records.add(Objects.requireNonNull(record, "Cannot add null record")); + } - public LdifData buildLdif() { - String ldif = records.stream() - .map(record -> record.toLdifRepresentation()) - .collect(Collectors.joining("\n##########\n")); - log.debug("Built ldif file: \n{}", ldif); - return new LdifData(getRootDistinguishedName(), ldif); - } + public LdifData buildLdif() { + String ldif = records.stream().map(record -> record.toLdifRepresentation()).collect(Collectors.joining("\n##########\n")); + log.debug("Built ldif file: \n{}", ldif); + return new LdifData(getRootDistinguishedName(), ldif); + } - private String getRootDistinguishedName() { - if(root == null) { - throw new IllegalStateException("Root object is not present."); - } - return root.getDistinguishedName(); - } + private String getRootDistinguishedName() { + if (root == null) { + throw new IllegalStateException("Root object is not present."); + } + return root.getDistinguishedName(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifData.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifData.java index a0f2026b73..4a1af5bc08 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifData.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/LdifData.java @@ -11,39 +11,38 @@ import org.apache.commons.lang3.StringUtils; - /** * Value object which represents LDIF file data and some metadata. Ensure type safety. */ public class LdifData { - - private final String rootDistinguishedName; - private final String content; + private final String rootDistinguishedName; + + private final String content; - LdifData(String rootDistinguishedName, String content) { - this.rootDistinguishedName = requireNotBlank(rootDistinguishedName, "Root distinguished name is required"); - this.content = requireNotBlank(content, "Ldif file content is required"); + LdifData(String rootDistinguishedName, String content) { + this.rootDistinguishedName = requireNotBlank(rootDistinguishedName, "Root distinguished name is required"); + this.content = requireNotBlank(content, "Ldif file content is required"); - } + } - private static String requireNotBlank(String string, String message) { - if(StringUtils.isBlank(string)) { - throw new IllegalArgumentException(message); - } - return string; - } + private static String requireNotBlank(String string, String message) { + if (StringUtils.isBlank(string)) { + throw new IllegalArgumentException(message); + } + return string; + } - String getContent() { - return content; - } + String getContent() { + return content; + } - String getRootDistinguishedName() { - return rootDistinguishedName; - } + String getRootDistinguishedName() { + return rootDistinguishedName; + } - @Override - public String toString() { - return "LdifData{" + "content='" + content + '\'' + '}'; - } + @Override + public String toString() { + return "LdifData{" + "content='" + content + '\'' + '}'; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/Record.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/Record.java index 76eea1771d..48e7484777 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/Record.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/Record.java @@ -18,51 +18,50 @@ class Record { - private final String distinguishedName; + private final String distinguishedName; - private final List classes; - private final List> attributes; + private final List classes; + private final List> attributes; - public Record(String distinguishedName) { - this.distinguishedName = Objects.requireNonNull(distinguishedName, "Distinguished name is required"); - this.classes = new ArrayList<>(); - this.attributes = new ArrayList<>(); - } + public Record(String distinguishedName) { + this.distinguishedName = Objects.requireNonNull(distinguishedName, "Distinguished name is required"); + this.classes = new ArrayList<>(); + this.attributes = new ArrayList<>(); + } - public String getDistinguishedName() { - return distinguishedName; - } + public String getDistinguishedName() { + return distinguishedName; + } - public void addClass(String clazz) { - classes.add(Objects.requireNonNull(clazz, "Object class is required.")); - } + public void addClass(String clazz) { + classes.add(Objects.requireNonNull(clazz, "Object class is required.")); + } - public void addAttribute(String name, String value) { - Objects.requireNonNull(name, "Attribute name is required"); - Objects.requireNonNull(value, "Attribute value is required"); - attributes.add(Pair.of(name, value)); - } + public void addAttribute(String name, String value) { + Objects.requireNonNull(name, "Attribute name is required"); + Objects.requireNonNull(value, "Attribute value is required"); + attributes.add(Pair.of(name, value)); + } - boolean isValid() { - return classes.size() > 0; - } + boolean isValid() { + return classes.size() > 0; + } - String toLdifRepresentation() { - return new StringBuilder("dn: ").append(distinguishedName).append("\n") - .append(formattedClasses()).append("\n") - .append(formattedAttributes()).append("\n") - .toString(); - } + String toLdifRepresentation() { + return new StringBuilder("dn: ").append(distinguishedName) + .append("\n") + .append(formattedClasses()) + .append("\n") + .append(formattedAttributes()) + .append("\n") + .toString(); + } - private String formattedAttributes() { - return attributes.stream() - .map(pair -> pair.getKey() + ": " + pair.getValue()) - .collect(Collectors.joining("\n")); - } + private String formattedAttributes() { + return attributes.stream().map(pair -> pair.getKey() + ": " + pair.getValue()).collect(Collectors.joining("\n")); + } - private String formattedClasses() { - return classes.stream() - .map(clazz -> "objectClass: " + clazz) - .collect(Collectors.joining("\n")); - } + private String formattedClasses() { + return classes.stream().map(clazz -> "objectClass: " + clazz).collect(Collectors.joining("\n")); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/ldap/RecordBuilder.java b/src/integrationTest/java/org/opensearch/test/framework/ldap/RecordBuilder.java index a54caef2af..1df27c72fe 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/ldap/RecordBuilder.java +++ b/src/integrationTest/java/org/opensearch/test/framework/ldap/RecordBuilder.java @@ -13,80 +13,80 @@ public class RecordBuilder { - private final LdifBuilder builder; - private final Record record; - - RecordBuilder(LdifBuilder builder, String distinguishedName) { - this.builder = Objects.requireNonNull(builder, "LdifBuilder is required"); - this.record = new Record(distinguishedName); - } - - public RecordBuilder classes(String...classes) { - for(String clazz : classes) { - this.record.addClass(clazz); - } - return this; - } - - public RecordBuilder dn(String distinguishedName) { - record.addAttribute("dn", distinguishedName); - return this; - } - - public RecordBuilder dc(String domainComponent) { - record.addAttribute("dc", domainComponent); - return this; - } - - public RecordBuilder ou(String organizationUnit) { - record.addAttribute("ou", organizationUnit); - return this; - } - - public RecordBuilder cn(String commonName) { - record.addAttribute("cn", commonName); - return this; - } - - public RecordBuilder sn(String surname) { - record.addAttribute("sn", surname); - return this; - } - - public RecordBuilder uid(String userId) { - record.addAttribute("uid", userId); - return this; - } - - public RecordBuilder userPassword(String password) { - record.addAttribute("userpassword", password); - return this; - } - - public RecordBuilder mail(String emailAddress) { - record.addAttribute("mail", emailAddress); - return this; - } - - public RecordBuilder uniqueMember(String userDistinguishedName) { - record.addAttribute("uniquemember", userDistinguishedName); - return this; - } - - public RecordBuilder attribute(String name, String value) { - record.addAttribute(name, value); - return this; - } - - public LdifBuilder buildRecord() { - if(record.isValid() == false) { - throw new IllegalStateException("Record is invalid"); - } - builder.addRecord(record); - return builder; - } - - public RecordBuilder newRecord(String distinguishedName) { - return buildRecord().newRecord(distinguishedName); - } + private final LdifBuilder builder; + private final Record record; + + RecordBuilder(LdifBuilder builder, String distinguishedName) { + this.builder = Objects.requireNonNull(builder, "LdifBuilder is required"); + this.record = new Record(distinguishedName); + } + + public RecordBuilder classes(String... classes) { + for (String clazz : classes) { + this.record.addClass(clazz); + } + return this; + } + + public RecordBuilder dn(String distinguishedName) { + record.addAttribute("dn", distinguishedName); + return this; + } + + public RecordBuilder dc(String domainComponent) { + record.addAttribute("dc", domainComponent); + return this; + } + + public RecordBuilder ou(String organizationUnit) { + record.addAttribute("ou", organizationUnit); + return this; + } + + public RecordBuilder cn(String commonName) { + record.addAttribute("cn", commonName); + return this; + } + + public RecordBuilder sn(String surname) { + record.addAttribute("sn", surname); + return this; + } + + public RecordBuilder uid(String userId) { + record.addAttribute("uid", userId); + return this; + } + + public RecordBuilder userPassword(String password) { + record.addAttribute("userpassword", password); + return this; + } + + public RecordBuilder mail(String emailAddress) { + record.addAttribute("mail", emailAddress); + return this; + } + + public RecordBuilder uniqueMember(String userDistinguishedName) { + record.addAttribute("uniquemember", userDistinguishedName); + return this; + } + + public RecordBuilder attribute(String name, String value) { + record.addAttribute(name, value); + return this; + } + + public LdifBuilder buildRecord() { + if (record.isValid() == false) { + throw new IllegalStateException("Record is invalid"); + } + builder.addRecord(record); + return builder; + } + + public RecordBuilder newRecord(String distinguishedName) { + return buildRecord().newRecord(distinguishedName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/log/LogCapturingAppender.java b/src/integrationTest/java/org/opensearch/test/framework/log/LogCapturingAppender.java index e0baec9cb2..63765dfd14 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/log/LogCapturingAppender.java +++ b/src/integrationTest/java/org/opensearch/test/framework/log/LogCapturingAppender.java @@ -47,84 +47,89 @@ @Plugin(name = PLUGIN_NAME, category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) public class LogCapturingAppender extends AbstractAppender { - public final static String PLUGIN_NAME = "LogCapturingAppender"; - /** - * Appender stores only last MAX_SIZE messages to avoid excessive RAM memory usage. - */ - public static final int MAX_SIZE = 100; + public final static String PLUGIN_NAME = "LogCapturingAppender"; + /** + * Appender stores only last MAX_SIZE messages to avoid excessive RAM memory usage. + */ + public static final int MAX_SIZE = 100; - /** - * Buffer for captured log messages - */ - private static final Buffer messages = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(MAX_SIZE)); + /** + * Buffer for captured log messages + */ + private static final Buffer messages = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(MAX_SIZE)); - /** - * Log messages are stored in buffer {@link #messages} only for classes which are added to the {@link #activeLoggers} set. - */ - private static final Set activeLoggers = Collections.synchronizedSet(new HashSet<>()); + /** + * Log messages are stored in buffer {@link #messages} only for classes which are added to the {@link #activeLoggers} set. + */ + private static final Set activeLoggers = Collections.synchronizedSet(new HashSet<>()); - protected LogCapturingAppender(String name, Filter filter, Layout layout, boolean ignoreExceptions, Property[] properties) { - super(name, filter, layout, ignoreExceptions, properties); - } + protected LogCapturingAppender( + String name, + Filter filter, + Layout layout, + boolean ignoreExceptions, + Property[] properties + ) { + super(name, filter, layout, ignoreExceptions, properties); + } - /** - * Method used by Log4j2 to create appender - * @param name appender name from Log4j2 configuration - * @return newly created appender - */ - @PluginFactory - public static LogCapturingAppender createAppender(@PluginAttribute(value = "name", defaultString = "logCapturingAppender") String name) { - return new LogCapturingAppender(name, null, null, true, Property.EMPTY_ARRAY); - } + /** + * Method used by Log4j2 to create appender + * @param name appender name from Log4j2 configuration + * @return newly created appender + */ + @PluginFactory + public static LogCapturingAppender createAppender( + @PluginAttribute(value = "name", defaultString = "logCapturingAppender") String name + ) { + return new LogCapturingAppender(name, null, null, true, Property.EMPTY_ARRAY); + } - /** - * Method invoked by Log4j2 to append log events - * @param event The LogEvent, represents log message. - */ - @Override - public void append(LogEvent event) { - String loggerName = event.getLoggerName(); - boolean loggable = activeLoggers.contains(loggerName); - if(loggable) { - event.getThrown(); - messages.add(new LogMessage(event.getMessage().getFormattedMessage(), event.getThrown())); - } - } + /** + * Method invoked by Log4j2 to append log events + * @param event The LogEvent, represents log message. + */ + @Override + public void append(LogEvent event) { + String loggerName = event.getLoggerName(); + boolean loggable = activeLoggers.contains(loggerName); + if (loggable) { + event.getThrown(); + messages.add(new LogMessage(event.getMessage().getFormattedMessage(), event.getThrown())); + } + } - /** - * To collect log messages form given logger the logger name must be passed to {@link #enable(String...)} method. - * @param loggerNames logger names - */ - public static void enable(String...loggerNames) { - disable(); - activeLoggers.addAll(Arrays.asList(loggerNames)); - } + /** + * To collect log messages form given logger the logger name must be passed to {@link #enable(String...)} method. + * @param loggerNames logger names + */ + public static void enable(String... loggerNames) { + disable(); + activeLoggers.addAll(Arrays.asList(loggerNames)); + } - /** - * Invocation cause that appender stops collecting log messages. Additionally, memory used by collected messages so far is released. - */ - public static void disable() { - activeLoggers.clear(); - messages.clear(); - } + /** + * Invocation cause that appender stops collecting log messages. Additionally, memory used by collected messages so far is released. + */ + public static void disable() { + activeLoggers.clear(); + messages.clear(); + } - /** - * Is used to obtain gathered log messages - * @return Log messages - */ - public static List getLogMessages() { - return new ArrayList<>(messages); - } + /** + * Is used to obtain gathered log messages + * @return Log messages + */ + public static List getLogMessages() { + return new ArrayList<>(messages); + } - public static List getLogMessagesAsString() { - return getLogMessages() - .stream() - .map(LogMessage::getMessage) - .collect(Collectors.toList()); - } + public static List getLogMessagesAsString() { + return getLogMessages().stream().map(LogMessage::getMessage).collect(Collectors.toList()); + } - @Override - public String toString() { - return "LogCapturingAppender{}"; - } + @Override + public String toString() { + return "LogCapturingAppender{}"; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/log/LogMessage.java b/src/integrationTest/java/org/opensearch/test/framework/log/LogMessage.java index 327e91c759..9342c7ee30 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/log/LogMessage.java +++ b/src/integrationTest/java/org/opensearch/test/framework/log/LogMessage.java @@ -16,25 +16,25 @@ class LogMessage { - private final String message; - private final String stackTrace; - - public LogMessage(String message, Throwable throwable) { - this.message = message; - this.stackTrace = Optional.ofNullable(throwable).map(ExceptionUtils::getStackTrace).orElse(""); - } - - public boolean containMessage(String expectedMessage) { - Objects.requireNonNull(expectedMessage, "Expected message must not be null."); - return expectedMessage.equals(message); - } - - public boolean stackTraceContains(String stackTraceFragment) { - Objects.requireNonNull(stackTraceFragment, "Stack trace fragment is required."); - return stackTrace.contains(stackTraceFragment); - } - - public String getMessage() { - return message; - } + private final String message; + private final String stackTrace; + + public LogMessage(String message, Throwable throwable) { + this.message = message; + this.stackTrace = Optional.ofNullable(throwable).map(ExceptionUtils::getStackTrace).orElse(""); + } + + public boolean containMessage(String expectedMessage) { + Objects.requireNonNull(expectedMessage, "Expected message must not be null."); + return expectedMessage.equals(message); + } + + public boolean stackTraceContains(String stackTraceFragment) { + Objects.requireNonNull(stackTraceFragment, "Stack trace fragment is required."); + return stackTrace.contains(stackTraceFragment); + } + + public String getMessage() { + return message; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/log/LogsRule.java b/src/integrationTest/java/org/opensearch/test/framework/log/LogsRule.java index c2dfabf537..46fa252df4 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/log/LogsRule.java +++ b/src/integrationTest/java/org/opensearch/test/framework/log/LogsRule.java @@ -27,66 +27,67 @@ */ public class LogsRule extends ExternalResource { - private final String[] loggerNames; + private final String[] loggerNames; - /** - * Constructor used to start gathering log messages from certain loggers - * @param loggerNames Loggers names. Log messages are collected only if the log message is associated with the logger with a name which - * is present in loggerNames parameter. - */ - public LogsRule(String...loggerNames) { - this.loggerNames = Objects.requireNonNull(loggerNames, "Logger names are required"); - } + /** + * Constructor used to start gathering log messages from certain loggers + * @param loggerNames Loggers names. Log messages are collected only if the log message is associated with the logger with a name which + * is present in loggerNames parameter. + */ + public LogsRule(String... loggerNames) { + this.loggerNames = Objects.requireNonNull(loggerNames, "Logger names are required"); + } - @Override - protected void before() { - LogCapturingAppender.enable(loggerNames); - } + @Override + protected void before() { + LogCapturingAppender.enable(loggerNames); + } - @Override - protected void after() { - LogCapturingAppender.disable(); - } + @Override + protected void after() { + LogCapturingAppender.disable(); + } - /** - * Check if during the tests certain log message was logged - * @param expectedLogMessage expected log message - */ - public void assertThatContainExactly(String expectedLogMessage) { - List messages = LogCapturingAppender.getLogMessagesAsString(); - String reason = reasonMessage(expectedLogMessage, messages); - assertThat(reason, messages, hasItem(expectedLogMessage)); - } + /** + * Check if during the tests certain log message was logged + * @param expectedLogMessage expected log message + */ + public void assertThatContainExactly(String expectedLogMessage) { + List messages = LogCapturingAppender.getLogMessagesAsString(); + String reason = reasonMessage(expectedLogMessage, messages); + assertThat(reason, messages, hasItem(expectedLogMessage)); + } - /** - * Check if during the tests certain log message was logged - * @param messageFragment expected log message fragment - */ - public void assertThatContain(String messageFragment) { - List messages = LogCapturingAppender.getLogMessagesAsString();; - String reason = reasonMessage(messageFragment, messages); - assertThat(reason, messages, hasItem(containsString(messageFragment))); - } + /** + * Check if during the tests certain log message was logged + * @param messageFragment expected log message fragment + */ + public void assertThatContain(String messageFragment) { + List messages = LogCapturingAppender.getLogMessagesAsString(); + ; + String reason = reasonMessage(messageFragment, messages); + assertThat(reason, messages, hasItem(containsString(messageFragment))); + } - /** - * Check if during the tests a stack trace was logged which contain given fragment - * @param stackTraceFragment stack trace fragment - */ - public void assertThatStackTraceContain(String stackTraceFragment) { - long count = LogCapturingAppender.getLogMessages() - .stream() - .filter(logMessage -> logMessage.stackTraceContains(stackTraceFragment)) - .count(); - String reason = "Stack trace does not contain element " + stackTraceFragment; - assertThat(reason, count, greaterThan(0L)); - } + /** + * Check if during the tests a stack trace was logged which contain given fragment + * @param stackTraceFragment stack trace fragment + */ + public void assertThatStackTraceContain(String stackTraceFragment) { + long count = LogCapturingAppender.getLogMessages() + .stream() + .filter(logMessage -> logMessage.stackTraceContains(stackTraceFragment)) + .count(); + String reason = "Stack trace does not contain element " + stackTraceFragment; + assertThat(reason, count, greaterThan(0L)); + } - private static String reasonMessage(String expectedLogMessage, List messages) { - String concatenatedLogMessages = messages.stream() - .map(message -> String.format("'%s'", message)) - .collect(Collectors.joining(", ")); - return String.format("Expected message '%s' has not been found in logs. All captured log messages: %s", - expectedLogMessage, - concatenatedLogMessages); - } + private static String reasonMessage(String expectedLogMessage, List messages) { + String concatenatedLogMessages = messages.stream().map(message -> String.format("'%s'", message)).collect(Collectors.joining(", ")); + return String.format( + "Expected message '%s' has not been found in logs. All captured log messages: %s", + expectedLogMessage, + concatenatedLogMessages + ); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/AliasExistsMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/AliasExistsMatcher.java index 4d8c81b037..42723168ff 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/AliasExistsMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/AliasExistsMatcher.java @@ -31,37 +31,36 @@ class AliasExistsMatcher extends TypeSafeDiagnosingMatcher { - private final String aliasName; + private final String aliasName; - public AliasExistsMatcher(String aliasName) { - this.aliasName = requireNonNull(aliasName, "Alias name is required"); - } + public AliasExistsMatcher(String aliasName) { + this.aliasName = requireNonNull(aliasName, "Alias name is required"); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - GetAliasesResponse response = client.admin().indices().getAliases(new GetAliasesRequest(aliasName)).get(); + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetAliasesResponse response = client.admin().indices().getAliases(new GetAliasesRequest(aliasName)).get(); - Map> aliases = response.getAliases(); - Set actualAliasNames = StreamSupport.stream(spliteratorUnknownSize(aliases.values().iterator(), IMMUTABLE), false) - .flatMap(Collection::stream) - .map(AliasMetadata::getAlias) - .collect(Collectors.toSet()); - if(actualAliasNames.contains(aliasName) == false) { - String existingAliases = String.join(", ", actualAliasNames); - mismatchDescription.appendText(" alias does not exist, defined aliases ").appendValue(existingAliases); - return false; - } - return true; - } catch (InterruptedException | ExecutionException e) { - mismatchDescription.appendText("Error occurred during checking if cluster contains alias ") - .appendValue(e); - return false; - } - } + Map> aliases = response.getAliases(); + Set actualAliasNames = StreamSupport.stream(spliteratorUnknownSize(aliases.values().iterator(), IMMUTABLE), false) + .flatMap(Collection::stream) + .map(AliasMetadata::getAlias) + .collect(Collectors.toSet()); + if (actualAliasNames.contains(aliasName) == false) { + String existingAliases = String.join(", ", actualAliasNames); + mismatchDescription.appendText(" alias does not exist, defined aliases ").appendValue(existingAliases); + return false; + } + return true; + } catch (InterruptedException | ExecutionException e) { + mismatchDescription.appendText("Error occurred during checking if cluster contains alias ").appendValue(e); + return false; + } + } - @Override - public void describeTo(Description description) { - description.appendText("Cluster should contain ").appendValue(aliasName).appendText(" alias"); - } + @Override + public void describeTo(Description description) { + description.appendText("Cluster should contain ").appendValue(aliasName).appendText(" alias"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/AtLeastCertainNumberOfAuditsFulfillPredicateMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/AtLeastCertainNumberOfAuditsFulfillPredicateMatcher.java index 922917bc21..ba7feed4c3 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/AtLeastCertainNumberOfAuditsFulfillPredicateMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/AtLeastCertainNumberOfAuditsFulfillPredicateMatcher.java @@ -18,27 +18,31 @@ class AtLeastCertainNumberOfAuditsFulfillPredicateMatcher extends AuditsFulfillPredicateMatcher { - private final long minimumNumberOfAudits; - - public AtLeastCertainNumberOfAuditsFulfillPredicateMatcher(Predicate predicate, long minimumNumberOfAudits) { - super(predicate); - this.minimumNumberOfAudits = minimumNumberOfAudits; - } - - @Override - protected boolean matchesSafely(List audits, Description mismatchDescription) { - long count = countAuditsWhichMatchPredicate(audits); - if(count < minimumNumberOfAudits) { - mismatchDescription.appendText(" only ").appendValue(count).appendText(" match predicate. Examined audit logs ") - .appendText(auditMessagesToString(audits)); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Al least ").appendValue(minimumNumberOfAudits).appendText(" audits records should match predicate ") - .appendValue(predicate); - } + private final long minimumNumberOfAudits; + + public AtLeastCertainNumberOfAuditsFulfillPredicateMatcher(Predicate predicate, long minimumNumberOfAudits) { + super(predicate); + this.minimumNumberOfAudits = minimumNumberOfAudits; + } + + @Override + protected boolean matchesSafely(List audits, Description mismatchDescription) { + long count = countAuditsWhichMatchPredicate(audits); + if (count < minimumNumberOfAudits) { + mismatchDescription.appendText(" only ") + .appendValue(count) + .appendText(" match predicate. Examined audit logs ") + .appendText(auditMessagesToString(audits)); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Al least ") + .appendValue(minimumNumberOfAudits) + .appendText(" audits records should match predicate ") + .appendValue(predicate); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditMessageMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditMessageMatchers.java index f15750259f..080d4473e1 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditMessageMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditMessageMatchers.java @@ -18,15 +18,21 @@ public class AuditMessageMatchers { - private AuditMessageMatchers() { - - } - - public static Matcher> exactNumberOfAuditsFulfillPredicate(long exactNumberOfAuditMessages, Predicate predicate) { - return new ExactNumberOfAuditsFulfillPredicateMatcher(exactNumberOfAuditMessages, predicate); - } - - public static Matcher> atLeastCertainNumberOfAuditsFulfillPredicate(long minimumNumberOfAudits, Predicate predicate) { - return new AtLeastCertainNumberOfAuditsFulfillPredicateMatcher(predicate, minimumNumberOfAudits); - } + private AuditMessageMatchers() { + + } + + public static Matcher> exactNumberOfAuditsFulfillPredicate( + long exactNumberOfAuditMessages, + Predicate predicate + ) { + return new ExactNumberOfAuditsFulfillPredicateMatcher(exactNumberOfAuditMessages, predicate); + } + + public static Matcher> atLeastCertainNumberOfAuditsFulfillPredicate( + long minimumNumberOfAudits, + Predicate predicate + ) { + return new AtLeastCertainNumberOfAuditsFulfillPredicateMatcher(predicate, minimumNumberOfAudits); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditsFulfillPredicateMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditsFulfillPredicateMatcher.java index e73267b452..2864c1df81 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditsFulfillPredicateMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/AuditsFulfillPredicateMatcher.java @@ -19,18 +19,18 @@ abstract class AuditsFulfillPredicateMatcher extends TypeSafeDiagnosingMatcher> { - protected final Predicate predicate; + protected final Predicate predicate; - public AuditsFulfillPredicateMatcher(Predicate predicate) { - this.predicate = predicate; - } + public AuditsFulfillPredicateMatcher(Predicate predicate) { + this.predicate = predicate; + } - protected String auditMessagesToString(List audits) { - return audits.stream().map(AuditMessage::toString).collect(Collectors.joining(",\n")); - } + protected String auditMessagesToString(List audits) { + return audits.stream().map(AuditMessage::toString).collect(Collectors.joining(",\n")); + } - protected long countAuditsWhichMatchPredicate(List audits) { - return audits.stream().filter(predicate).count(); - } + protected long countAuditsWhichMatchPredicate(List audits) { + return audits.stream().filter(predicate).count(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsAtIndexMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsAtIndexMatcher.java index d0b7e64673..2fb2cc5e74 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsAtIndexMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsAtIndexMatcher.java @@ -20,51 +20,57 @@ class BulkResponseContainExceptionsAtIndexMatcher extends TypeSafeDiagnosingMatcher { - private final int errorIndex; - private final Matcher exceptionMatcher; + private final int errorIndex; + private final Matcher exceptionMatcher; - public BulkResponseContainExceptionsAtIndexMatcher(int errorIndex, Matcher exceptionMatcher) { - this.errorIndex = errorIndex; - this.exceptionMatcher = requireNonNull(exceptionMatcher, "Exception matcher is required."); - } + public BulkResponseContainExceptionsAtIndexMatcher(int errorIndex, Matcher exceptionMatcher) { + this.errorIndex = errorIndex; + this.exceptionMatcher = requireNonNull(exceptionMatcher, "Exception matcher is required."); + } - @Override - protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { - if(response.hasFailures() == false) { - mismatchDescription.appendText("received successful bulk response what is not expected."); - return false; - } - BulkItemResponse[] items = response.getItems(); - if((items == null) || (items.length == 0) || (errorIndex >= items.length)) { - mismatchDescription.appendText("bulk response does not contain item with index ").appendValue(errorIndex); - return false; - } - BulkItemResponse item = items[errorIndex]; - if(item == null) { - mismatchDescription.appendText("bulk item response with index ").appendValue(errorIndex).appendText(" is null."); - return false; - } - BulkItemResponse.Failure failure = item.getFailure(); - if(failure == null) { - mismatchDescription.appendText("bulk response item with index ").appendValue(errorIndex).appendText(" does not contain failure"); - return false; - } - Exception exception = failure.getCause(); - if(exception == null) { - mismatchDescription.appendText("bulk response item with index ").appendValue(errorIndex).appendText(" does not contain exception."); - return false; - } - if(exceptionMatcher.matches(exception) == false) { - mismatchDescription.appendText("bulk response item with index ").appendValue(errorIndex) - .appendText(" contains incorrect exception which is ").appendValue(exception); - return false; - } + @Override + protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { + if (response.hasFailures() == false) { + mismatchDescription.appendText("received successful bulk response what is not expected."); + return false; + } + BulkItemResponse[] items = response.getItems(); + if ((items == null) || (items.length == 0) || (errorIndex >= items.length)) { + mismatchDescription.appendText("bulk response does not contain item with index ").appendValue(errorIndex); + return false; + } + BulkItemResponse item = items[errorIndex]; + if (item == null) { + mismatchDescription.appendText("bulk item response with index ").appendValue(errorIndex).appendText(" is null."); + return false; + } + BulkItemResponse.Failure failure = item.getFailure(); + if (failure == null) { + mismatchDescription.appendText("bulk response item with index ") + .appendValue(errorIndex) + .appendText(" does not contain failure"); + return false; + } + Exception exception = failure.getCause(); + if (exception == null) { + mismatchDescription.appendText("bulk response item with index ") + .appendValue(errorIndex) + .appendText(" does not contain exception."); + return false; + } + if (exceptionMatcher.matches(exception) == false) { + mismatchDescription.appendText("bulk response item with index ") + .appendValue(errorIndex) + .appendText(" contains incorrect exception which is ") + .appendValue(exception); + return false; + } - return true; - } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("bulk response should contain exceptions which indicate failure"); - } + @Override + public void describeTo(Description description) { + description.appendText("bulk response should contain exceptions which indicate failure"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsMatcher.java index 646a2aad93..b5e46ba9e2 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseContainExceptionsMatcher.java @@ -20,50 +20,52 @@ class BulkResponseContainExceptionsMatcher extends TypeSafeDiagnosingMatcher { - private final Matcher exceptionMatcher; + private final Matcher exceptionMatcher; - public BulkResponseContainExceptionsMatcher(Matcher exceptionMatcher) { - this.exceptionMatcher = requireNonNull(exceptionMatcher, "Exception matcher is required."); - } + public BulkResponseContainExceptionsMatcher(Matcher exceptionMatcher) { + this.exceptionMatcher = requireNonNull(exceptionMatcher, "Exception matcher is required."); + } - @Override - protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { - if(response.hasFailures() == false) { - mismatchDescription.appendText("received successful bulk response what is not expected."); - return false; - } - BulkItemResponse[] items = response.getItems(); - if((items == null) || (items.length == 0)) { - mismatchDescription.appendText("bulk response does not contain items ").appendValue(items); - return false; - } - for(int i = 0 ; i < items.length; ++i) { - BulkItemResponse item = items[i]; - if(item == null) { - mismatchDescription.appendText("bulk item response with index ").appendValue(i).appendText(" is null."); - return false; - } - BulkItemResponse.Failure failure = item.getFailure(); - if(failure == null) { - mismatchDescription.appendText("bulk response item with index ").appendValue(i).appendText(" does not contain failure"); - return false; - } - Exception exception = failure.getCause(); - if(exception == null) { - mismatchDescription.appendText("bulk response item with index ").appendValue(i).appendText(" does not contain exception."); - return false; - } - if(exceptionMatcher.matches(exception) == false) { - mismatchDescription.appendText("bulk response item with index ").appendValue(i) - .appendText(" contains incorrect exception which is ").appendValue(exception); - return false; - } - } - return true; - } + @Override + protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { + if (response.hasFailures() == false) { + mismatchDescription.appendText("received successful bulk response what is not expected."); + return false; + } + BulkItemResponse[] items = response.getItems(); + if ((items == null) || (items.length == 0)) { + mismatchDescription.appendText("bulk response does not contain items ").appendValue(items); + return false; + } + for (int i = 0; i < items.length; ++i) { + BulkItemResponse item = items[i]; + if (item == null) { + mismatchDescription.appendText("bulk item response with index ").appendValue(i).appendText(" is null."); + return false; + } + BulkItemResponse.Failure failure = item.getFailure(); + if (failure == null) { + mismatchDescription.appendText("bulk response item with index ").appendValue(i).appendText(" does not contain failure"); + return false; + } + Exception exception = failure.getCause(); + if (exception == null) { + mismatchDescription.appendText("bulk response item with index ").appendValue(i).appendText(" does not contain exception."); + return false; + } + if (exceptionMatcher.matches(exception) == false) { + mismatchDescription.appendText("bulk response item with index ") + .appendValue(i) + .appendText(" contains incorrect exception which is ") + .appendValue(exception); + return false; + } + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("bulk response should contain exceptions which indicate failure"); - } + @Override + public void describeTo(Description description) { + description.appendText("bulk response should contain exceptions which indicate failure"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseMatchers.java index 4a72a67aba..eedcd3a3a0 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/BulkResponseMatchers.java @@ -13,25 +13,25 @@ import org.opensearch.action.bulk.BulkResponse; -public class BulkResponseMatchers { +public class BulkResponseMatchers { - private BulkResponseMatchers(){ + private BulkResponseMatchers() { - } + } - public static Matcher successBulkResponse() { - return new SuccessBulkResponseMatcher(); - } + public static Matcher successBulkResponse() { + return new SuccessBulkResponseMatcher(); + } - public static Matcher failureBulkResponse() { - return new FailureBulkResponseMatcher(); - } + public static Matcher failureBulkResponse() { + return new FailureBulkResponseMatcher(); + } - public static Matcher bulkResponseContainExceptions(Matcher exceptionMatcher) { - return new BulkResponseContainExceptionsMatcher(exceptionMatcher); - } + public static Matcher bulkResponseContainExceptions(Matcher exceptionMatcher) { + return new BulkResponseContainExceptionsMatcher(exceptionMatcher); + } - public static Matcher bulkResponseContainExceptions(int index, Matcher exceptionMatcher) { - return new BulkResponseContainExceptionsAtIndexMatcher(index, exceptionMatcher); - } + public static Matcher bulkResponseContainExceptions(int index, Matcher exceptionMatcher) { + return new BulkResponseContainExceptionsAtIndexMatcher(index, exceptionMatcher); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainDocumentCountIndexMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainDocumentCountIndexMatcher.java index a8e1b5d78d..91d2a28ef8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainDocumentCountIndexMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainDocumentCountIndexMatcher.java @@ -20,24 +20,24 @@ class ClusterContainDocumentCountIndexMatcher extends TypeSafeDiagnosingMatcher { - private final String indexName; - private final int expectedDocumentCount; - - public ClusterContainDocumentCountIndexMatcher(String indexName, int expectedDocumentCount) { - this.indexName = requireNonNull(indexName, "Index name is required."); - this.expectedDocumentCount = expectedDocumentCount; - } - - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - GetIndexResponse response = client.admin().indices().getIndex(null).actionGet(); - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText("contains ").appendValue(expectedDocumentCount).appendText(" in index ").appendText(indexName); - } + private final String indexName; + private final int expectedDocumentCount; + + public ClusterContainDocumentCountIndexMatcher(String indexName, int expectedDocumentCount) { + this.indexName = requireNonNull(indexName, "Index name is required."); + this.expectedDocumentCount = expectedDocumentCount; + } + + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + GetIndexResponse response = client.admin().indices().getIndex(null).actionGet(); + } + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("contains ").appendValue(expectedDocumentCount).appendText(" in index ").appendText(indexName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainSuccessSnapshotMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainSuccessSnapshotMatcher.java index f710e2c1fa..362663e07b 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainSuccessSnapshotMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainSuccessSnapshotMatcher.java @@ -24,43 +24,46 @@ class ClusterContainSuccessSnapshotMatcher extends TypeSafeDiagnosingMatcher { - private final String repositoryName; - private final String snapshotName; + private final String repositoryName; + private final String snapshotName; - public ClusterContainSuccessSnapshotMatcher(String repositoryName, String snapshotName) { - this.repositoryName = requireNonNull(repositoryName, "Snapshot repository name is required."); - this.snapshotName = requireNonNull(snapshotName, "Snapshot name is required."); - } + public ClusterContainSuccessSnapshotMatcher(String repositoryName, String snapshotName) { + this.repositoryName = requireNonNull(repositoryName, "Snapshot repository name is required."); + this.snapshotName = requireNonNull(snapshotName, "Snapshot name is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName, new String[] { snapshotName }); - GetSnapshotsResponse response = client.admin().cluster().getSnapshots(request).actionGet(); - long count = response.getSnapshots() - .stream() - .map(snapshot -> snapshot.state()) - .filter(status -> SnapshotState.SUCCESS.equals(status)) - .count(); - if(count != 1){ - String snapshotStatuses = response.getSnapshots() - .stream() - .map(info -> String.format("%s %s", info.snapshotId().getName(), info.state())) - .collect(Collectors.joining(", ")); - mismatchDescription.appendText("snapshot is not present or has incorrect state, snapshots statuses ") - .appendValue(snapshotStatuses); - return false; - } - }catch (SnapshotMissingException e) { - mismatchDescription.appendText(" snapshot does not exist"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName, new String[] { snapshotName }); + GetSnapshotsResponse response = client.admin().cluster().getSnapshots(request).actionGet(); + long count = response.getSnapshots() + .stream() + .map(snapshot -> snapshot.state()) + .filter(status -> SnapshotState.SUCCESS.equals(status)) + .count(); + if (count != 1) { + String snapshotStatuses = response.getSnapshots() + .stream() + .map(info -> String.format("%s %s", info.snapshotId().getName(), info.state())) + .collect(Collectors.joining(", ")); + mismatchDescription.appendText("snapshot is not present or has incorrect state, snapshots statuses ") + .appendValue(snapshotStatuses); + return false; + } + } catch (SnapshotMissingException e) { + mismatchDescription.appendText(" snapshot does not exist"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Cluster contain snapshot ").appendValue(snapshotName).appendText(" in repository ") - .appendValue(repositoryName).appendText(" with success status"); - } + @Override + public void describeTo(Description description) { + description.appendText("Cluster contain snapshot ") + .appendValue(snapshotName) + .appendText(" in repository ") + .appendValue(repositoryName) + .appendText(" with success status"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateMatcher.java index 2d64a95c65..119e3a6a2f 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateMatcher.java @@ -9,7 +9,6 @@ */ package org.opensearch.test.framework.matcher; - import org.hamcrest.Description; import org.hamcrest.TypeSafeDiagnosingMatcher; @@ -20,25 +19,25 @@ class ClusterContainTemplateMatcher extends TypeSafeDiagnosingMatcher { - private final String templateName; + private final String templateName; - public ClusterContainTemplateMatcher(String templateName) { - this.templateName = requireNonNull(templateName, "Index template name is required."); + public ClusterContainTemplateMatcher(String templateName) { + this.templateName = requireNonNull(templateName, "Index template name is required."); - } + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - var response = client.admin().indices().getTemplates(new GetIndexTemplatesRequest(templateName)).actionGet(); - if(response.getIndexTemplates().isEmpty()) { - mismatchDescription.appendText("But template does not exists"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + var response = client.admin().indices().getTemplates(new GetIndexTemplatesRequest(templateName)).actionGet(); + if (response.getIndexTemplates().isEmpty()) { + mismatchDescription.appendText("But template does not exists"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("template ").appendValue(templateName).appendText(" exists"); - } + @Override + public void describeTo(Description description) { + description.appendText("template ").appendValue(templateName).appendText(" exists"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateWithAliasMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateWithAliasMatcher.java index 861aaa72e7..4addaa0dd5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateWithAliasMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainTemplateWithAliasMatcher.java @@ -27,48 +27,47 @@ class ClusterContainTemplateWithAliasMatcher extends TypeSafeDiagnosingMatcher { - private final String templateName; - private final String aliasName; + private final String templateName; + private final String aliasName; - public ClusterContainTemplateWithAliasMatcher(String templateName, String aliasName) { - this.templateName = requireNonNull(templateName, "Index template name is required."); - this.aliasName = requireNonNull(aliasName, "Alias name is required."); - } + public ClusterContainTemplateWithAliasMatcher(String templateName, String aliasName) { + this.templateName = requireNonNull(templateName, "Index template name is required."); + this.aliasName = requireNonNull(aliasName, "Alias name is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - var response = client.admin().indices().getTemplates(new GetIndexTemplatesRequest(templateName)).actionGet(); - if(response.getIndexTemplates().isEmpty()) { - mismatchDescription.appendText("but template does not exists"); - return false; - } - Set aliases = getAliases(response); - if(aliases.contains(aliasName) == false) { - mismatchDescription.appendText("alias ").appendValue(aliasName) - .appendText(" is not present in template, other aliases in template ") - .appendValue(aliases.stream().collect(Collectors.joining(", "))); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + var response = client.admin().indices().getTemplates(new GetIndexTemplatesRequest(templateName)).actionGet(); + if (response.getIndexTemplates().isEmpty()) { + mismatchDescription.appendText("but template does not exists"); + return false; + } + Set aliases = getAliases(response); + if (aliases.contains(aliasName) == false) { + mismatchDescription.appendText("alias ") + .appendValue(aliasName) + .appendText(" is not present in template, other aliases in template ") + .appendValue(aliases.stream().collect(Collectors.joining(", "))); + return false; + } + return true; + } - private Set getAliases(GetIndexTemplatesResponse response) { - return response.getIndexTemplates() - .stream() - .map(metadata -> metadata.getAliases()) - .flatMap(aliasMap -> aliasNames(aliasMap)) - .collect(Collectors.toSet()); - } + private Set getAliases(GetIndexTemplatesResponse response) { + return response.getIndexTemplates() + .stream() + .map(metadata -> metadata.getAliases()) + .flatMap(aliasMap -> aliasNames(aliasMap)) + .collect(Collectors.toSet()); + } - private Stream aliasNames(Map aliasMap) { - Iterable> iterable = () -> aliasMap.entrySet().iterator(); - return StreamSupport.stream(iterable.spliterator(), false) - .map(entry -> entry.getValue().getAlias()); - } + private Stream aliasNames(Map aliasMap) { + Iterable> iterable = () -> aliasMap.entrySet().iterator(); + return StreamSupport.stream(iterable.spliterator(), false).map(entry -> entry.getValue().getAlias()); + } - - @Override - public void describeTo(Description description) { - description.appendText("template ").appendValue(templateName).appendText(" exists and "); - } + @Override + public void describeTo(Description description) { + description.appendText("template ").appendValue(templateName).appendText(" exists and "); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentMatcher.java index ffcceaa9cb..3153214213 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentMatcher.java @@ -24,35 +24,34 @@ class ClusterContainsDocumentMatcher extends TypeSafeDiagnosingMatcher { - private static final Logger log = LogManager.getLogger(ClusterContainsDocumentMatcher.class); - - private final String indexName; - private final String documentId; - - ClusterContainsDocumentMatcher(String indexName, String documentId) { - this.indexName = requireNonNull(indexName, "Index name is required."); - this.documentId = requireNonNull(documentId, "Document id is required."); - } - - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try{ - GetResponse response = client.get(new GetRequest(indexName, documentId)).get(); - if(response.isExists() == false) { - mismatchDescription.appendText("Document does not exists"); - return false; - } - } catch (InterruptedException | ExecutionException e) { - log.error("Cannot verify if cluster contains document '{}' in index '{}'.", documentId, indexName, e); - mismatchDescription.appendText("Exception occured during verification if cluster contain document").appendValue(e); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Cluster contain document in index ").appendValue(indexName).appendText(" with id ") - .appendValue(documentId); - } + private static final Logger log = LogManager.getLogger(ClusterContainsDocumentMatcher.class); + + private final String indexName; + private final String documentId; + + ClusterContainsDocumentMatcher(String indexName, String documentId) { + this.indexName = requireNonNull(indexName, "Index name is required."); + this.documentId = requireNonNull(documentId, "Document id is required."); + } + + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetResponse response = client.get(new GetRequest(indexName, documentId)).get(); + if (response.isExists() == false) { + mismatchDescription.appendText("Document does not exists"); + return false; + } + } catch (InterruptedException | ExecutionException e) { + log.error("Cannot verify if cluster contains document '{}' in index '{}'.", documentId, indexName, e); + mismatchDescription.appendText("Exception occured during verification if cluster contain document").appendValue(e); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Cluster contain document in index ").appendValue(indexName).appendText(" with id ").appendValue(documentId); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentWithFieldValueMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentWithFieldValueMatcher.java index df67a1669a..21f062fabf 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentWithFieldValueMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsDocumentWithFieldValueMatcher.java @@ -25,56 +25,61 @@ class ClusterContainsDocumentWithFieldValueMatcher extends TypeSafeDiagnosingMatcher { - private static final Logger log = LogManager.getLogger(ClusterContainsDocumentWithFieldValueMatcher.class); + private static final Logger log = LogManager.getLogger(ClusterContainsDocumentWithFieldValueMatcher.class); - private final String indexName; - private final String documentId; + private final String indexName; + private final String documentId; - private final String fieldName; + private final String fieldName; - private final Object fieldValue; + private final Object fieldValue; - ClusterContainsDocumentWithFieldValueMatcher(String indexName, String documentId, String fieldName, Object fieldValue) { - this.indexName = requireNonNull(indexName, "Index name is required."); - this.documentId = requireNonNull(documentId, "Document id is required."); - this.fieldName = requireNonNull(fieldName, "Field name is required."); - this.fieldValue = requireNonNull(fieldValue, "Field value is required."); - } + ClusterContainsDocumentWithFieldValueMatcher(String indexName, String documentId, String fieldName, Object fieldValue) { + this.indexName = requireNonNull(indexName, "Index name is required."); + this.documentId = requireNonNull(documentId, "Document id is required."); + this.fieldName = requireNonNull(fieldName, "Field name is required."); + this.fieldValue = requireNonNull(fieldValue, "Field value is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - GetResponse response = client.get(new GetRequest(indexName, documentId)).get(); - if(response.isExists() == false) { - mismatchDescription.appendText("Document does not exists"); - return false; - } - Map source = response.getSource(); - if(source == null) { - mismatchDescription.appendText("Cannot retrieve document source"); - return false; - } - if(source.containsKey(fieldName) == false) { - mismatchDescription.appendText("document does not contain field ").appendValue(fieldName); - return false; - } - Object actualFieldValue = source.get(fieldName); - if(fieldValue.equals(actualFieldValue) == false) { - mismatchDescription.appendText(" document contain incorrect field value ").appendValue(actualFieldValue); - return false; - } - } catch (InterruptedException | ExecutionException e) { - log.error("Cannot verify if cluster contains document '{}' in index '{}'.", documentId, indexName, e); - mismatchDescription.appendText("Exception occured during verification if cluster contain document").appendValue(e); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetResponse response = client.get(new GetRequest(indexName, documentId)).get(); + if (response.isExists() == false) { + mismatchDescription.appendText("Document does not exists"); + return false; + } + Map source = response.getSource(); + if (source == null) { + mismatchDescription.appendText("Cannot retrieve document source"); + return false; + } + if (source.containsKey(fieldName) == false) { + mismatchDescription.appendText("document does not contain field ").appendValue(fieldName); + return false; + } + Object actualFieldValue = source.get(fieldName); + if (fieldValue.equals(actualFieldValue) == false) { + mismatchDescription.appendText(" document contain incorrect field value ").appendValue(actualFieldValue); + return false; + } + } catch (InterruptedException | ExecutionException e) { + log.error("Cannot verify if cluster contains document '{}' in index '{}'.", documentId, indexName, e); + mismatchDescription.appendText("Exception occured during verification if cluster contain document").appendValue(e); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Cluster contain document in index ").appendValue(indexName).appendText(" with id ") - .appendValue(documentId).appendText(" with field ").appendValue(fieldName).appendText(" which is equal to ") - .appendValue(fieldValue); - } + @Override + public void describeTo(Description description) { + description.appendText("Cluster contain document in index ") + .appendValue(indexName) + .appendText(" with id ") + .appendValue(documentId) + .appendText(" with field ") + .appendValue(fieldName) + .appendText(" which is equal to ") + .appendValue(fieldValue); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsSnapshotRepositoryMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsSnapshotRepositoryMatcher.java index 8b7dc777e4..fcff8bd6cf 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsSnapshotRepositoryMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterContainsSnapshotRepositoryMatcher.java @@ -26,41 +26,42 @@ class ClusterContainsSnapshotRepositoryMatcher extends TypeSafeDiagnosingMatcher { - private final String repositoryName; + private final String repositoryName; - public ClusterContainsSnapshotRepositoryMatcher(String repositoryName) { - this.repositoryName = requireNonNull(repositoryName, "Repository name is required."); - } + public ClusterContainsSnapshotRepositoryMatcher(String repositoryName) { + this.repositoryName = requireNonNull(repositoryName, "Repository name is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - ClusterAdminClient adminClient = client.admin().cluster(); - GetRepositoriesRequest request = new GetRepositoriesRequest(new String[]{"*"}); - GetRepositoriesResponse response = adminClient.getRepositories(request).actionGet(); - if(response == null) { - mismatchDescription.appendText("Cannot check if cluster contain repository"); - return false; - } - Set actualRepositoryNames = response.repositories() - .stream() - .map(metadata -> metadata.name()) - .collect(Collectors.toSet()); - if(actualRepositoryNames.contains(repositoryName) == false) { - mismatchDescription.appendText("Cluster does not contain snapshot repository ").appendValue(repositoryName) - .appendText(", but the following repositories are defined in the cluster ") - .appendValue(actualRepositoryNames.stream().collect(joining(", "))); - return false; - } - } catch (RepositoryMissingException e) { - mismatchDescription.appendText(" cluster does not contain any repository."); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + ClusterAdminClient adminClient = client.admin().cluster(); + GetRepositoriesRequest request = new GetRepositoriesRequest(new String[] { "*" }); + GetRepositoriesResponse response = adminClient.getRepositories(request).actionGet(); + if (response == null) { + mismatchDescription.appendText("Cannot check if cluster contain repository"); + return false; + } + Set actualRepositoryNames = response.repositories() + .stream() + .map(metadata -> metadata.name()) + .collect(Collectors.toSet()); + if (actualRepositoryNames.contains(repositoryName) == false) { + mismatchDescription.appendText("Cluster does not contain snapshot repository ") + .appendValue(repositoryName) + .appendText(", but the following repositories are defined in the cluster ") + .appendValue(actualRepositoryNames.stream().collect(joining(", "))); + return false; + } + } catch (RepositoryMissingException e) { + mismatchDescription.appendText(" cluster does not contain any repository."); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Cluster contain snapshot repository with name ").appendValue(repositoryName); - } + @Override + public void describeTo(Description description) { + description.appendText("Cluster contain snapshot repository with name ").appendValue(repositoryName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterMatchers.java index eff1f4c803..3829436d74 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ClusterMatchers.java @@ -20,55 +20,60 @@ public class ClusterMatchers { - private ClusterMatchers() { - - } - - public static Matcher clusterContainsDocument(String indexName, String documentId) { - return new ClusterContainsDocumentMatcher(indexName, documentId); - } - - public static Matcher clusterContainsDocumentWithFieldValue(String indexName, String documentId, String fieldName, Object fieldValue) { - return new ClusterContainsDocumentWithFieldValueMatcher(indexName, documentId, fieldName, fieldValue); - } - - public static Matcher clusterContainTemplate(String templateName) { - return new ClusterContainTemplateMatcher(templateName); - } - - public static Matcher clusterContainTemplateWithAlias(String templateName, String aliasName) { - return new ClusterContainTemplateWithAliasMatcher(templateName, aliasName); - } - - public static Matcher clusterContainsSnapshotRepository(String repositoryName) { - return new ClusterContainsSnapshotRepositoryMatcher(repositoryName); - } - - public static Matcher clusterContainSuccessSnapshot(String repositoryName, String snapshotName) { - return new ClusterContainSuccessSnapshotMatcher(repositoryName, snapshotName); - } - - public static Matcher snapshotInClusterDoesNotExists(String repositoryName, String snapshotName) { - return new SnapshotInClusterDoesNotExist(repositoryName, snapshotName); - } - - public static Matcher aliasExists(String aliasName) { - return new AliasExistsMatcher(aliasName); - } - - public static Matcher indexExists(String expectedIndexName) { - return new IndexExistsMatcher(expectedIndexName); - } - - public static Matcher indexStateIsEqualTo(String expectedIndexName, IndexMetadata.State expectedState) { - return new IndexStateIsEqualToMatcher(expectedIndexName, expectedState); - } - - public static Matcher indexSettingsContainValues(String expectedIndexName, Settings expectedSettings) { - return new IndexSettingsContainValuesMatcher(expectedIndexName, expectedSettings); - } - - public static Matcher indexMappingIsEqualTo(String expectedIndexName, Map expectedMapping) { - return new IndexMappingIsEqualToMatcher(expectedIndexName, expectedMapping); - } + private ClusterMatchers() { + + } + + public static Matcher clusterContainsDocument(String indexName, String documentId) { + return new ClusterContainsDocumentMatcher(indexName, documentId); + } + + public static Matcher clusterContainsDocumentWithFieldValue( + String indexName, + String documentId, + String fieldName, + Object fieldValue + ) { + return new ClusterContainsDocumentWithFieldValueMatcher(indexName, documentId, fieldName, fieldValue); + } + + public static Matcher clusterContainTemplate(String templateName) { + return new ClusterContainTemplateMatcher(templateName); + } + + public static Matcher clusterContainTemplateWithAlias(String templateName, String aliasName) { + return new ClusterContainTemplateWithAliasMatcher(templateName, aliasName); + } + + public static Matcher clusterContainsSnapshotRepository(String repositoryName) { + return new ClusterContainsSnapshotRepositoryMatcher(repositoryName); + } + + public static Matcher clusterContainSuccessSnapshot(String repositoryName, String snapshotName) { + return new ClusterContainSuccessSnapshotMatcher(repositoryName, snapshotName); + } + + public static Matcher snapshotInClusterDoesNotExists(String repositoryName, String snapshotName) { + return new SnapshotInClusterDoesNotExist(repositoryName, snapshotName); + } + + public static Matcher aliasExists(String aliasName) { + return new AliasExistsMatcher(aliasName); + } + + public static Matcher indexExists(String expectedIndexName) { + return new IndexExistsMatcher(expectedIndexName); + } + + public static Matcher indexStateIsEqualTo(String expectedIndexName, IndexMetadata.State expectedState) { + return new IndexStateIsEqualToMatcher(expectedIndexName, expectedState); + } + + public static Matcher indexSettingsContainValues(String expectedIndexName, Settings expectedSettings) { + return new IndexSettingsContainValuesMatcher(expectedIndexName, expectedSettings); + } + + public static Matcher indexMappingIsEqualTo(String expectedIndexName, Map expectedMapping) { + return new IndexMappingIsEqualToMatcher(expectedIndexName, expectedMapping); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainNotEmptyScrollingIdMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainNotEmptyScrollingIdMatcher.java index 094b26f33f..03b9b6bab8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainNotEmptyScrollingIdMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainNotEmptyScrollingIdMatcher.java @@ -17,18 +17,18 @@ class ContainNotEmptyScrollingIdMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - String scrollId = searchResponse.getScrollId(); - if(StringUtils.isEmpty(scrollId)) { - mismatchDescription.appendText("scrolling id is null or empty"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + String scrollId = searchResponse.getScrollId(); + if (StringUtils.isEmpty(scrollId)) { + mismatchDescription.appendText("scrolling id is null or empty"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Search response should contain scrolling id."); - } + @Override + public void describeTo(Description description) { + description.appendText("Search response should contain scrolling id."); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsAggregationWithNameAndTypeMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsAggregationWithNameAndTypeMatcher.java index 9f8fbd6dba..b1ef21c922 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsAggregationWithNameAndTypeMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsAggregationWithNameAndTypeMatcher.java @@ -20,36 +20,38 @@ class ContainsAggregationWithNameAndTypeMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedAggregationName; - private final String expectedAggregationType; - - public ContainsAggregationWithNameAndTypeMatcher(String expectedAggregationName, String expectedAggregationType) { - this.expectedAggregationName = requireNonNull(expectedAggregationName, "Aggregation name is required"); - this.expectedAggregationType = requireNonNull(expectedAggregationType, "Expected aggregation type is required."); - } - - @Override - protected boolean matchesSafely(SearchResponse response, Description mismatchDescription) { - Aggregations aggregations = response.getAggregations(); - if(aggregations == null) { - mismatchDescription.appendText("search response does not contain aggregations"); - return false; - } - Aggregation aggregation = aggregations.get(expectedAggregationName); - if(aggregation == null) { - mismatchDescription.appendText("Response does not contain aggregation with name ").appendValue(expectedAggregationName); - return false; - } - if(expectedAggregationType.equals(aggregation.getType()) == false) { - mismatchDescription.appendText("Aggregation contain incorrect type which is ").appendValue(aggregation.getType()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Search response should contains aggregation results with name ").appendValue(expectedAggregationName) - .appendText(" and type ").appendValue(expectedAggregationType); - } + private final String expectedAggregationName; + private final String expectedAggregationType; + + public ContainsAggregationWithNameAndTypeMatcher(String expectedAggregationName, String expectedAggregationType) { + this.expectedAggregationName = requireNonNull(expectedAggregationName, "Aggregation name is required"); + this.expectedAggregationType = requireNonNull(expectedAggregationType, "Expected aggregation type is required."); + } + + @Override + protected boolean matchesSafely(SearchResponse response, Description mismatchDescription) { + Aggregations aggregations = response.getAggregations(); + if (aggregations == null) { + mismatchDescription.appendText("search response does not contain aggregations"); + return false; + } + Aggregation aggregation = aggregations.get(expectedAggregationName); + if (aggregation == null) { + mismatchDescription.appendText("Response does not contain aggregation with name ").appendValue(expectedAggregationName); + return false; + } + if (expectedAggregationType.equals(aggregation.getType()) == false) { + mismatchDescription.appendText("Aggregation contain incorrect type which is ").appendValue(aggregation.getType()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Search response should contains aggregation results with name ") + .appendValue(expectedAggregationName) + .appendText(" and type ") + .appendValue(expectedAggregationType); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsExactlyIndicesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsExactlyIndicesMatcher.java index 551a1823bf..9b597ad1c8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsExactlyIndicesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsExactlyIndicesMatcher.java @@ -20,27 +20,27 @@ class ContainsExactlyIndicesMatcher extends TypeSafeDiagnosingMatcher { - private final Set expectedIndices; - - ContainsExactlyIndicesMatcher(String... expectedIndices) { - if (isNull(expectedIndices) || expectedIndices.length == 0) { - throw new IllegalArgumentException("expectedIndices cannot be null or empty"); - } - this.expectedIndices = Set.of(expectedIndices); - } - - @Override - protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { - Set actualIndices = Set.of(response.getIndices()); - if (!expectedIndices.equals(actualIndices)) { - mismatchDescription.appendText("Actual indices: ").appendValue(actualIndices); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response contains indices: ").appendValue(expectedIndices); - } + private final Set expectedIndices; + + ContainsExactlyIndicesMatcher(String... expectedIndices) { + if (isNull(expectedIndices) || expectedIndices.length == 0) { + throw new IllegalArgumentException("expectedIndices cannot be null or empty"); + } + this.expectedIndices = Set.of(expectedIndices); + } + + @Override + protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { + Set actualIndices = Set.of(response.getIndices()); + if (!expectedIndices.equals(actualIndices)) { + mismatchDescription.appendText("Actual indices: ").appendValue(actualIndices); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response contains indices: ").appendValue(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsFieldWithTypeMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsFieldWithTypeMatcher.java index 41db8a9ed5..cd6b4b05cc 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsFieldWithTypeMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ContainsFieldWithTypeMatcher.java @@ -21,31 +21,35 @@ class ContainsFieldWithTypeMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedFieldName; - private final String expectedFieldType; - - ContainsFieldWithTypeMatcher(String expectedFieldName, String expectedFieldType) { - this.expectedFieldName = requireNonNull(expectedFieldName, "Field name is required");; - this.expectedFieldType = requireNonNull(expectedFieldType, "Field type is required");; - } - - @Override - protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { - Map> fieldCapabilitiesMap = response.get(); - if (!fieldCapabilitiesMap.containsKey(expectedFieldName)) { - mismatchDescription.appendText("Response does not contain field with name ").appendText(expectedFieldName); - return false; - } - if (!fieldCapabilitiesMap.get(expectedFieldName).containsKey(expectedFieldType)) { - mismatchDescription.appendText("Field type does not match ").appendText(expectedFieldType); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response contains field with name ").appendValue(expectedFieldName) - .appendText(" and type ").appendValue(expectedFieldType); - } + private final String expectedFieldName; + private final String expectedFieldType; + + ContainsFieldWithTypeMatcher(String expectedFieldName, String expectedFieldType) { + this.expectedFieldName = requireNonNull(expectedFieldName, "Field name is required"); + ; + this.expectedFieldType = requireNonNull(expectedFieldType, "Field type is required"); + ; + } + + @Override + protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { + Map> fieldCapabilitiesMap = response.get(); + if (!fieldCapabilitiesMap.containsKey(expectedFieldName)) { + mismatchDescription.appendText("Response does not contain field with name ").appendText(expectedFieldName); + return false; + } + if (!fieldCapabilitiesMap.get(expectedFieldName).containsKey(expectedFieldType)) { + mismatchDescription.appendText("Field type does not match ").appendText(expectedFieldType); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response contains field with name ") + .appendValue(expectedFieldName) + .appendText(" and type ") + .appendValue(expectedFieldType); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/DeletePitContainsExactlyIdsResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/DeletePitContainsExactlyIdsResponseMatcher.java index fd921d0d72..788d023447 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/DeletePitContainsExactlyIdsResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/DeletePitContainsExactlyIdsResponseMatcher.java @@ -22,27 +22,27 @@ class DeletePitContainsExactlyIdsResponseMatcher extends TypeSafeDiagnosingMatcher { - private final Set expectedPitIds; - - DeletePitContainsExactlyIdsResponseMatcher(String[] expectedPitIds) { - if (isNull(expectedPitIds) || 0 == expectedPitIds.length) { - throw new IllegalArgumentException("expectedPitIds cannot be null or empty"); - } - this.expectedPitIds = Set.of(expectedPitIds); - } - - @Override - protected boolean matchesSafely(DeletePitResponse response, Description mismatchDescription) { - Set actualPitIds = response.getDeletePitResults().stream().map(DeletePitInfo::getPitId).collect(Collectors.toSet()); - if (!actualPitIds.equals(expectedPitIds)) { - mismatchDescription.appendText("Actual pit ids: ").appendValue(actualPitIds); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Should contain exactly pit with ids: ").appendValue(expectedPitIds); - } + private final Set expectedPitIds; + + DeletePitContainsExactlyIdsResponseMatcher(String[] expectedPitIds) { + if (isNull(expectedPitIds) || 0 == expectedPitIds.length) { + throw new IllegalArgumentException("expectedPitIds cannot be null or empty"); + } + this.expectedPitIds = Set.of(expectedPitIds); + } + + @Override + protected boolean matchesSafely(DeletePitResponse response, Description mismatchDescription) { + Set actualPitIds = response.getDeletePitResults().stream().map(DeletePitInfo::getPitId).collect(Collectors.toSet()); + if (!actualPitIds.equals(expectedPitIds)) { + mismatchDescription.appendText("Actual pit ids: ").appendValue(actualPitIds); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Should contain exactly pit with ids: ").appendValue(expectedPitIds); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/DeleteResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/DeleteResponseMatchers.java index 435c2521c8..4112d0bab8 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/DeleteResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/DeleteResponseMatchers.java @@ -15,9 +15,9 @@ public class DeleteResponseMatchers { - private DeleteResponseMatchers() {} + private DeleteResponseMatchers() {} - public static Matcher isSuccessfulDeleteResponse() { - return new SuccessfulDeleteResponseMatcher(); - } + public static Matcher isSuccessfulDeleteResponse() { + return new SuccessfulDeleteResponseMatcher(); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExactNumberOfAuditsFulfillPredicateMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExactNumberOfAuditsFulfillPredicateMatcher.java index c7d918db2c..9bbe966e07 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExactNumberOfAuditsFulfillPredicateMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExactNumberOfAuditsFulfillPredicateMatcher.java @@ -18,26 +18,28 @@ class ExactNumberOfAuditsFulfillPredicateMatcher extends AuditsFulfillPredicateMatcher { - private final long exactNumberOfAuditMessages; - - public ExactNumberOfAuditsFulfillPredicateMatcher(long exactNumberOfAuditMessages, Predicate predicate) { - super(predicate); - this.exactNumberOfAuditMessages = exactNumberOfAuditMessages; - } - - @Override - protected boolean matchesSafely(List audits, Description mismatchDescription) { - long count = countAuditsWhichMatchPredicate(audits); - if(exactNumberOfAuditMessages != count) { - mismatchDescription.appendText(" only ").appendValue(count).appendText(" match predicate. Examined audit logs ") - .appendText(auditMessagesToString(audits)); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendValue(exactNumberOfAuditMessages).appendText(" audit records should match predicate ").appendValue(predicate); - } + private final long exactNumberOfAuditMessages; + + public ExactNumberOfAuditsFulfillPredicateMatcher(long exactNumberOfAuditMessages, Predicate predicate) { + super(predicate); + this.exactNumberOfAuditMessages = exactNumberOfAuditMessages; + } + + @Override + protected boolean matchesSafely(List audits, Description mismatchDescription) { + long count = countAuditsWhichMatchPredicate(audits); + if (exactNumberOfAuditMessages != count) { + mismatchDescription.appendText(" only ") + .appendValue(count) + .appendText(" match predicate. Examined audit logs ") + .appendText(auditMessagesToString(audits)); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendValue(exactNumberOfAuditMessages).appendText(" audit records should match predicate ").appendValue(predicate); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionErrorMessageMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionErrorMessageMatcher.java index e0e7b11be3..2e07bd0ec5 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionErrorMessageMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionErrorMessageMatcher.java @@ -17,25 +17,27 @@ class ExceptionErrorMessageMatcher extends TypeSafeDiagnosingMatcher { - private final Matcher errorMessageMatcher; - - public ExceptionErrorMessageMatcher(Matcher errorMessageMatcher) { - this.errorMessageMatcher = requireNonNull(errorMessageMatcher, "Error message matcher is required"); - } - - @Override - protected boolean matchesSafely(Throwable ex, Description mismatchDescription) { - boolean matches = errorMessageMatcher.matches(ex.getMessage()); - if(matches == false) { - mismatchDescription.appendText("Exception of class ").appendValue(ex.getClass().getCanonicalName()) - .appendText("contains unexpected error message which is ").appendValue(ex.getMessage()); - } - return matches; - - } - - @Override - public void describeTo(Description description) { - description.appendText("Error message in exception matches").appendValue(errorMessageMatcher); - } + private final Matcher errorMessageMatcher; + + public ExceptionErrorMessageMatcher(Matcher errorMessageMatcher) { + this.errorMessageMatcher = requireNonNull(errorMessageMatcher, "Error message matcher is required"); + } + + @Override + protected boolean matchesSafely(Throwable ex, Description mismatchDescription) { + boolean matches = errorMessageMatcher.matches(ex.getMessage()); + if (matches == false) { + mismatchDescription.appendText("Exception of class ") + .appendValue(ex.getClass().getCanonicalName()) + .appendText("contains unexpected error message which is ") + .appendValue(ex.getMessage()); + } + return matches; + + } + + @Override + public void describeTo(Description description) { + description.appendText("Error message in exception matches").appendValue(errorMessageMatcher); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionHasCauseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionHasCauseMatcher.java index 3a200d8849..ed1b203898 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionHasCauseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionHasCauseMatcher.java @@ -16,28 +16,28 @@ class ExceptionHasCauseMatcher extends TypeSafeDiagnosingMatcher { - private final Class expectedCauseType; + private final Class expectedCauseType; - public ExceptionHasCauseMatcher(Class expectedCauseType) { - this.expectedCauseType = Objects.requireNonNull(expectedCauseType, "Exception cause type is required"); - } + public ExceptionHasCauseMatcher(Class expectedCauseType) { + this.expectedCauseType = Objects.requireNonNull(expectedCauseType, "Exception cause type is required"); + } - @Override - protected boolean matchesSafely(Throwable throwable, Description mismatchDescription) { - Throwable cause = throwable.getCause(); - if(cause == null) { - mismatchDescription.appendText("exception cause is null"); - return false; - } - if(expectedCauseType.isInstance(cause) == false) { - mismatchDescription.appendText(" cause is instance of ").appendValue(cause.getClass()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(Throwable throwable, Description mismatchDescription) { + Throwable cause = throwable.getCause(); + if (cause == null) { + mismatchDescription.appendText("exception cause is null"); + return false; + } + if (expectedCauseType.isInstance(cause) == false) { + mismatchDescription.appendText(" cause is instance of ").appendValue(cause.getClass()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Exception cause is instance of ").appendValue(expectedCauseType); - } + @Override + public void describeTo(Description description) { + description.appendText("Exception cause is instance of ").appendValue(expectedCauseType); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionMatcherAssert.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionMatcherAssert.java index d46107b0fb..671f22b8e3 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionMatcherAssert.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/ExceptionMatcherAssert.java @@ -17,24 +17,24 @@ public class ExceptionMatcherAssert { - @FunctionalInterface - public interface ThrowingCallable { - void call() throws Exception; - } + @FunctionalInterface + public interface ThrowingCallable { + void call() throws Exception; + } - public static void assertThatThrownBy(ThrowingCallable throwingCallable, Matcher matcher) { - Throwable expectedException = catchThrowable(throwingCallable); - assertThat("Expected exception was not thrown", expectedException, notNullValue()); - assertThat(expectedException, matcher); - } + public static void assertThatThrownBy(ThrowingCallable throwingCallable, Matcher matcher) { + Throwable expectedException = catchThrowable(throwingCallable); + assertThat("Expected exception was not thrown", expectedException, notNullValue()); + assertThat(expectedException, matcher); + } - public static Throwable catchThrowable(ThrowingCallable throwingCallable) { - Throwable expectedException = null; - try { - requireNonNull(throwingCallable, "ThrowingCallable must not be null.").call(); - } catch (Throwable e) { - expectedException = e; - } - return expectedException; - } + public static Throwable catchThrowable(ThrowingCallable throwingCallable) { + Throwable expectedException = null; + try { + requireNonNull(throwingCallable, "ThrowingCallable must not be null.").call(); + } catch (Throwable e) { + expectedException = e; + } + return expectedException; + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/FailureBulkResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/FailureBulkResponseMatcher.java index a018c1c924..3d912e0283 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/FailureBulkResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/FailureBulkResponseMatcher.java @@ -16,17 +16,17 @@ class FailureBulkResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { - if(response.hasFailures() == false) { - mismatchDescription.appendText(" bulk operation was executed correctly what is not expected."); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { + if (response.hasFailures() == false) { + mismatchDescription.appendText(" bulk operation was executed correctly what is not expected."); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("bulk operation failure"); - } + @Override + public void describeTo(Description description) { + description.appendText("bulk operation failure"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/FieldCapabilitiesResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/FieldCapabilitiesResponseMatchers.java index c5680f6055..2a78c7b71c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/FieldCapabilitiesResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/FieldCapabilitiesResponseMatchers.java @@ -15,18 +15,18 @@ public class FieldCapabilitiesResponseMatchers { - private FieldCapabilitiesResponseMatchers() {} + private FieldCapabilitiesResponseMatchers() {} - public static Matcher containsExactlyIndices(String... expectedIndices) { - return new ContainsExactlyIndicesMatcher(expectedIndices); - } + public static Matcher containsExactlyIndices(String... expectedIndices) { + return new ContainsExactlyIndicesMatcher(expectedIndices); + } - public static Matcher containsFieldWithNameAndType(String expectedFieldName, String expectedFieldType) { - return new ContainsFieldWithTypeMatcher(expectedFieldName, expectedFieldType); - } + public static Matcher containsFieldWithNameAndType(String expectedFieldName, String expectedFieldType) { + return new ContainsFieldWithTypeMatcher(expectedFieldName, expectedFieldType); + } - public static Matcher numberOfFieldsIsEqualTo(int expectedNumberOfFields) { - return new NumberOfFieldsIsEqualToMatcher(expectedNumberOfFields); - } + public static Matcher numberOfFieldsIsEqualTo(int expectedNumberOfFields) { + return new NumberOfFieldsIsEqualToMatcher(expectedNumberOfFields); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetAllPitsContainsExactlyIdsResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetAllPitsContainsExactlyIdsResponseMatcher.java index 447224345c..c568bfa9d7 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetAllPitsContainsExactlyIdsResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetAllPitsContainsExactlyIdsResponseMatcher.java @@ -22,27 +22,27 @@ class GetAllPitsContainsExactlyIdsResponseMatcher extends TypeSafeDiagnosingMatcher { - private final Set expectedPitIds; - - GetAllPitsContainsExactlyIdsResponseMatcher(String[] expectedPitIds) { - if (isNull(expectedPitIds) || 0 == expectedPitIds.length) { - throw new IllegalArgumentException("expectedPitIds cannot be null or empty"); - } - this.expectedPitIds = Set.of(expectedPitIds); - } - - @Override - protected boolean matchesSafely(GetAllPitNodesResponse response, Description mismatchDescription) { - Set actualPitIds = response.getPitInfos().stream().map(ListPitInfo::getPitId).collect(Collectors.toSet()); - if (!actualPitIds.equals(expectedPitIds)) { - mismatchDescription.appendText("Actual pit ids: ").appendValue(actualPitIds); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Should contain exactly pit with ids: ").appendValue(expectedPitIds); - } + private final Set expectedPitIds; + + GetAllPitsContainsExactlyIdsResponseMatcher(String[] expectedPitIds) { + if (isNull(expectedPitIds) || 0 == expectedPitIds.length) { + throw new IllegalArgumentException("expectedPitIds cannot be null or empty"); + } + this.expectedPitIds = Set.of(expectedPitIds); + } + + @Override + protected boolean matchesSafely(GetAllPitNodesResponse response, Description mismatchDescription) { + Set actualPitIds = response.getPitInfos().stream().map(ListPitInfo::getPitId).collect(Collectors.toSet()); + if (!actualPitIds.equals(expectedPitIds)) { + mismatchDescription.appendText("Actual pit ids: ").appendValue(actualPitIds); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Should contain exactly pit with ids: ").appendValue(expectedPitIds); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetIndexResponseContainsIndicesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetIndexResponseContainsIndicesMatcher.java index 43d1bce761..20f02b1319 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetIndexResponseContainsIndicesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetIndexResponseContainsIndicesMatcher.java @@ -21,31 +21,29 @@ class GetIndexResponseContainsIndicesMatcher extends TypeSafeDiagnosingMatcher { - private final String[] expectedIndices; - - GetIndexResponseContainsIndicesMatcher(String[] expectedIndices) { - if (isNull(expectedIndices) || 0 == expectedIndices.length) { - throw new IllegalArgumentException("expectedIndices cannot be null or empty"); - } - this.expectedIndices = expectedIndices; - } - - @Override - protected boolean matchesSafely(GetIndexResponse response, Description mismatchDescription) { - List actual = Arrays.asList(response.getIndices()); - for (String index : expectedIndices) { - if (!actual.contains(index)) { - mismatchDescription - .appendText("Actual indices: ") - .appendValue(response.getIndices()); - return false; - } - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain indices: ").appendValue(expectedIndices); - } + private final String[] expectedIndices; + + GetIndexResponseContainsIndicesMatcher(String[] expectedIndices) { + if (isNull(expectedIndices) || 0 == expectedIndices.length) { + throw new IllegalArgumentException("expectedIndices cannot be null or empty"); + } + this.expectedIndices = expectedIndices; + } + + @Override + protected boolean matchesSafely(GetIndexResponse response, Description mismatchDescription) { + List actual = Arrays.asList(response.getIndices()); + for (String index : expectedIndices) { + if (!actual.contains(index)) { + mismatchDescription.appendText("Actual indices: ").appendValue(response.getIndices()); + return false; + } + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain indices: ").appendValue(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetMappingsResponseContainsIndicesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetMappingsResponseContainsIndicesMatcher.java index a246ec14b3..8e2b3da097 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetMappingsResponseContainsIndicesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetMappingsResponseContainsIndicesMatcher.java @@ -21,31 +21,29 @@ class GetMappingsResponseContainsIndicesMatcher extends TypeSafeDiagnosingMatcher { - private final String[] expectedIndices; - - GetMappingsResponseContainsIndicesMatcher(String[] expectedIndices) { - if (isNull(expectedIndices) || 0 == expectedIndices.length) { - throw new IllegalArgumentException("expectedIndices cannot be null or empty"); - } - this.expectedIndices = expectedIndices; - } - - @Override - protected boolean matchesSafely(GetMappingsResponse response, Description mismatchDescription) { - Map indicesMappings = response.mappings(); - for (String index : expectedIndices) { - if (!indicesMappings.containsKey(index)) { - mismatchDescription - .appendText("Response contains mappings of indices: ") - .appendValue(indicesMappings.keySet()); - return false; - } - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain mappings of indices: ").appendValue(expectedIndices); - } + private final String[] expectedIndices; + + GetMappingsResponseContainsIndicesMatcher(String[] expectedIndices) { + if (isNull(expectedIndices) || 0 == expectedIndices.length) { + throw new IllegalArgumentException("expectedIndices cannot be null or empty"); + } + this.expectedIndices = expectedIndices; + } + + @Override + protected boolean matchesSafely(GetMappingsResponse response, Description mismatchDescription) { + Map indicesMappings = response.mappings(); + for (String index : expectedIndices) { + if (!indicesMappings.containsKey(index)) { + mismatchDescription.appendText("Response contains mappings of indices: ").appendValue(indicesMappings.keySet()); + return false; + } + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain mappings of indices: ").appendValue(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainOnlyDocumentIdMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainOnlyDocumentIdMatcher.java index b677d6e6e1..e6d7f02c6e 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainOnlyDocumentIdMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainOnlyDocumentIdMatcher.java @@ -18,34 +18,37 @@ class GetResponseContainOnlyDocumentIdMatcher extends TypeSafeDiagnosingMatcher { - private final String indexName; - private final String documentId; - - public GetResponseContainOnlyDocumentIdMatcher(String indexName, String documentId) { - this.indexName = requireNonNull(indexName, "Index name is required"); - this.documentId = requireNonNull(documentId, "Document id is required"); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - if(indexName.equals(response.getIndex()) == false ) { - mismatchDescription.appendText(" index name ").appendValue(response.getIndex()).appendText(" is incorrect "); - return false; - } - if(documentId.equals(response.getId()) == false) { - mismatchDescription.appendText(" id ").appendValue(response.getId()).appendText(" is incorrect "); - return false; - } - if(response.isExists()) { - mismatchDescription.appendText(" document exist what is not desired "); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain document id from index ").appendValue(indexName).appendText(" with id ") - .appendValue(documentId).appendText(" but document should not be present "); - } + private final String indexName; + private final String documentId; + + public GetResponseContainOnlyDocumentIdMatcher(String indexName, String documentId) { + this.indexName = requireNonNull(indexName, "Index name is required"); + this.documentId = requireNonNull(documentId, "Document id is required"); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + if (indexName.equals(response.getIndex()) == false) { + mismatchDescription.appendText(" index name ").appendValue(response.getIndex()).appendText(" is incorrect "); + return false; + } + if (documentId.equals(response.getId()) == false) { + mismatchDescription.appendText(" id ").appendValue(response.getId()).appendText(" is incorrect "); + return false; + } + if (response.isExists()) { + mismatchDescription.appendText(" document exist what is not desired "); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain document id from index ") + .appendValue(indexName) + .appendText(" with id ") + .appendValue(documentId) + .appendText(" but document should not be present "); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainsDocumentWithIdMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainsDocumentWithIdMatcher.java index 5dd0c72576..aa9d702243 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainsDocumentWithIdMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseContainsDocumentWithIdMatcher.java @@ -18,38 +18,40 @@ class GetResponseContainsDocumentWithIdMatcher extends TypeSafeDiagnosingMatcher { - private final String indexName; - private final String documentId; - - public GetResponseContainsDocumentWithIdMatcher(String indexName, String documentId) { - this.indexName = requireNonNull(indexName, "Index name is required"); - this.documentId = requireNonNull(documentId, "Document id is required"); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - if(indexName.equals(response.getIndex()) == false ) { - mismatchDescription.appendText("Document should not belong to index ").appendValue(response.getIndex()); - return false; - } - if(documentId.equals(response.getId()) == false) { - mismatchDescription.appendText("Document contain incorrect id which is ").appendValue(response.getId()); - return false; - } - if(response.isExists() == false) { - mismatchDescription.appendText("Document does not exist or is inaccessible"); - return false; - } - if(response.isSourceEmpty()) { - mismatchDescription.appendText("Document source is empty"); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain document from index ").appendValue(indexName).appendText(" with id ") - .appendValue(documentId); - } + private final String indexName; + private final String documentId; + + public GetResponseContainsDocumentWithIdMatcher(String indexName, String documentId) { + this.indexName = requireNonNull(indexName, "Index name is required"); + this.documentId = requireNonNull(documentId, "Document id is required"); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + if (indexName.equals(response.getIndex()) == false) { + mismatchDescription.appendText("Document should not belong to index ").appendValue(response.getIndex()); + return false; + } + if (documentId.equals(response.getId()) == false) { + mismatchDescription.appendText("Document contain incorrect id which is ").appendValue(response.getId()); + return false; + } + if (response.isExists() == false) { + mismatchDescription.appendText("Document does not exist or is inaccessible"); + return false; + } + if (response.isSourceEmpty()) { + mismatchDescription.appendText("Document source is empty"); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain document from index ") + .appendValue(indexName) + .appendText(" with id ") + .appendValue(documentId); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentContainsExactlyFieldsWithNamesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentContainsExactlyFieldsWithNamesMatcher.java index aa8daa0128..66bdc0a9b7 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentContainsExactlyFieldsWithNamesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentContainsExactlyFieldsWithNamesMatcher.java @@ -21,29 +21,31 @@ class GetResponseDocumentContainsExactlyFieldsWithNamesMatcher extends TypeSafeDiagnosingMatcher { - private final Set expectedFieldsNames; - - GetResponseDocumentContainsExactlyFieldsWithNamesMatcher(String... expectedFieldsNames) { - if (isNull(expectedFieldsNames) || expectedFieldsNames.length == 0) { - throw new IllegalArgumentException("expectedFieldsNames cannot be null or empty"); - } - this.expectedFieldsNames = Set.of(expectedFieldsNames); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - Map sourceMap = response.getSourceAsMap(); - Set actualFieldsNames = sourceMap.keySet(); - if (!expectedFieldsNames.equals(actualFieldsNames)) { - mismatchDescription.appendValue("Document with id ").appendValue(response.getId()) - .appendText(" contains fields with names: ").appendValue(actualFieldsNames); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Document contain exactly fields with names: ").appendValue(expectedFieldsNames); - } + private final Set expectedFieldsNames; + + GetResponseDocumentContainsExactlyFieldsWithNamesMatcher(String... expectedFieldsNames) { + if (isNull(expectedFieldsNames) || expectedFieldsNames.length == 0) { + throw new IllegalArgumentException("expectedFieldsNames cannot be null or empty"); + } + this.expectedFieldsNames = Set.of(expectedFieldsNames); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + Map sourceMap = response.getSourceAsMap(); + Set actualFieldsNames = sourceMap.keySet(); + if (!expectedFieldsNames.equals(actualFieldsNames)) { + mismatchDescription.appendValue("Document with id ") + .appendValue(response.getId()) + .appendText(" contains fields with names: ") + .appendValue(actualFieldsNames); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Document contain exactly fields with names: ").appendValue(expectedFieldsNames); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentDoesNotContainFieldMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentDoesNotContainFieldMatcher.java index f8f81f0e95..508e5b8b61 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentDoesNotContainFieldMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentDoesNotContainFieldMatcher.java @@ -20,28 +20,28 @@ class GetResponseDocumentDoesNotContainFieldMatcher extends TypeSafeDiagnosingMatcher { - private final String fieldName; - - public GetResponseDocumentDoesNotContainFieldMatcher(String fieldName) { - this.fieldName = requireNonNull(fieldName, "Field name is required."); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - Map source = response.getSource(); - if(source == null) { - mismatchDescription.appendText("Source is not available in search results"); - return false; - } - if(source.containsKey(fieldName)) { - mismatchDescription.appendText("Document contains field ").appendValue(fieldName); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Document does not contain field ").appendValue(fieldName); - } + private final String fieldName; + + public GetResponseDocumentDoesNotContainFieldMatcher(String fieldName) { + this.fieldName = requireNonNull(fieldName, "Field name is required."); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + Map source = response.getSource(); + if (source == null) { + mismatchDescription.appendText("Source is not available in search results"); + return false; + } + if (source.containsKey(fieldName)) { + mismatchDescription.appendText("Document contains field ").appendValue(fieldName); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Document does not contain field ").appendValue(fieldName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentFieldValueMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentFieldValueMatcher.java index 72418fe6e0..78bcae5494 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentFieldValueMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseDocumentFieldValueMatcher.java @@ -20,36 +20,38 @@ class GetResponseDocumentFieldValueMatcher extends TypeSafeDiagnosingMatcher { - private final String fieldName; - private final Object fieldValue; - - public GetResponseDocumentFieldValueMatcher(String fieldName, Object fieldValue) { - this.fieldName = requireNonNull(fieldName, "Field name is required."); - this.fieldValue = requireNonNull(fieldValue, "Field value is required."); - } - - @Override - protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { - Map source = response.getSource(); - if(source == null) { - mismatchDescription.appendText("Source is not available in search results"); - return false; - } - if(source.containsKey(fieldName) == false) { - mismatchDescription.appendText("Document does not contain field ").appendValue(fieldName); - return false; - } - Object actualFieldValue = source.get(fieldName); - if(fieldValue.equals(actualFieldValue) == false) { - mismatchDescription.appendText("Field ").appendValue(fieldName).appendText(" has incorrect value ") - .appendValue(actualFieldValue); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Document contain field ").appendValue(fieldName).appendText(" with value ").appendValue(fieldValue); - } + private final String fieldName; + private final Object fieldValue; + + public GetResponseDocumentFieldValueMatcher(String fieldName, Object fieldValue) { + this.fieldName = requireNonNull(fieldName, "Field name is required."); + this.fieldValue = requireNonNull(fieldValue, "Field value is required."); + } + + @Override + protected boolean matchesSafely(GetResponse response, Description mismatchDescription) { + Map source = response.getSource(); + if (source == null) { + mismatchDescription.appendText("Source is not available in search results"); + return false; + } + if (source.containsKey(fieldName) == false) { + mismatchDescription.appendText("Document does not contain field ").appendValue(fieldName); + return false; + } + Object actualFieldValue = source.get(fieldName); + if (fieldValue.equals(actualFieldValue) == false) { + mismatchDescription.appendText("Field ") + .appendValue(fieldName) + .appendText(" has incorrect value ") + .appendValue(actualFieldValue); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Document contain field ").appendValue(fieldName).appendText(" with value ").appendValue(fieldValue); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseMatchers.java index 6a494dc9cd..89c183fc34 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetResponseMatchers.java @@ -13,27 +13,27 @@ import org.opensearch.action.get.GetResponse; -public class GetResponseMatchers { +public class GetResponseMatchers { - private GetResponseMatchers() {} + private GetResponseMatchers() {} - public static Matcher containDocument(String indexName, String documentId) { - return new GetResponseContainsDocumentWithIdMatcher(indexName, documentId); - } + public static Matcher containDocument(String indexName, String documentId) { + return new GetResponseContainsDocumentWithIdMatcher(indexName, documentId); + } - public static Matcher containOnlyDocumentId(String indexName, String documentId) { - return new GetResponseContainOnlyDocumentIdMatcher(indexName, documentId); - } + public static Matcher containOnlyDocumentId(String indexName, String documentId) { + return new GetResponseContainOnlyDocumentIdMatcher(indexName, documentId); + } - public static Matcher documentContainField(String fieldName, Object fieldValue) { - return new GetResponseDocumentFieldValueMatcher(fieldName, fieldValue); - } + public static Matcher documentContainField(String fieldName, Object fieldValue) { + return new GetResponseDocumentFieldValueMatcher(fieldName, fieldValue); + } - public static Matcher documentDoesNotContainField(String fieldName) { - return new GetResponseDocumentDoesNotContainFieldMatcher(fieldName); - } + public static Matcher documentDoesNotContainField(String fieldName) { + return new GetResponseDocumentDoesNotContainFieldMatcher(fieldName); + } - public static Matcher documentContainsExactlyFieldsWithNames(String... expectedFieldsNames) { - return new GetResponseDocumentContainsExactlyFieldsWithNamesMatcher(expectedFieldsNames); - } + public static Matcher documentContainsExactlyFieldsWithNames(String... expectedFieldsNames) { + return new GetResponseDocumentContainsExactlyFieldsWithNamesMatcher(expectedFieldsNames); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetSettingsResponseContainsIndicesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetSettingsResponseContainsIndicesMatcher.java index d88b65875e..c96deef001 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/GetSettingsResponseContainsIndicesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/GetSettingsResponseContainsIndicesMatcher.java @@ -21,32 +21,30 @@ class GetSettingsResponseContainsIndicesMatcher extends TypeSafeDiagnosingMatcher { - private final String[] expectedIndices; - - GetSettingsResponseContainsIndicesMatcher(String[] expectedIndices) { - if (isNull(expectedIndices) || 0 == expectedIndices.length) { - throw new IllegalArgumentException("expectedIndices cannot be null or empty"); - } - this.expectedIndices = expectedIndices; - } - - @Override - protected boolean matchesSafely(GetSettingsResponse response, Description mismatchDescription) { - - final Map indexToSettings = response.getIndexToSettings(); - for (String index : expectedIndices) { - if (!indexToSettings.containsKey(index)) { - mismatchDescription - .appendText("Response contains settings of indices: ") - .appendValue(indexToSettings.keySet().toArray()); - return false; - } - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Response should contain settings of indices: ").appendValue(expectedIndices); - } + private final String[] expectedIndices; + + GetSettingsResponseContainsIndicesMatcher(String[] expectedIndices) { + if (isNull(expectedIndices) || 0 == expectedIndices.length) { + throw new IllegalArgumentException("expectedIndices cannot be null or empty"); + } + this.expectedIndices = expectedIndices; + } + + @Override + protected boolean matchesSafely(GetSettingsResponse response, Description mismatchDescription) { + + final Map indexToSettings = response.getIndexToSettings(); + for (String index : expectedIndices) { + if (!indexToSettings.containsKey(index)) { + mismatchDescription.appendText("Response contains settings of indices: ").appendValue(indexToSettings.keySet()); + return false; + } + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Response should contain settings of indices: ").appendValue(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexExistsMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexExistsMatcher.java index 09e76c93e0..aab3d426d2 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexExistsMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexExistsMatcher.java @@ -21,26 +21,29 @@ class IndexExistsMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - - IndexExistsMatcher(String expectedIndexName) { - this.expectedIndexName = requireNonNull(expectedIndexName); - } - - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - IndicesExistsResponse indicesExistsResponse = client.admin().indices().exists(new IndicesExistsRequest(expectedIndexName)).actionGet(); - if (!indicesExistsResponse.isExists()) { - mismatchDescription.appendText("Index ").appendValue(expectedIndexName).appendValue(" does not exist"); - return false; - } - return true; - } - } - - @Override - public void describeTo(Description description) { - description.appendText("Index ").appendValue(expectedIndexName).appendText(" exists"); - } + private final String expectedIndexName; + + IndexExistsMatcher(String expectedIndexName) { + this.expectedIndexName = requireNonNull(expectedIndexName); + } + + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + IndicesExistsResponse indicesExistsResponse = client.admin() + .indices() + .exists(new IndicesExistsRequest(expectedIndexName)) + .actionGet(); + if (!indicesExistsResponse.isExists()) { + mismatchDescription.appendText("Index ").appendValue(expectedIndexName).appendValue(" does not exist"); + return false; + } + return true; + } + } + + @Override + public void describeTo(Description description) { + description.appendText("Index ").appendValue(expectedIndexName).appendText(" exists"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexMappingIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexMappingIsEqualToMatcher.java index b90defef7d..ead0e9d1d7 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexMappingIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexMappingIsEqualToMatcher.java @@ -25,39 +25,43 @@ class IndexMappingIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - private final Map expectedMapping; - - IndexMappingIsEqualToMatcher(String expectedIndexName, Map expectedMapping) { - this.expectedIndexName = requireNonNull(expectedIndexName); - if (isNull(expectedMapping) || expectedMapping.isEmpty()) { - throw new IllegalArgumentException("expectedMapping cannot be null or empty"); - } - this.expectedMapping = expectedMapping; - } - - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - GetMappingsResponse response = client.admin().indices() - .getMappings(new GetMappingsRequest().indices(expectedIndexName)).actionGet(); - - Map actualIndexMapping = response.getMappings().get(expectedIndexName).sourceAsMap(); - - if (!expectedMapping.equals(actualIndexMapping)) { - mismatchDescription.appendText("Actual mapping ").appendValue(actualIndexMapping).appendText(" does not match expected"); - return false; - } - return true; - } catch (IndexNotFoundException e) { - mismatchDescription.appendText("Index: ").appendValue(expectedIndexName).appendText(" does not exist"); - return false; - } - } - - @Override - public void describeTo(Description description) { - description.appendText("Index ").appendValue(expectedIndexName) - .appendText(". Mapping should be equal to: ").appendValue(expectedMapping); - } + private final String expectedIndexName; + private final Map expectedMapping; + + IndexMappingIsEqualToMatcher(String expectedIndexName, Map expectedMapping) { + this.expectedIndexName = requireNonNull(expectedIndexName); + if (isNull(expectedMapping) || expectedMapping.isEmpty()) { + throw new IllegalArgumentException("expectedMapping cannot be null or empty"); + } + this.expectedMapping = expectedMapping; + } + + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + GetMappingsResponse response = client.admin() + .indices() + .getMappings(new GetMappingsRequest().indices(expectedIndexName)) + .actionGet(); + + Map actualIndexMapping = response.getMappings().get(expectedIndexName).sourceAsMap(); + + if (!expectedMapping.equals(actualIndexMapping)) { + mismatchDescription.appendText("Actual mapping ").appendValue(actualIndexMapping).appendText(" does not match expected"); + return false; + } + return true; + } catch (IndexNotFoundException e) { + mismatchDescription.appendText("Index: ").appendValue(expectedIndexName).appendText(" does not exist"); + return false; + } + } + + @Override + public void describeTo(Description description) { + description.appendText("Index ") + .appendValue(expectedIndexName) + .appendText(". Mapping should be equal to: ") + .appendValue(expectedMapping); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexResponseMatchers.java index 80d90ecc6b..88f3ac099d 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexResponseMatchers.java @@ -22,36 +22,36 @@ public class IndexResponseMatchers { - public static Matcher isSuccessfulCreateIndexResponse(String expectedIndexName) { - return new SuccessfulCreateIndexResponseMatcher(expectedIndexName); - } + public static Matcher isSuccessfulCreateIndexResponse(String expectedIndexName) { + return new SuccessfulCreateIndexResponseMatcher(expectedIndexName); + } - public static Matcher getIndexResponseContainsIndices(String... expectedIndices) { - return new GetIndexResponseContainsIndicesMatcher(expectedIndices); - } + public static Matcher getIndexResponseContainsIndices(String... expectedIndices) { + return new GetIndexResponseContainsIndicesMatcher(expectedIndices); + } - public static Matcher isSuccessfulCloseIndexResponse() { - return new SuccessfulCloseIndexResponseMatcher(); - } + public static Matcher isSuccessfulCloseIndexResponse() { + return new SuccessfulCloseIndexResponseMatcher(); + } - public static Matcher isSuccessfulOpenIndexResponse() { - return new SuccessfulOpenIndexResponseMatcher(); - } + public static Matcher isSuccessfulOpenIndexResponse() { + return new SuccessfulOpenIndexResponseMatcher(); + } - public static Matcher isSuccessfulResizeResponse(String expectedIndexName) { - return new SuccessfulResizeResponseMatcher(expectedIndexName); - } + public static Matcher isSuccessfulResizeResponse(String expectedIndexName) { + return new SuccessfulResizeResponseMatcher(expectedIndexName); + } - public static Matcher getSettingsResponseContainsIndices(String... expectedIndices) { - return new GetSettingsResponseContainsIndicesMatcher(expectedIndices); - } + public static Matcher getSettingsResponseContainsIndices(String... expectedIndices) { + return new GetSettingsResponseContainsIndicesMatcher(expectedIndices); + } - public static Matcher isSuccessfulClearIndicesCacheResponse() { - return new SuccessfulClearIndicesCacheResponseMatcher(); - } + public static Matcher isSuccessfulClearIndicesCacheResponse() { + return new SuccessfulClearIndicesCacheResponseMatcher(); + } - public static Matcher getMappingsResponseContainsIndices(String... expectedIndices) { - return new GetMappingsResponseContainsIndicesMatcher(expectedIndices); - } + public static Matcher getMappingsResponseContainsIndices(String... expectedIndices) { + return new GetMappingsResponseContainsIndicesMatcher(expectedIndices); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexSettingsContainValuesMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexSettingsContainValuesMatcher.java index 9af40fcd48..6bb89c6cae 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexSettingsContainValuesMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexSettingsContainValuesMatcher.java @@ -24,45 +24,52 @@ class IndexSettingsContainValuesMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - private final Settings expectedSettings; + private final String expectedIndexName; + private final Settings expectedSettings; - IndexSettingsContainValuesMatcher(String expectedIndexName, Settings expectedSettings) { - this.expectedIndexName = requireNonNull(expectedIndexName); - if (isNull(expectedSettings) || expectedSettings.isEmpty()) { - throw new IllegalArgumentException("expectedSettings cannot be null or empty"); - } - this.expectedSettings = expectedSettings; - } + IndexSettingsContainValuesMatcher(String expectedIndexName, Settings expectedSettings) { + this.expectedIndexName = requireNonNull(expectedIndexName); + if (isNull(expectedSettings) || expectedSettings.isEmpty()) { + throw new IllegalArgumentException("expectedSettings cannot be null or empty"); + } + this.expectedSettings = expectedSettings; + } - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - GetSettingsResponse response = client.admin().indices().getSettings(new GetSettingsRequest().indices(expectedIndexName)).actionGet(); + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + GetSettingsResponse response = client.admin() + .indices() + .getSettings(new GetSettingsRequest().indices(expectedIndexName)) + .actionGet(); - Settings actualSettings = response.getIndexToSettings().get(expectedIndexName); + Settings actualSettings = response.getIndexToSettings().get(expectedIndexName); - for (String setting : expectedSettings.keySet()) { - if (isNull(actualSettings.get(setting))) { - mismatchDescription.appendValue("Value of ").appendValue(setting).appendText(" property is missing"); - return false; - } - if (!expectedSettings.get(setting).equals(actualSettings.get(setting))) { - mismatchDescription.appendText("Actual value of `").appendValue(setting) - .appendText("` property: ").appendValue(actualSettings.get(setting)); - return false; - } - } - return true; - } catch (IndexNotFoundException e) { - mismatchDescription.appendText("Index: ").appendValue(expectedIndexName).appendText(" does not exist"); - return false; - } - } + for (String setting : expectedSettings.keySet()) { + if (isNull(actualSettings.get(setting))) { + mismatchDescription.appendValue("Value of ").appendValue(setting).appendText(" property is missing"); + return false; + } + if (!expectedSettings.get(setting).equals(actualSettings.get(setting))) { + mismatchDescription.appendText("Actual value of `") + .appendValue(setting) + .appendText("` property: ") + .appendValue(actualSettings.get(setting)); + return false; + } + } + return true; + } catch (IndexNotFoundException e) { + mismatchDescription.appendText("Index: ").appendValue(expectedIndexName).appendText(" does not exist"); + return false; + } + } - @Override - public void describeTo(Description description) { - description.appendText("Settings of index ").appendValue(expectedIndexName) - .appendText(" should contain values: ").appendValue(expectedSettings); - } + @Override + public void describeTo(Description description) { + description.appendText("Settings of index ") + .appendValue(expectedIndexName) + .appendText(" should contain values: ") + .appendValue(expectedSettings); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexStateIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexStateIsEqualToMatcher.java index ecff3fe2df..87270b1388 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexStateIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/IndexStateIsEqualToMatcher.java @@ -24,36 +24,38 @@ class IndexStateIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - private final IndexMetadata.State expectedState; - - IndexStateIsEqualToMatcher(String expectedIndexName, IndexMetadata.State expectedState) { - this.expectedIndexName = requireNonNull(expectedIndexName); - this.expectedState = requireNonNull(expectedState); - } - - @Override - protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { - try(Client client = cluster.getInternalNodeClient()) { - ClusterStateRequest clusterStateRequest = new ClusterStateRequest().indices(expectedIndexName); - ClusterStateResponse clusterStateResponse = client.admin().cluster().state(clusterStateRequest).actionGet(); - - Map indicesMetadata = clusterStateResponse.getState().getMetadata().indices(); - if (!indicesMetadata.containsKey(expectedIndexName)) { - mismatchDescription.appendValue("Index does not exist"); - } - IndexMetadata indexMetadata = indicesMetadata.get(expectedIndexName); - if (expectedState != indexMetadata.getState()) { - mismatchDescription.appendValue("Actual index state is equal to ").appendValue(indexMetadata.getState().name()); - return false; - } - return true; - } - } - - @Override - public void describeTo(Description description) { - description.appendText("Index: ").appendValue(expectedIndexName) - .appendText(" . State should be equal to ").appendValue(expectedState.name()); - } + private final String expectedIndexName; + private final IndexMetadata.State expectedState; + + IndexStateIsEqualToMatcher(String expectedIndexName, IndexMetadata.State expectedState) { + this.expectedIndexName = requireNonNull(expectedIndexName); + this.expectedState = requireNonNull(expectedState); + } + + @Override + protected boolean matchesSafely(LocalCluster cluster, Description mismatchDescription) { + try (Client client = cluster.getInternalNodeClient()) { + ClusterStateRequest clusterStateRequest = new ClusterStateRequest().indices(expectedIndexName); + ClusterStateResponse clusterStateResponse = client.admin().cluster().state(clusterStateRequest).actionGet(); + + Map indicesMetadata = clusterStateResponse.getState().getMetadata().indices(); + if (!indicesMetadata.containsKey(expectedIndexName)) { + mismatchDescription.appendValue("Index does not exist"); + } + IndexMetadata indexMetadata = indicesMetadata.get(expectedIndexName); + if (expectedState != indexMetadata.getState()) { + mismatchDescription.appendValue("Actual index state is equal to ").appendValue(indexMetadata.getState().name()); + return false; + } + return true; + } + } + + @Override + public void describeTo(Description description) { + description.appendText("Index: ") + .appendValue(expectedIndexName) + .appendText(" . State should be equal to ") + .appendValue(expectedState.name()); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiGetResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiGetResponseMatchers.java index 30b3037752..c2e86b1310 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiGetResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiGetResponseMatchers.java @@ -15,15 +15,14 @@ public class MultiGetResponseMatchers { - private MultiGetResponseMatchers() { - } + private MultiGetResponseMatchers() {} - public static Matcher isSuccessfulMultiGetResponse() { - return new SuccessfulMultiGetResponseMatcher(); - } + public static Matcher isSuccessfulMultiGetResponse() { + return new SuccessfulMultiGetResponseMatcher(); + } - public static Matcher numberOfGetItemResponsesIsEqualTo(int expectedNumberOfResponses) { - return new NumberOfGetItemResponsesIsEqualToMatcher(expectedNumberOfResponses); - } + public static Matcher numberOfGetItemResponsesIsEqualTo(int expectedNumberOfResponses) { + return new NumberOfGetItemResponsesIsEqualToMatcher(expectedNumberOfResponses); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiSearchResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiSearchResponseMatchers.java index 39a2645ce4..9709249d11 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiSearchResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/MultiSearchResponseMatchers.java @@ -15,15 +15,14 @@ public class MultiSearchResponseMatchers { - private MultiSearchResponseMatchers() { - } + private MultiSearchResponseMatchers() {} - public static Matcher isSuccessfulMultiSearchResponse() { - return new SuccessfulMultiSearchResponseMatcher(); - } + public static Matcher isSuccessfulMultiSearchResponse() { + return new SuccessfulMultiSearchResponseMatcher(); + } - public static Matcher numberOfSearchItemResponsesIsEqualTo(int expectedNumberOfResponses) { - return new NumberOfSearchItemResponsesIsEqualToMatcher(expectedNumberOfResponses); - } + public static Matcher numberOfSearchItemResponsesIsEqualTo(int expectedNumberOfResponses) { + return new NumberOfSearchItemResponsesIsEqualToMatcher(expectedNumberOfResponses); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfFieldsIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfFieldsIsEqualToMatcher.java index a11d360b98..ad8e9725c3 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfFieldsIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfFieldsIsEqualToMatcher.java @@ -16,24 +16,23 @@ class NumberOfFieldsIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfFields; + private final int expectedNumberOfFields; - NumberOfFieldsIsEqualToMatcher(int expectedNumberOfFields) { - this.expectedNumberOfFields = expectedNumberOfFields; - } + NumberOfFieldsIsEqualToMatcher(int expectedNumberOfFields) { + this.expectedNumberOfFields = expectedNumberOfFields; + } - @Override - protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { - if (expectedNumberOfFields != response.get().size()) { - mismatchDescription.appendText("Actual number of fields: ").appendValue(response.get().size()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(FieldCapabilitiesResponse response, Description mismatchDescription) { + if (expectedNumberOfFields != response.get().size()) { + mismatchDescription.appendText("Actual number of fields: ").appendValue(response.get().size()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Response contains information about ") - .appendValue(expectedNumberOfFields).appendText(" fields"); - } + @Override + public void describeTo(Description description) { + description.appendText("Response contains information about ").appendValue(expectedNumberOfFields).appendText(" fields"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfGetItemResponsesIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfGetItemResponsesIsEqualToMatcher.java index 141b235f2f..38cfaeb130 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfGetItemResponsesIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfGetItemResponsesIsEqualToMatcher.java @@ -16,25 +16,23 @@ class NumberOfGetItemResponsesIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfResponses; - - NumberOfGetItemResponsesIsEqualToMatcher(int expectedNumberOfResponses) { - this.expectedNumberOfResponses = expectedNumberOfResponses; - } - - - @Override - protected boolean matchesSafely(MultiGetResponse response, Description mismatchDescription) { - if (expectedNumberOfResponses != response.getResponses().length) { - mismatchDescription.appendText("Actual number of responses: ").appendValue(response.getResponses().length); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Multi get response contains: ").appendValue(expectedNumberOfResponses) - .appendText(" item responses"); - } + private final int expectedNumberOfResponses; + + NumberOfGetItemResponsesIsEqualToMatcher(int expectedNumberOfResponses) { + this.expectedNumberOfResponses = expectedNumberOfResponses; + } + + @Override + protected boolean matchesSafely(MultiGetResponse response, Description mismatchDescription) { + if (expectedNumberOfResponses != response.getResponses().length) { + mismatchDescription.appendText("Actual number of responses: ").appendValue(response.getResponses().length); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Multi get response contains: ").appendValue(expectedNumberOfResponses).appendText(" item responses"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfHitsInPageIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfHitsInPageIsEqualToMatcher.java index b8671bb885..8a25a336f3 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfHitsInPageIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfHitsInPageIsEqualToMatcher.java @@ -17,29 +17,29 @@ class NumberOfHitsInPageIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfHits; + private final int expectedNumberOfHits; - public NumberOfHitsInPageIsEqualToMatcher(int expectedNumberOfHits) { - this.expectedNumberOfHits = expectedNumberOfHits; - } + public NumberOfHitsInPageIsEqualToMatcher(int expectedNumberOfHits) { + this.expectedNumberOfHits = expectedNumberOfHits; + } - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - SearchHits hits = searchResponse.getHits(); - if((hits == null) || (hits.getHits() == null)) { - mismatchDescription.appendText("contains null hits"); - return false; - } - int actualNumberOfHits = hits.getHits().length; - if(expectedNumberOfHits != actualNumberOfHits) { - mismatchDescription.appendText("actual number of hits is equal to ").appendValue(actualNumberOfHits); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + SearchHits hits = searchResponse.getHits(); + if ((hits == null) || (hits.getHits() == null)) { + mismatchDescription.appendText("contains null hits"); + return false; + } + int actualNumberOfHits = hits.getHits().length; + if (expectedNumberOfHits != actualNumberOfHits) { + mismatchDescription.appendText("actual number of hits is equal to ").appendValue(actualNumberOfHits); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Number of hits on current page should be equal to ").appendValue(expectedNumberOfHits); - } + @Override + public void describeTo(Description description) { + description.appendText("Number of hits on current page should be equal to ").appendValue(expectedNumberOfHits); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfSearchItemResponsesIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfSearchItemResponsesIsEqualToMatcher.java index 971473148c..54bb83cba7 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfSearchItemResponsesIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfSearchItemResponsesIsEqualToMatcher.java @@ -16,26 +16,24 @@ class NumberOfSearchItemResponsesIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfResponses; - - NumberOfSearchItemResponsesIsEqualToMatcher(int expectedNumberOfResponses) { - this.expectedNumberOfResponses = expectedNumberOfResponses; - } - - - @Override - protected boolean matchesSafely(MultiSearchResponse response, Description mismatchDescription) { - if (expectedNumberOfResponses != response.getResponses().length) { - mismatchDescription.appendText("Actual number of responses: ").appendValue(response.getResponses().length); - return false; - } - - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Multi search response contains: ").appendValue(expectedNumberOfResponses) - .appendText(" item responses"); - } + private final int expectedNumberOfResponses; + + NumberOfSearchItemResponsesIsEqualToMatcher(int expectedNumberOfResponses) { + this.expectedNumberOfResponses = expectedNumberOfResponses; + } + + @Override + protected boolean matchesSafely(MultiSearchResponse response, Description mismatchDescription) { + if (expectedNumberOfResponses != response.getResponses().length) { + mismatchDescription.appendText("Actual number of responses: ").appendValue(response.getResponses().length); + return false; + } + + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Multi search response contains: ").appendValue(expectedNumberOfResponses).appendText(" item responses"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfTotalHitsIsEqualToMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfTotalHitsIsEqualToMatcher.java index 3045da00b1..3f2b379498 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfTotalHitsIsEqualToMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/NumberOfTotalHitsIsEqualToMatcher.java @@ -21,37 +21,39 @@ class NumberOfTotalHitsIsEqualToMatcher extends TypeSafeDiagnosingMatcher { - private final int expectedNumberOfHits; - - NumberOfTotalHitsIsEqualToMatcher(int expectedNumberOfHits) { - this.expectedNumberOfHits = expectedNumberOfHits; - } - - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - SearchHits hits = searchResponse.getHits(); - if(hits == null) { - mismatchDescription.appendText("contains null hits"); - return false; - } - TotalHits totalHits = hits.getTotalHits(); - if(totalHits == null) { - mismatchDescription.appendText("Total hits number is null."); - return false; - } - if(expectedNumberOfHits != totalHits.value) { - String documentIds = Arrays.stream(searchResponse.getHits().getHits()) - .map(hit -> hit.getIndex() + "/" + hit.getId()) - .collect(Collectors.joining(",")); - mismatchDescription.appendText( "contains ").appendValue(hits.getHits().length).appendText(" hits, found document ids ") - .appendValue(documentIds); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Search response should contains ").appendValue(expectedNumberOfHits).appendText(" hits"); - } + private final int expectedNumberOfHits; + + NumberOfTotalHitsIsEqualToMatcher(int expectedNumberOfHits) { + this.expectedNumberOfHits = expectedNumberOfHits; + } + + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + SearchHits hits = searchResponse.getHits(); + if (hits == null) { + mismatchDescription.appendText("contains null hits"); + return false; + } + TotalHits totalHits = hits.getTotalHits(); + if (totalHits == null) { + mismatchDescription.appendText("Total hits number is null."); + return false; + } + if (expectedNumberOfHits != totalHits.value) { + String documentIds = Arrays.stream(searchResponse.getHits().getHits()) + .map(hit -> hit.getIndex() + "/" + hit.getId()) + .collect(Collectors.joining(",")); + mismatchDescription.appendText("contains ") + .appendValue(hits.getHits().length) + .appendText(" hits, found document ids ") + .appendValue(documentIds); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Search response should contains ").appendValue(expectedNumberOfHits).appendText(" hits"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchExceptionMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchExceptionMatchers.java index 008922b4e8..8627e4bda2 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchExceptionMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchExceptionMatchers.java @@ -17,21 +17,21 @@ public class OpenSearchExceptionMatchers { - private OpenSearchExceptionMatchers() {} + private OpenSearchExceptionMatchers() {} - public static Matcher statusException(RestStatus expectedRestStatus) { - return new OpenSearchStatusExceptionMatcher(expectedRestStatus); - } + public static Matcher statusException(RestStatus expectedRestStatus) { + return new OpenSearchStatusExceptionMatcher(expectedRestStatus); + } - public static Matcher errorMessage(Matcher errorMessageMatcher) { - return new ExceptionErrorMessageMatcher(errorMessageMatcher); - } + public static Matcher errorMessage(Matcher errorMessageMatcher) { + return new ExceptionErrorMessageMatcher(errorMessageMatcher); + } - public static Matcher errorMessageContain(String errorMessage) { - return errorMessage(containsString(errorMessage)); - } + public static Matcher errorMessageContain(String errorMessage) { + return errorMessage(containsString(errorMessage)); + } - public static Matcher hasCause(Class clazz) { - return new ExceptionHasCauseMatcher(clazz); - } + public static Matcher hasCause(Class clazz) { + return new ExceptionHasCauseMatcher(clazz); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchStatusExceptionMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchStatusExceptionMatcher.java index 863f1e52a1..118251ec04 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchStatusExceptionMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/OpenSearchStatusExceptionMatcher.java @@ -19,30 +19,34 @@ class OpenSearchStatusExceptionMatcher extends TypeSafeDiagnosingMatcher { - private final RestStatus expectedRestStatus; - - public OpenSearchStatusExceptionMatcher(RestStatus expectedRestStatus) { - this.expectedRestStatus = requireNonNull(expectedRestStatus, "Expected rest status is required."); - } - - @Override - protected boolean matchesSafely(Throwable throwable, Description mismatchDescription) { - if((throwable instanceof OpenSearchException) == false) { - mismatchDescription.appendText("actual exception type is ").appendValue(throwable.getClass().getCanonicalName()) - .appendText(", error message ").appendValue(throwable.getMessage()); - return false; - } - OpenSearchException openSearchException = (OpenSearchException) throwable; - if(expectedRestStatus.equals(openSearchException.status()) == false) { - mismatchDescription.appendText("actual status code is ").appendValue(openSearchException.status()) - .appendText(", error message ").appendValue(throwable.getMessage()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("OpenSearchException with status code ").appendValue(expectedRestStatus); - } + private final RestStatus expectedRestStatus; + + public OpenSearchStatusExceptionMatcher(RestStatus expectedRestStatus) { + this.expectedRestStatus = requireNonNull(expectedRestStatus, "Expected rest status is required."); + } + + @Override + protected boolean matchesSafely(Throwable throwable, Description mismatchDescription) { + if ((throwable instanceof OpenSearchException) == false) { + mismatchDescription.appendText("actual exception type is ") + .appendValue(throwable.getClass().getCanonicalName()) + .appendText(", error message ") + .appendValue(throwable.getMessage()); + return false; + } + OpenSearchException openSearchException = (OpenSearchException) throwable; + if (expectedRestStatus.equals(openSearchException.status()) == false) { + mismatchDescription.appendText("actual status code is ") + .appendValue(openSearchException.status()) + .appendText(", error message ") + .appendValue(throwable.getMessage()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("OpenSearchException with status code ").appendValue(expectedRestStatus); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/PitResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/PitResponseMatchers.java index 3e72866092..84ab459210 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/PitResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/PitResponseMatchers.java @@ -17,22 +17,21 @@ public class PitResponseMatchers { - private PitResponseMatchers() { - } + private PitResponseMatchers() {} - public static Matcher isSuccessfulCreatePitResponse() { - return new SuccessfulCreatePitResponseMatcher(); - } + public static Matcher isSuccessfulCreatePitResponse() { + return new SuccessfulCreatePitResponseMatcher(); + } - public static Matcher getAllResponseContainsExactlyPitWithIds(String... expectedPitIds) { - return new GetAllPitsContainsExactlyIdsResponseMatcher(expectedPitIds); - } + public static Matcher getAllResponseContainsExactlyPitWithIds(String... expectedPitIds) { + return new GetAllPitsContainsExactlyIdsResponseMatcher(expectedPitIds); + } - public static Matcher isSuccessfulDeletePitResponse() { - return new SuccessfulDeletePitResponseMatcher(); - } + public static Matcher isSuccessfulDeletePitResponse() { + return new SuccessfulDeletePitResponseMatcher(); + } - public static Matcher deleteResponseContainsExactlyPitWithIds(String... expectedPitIds) { - return new DeletePitContainsExactlyIdsResponseMatcher(expectedPitIds); - } + public static Matcher deleteResponseContainsExactlyPitWithIds(String... expectedPitIds) { + return new DeletePitContainsExactlyIdsResponseMatcher(expectedPitIds); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitContainsFieldWithValueMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitContainsFieldWithValueMatcher.java index aa9cfe6864..c92924ebfe 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitContainsFieldWithValueMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitContainsFieldWithValueMatcher.java @@ -21,49 +21,54 @@ class SearchHitContainsFieldWithValueMatcher extends TypeSafeDiagnosingMatcher { - private final int hitIndex; + private final int hitIndex; - private final String fieldName; + private final String fieldName; - private final T expectedValue; + private final T expectedValue; - SearchHitContainsFieldWithValueMatcher(int hitIndex, String fieldName, T expectedValue) { - this.hitIndex = hitIndex; - this.fieldName = fieldName; - this.expectedValue = expectedValue; - } + SearchHitContainsFieldWithValueMatcher(int hitIndex, String fieldName, T expectedValue) { + this.hitIndex = hitIndex; + this.fieldName = fieldName; + this.expectedValue = expectedValue; + } - @Override protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - Long numberOfHits = readTotalHits(searchResponse); - if(numberOfHits == null) { - mismatchDescription.appendText("Total number of hits is unknown."); - return false; - } - if(hitIndex >= numberOfHits) { - mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); - return false; - } - SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); - Map source = searchHit.getSourceAsMap(); - if(source == null){ - mismatchDescription.appendText("Source document is null, is fetch source option set to true?"); - return false; - } - if(source.containsKey(fieldName) == false) { - mismatchDescription.appendText("Document does not contain field ").appendValue(fieldName); - return false; - } - Object actualValue = source.get(fieldName); - if(!expectedValue.equals(actualValue)) { - mismatchDescription.appendText("Field value is equal to ").appendValue(actualValue); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + Long numberOfHits = readTotalHits(searchResponse); + if (numberOfHits == null) { + mismatchDescription.appendText("Total number of hits is unknown."); + return false; + } + if (hitIndex >= numberOfHits) { + mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); + return false; + } + SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); + Map source = searchHit.getSourceAsMap(); + if (source == null) { + mismatchDescription.appendText("Source document is null, is fetch source option set to true?"); + return false; + } + if (source.containsKey(fieldName) == false) { + mismatchDescription.appendText("Document does not contain field ").appendValue(fieldName); + return false; + } + Object actualValue = source.get(fieldName); + if (!expectedValue.equals(actualValue)) { + mismatchDescription.appendText("Field value is equal to ").appendValue(actualValue); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Search hit with index ").appendValue(hitIndex).appendText(" should contain field ").appendValue(fieldName) - .appendValue(" with value equal to ").appendValue(expectedValue); - } + @Override + public void describeTo(Description description) { + description.appendText("Search hit with index ") + .appendValue(hitIndex) + .appendText(" should contain field ") + .appendValue(fieldName) + .appendValue(" with value equal to ") + .appendValue(expectedValue); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitDoesNotContainFieldMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitDoesNotContainFieldMatcher.java index 106f2ee943..0562acdcbb 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitDoesNotContainFieldMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitDoesNotContainFieldMatcher.java @@ -22,42 +22,44 @@ class SearchHitDoesNotContainFieldMatcher extends TypeSafeDiagnosingMatcher { - private final int hitIndex; - - private final String fieldName; - - public SearchHitDoesNotContainFieldMatcher(int hitIndex, String fieldName) { - this.hitIndex = hitIndex; - this.fieldName = requireNonNull(fieldName, "Field name is required."); - } - - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - Long numberOfHits = readTotalHits(searchResponse); - if(numberOfHits == null) { - mismatchDescription.appendText("Total number of hits is unknown."); - return false; - } - if(hitIndex >= numberOfHits) { - mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); - return false; - } - SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); - Map source = searchHit.getSourceAsMap(); - if(source == null){ - mismatchDescription.appendText("Source document is null, is fetch source option set to true?"); - return false; - } - if(source.containsKey(fieldName)) { - mismatchDescription.appendText(" document contains field ").appendValue(fieldName); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("search hit with index ").appendValue(hitIndex).appendText(" does not contain field ") - .appendValue(fieldName); - } + private final int hitIndex; + + private final String fieldName; + + public SearchHitDoesNotContainFieldMatcher(int hitIndex, String fieldName) { + this.hitIndex = hitIndex; + this.fieldName = requireNonNull(fieldName, "Field name is required."); + } + + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + Long numberOfHits = readTotalHits(searchResponse); + if (numberOfHits == null) { + mismatchDescription.appendText("Total number of hits is unknown."); + return false; + } + if (hitIndex >= numberOfHits) { + mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); + return false; + } + SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); + Map source = searchHit.getSourceAsMap(); + if (source == null) { + mismatchDescription.appendText("Source document is null, is fetch source option set to true?"); + return false; + } + if (source.containsKey(fieldName)) { + mismatchDescription.appendText(" document contains field ").appendValue(fieldName); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("search hit with index ") + .appendValue(hitIndex) + .appendText(" does not contain field ") + .appendValue(fieldName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentWithIdMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentWithIdMatcher.java index c3a7528432..d21df7a578 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentWithIdMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentWithIdMatcher.java @@ -19,42 +19,46 @@ class SearchHitsContainDocumentWithIdMatcher extends TypeSafeDiagnosingMatcher { - private final int hitIndex; - private final String indexName; - private final String id; - - public SearchHitsContainDocumentWithIdMatcher(int hitIndex, String indexName, String id) { - this.hitIndex = hitIndex; - this.indexName = indexName; - this.id = id; - } - - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - Long numberOfHits = readTotalHits(searchResponse); - if(numberOfHits == null) { - mismatchDescription.appendText("Number of total hits is unknown."); - return false; - } - if(hitIndex >= numberOfHits) { - mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); - return false; - } - SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); - if(indexName.equals(searchHit.getIndex()) == false) { - mismatchDescription.appendText("document is part of another index ").appendValue(indexName); - return false; - } - if(id.equals(searchHit.getId()) == false) { - mismatchDescription.appendText("Document has another id which is ").appendValue(searchHit.getId()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Search hit with index ").appendValue(hitIndex).appendText(" should contains document which is part of index ") - .appendValue(indexName).appendValue(" and has id ").appendValue(id); - } + private final int hitIndex; + private final String indexName; + private final String id; + + public SearchHitsContainDocumentWithIdMatcher(int hitIndex, String indexName, String id) { + this.hitIndex = hitIndex; + this.indexName = indexName; + this.id = id; + } + + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + Long numberOfHits = readTotalHits(searchResponse); + if (numberOfHits == null) { + mismatchDescription.appendText("Number of total hits is unknown."); + return false; + } + if (hitIndex >= numberOfHits) { + mismatchDescription.appendText("Search result contain only ").appendValue(numberOfHits).appendText(" hits"); + return false; + } + SearchHit searchHit = searchResponse.getHits().getAt(hitIndex); + if (indexName.equals(searchHit.getIndex()) == false) { + mismatchDescription.appendText("document is part of another index ").appendValue(indexName); + return false; + } + if (id.equals(searchHit.getId()) == false) { + mismatchDescription.appendText("Document has another id which is ").appendValue(searchHit.getId()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Search hit with index ") + .appendValue(hitIndex) + .appendText(" should contains document which is part of index ") + .appendValue(indexName) + .appendValue(" and has id ") + .appendValue(id); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentsInAnyOrderMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentsInAnyOrderMatcher.java index 78fd20557e..28bf13e321 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentsInAnyOrderMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchHitsContainDocumentsInAnyOrderMatcher.java @@ -26,49 +26,51 @@ class SearchHitsContainDocumentsInAnyOrderMatcher extends TypeSafeDiagnosingMatcher { - /** - * Pair contain index name and document id - */ - private final List> documentIds; + /** + * Pair contain index name and document id + */ + private final List> documentIds; - /** - * - * @param documentIds Pair contain index name and document id - */ - public SearchHitsContainDocumentsInAnyOrderMatcher(List> documentIds) { - this.documentIds = requireNonNull(documentIds, "Document ids are required."); - } + /** + * + * @param documentIds Pair contain index name and document id + */ + public SearchHitsContainDocumentsInAnyOrderMatcher(List> documentIds) { + this.documentIds = requireNonNull(documentIds, "Document ids are required."); + } - @Override - protected boolean matchesSafely(SearchResponse response, Description mismatchDescription) { - SearchHits hits = response.getHits(); - if(hits == null) { - mismatchDescription.appendText("Search response does not contains hits (null)."); - return false; - } - SearchHit[] hitsArray = hits.getHits(); - if(hitsArray == null) { - mismatchDescription.appendText("Search hits array is null"); - return false; - } - Set> actualDocumentIds = Arrays.stream(hitsArray) - .map(result -> Pair.of(result.getIndex(), result.getId())) - .collect(Collectors.toSet()); - for(Pair desiredDocumentId : documentIds) { - if(actualDocumentIds.contains(desiredDocumentId) == false) { - mismatchDescription.appendText("search result does not contain document with id ") - .appendValue(desiredDocumentId.getKey()).appendText("/").appendValue(desiredDocumentId.getValue()); - return false; - } - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse response, Description mismatchDescription) { + SearchHits hits = response.getHits(); + if (hits == null) { + mismatchDescription.appendText("Search response does not contains hits (null)."); + return false; + } + SearchHit[] hitsArray = hits.getHits(); + if (hitsArray == null) { + mismatchDescription.appendText("Search hits array is null"); + return false; + } + Set> actualDocumentIds = Arrays.stream(hitsArray) + .map(result -> Pair.of(result.getIndex(), result.getId())) + .collect(Collectors.toSet()); + for (Pair desiredDocumentId : documentIds) { + if (actualDocumentIds.contains(desiredDocumentId) == false) { + mismatchDescription.appendText("search result does not contain document with id ") + .appendValue(desiredDocumentId.getKey()) + .appendText("/") + .appendValue(desiredDocumentId.getValue()); + return false; + } + } + return true; + } - @Override - public void describeTo(Description description) { - String documentIdsString = documentIds.stream() - .map(pair -> pair.getKey() + "/" + pair.getValue()) - .collect(Collectors.joining(", ")); - description.appendText("Search response should contains following documents ").appendValue(documentIdsString); - } + @Override + public void describeTo(Description description) { + String documentIdsString = documentIds.stream() + .map(pair -> pair.getKey() + "/" + pair.getValue()) + .collect(Collectors.joining(", ")); + description.appendText("Search response should contains following documents ").appendValue(documentIdsString); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseMatchers.java index acb669a85e..c0a484b47c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseMatchers.java @@ -22,64 +22,66 @@ public class SearchResponseMatchers { - private SearchResponseMatchers() {} - - public static Matcher isSuccessfulSearchResponse() { - return new SuccessfulSearchResponseMatcher(); - } - - public static Matcher numberOfTotalHitsIsEqualTo(int expectedNumberOfHits) { - return new NumberOfTotalHitsIsEqualToMatcher(expectedNumberOfHits); - } - - public static Matcher numberOfHitsInPageIsEqualTo(int expectedNumberOfHits) { - return new NumberOfHitsInPageIsEqualToMatcher(expectedNumberOfHits); - } - - public static Matcher searchHitContainsFieldWithValue(int hitIndex, String fieldName, T expectedValue) { - return new SearchHitContainsFieldWithValueMatcher<>(hitIndex, fieldName, expectedValue); - } - - public static Matcher searchHitDoesNotContainField(int hitIndex, String fieldName) { - return new SearchHitDoesNotContainFieldMatcher(hitIndex, fieldName); - } - - - public static Matcher searchHitsContainDocumentWithId(int hitIndex, String indexName, String documentId) { - return new SearchHitsContainDocumentWithIdMatcher(hitIndex, indexName, documentId); - } - - public static Matcher restStatusIs(RestStatus expectedRestStatus) { - return new SearchResponseWithStatusCodeMatcher(expectedRestStatus); - } - - public static Matcher containNotEmptyScrollingId() { - return new ContainNotEmptyScrollingIdMatcher(); - } - - public static Matcher containAggregationWithNameAndType(String expectedAggregationName, String expectedAggregationType) { - return new ContainsAggregationWithNameAndTypeMatcher(expectedAggregationName, expectedAggregationType); - } - - /** - * Matcher checks if search result contains all expected documents - * - * @param documentIds Pair contain index name and document id - * @return matcher - */ - public static Matcher searchHitsContainDocumentsInAnyOrder(List> documentIds) { - return new SearchHitsContainDocumentsInAnyOrderMatcher(documentIds); - } - - public static Matcher searchHitsContainDocumentsInAnyOrder(Pair...documentIds) { - return new SearchHitsContainDocumentsInAnyOrderMatcher(Arrays.asList(documentIds)); - } - - static Long readTotalHits(SearchResponse searchResponse) { - return Optional.ofNullable(searchResponse) - .map(SearchResponse::getHits) - .map(SearchHits::getTotalHits) - .map(totalHits -> totalHits.value) - .orElse(null); - } + private SearchResponseMatchers() {} + + public static Matcher isSuccessfulSearchResponse() { + return new SuccessfulSearchResponseMatcher(); + } + + public static Matcher numberOfTotalHitsIsEqualTo(int expectedNumberOfHits) { + return new NumberOfTotalHitsIsEqualToMatcher(expectedNumberOfHits); + } + + public static Matcher numberOfHitsInPageIsEqualTo(int expectedNumberOfHits) { + return new NumberOfHitsInPageIsEqualToMatcher(expectedNumberOfHits); + } + + public static Matcher searchHitContainsFieldWithValue(int hitIndex, String fieldName, T expectedValue) { + return new SearchHitContainsFieldWithValueMatcher<>(hitIndex, fieldName, expectedValue); + } + + public static Matcher searchHitDoesNotContainField(int hitIndex, String fieldName) { + return new SearchHitDoesNotContainFieldMatcher(hitIndex, fieldName); + } + + public static Matcher searchHitsContainDocumentWithId(int hitIndex, String indexName, String documentId) { + return new SearchHitsContainDocumentWithIdMatcher(hitIndex, indexName, documentId); + } + + public static Matcher restStatusIs(RestStatus expectedRestStatus) { + return new SearchResponseWithStatusCodeMatcher(expectedRestStatus); + } + + public static Matcher containNotEmptyScrollingId() { + return new ContainNotEmptyScrollingIdMatcher(); + } + + public static Matcher containAggregationWithNameAndType( + String expectedAggregationName, + String expectedAggregationType + ) { + return new ContainsAggregationWithNameAndTypeMatcher(expectedAggregationName, expectedAggregationType); + } + + /** + * Matcher checks if search result contains all expected documents + * + * @param documentIds Pair contain index name and document id + * @return matcher + */ + public static Matcher searchHitsContainDocumentsInAnyOrder(List> documentIds) { + return new SearchHitsContainDocumentsInAnyOrderMatcher(documentIds); + } + + public static Matcher searchHitsContainDocumentsInAnyOrder(Pair... documentIds) { + return new SearchHitsContainDocumentsInAnyOrderMatcher(Arrays.asList(documentIds)); + } + + static Long readTotalHits(SearchResponse searchResponse) { + return Optional.ofNullable(searchResponse) + .map(SearchResponse::getHits) + .map(SearchHits::getTotalHits) + .map(totalHits -> totalHits.value) + .orElse(null); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseWithStatusCodeMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseWithStatusCodeMatcher.java index 8316cc3425..ede13bcb56 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseWithStatusCodeMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SearchResponseWithStatusCodeMatcher.java @@ -17,23 +17,23 @@ class SearchResponseWithStatusCodeMatcher extends TypeSafeDiagnosingMatcher { - private final RestStatus expectedRestStatus; + private final RestStatus expectedRestStatus; - public SearchResponseWithStatusCodeMatcher(RestStatus expectedRestStatus) { - this.expectedRestStatus = expectedRestStatus; - } + public SearchResponseWithStatusCodeMatcher(RestStatus expectedRestStatus) { + this.expectedRestStatus = expectedRestStatus; + } - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - if(expectedRestStatus.equals(searchResponse.status()) == false) { - mismatchDescription.appendText("actual response status is ").appendValue(searchResponse.status()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + if (expectedRestStatus.equals(searchResponse.status()) == false) { + mismatchDescription.appendText("actual response status is ").appendValue(searchResponse.status()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Expected response status is ").appendValue(expectedRestStatus); - } + @Override + public void describeTo(Description description) { + description.appendText("Expected response status is ").appendValue(expectedRestStatus); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SnapshotInClusterDoesNotExist.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SnapshotInClusterDoesNotExist.java index c2626669be..36e50143f0 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SnapshotInClusterDoesNotExist.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SnapshotInClusterDoesNotExist.java @@ -19,29 +19,31 @@ import static java.util.Objects.requireNonNull; class SnapshotInClusterDoesNotExist extends TypeSafeDiagnosingMatcher { - private final String repositoryName; - private final String snapshotName; + private final String repositoryName; + private final String snapshotName; - public SnapshotInClusterDoesNotExist(String repositoryName, String snapshotName) { - this.repositoryName = requireNonNull(repositoryName, "Snapshot repository name is required."); - this.snapshotName = requireNonNull(snapshotName, "Snapshot name is required."); - } + public SnapshotInClusterDoesNotExist(String repositoryName, String snapshotName) { + this.repositoryName = requireNonNull(repositoryName, "Snapshot repository name is required."); + this.snapshotName = requireNonNull(snapshotName, "Snapshot name is required."); + } - @Override - protected boolean matchesSafely(Client client, Description mismatchDescription) { - try { - GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName, new String[] { snapshotName }); - client.admin().cluster().getSnapshots(request).actionGet(); - mismatchDescription.appendText("snapshot exists"); - return false; - }catch (SnapshotMissingException e) { - return true; - } - } + @Override + protected boolean matchesSafely(Client client, Description mismatchDescription) { + try { + GetSnapshotsRequest request = new GetSnapshotsRequest(repositoryName, new String[] { snapshotName }); + client.admin().cluster().getSnapshots(request).actionGet(); + mismatchDescription.appendText("snapshot exists"); + return false; + } catch (SnapshotMissingException e) { + return true; + } + } - @Override - public void describeTo(Description description) { - description.appendText("Snapshot ").appendValue(snapshotName).appendText(" does not exist in repository ") - .appendValue(repositoryName); - } + @Override + public void describeTo(Description description) { + description.appendText("Snapshot ") + .appendValue(snapshotName) + .appendText(" does not exist in repository ") + .appendValue(repositoryName); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessBulkResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessBulkResponseMatcher.java index 72cc83491e..7bf4993783 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessBulkResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessBulkResponseMatcher.java @@ -21,27 +21,27 @@ class SuccessBulkResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { - RestStatus status = response.status(); - if(RestStatus.OK.equals(status) == false){ - mismatchDescription.appendText("incorrect response status ").appendValue(status); - return false; - } - if(response.hasFailures()) { - String failureDescription = Arrays.stream(response.getItems()) - .filter(BulkItemResponse::isFailed) - .map(BulkItemResponse::getFailure) - .map(Object::toString) - .collect(Collectors.joining(",\n")); - mismatchDescription.appendText("bulk response contains failures ").appendValue(failureDescription); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(BulkResponse response, Description mismatchDescription) { + RestStatus status = response.status(); + if (RestStatus.OK.equals(status) == false) { + mismatchDescription.appendText("incorrect response status ").appendValue(status); + return false; + } + if (response.hasFailures()) { + String failureDescription = Arrays.stream(response.getItems()) + .filter(BulkItemResponse::isFailed) + .map(BulkItemResponse::getFailure) + .map(Object::toString) + .collect(Collectors.joining(",\n")); + mismatchDescription.appendText("bulk response contains failures ").appendValue(failureDescription); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("success bulk response"); - } + @Override + public void describeTo(Description description) { + description.appendText("success bulk response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulClearIndicesCacheResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulClearIndicesCacheResponseMatcher.java index cc2a11d82b..e27ee17ef6 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulClearIndicesCacheResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulClearIndicesCacheResponseMatcher.java @@ -17,21 +17,21 @@ class SuccessfulClearIndicesCacheResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(ClearIndicesCacheResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.getStatus())) { - mismatchDescription.appendText("Status is equal to ").appendValue(response.getStatus()); - return false; - } - if(response.getShardFailures().length != 0) { - mismatchDescription.appendText("Contains ").appendValue(response.getShardFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(ClearIndicesCacheResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.getStatus())) { + mismatchDescription.appendText("Status is equal to ").appendValue(response.getStatus()); + return false; + } + if (response.getShardFailures().length != 0) { + mismatchDescription.appendText("Contains ").appendValue(response.getShardFailures().length).appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful clear index cache response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful clear index cache response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCloseIndexResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCloseIndexResponseMatcher.java index beda676540..480b7845e9 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCloseIndexResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCloseIndexResponseMatcher.java @@ -16,21 +16,21 @@ class SuccessfulCloseIndexResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(CloseIndexResponse response, Description mismatchDescription) { - if (!response.isShardsAcknowledged()) { - mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - if (!response.isAcknowledged()) { - mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(CloseIndexResponse response, Description mismatchDescription) { + if (!response.isShardsAcknowledged()) { + mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + if (!response.isAcknowledged()) { + mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful close index response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful close index response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreateIndexResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreateIndexResponseMatcher.java index 2a017e0ae0..810c93e034 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreateIndexResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreateIndexResponseMatcher.java @@ -18,32 +18,34 @@ class SuccessfulCreateIndexResponseMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - - SuccessfulCreateIndexResponseMatcher(String expectedIndexName) { - this.expectedIndexName = requireNonNull(expectedIndexName); - } - - @Override - protected boolean matchesSafely(CreateIndexResponse response, Description mismatchDescription) { - if (!expectedIndexName.equals(response.index())) { - mismatchDescription.appendText("Index name ").appendValue(response.index()) - .appendText(" does not match expected index name ").appendValue(expectedIndexName); - return false; - } - if (!response.isShardsAcknowledged()) { - mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - if (!response.isAcknowledged()) { - mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Successful create index response"); - } + private final String expectedIndexName; + + SuccessfulCreateIndexResponseMatcher(String expectedIndexName) { + this.expectedIndexName = requireNonNull(expectedIndexName); + } + + @Override + protected boolean matchesSafely(CreateIndexResponse response, Description mismatchDescription) { + if (!expectedIndexName.equals(response.index())) { + mismatchDescription.appendText("Index name ") + .appendValue(response.index()) + .appendText(" does not match expected index name ") + .appendValue(expectedIndexName); + return false; + } + if (!response.isShardsAcknowledged()) { + mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + if (!response.isAcknowledged()) { + mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Successful create index response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreatePitResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreatePitResponseMatcher.java index 29670334cc..7f9a68064c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreatePitResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulCreatePitResponseMatcher.java @@ -17,21 +17,21 @@ class SuccessfulCreatePitResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(CreatePitResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.status())) { - mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); - return false; - } - if(response.getShardFailures().length != 0) { - mismatchDescription.appendText("contains ").appendValue(response.getShardFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(CreatePitResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.status())) { + mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); + return false; + } + if (response.getShardFailures().length != 0) { + mismatchDescription.appendText("contains ").appendValue(response.getShardFailures().length).appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful create pit response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful create pit response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeletePitResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeletePitResponseMatcher.java index 0b0c0af09c..aec2e7d61a 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeletePitResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeletePitResponseMatcher.java @@ -18,23 +18,25 @@ class SuccessfulDeletePitResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(DeletePitResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.status())) { - mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); - return false; - } - for(DeletePitInfo deletePitInfo : response.getDeletePitResults()) { - if (!deletePitInfo.isSuccessful()) { - mismatchDescription.appendValue("Pit: ").appendValue(deletePitInfo.getPitId()).appendText(" - delete result was not successful"); - return false; - } - } - return true; - } + @Override + protected boolean matchesSafely(DeletePitResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.status())) { + mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); + return false; + } + for (DeletePitInfo deletePitInfo : response.getDeletePitResults()) { + if (!deletePitInfo.isSuccessful()) { + mismatchDescription.appendValue("Pit: ") + .appendValue(deletePitInfo.getPitId()) + .appendText(" - delete result was not successful"); + return false; + } + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful delete pit response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful delete pit response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeleteResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeleteResponseMatcher.java index 8d1df13ea9..eb4b1fc064 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeleteResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulDeleteResponseMatcher.java @@ -17,21 +17,23 @@ class SuccessfulDeleteResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(DeleteResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.status())) { - mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); - return false; - } - if(response.getShardInfo().getFailures().length != 0) { - mismatchDescription.appendText("contains ").appendValue(response.getShardInfo().getFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(DeleteResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.status())) { + mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); + return false; + } + if (response.getShardInfo().getFailures().length != 0) { + mismatchDescription.appendText("contains ") + .appendValue(response.getShardInfo().getFailures().length) + .appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful delete response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful delete response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiGetResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiGetResponseMatcher.java index 3aedb0174b..fce5d1201c 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiGetResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiGetResponseMatcher.java @@ -17,21 +17,23 @@ class SuccessfulMultiGetResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(MultiGetResponse response, Description mismatchDescription) { - for (MultiGetItemResponse getItemResponse : response.getResponses()) { - if (getItemResponse.isFailed()) { - mismatchDescription.appendValue("Get an item from index: ").appendValue(getItemResponse.getIndex()) - .appendText(" failed: ").appendValue(getItemResponse.getFailure().getMessage()); - return false; - } - } + @Override + protected boolean matchesSafely(MultiGetResponse response, Description mismatchDescription) { + for (MultiGetItemResponse getItemResponse : response.getResponses()) { + if (getItemResponse.isFailed()) { + mismatchDescription.appendValue("Get an item from index: ") + .appendValue(getItemResponse.getIndex()) + .appendText(" failed: ") + .appendValue(getItemResponse.getFailure().getMessage()); + return false; + } + } - return true; - } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful multi get response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful multi get response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiSearchResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiSearchResponseMatcher.java index b1dbd64c33..e601f16e8e 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiSearchResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulMultiSearchResponseMatcher.java @@ -16,20 +16,20 @@ class SuccessfulMultiSearchResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(MultiSearchResponse response, Description mismatchDescription) { - for (MultiSearchResponse.Item itemResponse : response.getResponses()) { - if (itemResponse.isFailure()) { - mismatchDescription.appendValue("Get an item failed: ").appendValue(itemResponse.getFailureMessage()); - return false; - } - } + @Override + protected boolean matchesSafely(MultiSearchResponse response, Description mismatchDescription) { + for (MultiSearchResponse.Item itemResponse : response.getResponses()) { + if (itemResponse.isFailure()) { + mismatchDescription.appendValue("Get an item failed: ").appendValue(itemResponse.getFailureMessage()); + return false; + } + } - return true; - } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful multi search response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful multi search response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulOpenIndexResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulOpenIndexResponseMatcher.java index 3147195474..68389979b1 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulOpenIndexResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulOpenIndexResponseMatcher.java @@ -16,21 +16,21 @@ class SuccessfulOpenIndexResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(OpenIndexResponse response, Description mismatchDescription) { - if (!response.isShardsAcknowledged()) { - mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - if (!response.isAcknowledged()) { - mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(OpenIndexResponse response, Description mismatchDescription) { + if (!response.isShardsAcknowledged()) { + mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + if (!response.isAcknowledged()) { + mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful open index response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful open index response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulResizeResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulResizeResponseMatcher.java index c9b5d92b94..915a0f39bb 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulResizeResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulResizeResponseMatcher.java @@ -18,32 +18,34 @@ class SuccessfulResizeResponseMatcher extends TypeSafeDiagnosingMatcher { - private final String expectedIndexName; - - SuccessfulResizeResponseMatcher(String expectedIndexName) { - this.expectedIndexName = requireNonNull(expectedIndexName); - } - - @Override - protected boolean matchesSafely(ResizeResponse response, Description mismatchDescription) { - if (!expectedIndexName.equals(response.index())) { - mismatchDescription.appendText("Index name ").appendValue(response.index()) - .appendText(" does not match expected index name ").appendValue(expectedIndexName); - return false; - } - if (!response.isShardsAcknowledged()) { - mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - if (!response.isAcknowledged()) { - mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); - return false; - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText("Successful create index response"); - } + private final String expectedIndexName; + + SuccessfulResizeResponseMatcher(String expectedIndexName) { + this.expectedIndexName = requireNonNull(expectedIndexName); + } + + @Override + protected boolean matchesSafely(ResizeResponse response, Description mismatchDescription) { + if (!expectedIndexName.equals(response.index())) { + mismatchDescription.appendText("Index name ") + .appendValue(response.index()) + .appendText(" does not match expected index name ") + .appendValue(expectedIndexName); + return false; + } + if (!response.isShardsAcknowledged()) { + mismatchDescription.appendText("shardsAcknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + if (!response.isAcknowledged()) { + mismatchDescription.appendText("acknowledged is equal to ").appendValue(response.isShardsAcknowledged()); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("Successful create index response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulSearchResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulSearchResponseMatcher.java index 6d59780798..fe2acff9b9 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulSearchResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulSearchResponseMatcher.java @@ -17,21 +17,21 @@ class SuccessfulSearchResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { - if(RestStatus.OK.equals(searchResponse.status()) == false) { - mismatchDescription.appendText("has status ").appendValue(searchResponse.status()).appendText(" which denotes failure."); - return false; - } - if(searchResponse.getShardFailures().length != 0) { - mismatchDescription.appendText("contains ").appendValue(searchResponse.getShardFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(SearchResponse searchResponse, Description mismatchDescription) { + if (RestStatus.OK.equals(searchResponse.status()) == false) { + mismatchDescription.appendText("has status ").appendValue(searchResponse.status()).appendText(" which denotes failure."); + return false; + } + if (searchResponse.getShardFailures().length != 0) { + mismatchDescription.appendText("contains ").appendValue(searchResponse.getShardFailures().length).appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful search response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful search response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulUpdateResponseMatcher.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulUpdateResponseMatcher.java index 35a9851055..dcff052f01 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulUpdateResponseMatcher.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/SuccessfulUpdateResponseMatcher.java @@ -17,21 +17,23 @@ class SuccessfulUpdateResponseMatcher extends TypeSafeDiagnosingMatcher { - @Override - protected boolean matchesSafely(UpdateResponse response, Description mismatchDescription) { - if(!RestStatus.OK.equals(response.status())) { - mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); - return false; - } - if(response.getShardInfo().getFailures().length != 0) { - mismatchDescription.appendText("contains ").appendValue(response.getShardInfo().getFailures().length).appendText(" shard failures"); - return false; - } - return true; - } + @Override + protected boolean matchesSafely(UpdateResponse response, Description mismatchDescription) { + if (!RestStatus.OK.equals(response.status())) { + mismatchDescription.appendText("has status ").appendValue(response.status()).appendText(" which denotes failure."); + return false; + } + if (response.getShardInfo().getFailures().length != 0) { + mismatchDescription.appendText("contains ") + .appendValue(response.getShardInfo().getFailures().length) + .appendText(" shard failures"); + return false; + } + return true; + } - @Override - public void describeTo(Description description) { - description.appendText("Successful update response"); - } + @Override + public void describeTo(Description description) { + description.appendText("Successful update response"); + } } diff --git a/src/integrationTest/java/org/opensearch/test/framework/matcher/UpdateResponseMatchers.java b/src/integrationTest/java/org/opensearch/test/framework/matcher/UpdateResponseMatchers.java index 9062d9bb68..ee01fabced 100644 --- a/src/integrationTest/java/org/opensearch/test/framework/matcher/UpdateResponseMatchers.java +++ b/src/integrationTest/java/org/opensearch/test/framework/matcher/UpdateResponseMatchers.java @@ -15,9 +15,9 @@ public class UpdateResponseMatchers { - private UpdateResponseMatchers() {} + private UpdateResponseMatchers() {} - public static Matcher isSuccessfulUpdateResponse() { - return new SuccessfulUpdateResponseMatcher(); - } + public static Matcher isSuccessfulUpdateResponse() { + return new SuccessfulUpdateResponseMatcher(); + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/AbstractHTTPJwtAuthenticator.java b/src/main/java/com/amazon/dlic/auth/http/jwt/AbstractHTTPJwtAuthenticator.java index 9978186f96..ffe9db81f2 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/AbstractHTTPJwtAuthenticator.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/AbstractHTTPJwtAuthenticator.java @@ -55,9 +55,11 @@ public abstract class AbstractHTTPJwtAuthenticator implements HTTPAuthenticator private final String jwtUrlParameter; private final String subjectKey; private final String rolesKey; + private final String requiredAudience; + private final String requiredIssuer; public static final int DEFAULT_CLOCK_SKEW_TOLERANCE_SECONDS = 30; - private final int clockSkewToleranceSeconds ; + private final int clockSkewToleranceSeconds; public AbstractHTTPJwtAuthenticator(Settings settings, Path configPath) { jwtUrlParameter = settings.get("jwt_url_parameter"); @@ -66,10 +68,12 @@ public AbstractHTTPJwtAuthenticator(Settings settings, Path configPath) { rolesKey = settings.get("roles_key"); subjectKey = settings.get("subject_key"); clockSkewToleranceSeconds = settings.getAsInt("jwt_clock_skew_tolerance_seconds", DEFAULT_CLOCK_SKEW_TOLERANCE_SECONDS); + requiredAudience = settings.get("required_audience"); + requiredIssuer = settings.get("required_issuer"); try { this.keyProvider = this.initKeyProvider(settings, configPath); - jwtVerifier = new JwtVerifier(keyProvider, clockSkewToleranceSeconds ); + jwtVerifier = new JwtVerifier(keyProvider, clockSkewToleranceSeconds, requiredIssuer, requiredAudience); } catch (Exception e) { log.error("Error creating JWT authenticator. JWT authentication will not work", e); @@ -79,8 +83,7 @@ public AbstractHTTPJwtAuthenticator(Settings settings, Path configPath) { @Override @SuppressWarnings("removal") - public AuthCredentials extractCredentials(RestRequest request, ThreadContext context) - throws OpenSearchSecurityException { + public AuthCredentials extractCredentials(RestRequest request, ThreadContext context) throws OpenSearchSecurityException { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -182,8 +185,11 @@ public String extractSubject(JwtClaims claims) { // warning if (!(subjectObject instanceof String)) { log.warn( - "Expected type String for roles in the JWT for subject_key {}, but value was '{}' ({}). Will convert this value to String.", - subjectKey, subjectObject, subjectObject.getClass()); + "Expected type String for roles in the JWT for subject_key {}, but value was '{}' ({}). Will convert this value to String.", + subjectKey, + subjectObject, + subjectObject.getClass() + ); subject = String.valueOf(subjectObject); } else { subject = (String) subjectObject; @@ -203,8 +209,9 @@ public String[] extractRoles(JwtClaims claims) { if (rolesObject == null) { log.warn( - "Failed to get roles from JWT claims with roles_key '{}'. Check if this key is correct and available in the JWT payload.", - rolesKey); + "Failed to get roles from JWT claims with roles_key '{}'. Check if this key is correct and available in the JWT payload.", + rolesKey + ); return new String[0]; } @@ -214,8 +221,11 @@ public String[] extractRoles(JwtClaims claims) { // String but issue a warning if (!(rolesObject instanceof String) && !(rolesObject instanceof Collection)) { log.warn( - "Expected type String or Collection for roles in the JWT for roles_key {}, but value was '{}' ({}). Will convert this value to String.", - rolesKey, rolesObject, rolesObject.getClass()); + "Expected type String or Collection for roles in the JWT for roles_key {}, but value was '{}' ({}). Will convert this value to String.", + rolesKey, + rolesObject, + rolesObject.getClass() + ); } else if (rolesObject instanceof Collection) { roles = ((Collection) rolesObject).toArray(new String[0]); } @@ -233,4 +243,12 @@ public boolean reRequestAuthentication(RestChannel channel, AuthCredentials auth return true; } + public String getRequiredAudience() { + return requiredAudience; + } + + public String getRequiredIssuer() { + return requiredIssuer; + } + } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/HTTPJwtAuthenticator.java b/src/main/java/com/amazon/dlic/auth/http/jwt/HTTPJwtAuthenticator.java index 16cc71ffbd..3468bb89af 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/HTTPJwtAuthenticator.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/HTTPJwtAuthenticator.java @@ -68,7 +68,7 @@ public HTTPJwtAuthenticator(final Settings settings, final Path configPath) { try { String signingKey = settings.get("signing_key"); - if(signingKey == null || signingKey.length() == 0) { + if (signingKey == null || signingKey.length() == 0) { log.error("signingKey must not be null or empty. JWT authentication will not work"); } else { @@ -90,7 +90,7 @@ public HTTPJwtAuthenticator(final Settings settings, final Path configPath) { log.debug("No public ECDSA key, try other algos ({})", e.toString()); } - if(key != null) { + if (key != null) { _jwtParser = Jwts.parser().setSigningKey(key); } else { _jwtParser = Jwts.parser().setSigningKey(decoded); @@ -121,7 +121,6 @@ public HTTPJwtAuthenticator(final Settings settings, final Path configPath) { jwtParser = _jwtParser; } - @Override @SuppressWarnings("removal") public AuthCredentials extractCredentials(RestRequest request, ThreadContext context) throws OpenSearchSecurityException { @@ -152,25 +151,29 @@ private AuthCredentials extractCredentials0(final RestRequest request) { jwtToken = null; } - if((jwtToken == null || jwtToken.isEmpty()) && jwtUrlParameter != null) { + if ((jwtToken == null || jwtToken.isEmpty()) && jwtUrlParameter != null) { jwtToken = request.param(jwtUrlParameter); } else { - //just consume to avoid "contains unrecognized parameter" + // just consume to avoid "contains unrecognized parameter" request.param(jwtUrlParameter); } if (jwtToken == null || jwtToken.length() == 0) { - if(log.isDebugEnabled()) { - log.debug("No JWT token found in '{}' {} header", jwtUrlParameter==null?jwtHeaderName:jwtUrlParameter, jwtUrlParameter==null?"header":"url parameter"); + if (log.isDebugEnabled()) { + log.debug( + "No JWT token found in '{}' {} header", + jwtUrlParameter == null ? jwtHeaderName : jwtUrlParameter, + jwtUrlParameter == null ? "header" : "url parameter" + ); } return null; } final int index; - if((index = jwtToken.toLowerCase().indexOf(BEARER)) > -1) { //detect Bearer - jwtToken = jwtToken.substring(index+BEARER.length()); + if ((index = jwtToken.toLowerCase().indexOf(BEARER)) > -1) { // detect Bearer + jwtToken = jwtToken.substring(index + BEARER.length()); } else { - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug("No Bearer scheme found in header"); } } @@ -181,16 +184,16 @@ private AuthCredentials extractCredentials0(final RestRequest request) { final String subject = extractSubject(claims, request); if (subject == null) { - log.error("No subject found in JWT token"); - return null; + log.error("No subject found in JWT token"); + return null; } final String[] roles = extractRoles(claims, request); final AuthCredentials ac = new AuthCredentials(subject, roles).markComplete(); - for(Entry claim: claims.entrySet()) { - ac.addAttribute("attr.jwt."+claim.getKey(), String.valueOf(claim.getValue())); + for (Entry claim : claims.entrySet()) { + ac.addAttribute("attr.jwt." + claim.getKey(), String.valueOf(claim.getValue())); } return ac; @@ -199,7 +202,7 @@ private AuthCredentials extractCredentials0(final RestRequest request) { log.error("Cannot authenticate user with JWT because of ", e); return null; } catch (Exception e) { - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug("Invalid or expired JWT token.", e); } return null; @@ -208,7 +211,7 @@ private AuthCredentials extractCredentials0(final RestRequest request) { @Override public boolean reRequestAuthentication(final RestChannel channel, AuthCredentials creds) { - final BytesRestResponse wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED,""); + final BytesRestResponse wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, ""); wwwAuthenticateResponse.addHeader("WWW-Authenticate", "Bearer realm=\"OpenSearch Security\""); channel.sendResponse(wwwAuthenticateResponse); return true; @@ -221,16 +224,21 @@ public String getType() { protected String extractSubject(final Claims claims, final RestRequest request) { String subject = claims.getSubject(); - if(subjectKey != null) { - // try to get roles from claims, first as Object to avoid having to catch the ExpectedTypeException + if (subjectKey != null) { + // try to get roles from claims, first as Object to avoid having to catch the ExpectedTypeException Object subjectObject = claims.get(subjectKey, Object.class); - if(subjectObject == null) { + if (subjectObject == null) { log.warn("Failed to get subject from JWT claims, check if subject_key '{}' is correct.", subjectKey); return null; } - // We expect a String. If we find something else, convert to String but issue a warning - if(!(subjectObject instanceof String)) { - log.warn("Expected type String for roles in the JWT for subject_key {}, but value was '{}' ({}). Will convert this value to String.", subjectKey, subjectObject, subjectObject.getClass()); + // We expect a String. If we find something else, convert to String but issue a warning + if (!(subjectObject instanceof String)) { + log.warn( + "Expected type String for roles in the JWT for subject_key {}, but value was '{}' ({}). Will convert this value to String.", + subjectKey, + subjectObject, + subjectObject.getClass() + ); } subject = String.valueOf(subjectObject); } @@ -239,34 +247,43 @@ protected String extractSubject(final Claims claims, final RestRequest request) @SuppressWarnings("unchecked") protected String[] extractRoles(final Claims claims, final RestRequest request) { - // no roles key specified - if(rolesKey == null) { - return new String[0]; - } - // try to get roles from claims, first as Object to avoid having to catch the ExpectedTypeException - final Object rolesObject = claims.get(rolesKey, Object.class); - if(rolesObject == null) { - log.warn("Failed to get roles from JWT claims with roles_key '{}'. Check if this key is correct and available in the JWT payload.", rolesKey); - return new String[0]; - } - - String[] roles = String.valueOf(rolesObject).split(","); - - // We expect a String or Collection. If we find something else, convert to String but issue a warning - if (!(rolesObject instanceof String) && !(rolesObject instanceof Collection)) { - log.warn("Expected type String or Collection for roles in the JWT for roles_key {}, but value was '{}' ({}). Will convert this value to String.", rolesKey, rolesObject, rolesObject.getClass()); - } else if (rolesObject instanceof Collection) { - roles = ((Collection) rolesObject).toArray(new String[0]); - } - - for (int i = 0; i < roles.length; i++) { - roles[i] = roles[i].trim(); - } - - return roles; + // no roles key specified + if (rolesKey == null) { + return new String[0]; + } + // try to get roles from claims, first as Object to avoid having to catch the ExpectedTypeException + final Object rolesObject = claims.get(rolesKey, Object.class); + if (rolesObject == null) { + log.warn( + "Failed to get roles from JWT claims with roles_key '{}'. Check if this key is correct and available in the JWT payload.", + rolesKey + ); + return new String[0]; + } + + String[] roles = String.valueOf(rolesObject).split(","); + + // We expect a String or Collection. If we find something else, convert to String but issue a warning + if (!(rolesObject instanceof String) && !(rolesObject instanceof Collection)) { + log.warn( + "Expected type String or Collection for roles in the JWT for roles_key {}, but value was '{}' ({}). Will convert this value to String.", + rolesKey, + rolesObject, + rolesObject.getClass() + ); + } else if (rolesObject instanceof Collection) { + roles = ((Collection) rolesObject).toArray(new String[0]); + } + + for (int i = 0; i < roles.length; i++) { + roles[i] = roles[i].trim(); + } + + return roles; } - private static PublicKey getPublicKey(final byte[] keyBytes, final String algo) throws NoSuchAlgorithmException, InvalidKeySpecException { + private static PublicKey getPublicKey(final byte[] keyBytes, final String algo) throws NoSuchAlgorithmException, + InvalidKeySpecException { X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance(algo); return kf.generatePublic(spec); diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/AuthenticatorUnavailableException.java b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/AuthenticatorUnavailableException.java index d9aa1aebb6..b17663b429 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/AuthenticatorUnavailableException.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/AuthenticatorUnavailableException.java @@ -12,27 +12,26 @@ package com.amazon.dlic.auth.http.jwt.keybyoidc; public class AuthenticatorUnavailableException extends RuntimeException { - private static final long serialVersionUID = -7007025852090301416L; + private static final long serialVersionUID = -7007025852090301416L; - public AuthenticatorUnavailableException() { - super(); - } + public AuthenticatorUnavailableException() { + super(); + } - public AuthenticatorUnavailableException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } + public AuthenticatorUnavailableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } - public AuthenticatorUnavailableException(String message, Throwable cause) { - super(message, cause); - } + public AuthenticatorUnavailableException(String message, Throwable cause) { + super(message, cause); + } - public AuthenticatorUnavailableException(String message) { - super(message); - } + public AuthenticatorUnavailableException(String message) { + super(message); + } - public AuthenticatorUnavailableException(Throwable cause) { - super(cause); - } + public AuthenticatorUnavailableException(Throwable cause) { + super(cause); + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/BadCredentialsException.java b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/BadCredentialsException.java index 12b9195c0e..0d705f98cf 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/BadCredentialsException.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/BadCredentialsException.java @@ -13,26 +13,25 @@ public class BadCredentialsException extends Exception { - private static final long serialVersionUID = 9092575587366580869L; + private static final long serialVersionUID = 9092575587366580869L; - public BadCredentialsException() { - super(); - } + public BadCredentialsException() { + super(); + } - public BadCredentialsException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } + public BadCredentialsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } - public BadCredentialsException(String message, Throwable cause) { - super(message, cause); - } + public BadCredentialsException(String message, Throwable cause) { + super(message, cause); + } - public BadCredentialsException(String message) { - super(message); - } + public BadCredentialsException(String message) { + super(message); + } - public BadCredentialsException(Throwable cause) { - super(cause); - } + public BadCredentialsException(Throwable cause) { + super(cause); + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/HTTPJwtKeyByOpenIdConnectAuthenticator.java b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/HTTPJwtKeyByOpenIdConnectAuthenticator.java index 0cede73911..808abfc5ea 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/HTTPJwtKeyByOpenIdConnectAuthenticator.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/HTTPJwtKeyByOpenIdConnectAuthenticator.java @@ -20,42 +20,54 @@ public class HTTPJwtKeyByOpenIdConnectAuthenticator extends AbstractHTTPJwtAuthenticator { - //private final static Logger log = LogManager.getLogger(HTTPJwtKeyByOpenIdConnectAuthenticator.class); - - public HTTPJwtKeyByOpenIdConnectAuthenticator(Settings settings, Path configPath) { - super(settings, configPath); - } - - protected KeyProvider initKeyProvider(Settings settings, Path configPath) throws Exception { - int idpRequestTimeoutMs = settings.getAsInt("idp_request_timeout_ms", 5000); - int idpQueuedThreadTimeoutMs = settings.getAsInt("idp_queued_thread_timeout_ms", 2500); - - int refreshRateLimitTimeWindowMs = settings.getAsInt("refresh_rate_limit_time_window_ms", 10000); - int refreshRateLimitCount = settings.getAsInt("refresh_rate_limit_count", 10); - - KeySetRetriever keySetRetriever = new KeySetRetriever(settings.get("openid_connect_url"), - getSSLConfig(settings, configPath), settings.getAsBoolean("cache_jwks_endpoint", false)); - - keySetRetriever.setRequestTimeoutMs(idpRequestTimeoutMs); - - SelfRefreshingKeySet selfRefreshingKeySet = new SelfRefreshingKeySet(keySetRetriever); - - selfRefreshingKeySet.setRequestTimeoutMs(idpRequestTimeoutMs); - selfRefreshingKeySet.setQueuedThreadTimeoutMs(idpQueuedThreadTimeoutMs); - selfRefreshingKeySet.setRefreshRateLimitTimeWindowMs(refreshRateLimitTimeWindowMs); - selfRefreshingKeySet.setRefreshRateLimitCount(refreshRateLimitCount); - - return selfRefreshingKeySet; - } - - private static SettingsBasedSSLConfigurator.SSLConfig getSSLConfig(Settings settings, Path configPath) - throws Exception { - return new SettingsBasedSSLConfigurator(settings, configPath, "openid_connect_idp").buildSSLConfig(); - } - - @Override - public String getType() { - return "jwt-key-by-oidc"; - } + // private final static Logger log = LogManager.getLogger(HTTPJwtKeyByOpenIdConnectAuthenticator.class); + + public HTTPJwtKeyByOpenIdConnectAuthenticator(Settings settings, Path configPath) { + super(settings, configPath); + } + + protected KeyProvider initKeyProvider(Settings settings, Path configPath) throws Exception { + int idpRequestTimeoutMs = settings.getAsInt("idp_request_timeout_ms", 5000); + int idpQueuedThreadTimeoutMs = settings.getAsInt("idp_queued_thread_timeout_ms", 2500); + + int refreshRateLimitTimeWindowMs = settings.getAsInt("refresh_rate_limit_time_window_ms", 10000); + int refreshRateLimitCount = settings.getAsInt("refresh_rate_limit_count", 10); + String jwksUri = settings.get("jwks_uri"); + + KeySetRetriever keySetRetriever; + if (jwksUri != null && !jwksUri.isBlank()) { + keySetRetriever = new KeySetRetriever( + getSSLConfig(settings, configPath), + settings.getAsBoolean("cache_jwks_endpoint", false), + jwksUri + ); + } else { + keySetRetriever = new KeySetRetriever( + settings.get("openid_connect_url"), + getSSLConfig(settings, configPath), + settings.getAsBoolean("cache_jwks_endpoint", false) + ); + } + + keySetRetriever.setRequestTimeoutMs(idpRequestTimeoutMs); + + SelfRefreshingKeySet selfRefreshingKeySet = new SelfRefreshingKeySet(keySetRetriever); + + selfRefreshingKeySet.setRequestTimeoutMs(idpRequestTimeoutMs); + selfRefreshingKeySet.setQueuedThreadTimeoutMs(idpQueuedThreadTimeoutMs); + selfRefreshingKeySet.setRefreshRateLimitTimeWindowMs(refreshRateLimitTimeWindowMs); + selfRefreshingKeySet.setRefreshRateLimitCount(refreshRateLimitCount); + + return selfRefreshingKeySet; + } + + private static SettingsBasedSSLConfigurator.SSLConfig getSSLConfig(Settings settings, Path configPath) throws Exception { + return new SettingsBasedSSLConfigurator(settings, configPath, "openid_connect_idp").buildSSLConfig(); + } + + @Override + public String getType() { + return "jwt-key-by-oidc"; + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/JwtVerifier.java b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/JwtVerifier.java index 99074ab233..5893d623a7 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/JwtVerifier.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/JwtVerifier.java @@ -29,89 +29,106 @@ public class JwtVerifier { - private final static Logger log = LogManager.getLogger(JwtVerifier.class); - - private final KeyProvider keyProvider; - private final int clockSkewToleranceSeconds; - - public JwtVerifier(KeyProvider keyProvider, int clockSkewToleranceSeconds ) { - this.keyProvider = keyProvider; - this.clockSkewToleranceSeconds = clockSkewToleranceSeconds; - } - - public JwtToken getVerifiedJwtToken(String encodedJwt) throws BadCredentialsException { - try { - JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(encodedJwt); - JwtToken jwt = jwtConsumer.getJwtToken(); - - String escapedKid = jwt.getJwsHeaders().getKeyId(); - String kid = escapedKid; - if (!Strings.isNullOrEmpty(kid)) { - kid = StringEscapeUtils.unescapeJava(escapedKid); - } - JsonWebKey key = keyProvider.getKey(kid); - - // Algorithm is not mandatory for the key material, so we set it to the same as the JWT - if (key.getAlgorithm() == null && key.getPublicKeyUse() == PublicKeyUse.SIGN && key.getKeyType() == KeyType.RSA) - { - key.setAlgorithm(jwt.getJwsHeaders().getAlgorithm()); - } - - JwsSignatureVerifier signatureVerifier = getInitializedSignatureVerifier(key, jwt); - - - boolean signatureValid = jwtConsumer.verifySignatureWith(signatureVerifier); - - if (!signatureValid && Strings.isNullOrEmpty(kid)) { - key = keyProvider.getKeyAfterRefresh(null); - signatureVerifier = getInitializedSignatureVerifier(key, jwt); - signatureValid = jwtConsumer.verifySignatureWith(signatureVerifier); - } - - if (!signatureValid) { - throw new BadCredentialsException("Invalid JWT signature"); - } - - validateClaims(jwt); - - return jwt; - } catch (JwtException e) { - throw new BadCredentialsException(e.getMessage(), e); - } - } + private final static Logger log = LogManager.getLogger(JwtVerifier.class); + + private final KeyProvider keyProvider; + private final int clockSkewToleranceSeconds; + private final String requiredIssuer; + private final String requiredAudience; + + public JwtVerifier(KeyProvider keyProvider, int clockSkewToleranceSeconds, String requiredIssuer, String requiredAudience) { + this.keyProvider = keyProvider; + this.clockSkewToleranceSeconds = clockSkewToleranceSeconds; + this.requiredIssuer = requiredIssuer; + this.requiredAudience = requiredAudience; + } + + public JwtToken getVerifiedJwtToken(String encodedJwt) throws BadCredentialsException { + try { + JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(encodedJwt); + JwtToken jwt = jwtConsumer.getJwtToken(); + + String escapedKid = jwt.getJwsHeaders().getKeyId(); + String kid = escapedKid; + if (!Strings.isNullOrEmpty(kid)) { + kid = StringEscapeUtils.unescapeJava(escapedKid); + } + JsonWebKey key = keyProvider.getKey(kid); + + // Algorithm is not mandatory for the key material, so we set it to the same as the JWT + if (key.getAlgorithm() == null && key.getPublicKeyUse() == PublicKeyUse.SIGN && key.getKeyType() == KeyType.RSA) { + key.setAlgorithm(jwt.getJwsHeaders().getAlgorithm()); + } + + JwsSignatureVerifier signatureVerifier = getInitializedSignatureVerifier(key, jwt); + + boolean signatureValid = jwtConsumer.verifySignatureWith(signatureVerifier); + + if (!signatureValid && Strings.isNullOrEmpty(kid)) { + key = keyProvider.getKeyAfterRefresh(null); + signatureVerifier = getInitializedSignatureVerifier(key, jwt); + signatureValid = jwtConsumer.verifySignatureWith(signatureVerifier); + } + + if (!signatureValid) { + throw new BadCredentialsException("Invalid JWT signature"); + } + + validateClaims(jwt); + + return jwt; + } catch (JwtException e) { + throw new BadCredentialsException(e.getMessage(), e); + } + } private void validateSignatureAlgorithm(JsonWebKey key, JwtToken jwt) throws BadCredentialsException { if (Strings.isNullOrEmpty(key.getAlgorithm())) { return; } - SignatureAlgorithm keyAlgorithm =SignatureAlgorithm.getAlgorithm(key.getAlgorithm()); + SignatureAlgorithm keyAlgorithm = SignatureAlgorithm.getAlgorithm(key.getAlgorithm()); SignatureAlgorithm tokenAlgorithm = SignatureAlgorithm.getAlgorithm(jwt.getJwsHeaders().getAlgorithm()); if (!keyAlgorithm.equals(tokenAlgorithm)) { - throw new BadCredentialsException("Algorithm of JWT does not match algorithm of JWK (" + keyAlgorithm + " != " + tokenAlgorithm + ")"); + throw new BadCredentialsException( + "Algorithm of JWT does not match algorithm of JWK (" + keyAlgorithm + " != " + tokenAlgorithm + ")" + ); } } + private JwsSignatureVerifier getInitializedSignatureVerifier(JsonWebKey key, JwtToken jwt) throws BadCredentialsException, + JwtException { - private JwsSignatureVerifier getInitializedSignatureVerifier(JsonWebKey key, JwtToken jwt) - throws BadCredentialsException, JwtException { - - validateSignatureAlgorithm(key, jwt); + validateSignatureAlgorithm(key, jwt); JwsSignatureVerifier result = JwsUtils.getSignatureVerifier(key, jwt.getJwsHeaders().getSignatureAlgorithm()); - if (result == null) { - throw new BadCredentialsException("Cannot verify JWT"); - } else { - return result; - } - } - - private void validateClaims(JwtToken jwt) throws BadCredentialsException, JwtException { - JwtClaims claims = jwt.getClaims(); - - if (claims != null) { - JwtUtils.validateJwtExpiry(claims, clockSkewToleranceSeconds, false); - JwtUtils.validateJwtNotBefore(claims, clockSkewToleranceSeconds, false); - } - } + if (result == null) { + throw new BadCredentialsException("Cannot verify JWT"); + } else { + return result; + } + } + + private void validateClaims(JwtToken jwt) throws JwtException { + JwtClaims claims = jwt.getClaims(); + + if (claims != null) { + JwtUtils.validateJwtExpiry(claims, clockSkewToleranceSeconds, false); + JwtUtils.validateJwtNotBefore(claims, clockSkewToleranceSeconds, false); + validateRequiredAudienceAndIssuer(claims); + } + } + + private void validateRequiredAudienceAndIssuer(JwtClaims claims) { + String audience = claims.getAudience(); + String issuer = claims.getIssuer(); + + if (!Strings.isNullOrEmpty(requiredAudience) && !requiredAudience.equals(audience)) { + throw new JwtException("Invalid audience"); + } + + if (!Strings.isNullOrEmpty(requiredIssuer) && !requiredIssuer.equals(issuer)) { + throw new JwtException("Invalid issuer"); + } + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeyProvider.java b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeyProvider.java index 5eff7cb213..a0e76c918f 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeyProvider.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeyProvider.java @@ -14,6 +14,7 @@ import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; public interface KeyProvider { - public JsonWebKey getKey(String kid) throws AuthenticatorUnavailableException, BadCredentialsException; - public JsonWebKey getKeyAfterRefresh(String kid) throws AuthenticatorUnavailableException, BadCredentialsException; + public JsonWebKey getKey(String kid) throws AuthenticatorUnavailableException, BadCredentialsException; + + public JsonWebKey getKeyAfterRefresh(String kid) throws AuthenticatorUnavailableException, BadCredentialsException; } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetProvider.java b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetProvider.java index edbe39f020..53ea0237db 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetProvider.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetProvider.java @@ -15,5 +15,5 @@ @FunctionalInterface public interface KeySetProvider { - JsonWebKeys get() throws AuthenticatorUnavailableException; + JsonWebKeys get() throws AuthenticatorUnavailableException; } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetRetriever.java b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetRetriever.java index 50be122aec..9ef50a4404 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetRetriever.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetRetriever.java @@ -14,6 +14,7 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; +import joptsimple.internal.Strings; import org.apache.cxf.rs.security.jose.jwk.JsonWebKeys; import org.apache.cxf.rs.security.jose.jwk.JwkUtils; import org.apache.hc.client5.http.cache.HttpCacheContext; @@ -38,185 +39,218 @@ import org.opensearch.security.DefaultObjectMapper; - public class KeySetRetriever implements KeySetProvider { - private final static Logger log = LogManager.getLogger(KeySetRetriever.class); - private static final long CACHE_STATUS_LOG_INTERVAL_MS = 60L * 60L * 1000L; - - private String openIdConnectEndpoint; - private SSLConfig sslConfig; - private int requestTimeoutMs = 10000; - private CacheConfig cacheConfig; - private HttpCacheStorage oidcHttpCacheStorage; - private int oidcCacheHits = 0; - private int oidcCacheMisses = 0; - private int oidcCacheHitsValidated = 0; - private int oidcCacheModuleResponses = 0; - private long oidcRequests = 0; - private long lastCacheStatusLog = 0; - - KeySetRetriever(String openIdConnectEndpoint, SSLConfig sslConfig, boolean useCacheForOidConnectEndpoint) { - this.openIdConnectEndpoint = openIdConnectEndpoint; - this.sslConfig = sslConfig; - - if (useCacheForOidConnectEndpoint) { - cacheConfig = CacheConfig.custom().setMaxCacheEntries(10).setMaxObjectSize(1024L * 1024L).build(); - oidcHttpCacheStorage = new BasicHttpCacheStorage(cacheConfig); - } - } - - public JsonWebKeys get() throws AuthenticatorUnavailableException { - String uri = getJwksUri(); - - try (CloseableHttpClient httpClient = createHttpClient(null)) { - - HttpGet httpGet = new HttpGet(uri); - - RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(getRequestTimeoutMs(), TimeUnit.MILLISECONDS) - .setConnectTimeout(getRequestTimeoutMs(), TimeUnit.MILLISECONDS).build(); - - httpGet.setConfig(requestConfig); - - try (CloseableHttpResponse response = httpClient.execute(httpGet)) { - if (response.getCode() < 200 || response.getCode() >= 300) { - throw new AuthenticatorUnavailableException("Error while getting " + uri + ": " + response.getReasonPhrase()); - } - - HttpEntity httpEntity = response.getEntity(); - - if (httpEntity == null) { - throw new AuthenticatorUnavailableException( - "Error while getting " + uri + ": Empty response entity"); - } - - JsonWebKeys keySet = JwkUtils.readJwkSet(httpEntity.getContent()); + private final static Logger log = LogManager.getLogger(KeySetRetriever.class); + private static final long CACHE_STATUS_LOG_INTERVAL_MS = 60L * 60L * 1000L; - return keySet; - } - } catch (IOException e) { - throw new AuthenticatorUnavailableException("Error while getting " + uri + ": " + e, e); - } + private String openIdConnectEndpoint; + private SSLConfig sslConfig; + private int requestTimeoutMs = 10000; + private CacheConfig cacheConfig; + private HttpCacheStorage oidcHttpCacheStorage; + private int oidcCacheHits = 0; + private int oidcCacheMisses = 0; + private int oidcCacheHitsValidated = 0; + private int oidcCacheModuleResponses = 0; + private long oidcRequests = 0; + private long lastCacheStatusLog = 0; + private String jwksUri; - } + KeySetRetriever(String openIdConnectEndpoint, SSLConfig sslConfig, boolean useCacheForOidConnectEndpoint) { + this.openIdConnectEndpoint = openIdConnectEndpoint; + this.sslConfig = sslConfig; - String getJwksUri() throws AuthenticatorUnavailableException { + configureCache(useCacheForOidConnectEndpoint); + } - try (CloseableHttpClient httpClient = createHttpClient(oidcHttpCacheStorage)) { + KeySetRetriever(SSLConfig sslConfig, boolean useCacheForOidConnectEndpoint, String jwksUri) { + this.jwksUri = jwksUri; + this.sslConfig = sslConfig; - HttpGet httpGet = new HttpGet(openIdConnectEndpoint); + configureCache(useCacheForOidConnectEndpoint); + } - RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(getRequestTimeoutMs(), TimeUnit.MILLISECONDS) - .setConnectTimeout(getRequestTimeoutMs(), TimeUnit.MILLISECONDS).build(); + public JsonWebKeys get() throws AuthenticatorUnavailableException { + String uri = getJwksUri(); - httpGet.setConfig(requestConfig); + try (CloseableHttpClient httpClient = createHttpClient(null)) { - HttpCacheContext httpContext = null; + HttpGet httpGet = new HttpGet(uri); - if (oidcHttpCacheStorage != null) { - httpContext = new HttpCacheContext(); - } + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(getRequestTimeoutMs(), TimeUnit.MILLISECONDS) + .setConnectTimeout(getRequestTimeoutMs(), TimeUnit.MILLISECONDS) + .build(); - try (CloseableHttpResponse response = httpClient.execute(httpGet, httpContext)) { - if (httpContext != null) { - logCacheResponseStatus(httpContext); - } + httpGet.setConfig(requestConfig); - if (response.getCode() < 200 || response.getCode() >= 300) { - throw new AuthenticatorUnavailableException( - "Error while getting " + openIdConnectEndpoint + ": " + response.getReasonPhrase()); - } + try (CloseableHttpResponse response = httpClient.execute(httpGet)) { + if (response.getCode() < 200 || response.getCode() >= 300) { + throw new AuthenticatorUnavailableException("Error while getting " + uri + ": " + response.getReasonPhrase()); + } - HttpEntity httpEntity = response.getEntity(); + HttpEntity httpEntity = response.getEntity(); - if (httpEntity == null) { - throw new AuthenticatorUnavailableException( - "Error while getting " + openIdConnectEndpoint + ": Empty response entity"); - } + if (httpEntity == null) { + throw new AuthenticatorUnavailableException("Error while getting " + uri + ": Empty response entity"); + } - OpenIdProviderConfiguration parsedEntity = DefaultObjectMapper.objectMapper.readValue(httpEntity.getContent(), - OpenIdProviderConfiguration.class); + JsonWebKeys keySet = JwkUtils.readJwkSet(httpEntity.getContent()); - return parsedEntity.getJwksUri(); + return keySet; + } + } catch (IOException e) { + throw new AuthenticatorUnavailableException("Error while getting " + uri + ": " + e, e); + } - } + } + + String getJwksUri() throws AuthenticatorUnavailableException { - } catch (IOException e) { - throw new AuthenticatorUnavailableException("Error while getting " + openIdConnectEndpoint + ": " + e, e); - } + if (!Strings.isNullOrEmpty(jwksUri)) { + return jwksUri; + } - } + if (Strings.isNullOrEmpty(openIdConnectEndpoint)) { + throw new AuthenticatorUnavailableException( + "Either openid_connect_url or jwks_uri must be configured for OIDC Authentication backend" + ); + } + + try (CloseableHttpClient httpClient = createHttpClient(oidcHttpCacheStorage)) { - public int getRequestTimeoutMs() { - return requestTimeoutMs; - } + HttpGet httpGet = new HttpGet(openIdConnectEndpoint); - public void setRequestTimeoutMs(int httpTimeoutMs) { - this.requestTimeoutMs = httpTimeoutMs; - } + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(getRequestTimeoutMs(), TimeUnit.MILLISECONDS) + .setConnectTimeout(getRequestTimeoutMs(), TimeUnit.MILLISECONDS) + .build(); - private void logCacheResponseStatus(HttpCacheContext httpContext) { - this.oidcRequests++; + httpGet.setConfig(requestConfig); - switch (httpContext.getCacheResponseStatus()) { - case CACHE_HIT: - this.oidcCacheHits++; - break; - case CACHE_MODULE_RESPONSE: - this.oidcCacheModuleResponses++; - break; - case CACHE_MISS: - this.oidcCacheMisses++; - break; - case VALIDATED: - this.oidcCacheHitsValidated++; - break; - } + HttpCacheContext httpContext = null; - long now = System.currentTimeMillis(); + if (oidcHttpCacheStorage != null) { + httpContext = new HttpCacheContext(); + } - if (this.oidcRequests >= 2 && now - lastCacheStatusLog > CACHE_STATUS_LOG_INTERVAL_MS) { - log.info("Cache status for KeySetRetriever:\noidcCacheHits: {}\noidcCacheHitsValidated: {}" - + "\noidcCacheModuleResponses: {}" + "\noidcCacheMisses: {}", oidcCacheHits, oidcCacheHitsValidated, oidcCacheModuleResponses, oidcCacheMisses); - lastCacheStatusLog = now; - } + try (CloseableHttpResponse response = httpClient.execute(httpGet, httpContext)) { + if (httpContext != null) { + logCacheResponseStatus(httpContext); + } - } + if (response.getCode() < 200 || response.getCode() >= 300) { + throw new AuthenticatorUnavailableException( + "Error while getting " + openIdConnectEndpoint + ": " + response.getReasonPhrase() + ); + } + + HttpEntity httpEntity = response.getEntity(); - private CloseableHttpClient createHttpClient(HttpCacheStorage httpCacheStorage) { - HttpClientBuilder builder; + if (httpEntity == null) { + throw new AuthenticatorUnavailableException("Error while getting " + openIdConnectEndpoint + ": Empty response entity"); + } - if (httpCacheStorage != null) { - builder = CachingHttpClients.custom().setCacheConfig(cacheConfig).setHttpCacheStorage(httpCacheStorage); - } else { - builder = HttpClients.custom(); - } + OpenIdProviderConfiguration parsedEntity = DefaultObjectMapper.objectMapper.readValue( + httpEntity.getContent(), + OpenIdProviderConfiguration.class + ); - builder.useSystemProperties(); + return parsedEntity.getJwksUri(); - if (sslConfig != null) { - final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()) - .build(); + } - builder.setConnectionManager(cm); - } + } catch (IOException e) { + throw new AuthenticatorUnavailableException("Error while getting " + openIdConnectEndpoint + ": " + e, e); + } - return builder.build(); - } + } - public int getOidcCacheHits() { - return oidcCacheHits; - } + public int getRequestTimeoutMs() { + return requestTimeoutMs; + } - public int getOidcCacheMisses() { - return oidcCacheMisses; - } + public void setRequestTimeoutMs(int httpTimeoutMs) { + this.requestTimeoutMs = httpTimeoutMs; + } - public int getOidcCacheHitsValidated() { - return oidcCacheHitsValidated; - } + private void logCacheResponseStatus(HttpCacheContext httpContext) { + this.oidcRequests++; - public int getOidcCacheModuleResponses() { - return oidcCacheModuleResponses; - } + switch (httpContext.getCacheResponseStatus()) { + case CACHE_HIT: + this.oidcCacheHits++; + break; + case CACHE_MODULE_RESPONSE: + this.oidcCacheModuleResponses++; + break; + case CACHE_MISS: + this.oidcCacheMisses++; + break; + case VALIDATED: + this.oidcCacheHitsValidated++; + break; + } + + long now = System.currentTimeMillis(); + + if (this.oidcRequests >= 2 && now - lastCacheStatusLog > CACHE_STATUS_LOG_INTERVAL_MS) { + log.info( + "Cache status for KeySetRetriever:\noidcCacheHits: {}\noidcCacheHitsValidated: {}" + + "\noidcCacheModuleResponses: {}" + + "\noidcCacheMisses: {}", + oidcCacheHits, + oidcCacheHitsValidated, + oidcCacheModuleResponses, + oidcCacheMisses + ); + lastCacheStatusLog = now; + } + + } + + private CloseableHttpClient createHttpClient(HttpCacheStorage httpCacheStorage) { + HttpClientBuilder builder; + + if (httpCacheStorage != null) { + builder = CachingHttpClients.custom().setCacheConfig(cacheConfig).setHttpCacheStorage(httpCacheStorage); + } else { + builder = HttpClients.custom(); + } + + builder.useSystemProperties(); + + if (sslConfig != null) { + final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() + .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()) + .build(); + + builder.setConnectionManager(cm); + } + + return builder.build(); + } + + private void configureCache(boolean useCacheForOidConnectEndpoint) { + if (useCacheForOidConnectEndpoint) { + cacheConfig = CacheConfig.custom().setMaxCacheEntries(10).setMaxObjectSize(1024L * 1024L).build(); + oidcHttpCacheStorage = new BasicHttpCacheStorage(cacheConfig); + } + } + + public int getOidcCacheHits() { + return oidcCacheHits; + } + + public int getOidcCacheMisses() { + return oidcCacheMisses; + } + + public int getOidcCacheHitsValidated() { + return oidcCacheHitsValidated; + } + + public int getOidcCacheModuleResponses() { + return oidcCacheModuleResponses; + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SelfRefreshingKeySet.java b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SelfRefreshingKeySet.java index 7e3cec8246..fe410b171c 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SelfRefreshingKeySet.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SelfRefreshingKeySet.java @@ -25,295 +25,300 @@ import org.apache.logging.log4j.Logger; public class SelfRefreshingKeySet implements KeyProvider { - private static final Logger log = LogManager.getLogger(SelfRefreshingKeySet.class); - - private final KeySetProvider keySetProvider; - private final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue()); - private volatile JsonWebKeys jsonWebKeys = new JsonWebKeys(); - private boolean refreshInProgress = false; - private long refreshCount = 0; - private long queuedGetCount = 0; - private long recentRefreshCount = 0; - private long refreshTime = 0; - private Throwable lastRefreshFailure = null; - private int requestTimeoutMs = 5000; - private int queuedThreadTimeoutMs = 2500; - private int refreshRateLimitTimeWindowMs = 10000; - private int refreshRateLimitCount = 10; - - public SelfRefreshingKeySet(KeySetProvider refreshFunction) { - this.keySetProvider = refreshFunction; - } - - public JsonWebKey getKey(String kid) throws AuthenticatorUnavailableException, BadCredentialsException { - if (Strings.isNullOrEmpty(kid)) { - return getKeyWithoutKeyId(); - } else { - return getKeyWithKeyId(kid); - } - } - - public synchronized JsonWebKey getKeyAfterRefresh(String kid) - throws AuthenticatorUnavailableException, BadCredentialsException { - JsonWebKey result = getKeyAfterRefreshInternal(kid); - - if (result != null) { - return result; - } else if (jsonWebKeys.getKeys().size() == 0) { - throw new AuthenticatorUnavailableException("No JWK are available from IdP"); - } else { - throw new BadCredentialsException("JWT did not contain KID which is required if IdP provides multiple JWK"); - } - } - - private synchronized JsonWebKey getKeyAfterRefreshInternal(String kid) throws AuthenticatorUnavailableException { - if (refreshInProgress) { - return waitForRefreshToFinish(kid); - } else { - return performRefresh(kid); - } - } - - private JsonWebKey getKeyWithoutKeyId() throws AuthenticatorUnavailableException, BadCredentialsException { - List keys = jsonWebKeys.getKeys(); - - if (keys == null || keys.size() == 0) { - JsonWebKey result = getKeyWithRefresh(null); - - if (result != null) { - return result; - } else { - throw new AuthenticatorUnavailableException("No JWK are available from IdP"); - } - } else if (keys.size() == 1) { - return keys.get(0); - } else { - JsonWebKey result = getKeyWithRefresh(null); - - if (result != null) { - return result; - } else { - throw new BadCredentialsException( - "JWT did not contain KID which is required if IdP provides multiple JWK"); - } - } - } - - private JsonWebKey getKeyWithKeyId(String kid) throws AuthenticatorUnavailableException, BadCredentialsException { - JsonWebKey result = jsonWebKeys.getKey(kid); - - if (result != null) { - return result; - } - - result = getKeyWithRefresh(kid); - - if (result == null) { - throw new BadCredentialsException("Unknown kid " + kid); - } - - return result; - } - - private synchronized JsonWebKey getKeyWithRefresh(String kid) throws AuthenticatorUnavailableException { - - // Always re-check within synchronized to handle any races - - JsonWebKey result = getKeySimple(kid); - - if (result != null) { - return result; - } - - return getKeyAfterRefreshInternal(kid); - } - - private JsonWebKey getKeySimple(String kid) { - if (Strings.isNullOrEmpty(kid)) { - List keys = jsonWebKeys.getKeys(); - - if (keys != null && keys.size() == 1) { - return keys.get(0); - } else { - return null; - } - - } else { - return jsonWebKeys.getKey(kid); - } - } - - private synchronized JsonWebKey waitForRefreshToFinish(String kid) { - queuedGetCount++; - long currentRefreshCount = refreshCount; - - try { - wait(queuedThreadTimeoutMs); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - log.debug(e.toString()); - } - - // Just be optimistic and re-check the key - - JsonWebKey result = getKeySimple(kid); - - if (result != null) { - return result; - } - - if (refreshInProgress && currentRefreshCount == refreshCount) { - // The wait() call returned due to the timeout. - throw new AuthenticatorUnavailableException("Authentication backend timed out"); - } else if (lastRefreshFailure != null) { - throw new AuthenticatorUnavailableException("Authentication backend failed", lastRefreshFailure); - } else { - // Refresh was successful, but we did not get a matching key - return null; - } - } - - private synchronized JsonWebKey performRefresh(String kid) { - if (log.isDebugEnabled()) { - log.debug("performRefresh({})", kid); - } - - final boolean recentRefresh; - - if (System.currentTimeMillis() - refreshTime < refreshRateLimitTimeWindowMs) { - recentRefreshCount++; - recentRefresh = true; - - if (recentRefreshCount > refreshRateLimitCount) { - throw new AuthenticatorUnavailableException("Too many unknown kids recently: " + recentRefreshCount); - } - } else { - recentRefresh = false; - } - - refreshInProgress = true; - refreshCount++; - - log.info("Performing refresh {}", refreshCount); - - long currentRefreshCount = refreshCount; - - try { - - Future future = threadPoolExecutor.submit(new Runnable() { - - @Override - public void run() { - try { - JsonWebKeys newKeys = keySetProvider.get(); - - if (newKeys == null) { - throw new RuntimeException("Refresh function " + keySetProvider + " yielded null"); - } - - log.info("KeySetProvider finished"); - - synchronized (SelfRefreshingKeySet.this) { - jsonWebKeys = newKeys; - refreshInProgress = false; - lastRefreshFailure = null; - SelfRefreshingKeySet.this.notifyAll(); - } - } catch (Throwable e) { - synchronized (SelfRefreshingKeySet.this) { - lastRefreshFailure = e; - refreshInProgress = false; - SelfRefreshingKeySet.this.notifyAll(); - } - log.warn("KeySetProvider threw error", e); - } finally { - if (!recentRefresh) { - recentRefreshCount = 0; - refreshTime = System.currentTimeMillis(); - } - } - - } - }); - - try { - wait(requestTimeoutMs); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - log.debug(e.toString()); - } - - JsonWebKey result = getKeySimple(kid); - - if (result != null) { - return result; - } - - if (refreshInProgress && currentRefreshCount == refreshCount) { - if (!future.isDone()) { - future.cancel(true); - } - - lastRefreshFailure = new AuthenticatorUnavailableException("Authentication backend timed out"); - - throw new AuthenticatorUnavailableException("Authentication backend timed out"); - } - - if (lastRefreshFailure != null) { - throw new AuthenticatorUnavailableException("Authentication backend failed", lastRefreshFailure); - } - - return null; - - } catch (RejectedExecutionException e) { - throw new AuthenticatorUnavailableException("Did not try to call authentication backend because of " - + threadPoolExecutor.getActiveCount() + " pending threads", e); - } finally { - if (refreshInProgress && currentRefreshCount == refreshCount) { - refreshInProgress = false; - notifyAll(); - } - } - } - - public int getRequestTimeoutMs() { - return requestTimeoutMs; - } - - public void setRequestTimeoutMs(int requestTimeoutMs) { - this.requestTimeoutMs = requestTimeoutMs; - } - - public int getQueuedThreadTimeoutMs() { - return queuedThreadTimeoutMs; - } - - public void setQueuedThreadTimeoutMs(int queuedThreadTimeoutMs) { - this.queuedThreadTimeoutMs = queuedThreadTimeoutMs; - } - - public long getRefreshCount() { - return refreshCount; - } - - public long getQueuedGetCount() { - return queuedGetCount; - } - - public int getRefreshRateLimitTimeWindowMs() { - return refreshRateLimitTimeWindowMs; - } - - public void setRefreshRateLimitTimeWindowMs(int refreshRateLimitTimeWindowMs) { - this.refreshRateLimitTimeWindowMs = refreshRateLimitTimeWindowMs; - } - - public int getRefreshRateLimitCount() { - return refreshRateLimitCount; - } - - public void setRefreshRateLimitCount(int refreshRateLimitCount) { - this.refreshRateLimitCount = refreshRateLimitCount; - } + private static final Logger log = LogManager.getLogger(SelfRefreshingKeySet.class); + + private final KeySetProvider keySetProvider; + private final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( + 1, + 10, + 1000, + TimeUnit.MILLISECONDS, + new LinkedBlockingQueue() + ); + private volatile JsonWebKeys jsonWebKeys = new JsonWebKeys(); + private boolean refreshInProgress = false; + private long refreshCount = 0; + private long queuedGetCount = 0; + private long recentRefreshCount = 0; + private long refreshTime = 0; + private Throwable lastRefreshFailure = null; + private int requestTimeoutMs = 5000; + private int queuedThreadTimeoutMs = 2500; + private int refreshRateLimitTimeWindowMs = 10000; + private int refreshRateLimitCount = 10; + + public SelfRefreshingKeySet(KeySetProvider refreshFunction) { + this.keySetProvider = refreshFunction; + } + + public JsonWebKey getKey(String kid) throws AuthenticatorUnavailableException, BadCredentialsException { + if (Strings.isNullOrEmpty(kid)) { + return getKeyWithoutKeyId(); + } else { + return getKeyWithKeyId(kid); + } + } + + public synchronized JsonWebKey getKeyAfterRefresh(String kid) throws AuthenticatorUnavailableException, BadCredentialsException { + JsonWebKey result = getKeyAfterRefreshInternal(kid); + + if (result != null) { + return result; + } else if (jsonWebKeys.getKeys().size() == 0) { + throw new AuthenticatorUnavailableException("No JWK are available from IdP"); + } else { + throw new BadCredentialsException("JWT did not contain KID which is required if IdP provides multiple JWK"); + } + } + + private synchronized JsonWebKey getKeyAfterRefreshInternal(String kid) throws AuthenticatorUnavailableException { + if (refreshInProgress) { + return waitForRefreshToFinish(kid); + } else { + return performRefresh(kid); + } + } + + private JsonWebKey getKeyWithoutKeyId() throws AuthenticatorUnavailableException, BadCredentialsException { + List keys = jsonWebKeys.getKeys(); + + if (keys == null || keys.size() == 0) { + JsonWebKey result = getKeyWithRefresh(null); + + if (result != null) { + return result; + } else { + throw new AuthenticatorUnavailableException("No JWK are available from IdP"); + } + } else if (keys.size() == 1) { + return keys.get(0); + } else { + JsonWebKey result = getKeyWithRefresh(null); + + if (result != null) { + return result; + } else { + throw new BadCredentialsException("JWT did not contain KID which is required if IdP provides multiple JWK"); + } + } + } + + private JsonWebKey getKeyWithKeyId(String kid) throws AuthenticatorUnavailableException, BadCredentialsException { + JsonWebKey result = jsonWebKeys.getKey(kid); + + if (result != null) { + return result; + } + + result = getKeyWithRefresh(kid); + + if (result == null) { + throw new BadCredentialsException("Unknown kid " + kid); + } + + return result; + } + + private synchronized JsonWebKey getKeyWithRefresh(String kid) throws AuthenticatorUnavailableException { + + // Always re-check within synchronized to handle any races + + JsonWebKey result = getKeySimple(kid); + + if (result != null) { + return result; + } + + return getKeyAfterRefreshInternal(kid); + } + + private JsonWebKey getKeySimple(String kid) { + if (Strings.isNullOrEmpty(kid)) { + List keys = jsonWebKeys.getKeys(); + + if (keys != null && keys.size() == 1) { + return keys.get(0); + } else { + return null; + } + + } else { + return jsonWebKeys.getKey(kid); + } + } + + private synchronized JsonWebKey waitForRefreshToFinish(String kid) { + queuedGetCount++; + long currentRefreshCount = refreshCount; + + try { + wait(queuedThreadTimeoutMs); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + log.debug(e.toString()); + } + + // Just be optimistic and re-check the key + + JsonWebKey result = getKeySimple(kid); + + if (result != null) { + return result; + } + + if (refreshInProgress && currentRefreshCount == refreshCount) { + // The wait() call returned due to the timeout. + throw new AuthenticatorUnavailableException("Authentication backend timed out"); + } else if (lastRefreshFailure != null) { + throw new AuthenticatorUnavailableException("Authentication backend failed", lastRefreshFailure); + } else { + // Refresh was successful, but we did not get a matching key + return null; + } + } + + private synchronized JsonWebKey performRefresh(String kid) { + if (log.isDebugEnabled()) { + log.debug("performRefresh({})", kid); + } + + final boolean recentRefresh; + + if (System.currentTimeMillis() - refreshTime < refreshRateLimitTimeWindowMs) { + recentRefreshCount++; + recentRefresh = true; + + if (recentRefreshCount > refreshRateLimitCount) { + throw new AuthenticatorUnavailableException("Too many unknown kids recently: " + recentRefreshCount); + } + } else { + recentRefresh = false; + } + + refreshInProgress = true; + refreshCount++; + + log.info("Performing refresh {}", refreshCount); + + long currentRefreshCount = refreshCount; + + try { + + Future future = threadPoolExecutor.submit(new Runnable() { + + @Override + public void run() { + try { + JsonWebKeys newKeys = keySetProvider.get(); + + if (newKeys == null) { + throw new RuntimeException("Refresh function " + keySetProvider + " yielded null"); + } + + log.info("KeySetProvider finished"); + + synchronized (SelfRefreshingKeySet.this) { + jsonWebKeys = newKeys; + refreshInProgress = false; + lastRefreshFailure = null; + SelfRefreshingKeySet.this.notifyAll(); + } + } catch (Throwable e) { + synchronized (SelfRefreshingKeySet.this) { + lastRefreshFailure = e; + refreshInProgress = false; + SelfRefreshingKeySet.this.notifyAll(); + } + log.warn("KeySetProvider threw error", e); + } finally { + if (!recentRefresh) { + recentRefreshCount = 0; + refreshTime = System.currentTimeMillis(); + } + } + + } + }); + + try { + wait(requestTimeoutMs); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + log.debug(e.toString()); + } + + JsonWebKey result = getKeySimple(kid); + + if (result != null) { + return result; + } + + if (refreshInProgress && currentRefreshCount == refreshCount) { + if (!future.isDone()) { + future.cancel(true); + } + + lastRefreshFailure = new AuthenticatorUnavailableException("Authentication backend timed out"); + + throw new AuthenticatorUnavailableException("Authentication backend timed out"); + } + + if (lastRefreshFailure != null) { + throw new AuthenticatorUnavailableException("Authentication backend failed", lastRefreshFailure); + } + + return null; + + } catch (RejectedExecutionException e) { + throw new AuthenticatorUnavailableException( + "Did not try to call authentication backend because of " + threadPoolExecutor.getActiveCount() + " pending threads", + e + ); + } finally { + if (refreshInProgress && currentRefreshCount == refreshCount) { + refreshInProgress = false; + notifyAll(); + } + } + } + + public int getRequestTimeoutMs() { + return requestTimeoutMs; + } + + public void setRequestTimeoutMs(int requestTimeoutMs) { + this.requestTimeoutMs = requestTimeoutMs; + } + + public int getQueuedThreadTimeoutMs() { + return queuedThreadTimeoutMs; + } + + public void setQueuedThreadTimeoutMs(int queuedThreadTimeoutMs) { + this.queuedThreadTimeoutMs = queuedThreadTimeoutMs; + } + + public long getRefreshCount() { + return refreshCount; + } + + public long getQueuedGetCount() { + return queuedGetCount; + } + + public int getRefreshRateLimitTimeWindowMs() { + return refreshRateLimitTimeWindowMs; + } + + public void setRefreshRateLimitTimeWindowMs(int refreshRateLimitTimeWindowMs) { + this.refreshRateLimitTimeWindowMs = refreshRateLimitTimeWindowMs; + } + + public int getRefreshRateLimitCount() { + return refreshRateLimitCount; + } + + public void setRefreshRateLimitCount(int refreshRateLimitCount) { + this.refreshRateLimitCount = refreshRateLimitCount; + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/oidc/json/OpenIdProviderConfiguration.java b/src/main/java/com/amazon/dlic/auth/http/jwt/oidc/json/OpenIdProviderConfiguration.java index 58a4310a2d..3bcfb796b0 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/oidc/json/OpenIdProviderConfiguration.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/oidc/json/OpenIdProviderConfiguration.java @@ -17,15 +17,15 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class OpenIdProviderConfiguration { - @JsonProperty("jwks_uri") - private String jwksUri; + @JsonProperty("jwks_uri") + private String jwksUri; - public String getJwksUri() { - return jwksUri; - } + public String getJwksUri() { + return jwksUri; + } - public void setJwksUri(String jwksUri) { - this.jwksUri = jwksUri; - } + public void setJwksUri(String jwksUri) { + this.jwksUri = jwksUri; + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/kerberos/HTTPSpnegoAuthenticator.java b/src/main/java/com/amazon/dlic/auth/http/kerberos/HTTPSpnegoAuthenticator.java index 15aff90f1a..d8e11960d6 100644 --- a/src/main/java/com/amazon/dlic/auth/http/kerberos/HTTPSpnegoAuthenticator.java +++ b/src/main/java/com/amazon/dlic/auth/http/kerberos/HTTPSpnegoAuthenticator.java @@ -58,7 +58,7 @@ public class HTTPSpnegoAuthenticator implements HTTPAuthenticator { private static final String EMPTY_STRING = ""; - private static final Oid[] KRB_OIDS = new Oid[] {KrbConstants.SPNEGO, KrbConstants.KRB5MECH}; + private static final Oid[] KRB_OIDS = new Oid[] { KrbConstants.SPNEGO, KrbConstants.KRB5MECH }; protected final Logger log = LogManager.getLogger(this.getClass()); @@ -98,17 +98,17 @@ public Void run() { } } catch (Throwable e) { log.error("Unable to enable krb_debug due to ", e); - System.err.println("Unable to enable krb_debug due to "+ExceptionsHelper.stackTrace(e)); - System.out.println("Unable to enable krb_debug due to "+ExceptionsHelper.stackTrace(e)); + System.err.println("Unable to enable krb_debug due to " + ExceptionsHelper.stackTrace(e)); + System.out.println("Unable to enable krb_debug due to " + ExceptionsHelper.stackTrace(e)); } System.setProperty(KrbConstants.USE_SUBJECT_CREDS_ONLY_PROP, "false"); String krb5Path = krb5PathSetting; - if(!Strings.isNullOrEmpty(krb5Path)) { + if (!Strings.isNullOrEmpty(krb5Path)) { - if(Paths.get(krb5Path).isAbsolute()) { + if (Paths.get(krb5Path).isAbsolute()) { log.debug("krb5_filepath: {}", krb5Path); System.setProperty(KrbConstants.KRB5_CONF_PROP, krb5Path); } else { @@ -118,29 +118,36 @@ public Void run() { System.setProperty(KrbConstants.KRB5_CONF_PROP, krb5Path); } else { - if(Strings.isNullOrEmpty(System.getProperty(KrbConstants.KRB5_CONF_PROP))) { + if (Strings.isNullOrEmpty(System.getProperty(KrbConstants.KRB5_CONF_PROP))) { System.setProperty(KrbConstants.KRB5_CONF_PROP, "/etc/krb5.conf"); log.debug("krb5_filepath (was not set or configured, set to default): /etc/krb5.conf"); } } stripRealmFromPrincipalName = settings.getAsBoolean("strip_realm_from_principal", true); - acceptorPrincipal = new HashSet<>(settings.getAsList("plugins.security.kerberos.acceptor_principal", Collections.emptyList())); + acceptorPrincipal = new HashSet<>( + settings.getAsList("plugins.security.kerberos.acceptor_principal", Collections.emptyList()) + ); final String _acceptorKeyTabPath = settings.get("plugins.security.kerberos.acceptor_keytab_filepath"); - if(acceptorPrincipal == null || acceptorPrincipal.size() == 0) { + if (acceptorPrincipal == null || acceptorPrincipal.size() == 0) { log.error("acceptor_principal must not be null or empty. Kerberos authentication will not work"); acceptorPrincipal = null; } - if(_acceptorKeyTabPath == null || _acceptorKeyTabPath.length() == 0) { - log.error("plugins.security.kerberos.acceptor_keytab_filepath must not be null or empty. Kerberos authentication will not work"); + if (_acceptorKeyTabPath == null || _acceptorKeyTabPath.length() == 0) { + log.error( + "plugins.security.kerberos.acceptor_keytab_filepath must not be null or empty. Kerberos authentication will not work" + ); acceptorKeyTabPath = null; } else { acceptorKeyTabPath = configDir.resolve(settings.get("plugins.security.kerberos.acceptor_keytab_filepath")); - if(!Files.exists(acceptorKeyTabPath)) { - log.error("Unable to read keytab from {} - Maybe the file does not exist or is not readable. Kerberos authentication will not work", acceptorKeyTabPath); + if (!Files.exists(acceptorKeyTabPath)) { + log.error( + "Unable to read keytab from {} - Maybe the file does not exist or is not readable. Kerberos authentication will not work", + acceptorKeyTabPath + ); acceptorKeyTabPath = null; } } @@ -155,7 +162,9 @@ public Void run() { } catch (Throwable e) { log.error("Cannot construct HTTPSpnegoAuthenticator due to {}", e.getMessage(), e); - log.error("Please make sure you configured 'plugins.security.kerberos.acceptor_keytab_filepath' realtive to the ES config/ dir!"); + log.error( + "Please make sure you configured 'plugins.security.kerberos.acceptor_keytab_filepath' realtive to the ES config/ dir!" + ); throw e; } @@ -252,11 +261,13 @@ public GSSCredential run() throws GSSException { return new AuthCredentials("_incomplete_", (Object) outToken); } - final String username = ((SimpleUserPrincipal) principal).getName(); - if(username == null || username.length() == 0) { - log.error("Got empty or null user from kerberos. Normally this means that you acceptor principal {} does not match the server hostname", acceptorPrincipal); + if (username == null || username.length() == 0) { + log.error( + "Got empty or null user from kerberos. Normally this means that you acceptor principal {} does not match the server hostname", + acceptorPrincipal + ); } return new AuthCredentials(username, (Object) outToken).markComplete(); @@ -272,19 +283,22 @@ public GSSCredential run() throws GSSException { @Override public boolean reRequestAuthentication(final RestChannel channel, AuthCredentials creds) { - final BytesRestResponse wwwAuthenticateResponse; - XContentBuilder response = getNegotiateResponseBody(); + final BytesRestResponse wwwAuthenticateResponse; + XContentBuilder response = getNegotiateResponseBody(); - if (response != null) { - wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, response); + if (response != null) { + wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, response); } else { - wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, EMPTY_STRING); + wwwAuthenticateResponse = new BytesRestResponse(RestStatus.UNAUTHORIZED, EMPTY_STRING); } - if(creds == null || creds.getNativeCredentials() == null) { + if (creds == null || creds.getNativeCredentials() == null) { wwwAuthenticateResponse.addHeader("WWW-Authenticate", "Negotiate"); } else { - wwwAuthenticateResponse.addHeader("WWW-Authenticate", "Negotiate "+Base64.getEncoder().encodeToString((byte[]) creds.getNativeCredentials())); + wwwAuthenticateResponse.addHeader( + "WWW-Authenticate", + "Negotiate " + Base64.getEncoder().encodeToString((byte[]) creds.getNativeCredentials()) + ); } channel.sendResponse(wwwAuthenticateResponse); return true; @@ -298,7 +312,7 @@ public String getType() { /** * This class gets a gss credential via a privileged action. */ - //borrowed from Apache Tomcat 8 http://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk/ + // borrowed from Apache Tomcat 8 http://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk/ private static class AcceptAction implements PrivilegedExceptionAction { GSSContext gssContext; @@ -316,7 +330,7 @@ public byte[] run() throws GSSException { } } - //borrowed from Apache Tomcat 8 http://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk/ + // borrowed from Apache Tomcat 8 http://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk/ private static class AuthenticateAction implements PrivilegedAction { private final Logger logger; @@ -336,7 +350,7 @@ public Principal run() { } } - //borrowed from Apache Tomcat 8 http://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk/ + // borrowed from Apache Tomcat 8 http://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk/ private static String getUsernameFromGSSContext(final GSSContext gssContext, final boolean strip, final Logger logger) { if (gssContext.isEstablished()) { GSSName gssName = null; @@ -359,26 +373,26 @@ private static String getUsernameFromGSSContext(final GSSContext gssContext, fin return null; } - private XContentBuilder getNegotiateResponseBody() { - try { - XContentBuilder negotiateResponseBody = XContentFactory.jsonBuilder(); - negotiateResponseBody.startObject(); - negotiateResponseBody.field("error"); - negotiateResponseBody.startObject(); - negotiateResponseBody.field("header"); - negotiateResponseBody.startObject(); - negotiateResponseBody.field("WWW-Authenticate", "Negotiate"); - negotiateResponseBody.endObject(); - negotiateResponseBody.endObject(); - negotiateResponseBody.endObject(); - return negotiateResponseBody; - } catch (Exception ex) { - log.error("Can't construct response body", ex); - return null; - } - } - - private static String stripRealmName(String name, boolean strip){ + private XContentBuilder getNegotiateResponseBody() { + try { + XContentBuilder negotiateResponseBody = XContentFactory.jsonBuilder(); + negotiateResponseBody.startObject(); + negotiateResponseBody.field("error"); + negotiateResponseBody.startObject(); + negotiateResponseBody.field("header"); + negotiateResponseBody.startObject(); + negotiateResponseBody.field("WWW-Authenticate", "Negotiate"); + negotiateResponseBody.endObject(); + negotiateResponseBody.endObject(); + negotiateResponseBody.endObject(); + return negotiateResponseBody; + } catch (Exception ex) { + log.error("Can't construct response body", ex); + return null; + } + } + + private static String stripRealmName(String name, boolean strip) { if (strip && name != null) { final int i = name.indexOf('@'); if (i > 0) { diff --git a/src/main/java/com/amazon/dlic/auth/http/kerberos/util/JaasKrbUtil.java b/src/main/java/com/amazon/dlic/auth/http/kerberos/util/JaasKrbUtil.java index 6574728da4..619c780027 100644 --- a/src/main/java/com/amazon/dlic/auth/http/kerberos/util/JaasKrbUtil.java +++ b/src/main/java/com/amazon/dlic/auth/http/kerberos/util/JaasKrbUtil.java @@ -38,177 +38,177 @@ */ public final class JaasKrbUtil { - private static boolean debug = false; - - private JaasKrbUtil() { - } - - public static void setDebug(final boolean debug) { - JaasKrbUtil.debug = debug; - } - - public static Subject loginUsingPassword(final String principal, final String password) throws LoginException { - final Set principals = new HashSet(); - principals.add(new KerberosPrincipal(principal)); - - final Subject subject = new Subject(false, principals, new HashSet(), new HashSet()); - - final Configuration conf = usePassword(principal); - final String confName = "PasswordConf"; - final CallbackHandler callback = new KrbCallbackHandler(principal, password); - final LoginContext loginContext = new LoginContext(confName, subject, callback, conf); - loginContext.login(); - return loginContext.getSubject(); - } - - public static Subject loginUsingTicketCache(final String principal, final Path cachePath) throws LoginException { - final Set principals = new HashSet(); - principals.add(new KerberosPrincipal(principal)); - - final Subject subject = new Subject(false, principals, new HashSet(), new HashSet()); - - final Configuration conf = useTicketCache(principal, cachePath); - final String confName = "TicketCacheConf"; - final LoginContext loginContext = new LoginContext(confName, subject, null, conf); - loginContext.login(); - return loginContext.getSubject(); - } - - public static Subject loginUsingKeytab(final Set principalAsStrings, final Path keytabPath, final boolean initiator) throws LoginException { - final Set principals = new HashSet(); - - for(String p: principalAsStrings) { - principals.add(new KerberosPrincipal(p)); - } - - - final Subject subject = new Subject(false, principals, new HashSet(), new HashSet()); - - final Configuration conf = useKeytab("*", keytabPath, initiator); - final String confName = "KeytabConf"; - final LoginContext loginContext = new LoginContext(confName, subject, null, conf); - loginContext.login(); - return loginContext.getSubject(); - } - - public static Configuration usePassword(final String principal) { - return new PasswordJaasConf(principal); - } - - public static Configuration useTicketCache(final String principal, final Path credentialPath) { - return new TicketCacheJaasConf(principal, credentialPath); - } - - public static Configuration useKeytab(final String principal, final Path keytabPath, final boolean initiator) { - return new KeytabJaasConf(principal, keytabPath, initiator); - } - - private static String getKrb5LoginModuleName() { - return System.getProperty("java.vendor").contains("IBM") ? "com.ibm.security.auth.module.Krb5LoginModule" - : "com.sun.security.auth.module.Krb5LoginModule"; - } - - static class KeytabJaasConf extends Configuration { - private final String principal; - private final Path keytabPath; - private final boolean initiator; - - public KeytabJaasConf(final String principal, final Path keytab, final boolean initiator) { - this.principal = principal; - this.keytabPath = keytab; - this.initiator = initiator; - } - - @Override - public AppConfigurationEntry[] getAppConfigurationEntry(final String name) { - final Map options = new HashMap(); - options.put("keyTab", keytabPath.toAbsolutePath().toString()); - options.put("principal", principal); - options.put("useKeyTab", "true"); - options.put("storeKey", "true"); - options.put("doNotPrompt", "true"); - options.put("renewTGT", "false"); - options.put("refreshKrb5Config", "true"); - options.put("isInitiator", String.valueOf(initiator)); - options.put("debug", String.valueOf(debug)); - - return new AppConfigurationEntry[] { new AppConfigurationEntry(getKrb5LoginModuleName(), - AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) }; - } - } - - static class TicketCacheJaasConf extends Configuration { - private final String principal; - private final Path clientCredentialPath; - - public TicketCacheJaasConf(final String principal, final Path clientCredentialPath) { - this.principal = principal; - this.clientCredentialPath = clientCredentialPath; - } - - @Override - public AppConfigurationEntry[] getAppConfigurationEntry(final String name) { - final Map options = new HashMap(); - options.put("principal", principal); - options.put("storeKey", "false"); - options.put("doNotPrompt", "false"); - options.put("useTicketCache", "true"); - options.put("renewTGT", "true"); - options.put("refreshKrb5Config", "true"); - options.put("isInitiator", "true"); - options.put("ticketCache", clientCredentialPath.toAbsolutePath().toString()); - options.put("debug", String.valueOf(debug)); - - return new AppConfigurationEntry[] { new AppConfigurationEntry(getKrb5LoginModuleName(), - AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) }; - } - } - - static class PasswordJaasConf extends Configuration { - private final String principal; - - public PasswordJaasConf(final String principal) { - this.principal = principal; - } - - @Override - public AppConfigurationEntry[] getAppConfigurationEntry(final String name) { - final Map options = new HashMap<>(); - options.put("principal", principal); - options.put("storeKey", "true"); - options.put("useTicketCache", "true"); - options.put("useKeyTab", "false"); - options.put("renewTGT", "true"); - options.put("refreshKrb5Config", "true"); - options.put("isInitiator", "true"); - options.put("debug", String.valueOf(debug)); - - return new AppConfigurationEntry[] { new AppConfigurationEntry(getKrb5LoginModuleName(), - AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) }; - } - } - - public static class KrbCallbackHandler implements CallbackHandler { - private final String principal; - private final String password; - - public KrbCallbackHandler(final String principal, final String password) { - this.principal = principal; - this.password = password; - } - - @Override - public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException { - for (int i = 0; i < callbacks.length; i++) { - if (callbacks[i] instanceof PasswordCallback) { - final PasswordCallback pc = (PasswordCallback) callbacks[i]; - if (pc.getPrompt().contains(principal)) { - pc.setPassword(password.toCharArray()); - break; - } - } - } - } - } + private static boolean debug = false; + + private JaasKrbUtil() {} + + public static void setDebug(final boolean debug) { + JaasKrbUtil.debug = debug; + } + + public static Subject loginUsingPassword(final String principal, final String password) throws LoginException { + final Set principals = new HashSet(); + principals.add(new KerberosPrincipal(principal)); + + final Subject subject = new Subject(false, principals, new HashSet(), new HashSet()); + + final Configuration conf = usePassword(principal); + final String confName = "PasswordConf"; + final CallbackHandler callback = new KrbCallbackHandler(principal, password); + final LoginContext loginContext = new LoginContext(confName, subject, callback, conf); + loginContext.login(); + return loginContext.getSubject(); + } + + public static Subject loginUsingTicketCache(final String principal, final Path cachePath) throws LoginException { + final Set principals = new HashSet(); + principals.add(new KerberosPrincipal(principal)); + + final Subject subject = new Subject(false, principals, new HashSet(), new HashSet()); + + final Configuration conf = useTicketCache(principal, cachePath); + final String confName = "TicketCacheConf"; + final LoginContext loginContext = new LoginContext(confName, subject, null, conf); + loginContext.login(); + return loginContext.getSubject(); + } + + public static Subject loginUsingKeytab(final Set principalAsStrings, final Path keytabPath, final boolean initiator) + throws LoginException { + final Set principals = new HashSet(); + + for (String p : principalAsStrings) { + principals.add(new KerberosPrincipal(p)); + } + + final Subject subject = new Subject(false, principals, new HashSet(), new HashSet()); + + final Configuration conf = useKeytab("*", keytabPath, initiator); + final String confName = "KeytabConf"; + final LoginContext loginContext = new LoginContext(confName, subject, null, conf); + loginContext.login(); + return loginContext.getSubject(); + } + + public static Configuration usePassword(final String principal) { + return new PasswordJaasConf(principal); + } + + public static Configuration useTicketCache(final String principal, final Path credentialPath) { + return new TicketCacheJaasConf(principal, credentialPath); + } + + public static Configuration useKeytab(final String principal, final Path keytabPath, final boolean initiator) { + return new KeytabJaasConf(principal, keytabPath, initiator); + } + + private static String getKrb5LoginModuleName() { + return System.getProperty("java.vendor").contains("IBM") + ? "com.ibm.security.auth.module.Krb5LoginModule" + : "com.sun.security.auth.module.Krb5LoginModule"; + } + + static class KeytabJaasConf extends Configuration { + private final String principal; + private final Path keytabPath; + private final boolean initiator; + + public KeytabJaasConf(final String principal, final Path keytab, final boolean initiator) { + this.principal = principal; + this.keytabPath = keytab; + this.initiator = initiator; + } + + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(final String name) { + final Map options = new HashMap(); + options.put("keyTab", keytabPath.toAbsolutePath().toString()); + options.put("principal", principal); + options.put("useKeyTab", "true"); + options.put("storeKey", "true"); + options.put("doNotPrompt", "true"); + options.put("renewTGT", "false"); + options.put("refreshKrb5Config", "true"); + options.put("isInitiator", String.valueOf(initiator)); + options.put("debug", String.valueOf(debug)); + + return new AppConfigurationEntry[] { + new AppConfigurationEntry(getKrb5LoginModuleName(), AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) }; + } + } + + static class TicketCacheJaasConf extends Configuration { + private final String principal; + private final Path clientCredentialPath; + + public TicketCacheJaasConf(final String principal, final Path clientCredentialPath) { + this.principal = principal; + this.clientCredentialPath = clientCredentialPath; + } + + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(final String name) { + final Map options = new HashMap(); + options.put("principal", principal); + options.put("storeKey", "false"); + options.put("doNotPrompt", "false"); + options.put("useTicketCache", "true"); + options.put("renewTGT", "true"); + options.put("refreshKrb5Config", "true"); + options.put("isInitiator", "true"); + options.put("ticketCache", clientCredentialPath.toAbsolutePath().toString()); + options.put("debug", String.valueOf(debug)); + + return new AppConfigurationEntry[] { + new AppConfigurationEntry(getKrb5LoginModuleName(), AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) }; + } + } + + static class PasswordJaasConf extends Configuration { + private final String principal; + + public PasswordJaasConf(final String principal) { + this.principal = principal; + } + + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(final String name) { + final Map options = new HashMap<>(); + options.put("principal", principal); + options.put("storeKey", "true"); + options.put("useTicketCache", "true"); + options.put("useKeyTab", "false"); + options.put("renewTGT", "true"); + options.put("refreshKrb5Config", "true"); + options.put("isInitiator", "true"); + options.put("debug", String.valueOf(debug)); + + return new AppConfigurationEntry[] { + new AppConfigurationEntry(getKrb5LoginModuleName(), AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) }; + } + } + + public static class KrbCallbackHandler implements CallbackHandler { + private final String principal; + private final String password; + + public KrbCallbackHandler(final String principal, final String password) { + this.principal = principal; + this.password = password; + } + + @Override + public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof PasswordCallback) { + final PasswordCallback pc = (PasswordCallback) callbacks[i]; + if (pc.getPrompt().contains(principal)) { + pc.setPassword(password.toCharArray()); + break; + } + } + } + } + } } diff --git a/src/main/java/com/amazon/dlic/auth/http/kerberos/util/KrbConstants.java b/src/main/java/com/amazon/dlic/auth/http/kerberos/util/KrbConstants.java index 801ca78e27..a8a57633dc 100644 --- a/src/main/java/com/amazon/dlic/auth/http/kerberos/util/KrbConstants.java +++ b/src/main/java/com/amazon/dlic/auth/http/kerberos/util/KrbConstants.java @@ -16,28 +16,27 @@ public final class KrbConstants { - static { - Oid spnegoTmp = null; - Oid krbTmp = null; - try { - spnegoTmp = new Oid("1.3.6.1.5.5.2"); - krbTmp = new Oid("1.2.840.113554.1.2.2"); - } catch (final GSSException e) { - - } - SPNEGO = spnegoTmp; - KRB5MECH = krbTmp; - } - - public static final Oid SPNEGO; - public static final Oid KRB5MECH; - public static final String KRB5_CONF_PROP = "java.security.krb5.conf"; - public static final String JAAS_LOGIN_CONF_PROP = "java.security.auth.login.config"; - public static final String USE_SUBJECT_CREDS_ONLY_PROP = "javax.security.auth.useSubjectCredsOnly"; - public static final String NEGOTIATE = "Negotiate"; - public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; - - private KrbConstants() { - } + static { + Oid spnegoTmp = null; + Oid krbTmp = null; + try { + spnegoTmp = new Oid("1.3.6.1.5.5.2"); + krbTmp = new Oid("1.2.840.113554.1.2.2"); + } catch (final GSSException e) { + + } + SPNEGO = spnegoTmp; + KRB5MECH = krbTmp; + } + + public static final Oid SPNEGO; + public static final Oid KRB5MECH; + public static final String KRB5_CONF_PROP = "java.security.krb5.conf"; + public static final String JAAS_LOGIN_CONF_PROP = "java.security.auth.login.config"; + public static final String USE_SUBJECT_CREDS_ONLY_PROP = "javax.security.auth.useSubjectCredsOnly"; + public static final String NEGOTIATE = "Negotiate"; + public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + + private KrbConstants() {} } diff --git a/src/main/java/com/amazon/dlic/auth/http/saml/AuthTokenProcessorHandler.java b/src/main/java/com/amazon/dlic/auth/http/saml/AuthTokenProcessorHandler.java index 4ab5673adb..1c49d10b2e 100644 --- a/src/main/java/com/amazon/dlic/auth/http/saml/AuthTokenProcessorHandler.java +++ b/src/main/java/com/amazon/dlic/auth/http/saml/AuthTokenProcessorHandler.java @@ -83,8 +83,7 @@ class AuthTokenProcessorHandler { private JsonMapObjectReaderWriter jsonMapReaderWriter = new JsonMapObjectReaderWriter(); private Pattern samlRolesSeparatorPattern; - AuthTokenProcessorHandler(Settings settings, Settings jwtSettings, Saml2SettingsProvider saml2SettingsProvider) - throws Exception { + AuthTokenProcessorHandler(Settings settings, Settings jwtSettings, Saml2SettingsProvider saml2SettingsProvider) throws Exception { this.saml2SettingsProvider = saml2SettingsProvider; this.jwtRolesKey = jwtSettings.get("roles_key", "roles"); @@ -133,8 +132,8 @@ boolean handle(RestRequest restRequest, RestChannel restChannel) throws Exceptio return AccessController.doPrivileged(new PrivilegedExceptionAction() { @Override - public Boolean run() throws XPathExpressionException, SamlConfigException, IOException, - ParserConfigurationException, SAXException, SettingsException { + public Boolean run() throws XPathExpressionException, SamlConfigException, IOException, ParserConfigurationException, + SAXException, SettingsException { return handleLowLevel(restRequest, restChannel); } }); @@ -147,17 +146,23 @@ public Boolean run() throws XPathExpressionException, SamlConfigException, IOExc } } - private AuthTokenProcessorAction.Response handleImpl(RestRequest restRequest, RestChannel restChannel, - String samlResponseBase64, String samlRequestId, String acsEndpoint, Saml2Settings saml2Settings) - throws XPathExpressionException, ParserConfigurationException, SAXException, IOException, - SettingsException { + private AuthTokenProcessorAction.Response handleImpl( + RestRequest restRequest, + RestChannel restChannel, + String samlResponseBase64, + String samlRequestId, + String acsEndpoint, + Saml2Settings saml2Settings + ) throws XPathExpressionException, ParserConfigurationException, SAXException, IOException, SettingsException { if (token_log.isDebugEnabled()) { try { - token_log.debug("SAMLResponse for {}\n{}", samlRequestId, new String(Util.base64decoder(samlResponseBase64), StandardCharsets.UTF_8)); + token_log.debug( + "SAMLResponse for {}\n{}", + samlRequestId, + new String(Util.base64decoder(samlResponseBase64), StandardCharsets.UTF_8) + ); } catch (Exception e) { - token_log.warn( - "SAMLResponse for {} cannot be decoded from base64\n{}", - samlRequestId, samlResponseBase64, e); + token_log.warn("SAMLResponse for {} cannot be decoded from base64\n{}", samlRequestId, samlResponseBase64, e); } } @@ -185,20 +190,23 @@ private AuthTokenProcessorAction.Response handleImpl(RestRequest restRequest, Re } } - private boolean handleLowLevel(RestRequest restRequest, RestChannel restChannel) throws SamlConfigException, - IOException, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException { + private boolean handleLowLevel(RestRequest restRequest, RestChannel restChannel) throws SamlConfigException, IOException, + XPathExpressionException, ParserConfigurationException, SAXException, SettingsException { try { if (restRequest.getXContentType() != XContentType.JSON) { throw new OpenSearchSecurityException( - "/_opendistro/_security/api/authtoken expects content with type application/json", - RestStatus.UNSUPPORTED_MEDIA_TYPE); + "/_opendistro/_security/api/authtoken expects content with type application/json", + RestStatus.UNSUPPORTED_MEDIA_TYPE + ); } if (restRequest.method() != Method.POST) { - throw new OpenSearchSecurityException("/_opendistro/_security/api/authtoken expects POST requests", - RestStatus.METHOD_NOT_ALLOWED); + throw new OpenSearchSecurityException( + "/_opendistro/_security/api/authtoken expects POST requests", + RestStatus.METHOD_NOT_ALLOWED + ); } Saml2Settings saml2Settings = this.saml2SettingsProvider.getCached(); @@ -214,24 +222,28 @@ private boolean handleLowLevel(RestRequest restRequest, RestChannel restChannel) if (((ObjectNode) jsonRoot).get("SAMLResponse") == null) { log.warn("SAMLResponse is missing from request "); - throw new OpenSearchSecurityException("SAMLResponse is missing from request", - RestStatus.BAD_REQUEST); + throw new OpenSearchSecurityException("SAMLResponse is missing from request", RestStatus.BAD_REQUEST); } String samlResponseBase64 = ((ObjectNode) jsonRoot).get("SAMLResponse").asText(); String samlRequestId = ((ObjectNode) jsonRoot).get("RequestId") != null - ? ((ObjectNode) jsonRoot).get("RequestId").textValue() - : null; + ? ((ObjectNode) jsonRoot).get("RequestId").textValue() + : null; String acsEndpoint = saml2Settings.getSpAssertionConsumerServiceUrl().toString(); - if (((ObjectNode) jsonRoot).get("acsEndpoint") != null - && ((ObjectNode) jsonRoot).get("acsEndpoint").textValue() != null) { + if (((ObjectNode) jsonRoot).get("acsEndpoint") != null && ((ObjectNode) jsonRoot).get("acsEndpoint").textValue() != null) { acsEndpoint = getAbsoluteAcsEndpoint(((ObjectNode) jsonRoot).get("acsEndpoint").textValue()); } - AuthTokenProcessorAction.Response responseBody = this.handleImpl(restRequest, restChannel, - samlResponseBase64, samlRequestId, acsEndpoint, saml2Settings); + AuthTokenProcessorAction.Response responseBody = this.handleImpl( + restRequest, + restChannel, + samlResponseBase64, + samlRequestId, + acsEndpoint, + saml2Settings + ); if (responseBody == null) { return false; @@ -239,16 +251,14 @@ private boolean handleLowLevel(RestRequest restRequest, RestChannel restChannel) String responseBodyString = DefaultObjectMapper.objectMapper.writeValueAsString(responseBody); - BytesRestResponse authenticateResponse = new BytesRestResponse(RestStatus.OK, "application/json", - responseBodyString); + BytesRestResponse authenticateResponse = new BytesRestResponse(RestStatus.OK, "application/json", responseBodyString); restChannel.sendResponse(authenticateResponse); return true; } catch (JsonProcessingException e) { log.warn("Error while parsing JSON for /_opendistro/_security/api/authtoken", e); - BytesRestResponse authenticateResponse = new BytesRestResponse(RestStatus.BAD_REQUEST, - "JSON could not be parsed"); + BytesRestResponse authenticateResponse = new BytesRestResponse(RestStatus.BAD_REQUEST, "JSON could not be parsed"); restChannel.sendResponse(authenticateResponse); return true; } @@ -274,7 +284,8 @@ JsonWebKey createJwkFromSettings(Settings settings, Settings jwtSettings) throws if (jwkSettings.isEmpty()) { throw new Exception( - "Settings for key exchange missing. Please specify at least the option exchange_key with a shared secret."); + "Settings for key exchange missing. Please specify at least the option exchange_key with a shared secret." + ); } JsonWebKey jwk = new JsonWebKey(); @@ -319,8 +330,14 @@ private String createJwt(SamlResponse samlResponse) throws Exception { String encodedJwt = this.jwtProducer.processJwt(jwt); if (token_log.isDebugEnabled()) { - token_log.debug("Created JWT: " + encodedJwt + "\n" + jsonMapReaderWriter.toJson(jwt.getJwsHeaders()) + "\n" - + JwtUtils.claimsToJson(jwt.getClaims())); + token_log.debug( + "Created JWT: " + + encodedJwt + + "\n" + + jsonMapReaderWriter.toJson(jwt.getJwsHeaders()) + + "\n" + + JwtUtils.claimsToJson(jwt.getClaims()) + ); } return encodedJwt; @@ -335,8 +352,7 @@ private long getJwtExpiration(SamlResponse samlResponse) throws Exception { if (sessionNotOnOrAfter != null) { return sessionNotOnOrAfter.getMillis() / 1000 + this.expiryOffset; } else { - throw new Exception( - "Error while determining JWT expiration time: SamlResponse did not contain sessionNotOnOrAfter value"); + throw new Exception("Error while determining JWT expiration time: SamlResponse did not contain sessionNotOnOrAfter value"); } } else { // AUTO @@ -419,9 +435,9 @@ private String[] extractRoles(SamlResponse samlResponse) throws XPathExpressionE private List splitRoles(List values) { return values.stream() - .flatMap(v -> samlRolesSeparatorPattern.splitAsStream(v)) - .filter(r -> !Strings.isNullOrEmpty(r)) - .collect(Collectors.toList()); + .flatMap(v -> samlRolesSeparatorPattern.splitAsStream(v)) + .filter(r -> !Strings.isNullOrEmpty(r)) + .collect(Collectors.toList()); } private String getAbsoluteAcsEndpoint(String acsEndpoint) { @@ -440,7 +456,9 @@ private String getAbsoluteAcsEndpoint(String acsEndpoint) { } private enum ExpiryBaseValue { - AUTO, NOW, SESSION + AUTO, + NOW, + SESSION } public JsonWebKey getSigningKey() { diff --git a/src/main/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticator.java b/src/main/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticator.java index 7015017fc7..d3068b852a 100644 --- a/src/main/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticator.java +++ b/src/main/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticator.java @@ -68,7 +68,6 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; - public class HTTPSamlAuthenticator implements HTTPAuthenticator, Destroyable { protected final static Logger log = LogManager.getLogger(HTTPSamlAuthenticator.class); @@ -78,9 +77,8 @@ public class HTTPSamlAuthenticator implements HTTPAuthenticator, Destroyable { private static final String API_AUTHTOKEN_SUFFIX = "api/authtoken"; private static final String AUTHINFO_SUFFIX = "authinfo"; - private static final String REGEX_PATH_PREFIX = "/(" + LEGACY_OPENDISTRO_PREFIX + "|" + PLUGINS_PREFIX + ")/" +"(.*)"; - private static final Pattern PATTERN_PATH_PREFIX = Pattern.compile(REGEX_PATH_PREFIX); - + private static final String REGEX_PATH_PREFIX = "/(" + LEGACY_OPENDISTRO_PREFIX + "|" + PLUGINS_PREFIX + ")/" + "(.*)"; + private static final Pattern PATTERN_PATH_PREFIX = Pattern.compile(REGEX_PATH_PREFIX); private static boolean openSamlInitialized = false; @@ -132,13 +130,15 @@ public HTTPSamlAuthenticator(final Settings settings, final Path configPath) { try { this.saml2SettingsProvider.getCached(); } catch (Exception e) { - log.debug("Exception while initializing Saml2SettingsProvider. Possibly, the IdP is unreachable right now. This is recoverable by a meta data refresh.", e); + log.debug( + "Exception while initializing Saml2SettingsProvider. Possibly, the IdP is unreachable right now. This is recoverable by a meta data refresh.", + e + ); } this.jwtSettings = this.createJwtAuthenticatorSettings(settings); - this.authTokenProcessorHandler = new AuthTokenProcessorHandler(settings, jwtSettings, - this.saml2SettingsProvider); + this.authTokenProcessorHandler = new AuthTokenProcessorHandler(settings, jwtSettings, this.saml2SettingsProvider); this.httpJwtAuthenticator = new HTTPJwtAuthenticator(this.jwtSettings, configPath); @@ -149,8 +149,7 @@ public HTTPSamlAuthenticator(final Settings settings, final Path configPath) { } @Override - public AuthCredentials extractCredentials(RestRequest restRequest, ThreadContext threadContext) - throws OpenSearchSecurityException { + public AuthCredentials extractCredentials(RestRequest restRequest, ThreadContext threadContext) throws OpenSearchSecurityException { Matcher matcher = PATTERN_PATH_PREFIX.matcher(restRequest.path()); final String suffix = matcher.matches() ? matcher.group(2) : null; if (API_AUTHTOKEN_SUFFIX.equals(suffix)) { @@ -177,8 +176,7 @@ public boolean reRequestAuthentication(RestChannel restChannel, AuthCredentials RestRequest restRequest = restChannel.request(); Matcher matcher = PATTERN_PATH_PREFIX.matcher(restRequest.path()); final String suffix = matcher.matches() ? matcher.group(2) : null; - if (API_AUTHTOKEN_SUFFIX.equals(suffix) - && this.authTokenProcessorHandler.handle(restRequest, restChannel)){ + if (API_AUTHTOKEN_SUFFIX.equals(suffix) && this.authTokenProcessorHandler.handle(restRequest, restChannel)) { return true; } @@ -200,9 +198,12 @@ private String getWwwAuthenticateHeader(Saml2Settings saml2Settings) throws Exce AuthnRequest authnRequest = this.buildAuthnRequest(saml2Settings); return "X-Security-IdP realm=\"OpenSearch Security\" location=\"" - + StringEscapeUtils.escapeJava(getSamlRequestRedirectBindingLocation(IdpEndpointType.SSO, saml2Settings, - authnRequest.getEncodedAuthnRequest(true))) - + "\" requestId=\"" + StringEscapeUtils.escapeJava(authnRequest.getId()) + "\""; + + StringEscapeUtils.escapeJava( + getSamlRequestRedirectBindingLocation(IdpEndpointType.SSO, saml2Settings, authnRequest.getEncodedAuthnRequest(true)) + ) + + "\" requestId=\"" + + StringEscapeUtils.escapeJava(authnRequest.getId()) + + "\""; } private AuthnRequest buildAuthnRequest(Saml2Settings saml2Settings) { @@ -221,12 +222,16 @@ private AuthnRequest buildAuthnRequest(Saml2Settings saml2Settings) { private PrivateKey getSpSignaturePrivateKey(Settings settings, Path configPath) throws Exception { try { - PrivateKey result = PemKeyReader.loadKeyFromStream(settings.get("sp.signature_private_key_password"), - PemKeyReader.resolveStream("sp.signature_private_key", settings)); + PrivateKey result = PemKeyReader.loadKeyFromStream( + settings.get("sp.signature_private_key_password"), + PemKeyReader.resolveStream("sp.signature_private_key", settings) + ); if (result == null) { - result = PemKeyReader.loadKeyFromFile(settings.get("sp.signature_private_key_password"), - PemKeyReader.resolve("sp.signature_private_key_filepath", settings, configPath, false)); + result = PemKeyReader.loadKeyFromFile( + settings.get("sp.signature_private_key_password"), + PemKeyReader.resolve("sp.signature_private_key_filepath", settings, configPath, false) + ); } return result; @@ -297,8 +302,7 @@ public Void run() throws InitializationException { } @SuppressWarnings("removal") - private MetadataResolver createMetadataResolver(final Settings settings, final Path configPath) - throws Exception { + private MetadataResolver createMetadataResolver(final Settings settings, final Path configPath) throws Exception { final AbstractMetadataResolver metadataResolver; final String idpMetadataUrl = settings.get(IDP_METADATA_URL); @@ -311,7 +315,9 @@ private MetadataResolver createMetadataResolver(final Settings settings, final P } else if (idpMetadataBody != null) { metadataResolver = new DOMMetadataResolver(getMetadataDOM(idpMetadataBody)); } else { - throw new Exception(String.format("One of %s, %s or %s must be configured", IDP_METADATA_URL, IDP_METADATA_FILE, IDP_METADATA_CONTENT)); + throw new Exception( + String.format("One of %s, %s or %s must be configured", IDP_METADATA_URL, IDP_METADATA_FILE, IDP_METADATA_CONTENT) + ); } metadataResolver.setId(HTTPSamlAuthenticator.class.getName() + "_" + (++resolverIdCounter)); @@ -378,14 +384,12 @@ String buildLogoutUrl(AuthCredentials authCredentials) { String nameIdClaim = this.subjectKey == null ? "sub" : "saml_ni"; String nameId = authCredentials.getAttributes().get("attr.jwt." + nameIdClaim); - String nameIdFormat = SamlNameIdFormat - .getByShortName(authCredentials.getAttributes().get("attr.jwt.saml_nif")).getUri(); + String nameIdFormat = SamlNameIdFormat.getByShortName(authCredentials.getAttributes().get("attr.jwt.saml_nif")).getUri(); String sessionIndex = authCredentials.getAttributes().get("attr.jwt.saml_si"); LogoutRequest logoutRequest = new LogoutRequest(saml2Settings, null, nameId, sessionIndex, nameIdFormat); - return getSamlRequestRedirectBindingLocation(IdpEndpointType.SLO, saml2Settings, - logoutRequest.getEncodedLogoutRequest(true)); + return getSamlRequestRedirectBindingLocation(IdpEndpointType.SLO, saml2Settings, logoutRequest.getEncodedLogoutRequest(true)); } catch (Exception e) { log.error("Error while creating logout URL. Logout will be not available", e); @@ -398,8 +402,8 @@ private void initLogoutUrl(RestRequest restRequest, ThreadContext threadContext, threadContext.putTransient(ConfigConstants.SSO_LOGOUT_URL, buildLogoutUrl(authCredentials)); } - private String getSamlRequestRedirectBindingLocation(IdpEndpointType idpEndpointType, Saml2Settings saml2Settings, - String samlRequest) throws Exception { + private String getSamlRequestRedirectBindingLocation(IdpEndpointType idpEndpointType, Saml2Settings saml2Settings, String samlRequest) + throws Exception { URL idpUrl = getIdpUrl(idpEndpointType, saml2Settings); @@ -417,8 +421,7 @@ private String getSamlRequestQueryString(String samlRequest) throws Exception { return "SAMLRequest=" + Util.urlEncoder(samlRequest); } - String queryString = "SAMLRequest=" + Util.urlEncoder(samlRequest) + "&SigAlg=" - + Util.urlEncoder(this.spSignatureAlgorithm); + String queryString = "SAMLRequest=" + Util.urlEncoder(samlRequest) + "&SigAlg=" + Util.urlEncoder(this.spSignatureAlgorithm); String signature = getSamlRequestQueryStringSignature(queryString); @@ -429,8 +432,7 @@ private String getSamlRequestQueryString(String samlRequest) throws Exception { private String getSamlRequestQueryStringSignature(String samlRequestQueryString) throws Exception { try { - return Util.base64encoder( - Util.sign(samlRequestQueryString, this.spSignaturePrivateKey, this.spSignatureAlgorithm)); + return Util.base64encoder(Util.sign(samlRequestQueryString, this.spSignaturePrivateKey, this.spSignatureAlgorithm)); } catch (Exception e) { throw new Exception("Error while signing SAML request", e); } @@ -462,8 +464,7 @@ protected KeyProvider initKeyProvider(Settings settings, Path configPath) throws return new KeyProvider() { @Override - public JsonWebKey getKeyAfterRefresh(String kid) - throws AuthenticatorUnavailableException, BadCredentialsException { + public JsonWebKey getKeyAfterRefresh(String kid) throws AuthenticatorUnavailableException, BadCredentialsException { return authTokenProcessorHandler.getSigningKey(); } @@ -477,6 +478,7 @@ public JsonWebKey getKey(String kid) throws AuthenticatorUnavailableException, B } private enum IdpEndpointType { - SSO, SLO + SSO, + SLO } } diff --git a/src/main/java/com/amazon/dlic/auth/http/saml/Saml2SettingsProvider.java b/src/main/java/com/amazon/dlic/auth/http/saml/Saml2SettingsProvider.java index 5274569502..881c9c3553 100644 --- a/src/main/java/com/amazon/dlic/auth/http/saml/Saml2SettingsProvider.java +++ b/src/main/java/com/amazon/dlic/auth/http/saml/Saml2SettingsProvider.java @@ -68,19 +68,23 @@ Saml2Settings get() throws SamlConfigException { try { HashMap configProperties = new HashMap<>(); - EntityDescriptor entityDescriptor = this.metadataResolver - .resolveSingle(new CriteriaSet(new EntityIdCriterion(this.idpEntityId))); + EntityDescriptor entityDescriptor = this.metadataResolver.resolveSingle( + new CriteriaSet(new EntityIdCriterion(this.idpEntityId)) + ); if (entityDescriptor == null) { throw new SamlConfigException("Could not find entity descriptor for " + this.idpEntityId); } - IDPSSODescriptor idpSsoDescriptor = entityDescriptor - .getIDPSSODescriptor("urn:oasis:names:tc:SAML:2.0:protocol"); + IDPSSODescriptor idpSsoDescriptor = entityDescriptor.getIDPSSODescriptor("urn:oasis:names:tc:SAML:2.0:protocol"); if (idpSsoDescriptor == null) { - throw new SamlConfigException("Could not find IDPSSODescriptor supporting SAML 2.0 in " - + this.idpEntityId + "; role descriptors: " + entityDescriptor.getRoleDescriptors()); + throw new SamlConfigException( + "Could not find IDPSSODescriptor supporting SAML 2.0 in " + + this.idpEntityId + + "; role descriptors: " + + entityDescriptor.getRoleDescriptors() + ); } initIdpEndpoints(idpSsoDescriptor, configProperties); @@ -121,8 +125,7 @@ Saml2Settings getCached() throws SamlConfigException { private boolean isUpdateRequired() { RefreshableMetadataResolver refreshableMetadataResolver = (RefreshableMetadataResolver) this.metadataResolver; - if (this.cachedSaml2Settings == null || this.metadataUpdateTime == null - || refreshableMetadataResolver.getLastUpdate() == null) { + if (this.cachedSaml2Settings == null || this.metadataUpdateTime == null || refreshableMetadataResolver.getLastUpdate() == null) { return true; } @@ -140,35 +143,39 @@ private void initMisc(HashMap configProperties) { } private void initSpEndpoints(HashMap configProperties) { - configProperties.put(SettingsBuilder.SP_ASSERTION_CONSUMER_SERVICE_URL_PROPERTY_KEY, - this.buildAssertionConsumerEndpoint(this.opensearchSettings.get("kibana_url"))); - configProperties.put(SettingsBuilder.SP_ASSERTION_CONSUMER_SERVICE_BINDING_PROPERTY_KEY, - "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); + configProperties.put( + SettingsBuilder.SP_ASSERTION_CONSUMER_SERVICE_URL_PROPERTY_KEY, + this.buildAssertionConsumerEndpoint(this.opensearchSettings.get("kibana_url")) + ); + configProperties.put( + SettingsBuilder.SP_ASSERTION_CONSUMER_SERVICE_BINDING_PROPERTY_KEY, + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + ); configProperties.put(SettingsBuilder.SP_ENTITYID_PROPERTY_KEY, this.opensearchSettings.get("sp.entity_id")); } - private void initIdpEndpoints(IDPSSODescriptor idpSsoDescriptor, HashMap configProperties) - throws SamlConfigException { - SingleSignOnService singleSignOnService = this.findSingleSignOnService(idpSsoDescriptor, - "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"); + private void initIdpEndpoints(IDPSSODescriptor idpSsoDescriptor, HashMap configProperties) throws SamlConfigException { + SingleSignOnService singleSignOnService = this.findSingleSignOnService( + idpSsoDescriptor, + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + ); - configProperties.put(SettingsBuilder.IDP_SINGLE_SIGN_ON_SERVICE_URL_PROPERTY_KEY, - singleSignOnService.getLocation()); - configProperties.put(SettingsBuilder.IDP_SINGLE_SIGN_ON_SERVICE_BINDING_PROPERTY_KEY, - singleSignOnService.getBinding()); + configProperties.put(SettingsBuilder.IDP_SINGLE_SIGN_ON_SERVICE_URL_PROPERTY_KEY, singleSignOnService.getLocation()); + configProperties.put(SettingsBuilder.IDP_SINGLE_SIGN_ON_SERVICE_BINDING_PROPERTY_KEY, singleSignOnService.getBinding()); configProperties.put(SettingsBuilder.IDP_ENTITYID_PROPERTY_KEY, this.opensearchSettings.get("idp.entity_id")); - SingleLogoutService singleLogoutService = this.findSingleLogoutService(idpSsoDescriptor, - "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"); + SingleLogoutService singleLogoutService = this.findSingleLogoutService( + idpSsoDescriptor, + "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + ); if (singleLogoutService != null) { - configProperties.put(SettingsBuilder.IDP_SINGLE_LOGOUT_SERVICE_URL_PROPERTY_KEY, - singleLogoutService.getLocation()); - configProperties.put(SettingsBuilder.IDP_SINGLE_LOGOUT_SERVICE_BINDING_PROPERTY_KEY, - singleLogoutService.getBinding()); + configProperties.put(SettingsBuilder.IDP_SINGLE_LOGOUT_SERVICE_URL_PROPERTY_KEY, singleLogoutService.getLocation()); + configProperties.put(SettingsBuilder.IDP_SINGLE_LOGOUT_SERVICE_BINDING_PROPERTY_KEY, singleLogoutService.getBinding()); } else { log.warn( - "The IdP does not provide a Single Logout Service. In order to ensure that users have to re-enter their password after logging out, OpenSearch Security will issue all SAML authentication requests with a mandatory password input (ForceAuthn=true)"); + "The IdP does not provide a Single Logout Service. In order to ensure that users have to re-enter their password after logging out, OpenSearch Security will issue all SAML authentication requests with a mandatory password input (ForceAuthn=true)" + ); } } @@ -176,32 +183,32 @@ private void initIdpCerts(IDPSSODescriptor idpSsoDescriptor, HashMap extractLdapAttributes(String originalUsername, final LdapEntry userEntry, - int customAttrMaxValueLen, WildcardMatcher allowlistedCustomLdapAttrMatcher) { + + public static Map extractLdapAttributes( + String originalUsername, + final LdapEntry userEntry, + int customAttrMaxValueLen, + WildcardMatcher allowlistedCustomLdapAttrMatcher + ) { Map attributes = new HashMap<>(); attributes.put("ldap.original.username", originalUsername); attributes.put("ldap.dn", userEntry.getDn()); diff --git a/src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthenticationBackend.java b/src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthenticationBackend.java index 1ce545e8da..96cd7a40c9 100755 --- a/src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthenticationBackend.java +++ b/src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthenticationBackend.java @@ -67,13 +67,16 @@ public LDAPAuthenticationBackend(final Settings settings, final Path configPath) this.settings = settings; this.configPath = configPath; this.userBaseSettings = getUserBaseSettings(settings); - this.returnAttributes = settings.getAsList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, Arrays.asList(ReturnAttributes.ALL.value())).toArray(new String[0]); + this.returnAttributes = settings.getAsList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, Arrays.asList(ReturnAttributes.ALL.value())) + .toArray(new String[0]); this.shouldFollowReferrals = settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT); customAttrMaxValueLen = settings.getAsInt(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 36); checkForDeprecatedSetting(settings, ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, ConfigConstants.LDAP_CUSTOM_ATTR_ALLOWLIST); - final List customAttrAllowList = settings.getAsList(ConfigConstants.LDAP_CUSTOM_ATTR_ALLOWLIST, settings.getAsList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, - Collections.singletonList("*"))); + final List customAttrAllowList = settings.getAsList( + ConfigConstants.LDAP_CUSTOM_ATTR_ALLOWLIST, + settings.getAsList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, Collections.singletonList("*")) + ); allowlistedCustomLdapAttrMatcher = WildcardMatcher.from(customAttrAllowList); } @@ -81,7 +84,7 @@ public LDAPAuthenticationBackend(final Settings settings, final Path configPath) public User authenticate(final AuthCredentials credentials) throws OpenSearchSecurityException { Connection ldapConnection = null; - final String user =credentials.getUsername(); + final String user = credentials.getUsername(); byte[] password = credentials.getPassword(); try { @@ -98,11 +101,12 @@ public User authenticate(final AuthCredentials credentials) throws OpenSearchSec // makes guessing if a user exists or not harder when looking on the // authentication delay time if (entry == null && settings.getAsBoolean(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, false)) { - String fakeLognDn = settings.get(ConfigConstants.LDAP_FAKE_LOGIN_DN, - "CN=faketomakebindfail,DC=" + UUID.randomUUID().toString()); + String fakeLognDn = settings.get( + ConfigConstants.LDAP_FAKE_LOGIN_DN, + "CN=faketomakebindfail,DC=" + UUID.randomUUID().toString() + ); entry = new LdapEntry(fakeLognDn); - password = settings.get(ConfigConstants.LDAP_FAKE_LOGIN_PASSWORD, "fakeLoginPwd123") - .getBytes(StandardCharsets.UTF_8); + password = settings.get(ConfigConstants.LDAP_FAKE_LOGIN_PASSWORD, "fakeLoginPwd123").getBytes(StandardCharsets.UTF_8); } else if (entry == null) { throw new OpenSearchSecurityException("No user " + user + " found"); } @@ -166,15 +170,24 @@ public boolean exists(final User user) { try { ldapConnection = LDAPAuthorizationBackend.getConnection(settings, configPath); - LdapEntry userEntry = exists(userName, ldapConnection, settings, userBaseSettings, this.returnAttributes, this.shouldFollowReferrals); + LdapEntry userEntry = exists( + userName, + ldapConnection, + settings, + userBaseSettings, + this.returnAttributes, + this.shouldFollowReferrals + ); boolean exists = userEntry != null; - - if(exists) { - user.addAttributes(LdapUser.extractLdapAttributes(userName, userEntry, customAttrMaxValueLen, allowlistedCustomLdapAttrMatcher)); + + if (exists) { + user.addAttributes( + LdapUser.extractLdapAttributes(userName, userEntry, customAttrMaxValueLen, allowlistedCustomLdapAttrMatcher) + ); } - + return exists; - + } catch (final Exception e) { log.warn("User {} does not exist due to ", userName, e); return false; @@ -184,33 +197,39 @@ public boolean exists(final User user) { } static List> getUserBaseSettings(Settings settings) { - Map userBaseSettingsMap = new HashMap<>( - settings.getGroups(ConfigConstants.LDAP_AUTHCZ_USERS)); + Map userBaseSettingsMap = new HashMap<>(settings.getGroups(ConfigConstants.LDAP_AUTHCZ_USERS)); if (!userBaseSettingsMap.isEmpty()) { if (settings.hasValue(ConfigConstants.LDAP_AUTHC_USERBASE)) { throw new RuntimeException( - "Both old-style and new-style configuration defined for LDAP authentication backend: " - + settings); + "Both old-style and new-style configuration defined for LDAP authentication backend: " + settings + ); } return Utils.getOrderedBaseSettings(userBaseSettingsMap); } else { Settings.Builder settingsBuilder = Settings.builder(); - settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_BASE, - settings.get(ConfigConstants.LDAP_AUTHC_USERBASE, DEFAULT_USERBASE)); - settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_SEARCH, - settings.get(ConfigConstants.LDAP_AUTHC_USERSEARCH, DEFAULT_USERSEARCH_PATTERN)); + settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_BASE, settings.get(ConfigConstants.LDAP_AUTHC_USERBASE, DEFAULT_USERBASE)); + settingsBuilder.put( + ConfigConstants.LDAP_AUTHCZ_SEARCH, + settings.get(ConfigConstants.LDAP_AUTHC_USERSEARCH, DEFAULT_USERSEARCH_PATTERN) + ); return Collections.singletonList(Pair.of("_legacyConfig", settingsBuilder.build())); } } - static LdapEntry exists(final String user, Connection ldapConnection, Settings settings, - List> userBaseSettings, String[] returnAttributes, final boolean shouldFollowReferrals) throws Exception { + static LdapEntry exists( + final String user, + Connection ldapConnection, + Settings settings, + List> userBaseSettings, + String[] returnAttributes, + final boolean shouldFollowReferrals + ) throws Exception { if (settings.getAsBoolean(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, false) - || settings.getAsBoolean(ConfigConstants.LDAP_SEARCH_ALL_BASES, false) - || settings.hasValue(ConfigConstants.LDAP_AUTHC_USERBASE)) { + || settings.getAsBoolean(ConfigConstants.LDAP_SEARCH_ALL_BASES, false) + || settings.hasValue(ConfigConstants.LDAP_AUTHC_USERBASE)) { return existsSearchingAllBases(user, ldapConnection, userBaseSettings, returnAttributes, shouldFollowReferrals); } else { return existsSearchingUntilFirstHit(user, ldapConnection, userBaseSettings, returnAttributes, shouldFollowReferrals); @@ -218,8 +237,13 @@ static LdapEntry exists(final String user, Connection ldapConnection, Settings s } - private static LdapEntry existsSearchingUntilFirstHit(final String user, Connection ldapConnection, - List> userBaseSettings, final String[] returnAttributes, final boolean shouldFollowReferrals) throws Exception { + private static LdapEntry existsSearchingUntilFirstHit( + final String user, + Connection ldapConnection, + List> userBaseSettings, + final String[] returnAttributes, + final boolean shouldFollowReferrals + ) throws Exception { final String username = user; final boolean isDebugEnabled = log.isDebugEnabled(); @@ -230,11 +254,14 @@ private static LdapEntry existsSearchingUntilFirstHit(final String user, Connect f.setFilter(baseSettings.get(ConfigConstants.LDAP_AUTHCZ_SEARCH, DEFAULT_USERSEARCH_PATTERN)); f.setParameter(ZERO_PLACEHOLDER, username); - List result = LdapHelper.search(ldapConnection, - baseSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_USERBASE), - f, - SearchScope.SUBTREE, - returnAttributes, shouldFollowReferrals); + List result = LdapHelper.search( + ldapConnection, + baseSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_USERBASE), + f, + SearchScope.SUBTREE, + returnAttributes, + shouldFollowReferrals + ); if (isDebugEnabled) { log.debug("Results for LDAP search for {} in base {} is {}", user, entry.getKey(), result); @@ -248,8 +275,13 @@ private static LdapEntry existsSearchingUntilFirstHit(final String user, Connect return null; } - private static LdapEntry existsSearchingAllBases(final String user, Connection ldapConnection, - List> userBaseSettings, final String[] returnAttributes, final boolean shouldFollowReferrals) throws Exception { + private static LdapEntry existsSearchingAllBases( + final String user, + Connection ldapConnection, + List> userBaseSettings, + final String[] returnAttributes, + final boolean shouldFollowReferrals + ) throws Exception { final String username = user; Set result = new HashSet<>(); @@ -261,11 +293,14 @@ private static LdapEntry existsSearchingAllBases(final String user, Connection l f.setFilter(baseSettings.get(ConfigConstants.LDAP_AUTHCZ_SEARCH, DEFAULT_USERSEARCH_PATTERN)); f.setParameter(ZERO_PLACEHOLDER, username); - List foundEntries = LdapHelper.search(ldapConnection, - baseSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_USERBASE), - f, - SearchScope.SUBTREE, - returnAttributes, shouldFollowReferrals); + List foundEntries = LdapHelper.search( + ldapConnection, + baseSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_USERBASE), + f, + SearchScope.SUBTREE, + returnAttributes, + shouldFollowReferrals + ); if (isDebugEnabled) { log.debug("Results for LDAP search for " + user + " in base " + entry.getKey() + ":\n" + result); diff --git a/src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthorizationBackend.java b/src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthorizationBackend.java index 68a8a3fba6..ac3fd8b32f 100755 --- a/src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthorizationBackend.java +++ b/src/main/java/com/amazon/dlic/auth/ldap/backend/LDAPAuthorizationBackend.java @@ -89,7 +89,8 @@ public class LDAPAuthorizationBackend implements AuthorizationBackend { private static final AtomicInteger CONNECTION_COUNTER = new AtomicInteger(); - private static final String COM_SUN_JNDI_LDAP_OBJECT_DISABLE_ENDPOINT_IDENTIFICATION = "com.sun.jndi.ldap.object.disableEndpointIdentification"; + private static final String COM_SUN_JNDI_LDAP_OBJECT_DISABLE_ENDPOINT_IDENTIFICATION = + "com.sun.jndi.ldap.object.disableEndpointIdentification"; private static final List DEFAULT_TLS_PROTOCOLS = Arrays.asList("TLSv1.2", "TLSv1.1"); static final int ONE_PLACEHOLDER = 1; static final int TWO_PLACEHOLDER = 2; @@ -112,12 +113,14 @@ public class LDAPAuthorizationBackend implements AuthorizationBackend { public LDAPAuthorizationBackend(final Settings settings, final Path configPath) { this.settings = settings; this.skipUsersMatcher = WildcardMatcher.from(settings.getAsList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS)); - this.nestedRoleMatcher = settings.getAsBoolean(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) ? - WildcardMatcher.from(settings.getAsList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER)) : null; + this.nestedRoleMatcher = settings.getAsBoolean(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) + ? WildcardMatcher.from(settings.getAsList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER)) + : null; this.configPath = configPath; this.roleBaseSettings = getRoleSearchSettings(settings); this.userBaseSettings = LDAPAuthenticationBackend.getUserBaseSettings(settings); - this.returnAttributes = settings.getAsList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, Arrays.asList(ReturnAttributes.ALL.value())).toArray(new String[0]); + this.returnAttributes = settings.getAsList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, Arrays.asList(ReturnAttributes.ALL.value())) + .toArray(new String[0]); this.shouldFollowReferrals = settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT); } @@ -198,10 +201,8 @@ private static List> convertOldStyleSettingsToNewSty Settings.Builder settingsBuilder = Settings.builder(); - settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_BASE, - settings.get(ConfigConstants.LDAP_AUTHZ_ROLEBASE, DEFAULT_ROLEBASE)); - settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_SEARCH, - settings.get(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, DEFAULT_ROLESEARCH)); + settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_BASE, settings.get(ConfigConstants.LDAP_AUTHZ_ROLEBASE, DEFAULT_ROLEBASE)); + settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_SEARCH, settings.get(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, DEFAULT_ROLESEARCH)); result.put("convertedOldStyleSettings", settingsBuilder.build()); @@ -209,9 +210,13 @@ private static List> convertOldStyleSettingsToNewSty } @SuppressWarnings("removal") - private static void checkConnection0(final ConnectionConfig connectionConfig, String bindDn, byte[] password, final ClassLoader cl, - final boolean needRestore) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, - FileNotFoundException, IOException, LdapException { + private static void checkConnection0( + final ConnectionConfig connectionConfig, + String bindDn, + byte[] password, + final ClassLoader cl, + final boolean needRestore + ) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, LdapException { Connection connection = null; @@ -251,13 +256,15 @@ public Void run() throws Exception { } } - private static Connection getConnection0(final Settings settings, final Path configPath, final ClassLoader cl, - final boolean needRestore) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, - FileNotFoundException, IOException, LdapException { + private static Connection getConnection0( + final Settings settings, + final Path configPath, + final ClassLoader cl, + final boolean needRestore + ) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, LdapException { final boolean enableSSL = settings.getAsBoolean(ConfigConstants.LDAPS_ENABLE_SSL, false); - final List ldapHosts = settings.getAsList(ConfigConstants.LDAP_HOSTS, - Collections.singletonList("localhost")); + final List ldapHosts = settings.getAsList(ConfigConstants.LDAP_HOSTS, Collections.singletonList("localhost")); Connection connection = null; Exception lastException = null; @@ -295,16 +302,17 @@ private static Connection getConnection0(final Settings settings, final Path con final String password = settings.get(ConfigConstants.LDAP_PASSWORD, null); if (isDebugEnabled) { - log.debug("bindDn {}, password {}", bindDn, - password != null && password.length() > 0 ? "****" : ""); + log.debug("bindDn {}, password {}", bindDn, password != null && password.length() > 0 ? "****" : ""); } if (bindDn != null && (password == null || password.length() == 0)) { log.error("No password given for bind_dn {}. Will try to authenticate anonymously to ldap", bindDn); } - final boolean enableClientAuth = settings.getAsBoolean(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, - ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH_DEFAULT); + final boolean enableClientAuth = settings.getAsBoolean( + ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, + ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH_DEFAULT + ); if (isDebugEnabled) { if (enableClientAuth && bindDn == null) { @@ -313,7 +321,8 @@ private static Connection getConnection0(final Settings settings, final Path con log.debug("Will perform anonymous bind because no bind dn is given"); } else if (enableClientAuth && bindDn != null) { log.debug( - "Will perform simple bind with bind dn because to bind dn is given and overrides client cert authentication"); + "Will perform simple bind with bind dn because to bind dn is given and overrides client cert authentication" + ); } else if (!enableClientAuth && bindDn != null) { log.debug("Will perform simple bind with bind dn"); } @@ -358,7 +367,7 @@ private static Connection getConnection0(final Settings settings, final Path con } if (connection == null || !connection.isOpen()) { - Utils.unbindAndCloseSilently(connection); //just in case + Utils.unbindAndCloseSilently(connection); // just in case if (needRestore) { restoreClassLoader0(cl); } @@ -367,8 +376,9 @@ private static Connection getConnection0(final Settings settings, final Path con throw new LdapException("Unable to connect to any of those ldap servers " + ldapHosts); } else { throw new LdapException( - "Unable to connect to any of those ldap servers " + ldapHosts + " due to " + lastException, - lastException); + "Unable to connect to any of those ldap servers " + ldapHosts + " due to " + lastException, + lastException + ); } } @@ -398,29 +408,29 @@ public Response reopen() throws LdapException { @Override public Response open(BindRequest request) throws LdapException { - + try { - if(isDebugEnabled && delegate != null && delegate.isOpen()) { + if (isDebugEnabled && delegate != null && delegate.isOpen()) { log.debug("Opened a connection, total count is now {}", CONNECTION_COUNTER.incrementAndGet()); } } catch (Throwable e) { - //ignore + // ignore } - + return delegate.open(request); } @Override public Response open() throws LdapException { - + try { - if(isDebugEnabled && delegate != null && delegate.isOpen()) { + if (isDebugEnabled && delegate != null && delegate.isOpen()) { log.debug("Opened a connection, total count is now {}", CONNECTION_COUNTER.incrementAndGet()); } } catch (Throwable e) { - //ignore + // ignore } - + return delegate.open(); } @@ -441,15 +451,15 @@ public ConnectionConfig getConnectionConfig() { @Override public void close(RequestControl[] controls) { - + try { - if(isDebugEnabled && delegate != null && delegate.isOpen()) { + if (isDebugEnabled && delegate != null && delegate.isOpen()) { log.debug("Closed a connection, total count is now {}", CONNECTION_COUNTER.decrementAndGet()); } } catch (Throwable e) { - //ignore + // ignore } - + try { delegate.close(controls); } finally { @@ -459,15 +469,15 @@ public void close(RequestControl[] controls) { @Override public void close() { - + try { - if(isDebugEnabled && delegate != null && delegate.isOpen()) { + if (isDebugEnabled && delegate != null && delegate.isOpen()) { log.debug("Closed a connection, total count is now {}", CONNECTION_COUNTER.decrementAndGet()); } } catch (Throwable e) { - //ignore + // ignore } - + try { delegate.close(); } finally { @@ -498,8 +508,7 @@ public Void run() throws Exception { } } - private static void configureSSL(final ConnectionConfig config, final Settings settings, - final Path configPath) throws Exception { + private static void configureSSL(final ConnectionConfig config, final Settings settings, final Path configPath) throws Exception { final boolean isDebugEnabled = log.isDebugEnabled(); final boolean enableSSL = settings.getAsBoolean(ConfigConstants.LDAPS_ENABLE_SSL, false); @@ -507,13 +516,15 @@ private static void configureSSL(final ConnectionConfig config, final Settings s if (enableSSL || enableStartTLS) { - final boolean enableClientAuth = settings.getAsBoolean(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, - ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH_DEFAULT); + final boolean enableClientAuth = settings.getAsBoolean( + ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, + ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH_DEFAULT + ); final boolean trustAll = settings.getAsBoolean(ConfigConstants.LDAPS_TRUST_ALL, false); - final boolean verifyHostnames = !trustAll && settings.getAsBoolean(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, - ConfigConstants.LDAPS_VERIFY_HOSTNAMES_DEFAULT); + final boolean verifyHostnames = !trustAll + && settings.getAsBoolean(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, ConfigConstants.LDAPS_VERIFY_HOSTNAMES_DEFAULT); if (isDebugEnabled) { log.debug("verifyHostname {}:", verifyHostnames); @@ -525,64 +536,74 @@ private static void configureSSL(final ConnectionConfig config, final Settings s } final boolean pem = settings.get(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, null) != null - || settings.get(ConfigConstants.LDAPS_PEMTRUSTEDCAS_CONTENT, null) != null; + || settings.get(ConfigConstants.LDAPS_PEMTRUSTEDCAS_CONTENT, null) != null; final SslConfig sslConfig = new SslConfig(); CredentialConfig cc; if (pem) { X509Certificate[] trustCertificates = PemKeyReader.loadCertificatesFromStream( - PemKeyReader.resolveStream(ConfigConstants.LDAPS_PEMTRUSTEDCAS_CONTENT, settings)); + PemKeyReader.resolveStream(ConfigConstants.LDAPS_PEMTRUSTEDCAS_CONTENT, settings) + ); if (trustCertificates == null) { - trustCertificates = PemKeyReader.loadCertificatesFromFile(PemKeyReader - .resolve(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, settings, configPath, !trustAll)); + trustCertificates = PemKeyReader.loadCertificatesFromFile( + PemKeyReader.resolve(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, settings, configPath, !trustAll) + ); } // for client authentication X509Certificate authenticationCertificate = PemKeyReader.loadCertificateFromStream( - PemKeyReader.resolveStream(ConfigConstants.LDAPS_PEMCERT_CONTENT, settings)); + PemKeyReader.resolveStream(ConfigConstants.LDAPS_PEMCERT_CONTENT, settings) + ); if (authenticationCertificate == null) { - authenticationCertificate = PemKeyReader.loadCertificateFromFile(PemKeyReader - .resolve(ConfigConstants.LDAPS_PEMCERT_FILEPATH, settings, configPath, enableClientAuth)); + authenticationCertificate = PemKeyReader.loadCertificateFromFile( + PemKeyReader.resolve(ConfigConstants.LDAPS_PEMCERT_FILEPATH, settings, configPath, enableClientAuth) + ); } PrivateKey authenticationKey = PemKeyReader.loadKeyFromStream( - settings.get(ConfigConstants.LDAPS_PEMKEY_PASSWORD), - PemKeyReader.resolveStream(ConfigConstants.LDAPS_PEMKEY_CONTENT, settings)); + settings.get(ConfigConstants.LDAPS_PEMKEY_PASSWORD), + PemKeyReader.resolveStream(ConfigConstants.LDAPS_PEMKEY_CONTENT, settings) + ); if (authenticationKey == null) { - authenticationKey = PemKeyReader - .loadKeyFromFile(settings.get(ConfigConstants.LDAPS_PEMKEY_PASSWORD), PemKeyReader.resolve( - ConfigConstants.LDAPS_PEMKEY_FILEPATH, settings, configPath, enableClientAuth)); + authenticationKey = PemKeyReader.loadKeyFromFile( + settings.get(ConfigConstants.LDAPS_PEMKEY_PASSWORD), + PemKeyReader.resolve(ConfigConstants.LDAPS_PEMKEY_FILEPATH, settings, configPath, enableClientAuth) + ); } - cc = CredentialConfigFactory.createX509CredentialConfig(trustCertificates, authenticationCertificate, - authenticationKey); + cc = CredentialConfigFactory.createX509CredentialConfig(trustCertificates, authenticationCertificate, authenticationKey); if (isDebugEnabled) { - log.debug("Use PEM to secure communication with LDAP server (client auth is {})", - authenticationKey != null); + log.debug("Use PEM to secure communication with LDAP server (client auth is {})", authenticationKey != null); } } else { final KeyStore trustStore = PemKeyReader.loadKeyStore( - PemKeyReader.resolve(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, settings, - configPath, !trustAll), - SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.getSetting(settings), - settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_TYPE)); + PemKeyReader.resolve(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, settings, configPath, !trustAll), + SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.getSetting(settings), + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_TYPE) + ); final List trustStoreAliases = settings.getAsList(ConfigConstants.LDAPS_JKS_TRUST_ALIAS, null); // for client authentication final KeyStore keyStore = PemKeyReader.loadKeyStore( - PemKeyReader.resolve(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, settings, - configPath, enableClientAuth), - SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, - SSLConfigConstants.DEFAULT_STORE_PASSWORD), - settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE)); - final String keyStorePassword = SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD - .getSetting(settings, SSLConfigConstants.DEFAULT_STORE_PASSWORD); + PemKeyReader.resolve( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + settings, + configPath, + enableClientAuth + ), + SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, SSLConfigConstants.DEFAULT_STORE_PASSWORD), + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE) + ); + final String keyStorePassword = SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting( + settings, + SSLConfigConstants.DEFAULT_STORE_PASSWORD + ); final String keyStoreAlias = settings.get(ConfigConstants.LDAPS_JKS_CERT_ALIAS, null); final String[] keyStoreAliases = keyStoreAlias == null ? null : new String[] { keyStoreAlias }; @@ -592,14 +613,17 @@ private static void configureSSL(final ConnectionConfig config, final Settings s } if (isDebugEnabled) { - log.debug("Use Trust-/Keystore to secure communication with LDAP server (client auth is {})", - keyStore != null); + log.debug("Use Trust-/Keystore to secure communication with LDAP server (client auth is {})", keyStore != null); log.debug("trustStoreAliases: {}, keyStoreAlias: {}", trustStoreAliases, keyStoreAlias); } - cc = CredentialConfigFactory.createKeyStoreCredentialConfig(trustStore, - trustStoreAliases == null ? null : trustStoreAliases.toArray(new String[0]), keyStore, - keyStorePassword, keyStoreAliases); + cc = CredentialConfigFactory.createKeyStoreCredentialConfig( + trustStore, + trustStoreAliases == null ? null : trustStoreAliases.toArray(new String[0]), + keyStore, + keyStorePassword, + keyStoreAliases + ); } @@ -614,9 +638,13 @@ private static void configureSSL(final ConnectionConfig config, final Settings s final String deiProp = System.getProperty(COM_SUN_JNDI_LDAP_OBJECT_DISABLE_ENDPOINT_IDENTIFICATION); if (deiProp == null || !Boolean.parseBoolean(deiProp)) { - log.warn("In order to disable host name verification for LDAP connections (verify_hostnames: true), " - + "you also need to set set the system property "+COM_SUN_JNDI_LDAP_OBJECT_DISABLE_ENDPOINT_IDENTIFICATION+" to true when starting the JVM running OpenSearch. " - + "This applies for all Java versions released since July 2018."); + log.warn( + "In order to disable host name verification for LDAP connections (verify_hostnames: true), " + + "you also need to set set the system property " + + COM_SUN_JNDI_LDAP_OBJECT_DISABLE_ENDPOINT_IDENTIFICATION + + " to true when starting the JVM running OpenSearch. " + + "This applies for all Java versions released since July 2018." + ); // See: // https://www.oracle.com/technetwork/java/javase/8u181-relnotes-4479407.html // https://www.oracle.com/technetwork/java/javase/10-0-2-relnotes-4477557.html @@ -627,10 +655,8 @@ private static void configureSSL(final ConnectionConfig config, final Settings s } - final List enabledCipherSuites = settings.getAsList(ConfigConstants.LDAPS_ENABLED_SSL_CIPHERS, - Collections.emptyList()); - final List enabledProtocols = settings.getAsList(ConfigConstants.LDAPS_ENABLED_SSL_PROTOCOLS, - DEFAULT_TLS_PROTOCOLS); + final List enabledCipherSuites = settings.getAsList(ConfigConstants.LDAPS_ENABLED_SSL_CIPHERS, Collections.emptyList()); + final List enabledProtocols = settings.getAsList(ConfigConstants.LDAPS_ENABLED_SSL_PROTOCOLS, DEFAULT_TLS_PROTOCOLS); if (!enabledCipherSuites.isEmpty()) { sslConfig.setEnabledCipherSuites(enabledCipherSuites.toArray(new String[0])); @@ -654,14 +680,12 @@ private static void configureSSL(final ConnectionConfig config, final Settings s config.setResponseTimeout(Duration.ofMillis(responseTimeout < 0L ? 0L : responseTimeout)); if (isDebugEnabled) { - log.debug("Connect timeout: " + config.getConnectTimeout() + "/ResponseTimeout: " - + config.getResponseTimeout()); + log.debug("Connect timeout: " + config.getConnectTimeout() + "/ResponseTimeout: " + config.getResponseTimeout()); } } @Override - public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) - throws OpenSearchSecurityException { + public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) throws OpenSearchSecurityException { if (user == null) { return; @@ -673,7 +697,7 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) String dn = null; final boolean isDebugEnabled = log.isDebugEnabled(); - if (isDebugEnabled){ + if (isDebugEnabled) { log.debug("DBGTRACE (2): username: {} -> {}", user.getName(), Arrays.toString(user.getName().getBytes(StandardCharsets.UTF_8))); } @@ -686,11 +710,14 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) originalUserName = user.getName(); } - if (isDebugEnabled){ - log.debug("DBGTRACE (3): authenticatedUser: {} -> {}", authenticatedUser, Arrays.toString(authenticatedUser.getBytes(StandardCharsets.UTF_8))); + if (isDebugEnabled) { + log.debug( + "DBGTRACE (3): authenticatedUser: {} -> {}", + authenticatedUser, + Arrays.toString(authenticatedUser.getBytes(StandardCharsets.UTF_8)) + ); } - final boolean rolesearchEnabled = settings.getAsBoolean(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true); if (isDebugEnabled) { @@ -727,8 +754,13 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) log.trace("{} is a valid DN", authenticatedUser); } - if (isDebugEnabled){ - log.debug("DBGTRACE (4): authenticatedUser="+authenticatedUser+" -> "+Arrays.toString(authenticatedUser.getBytes(StandardCharsets.UTF_8))); + if (isDebugEnabled) { + log.debug( + "DBGTRACE (4): authenticatedUser=" + + authenticatedUser + + " -> " + + Arrays.toString(authenticatedUser.getBytes(StandardCharsets.UTF_8)) + ); } entry = LdapHelper.lookup(connection, authenticatedUser, this.returnAttributes, this.shouldFollowReferrals); @@ -739,10 +771,21 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) } else { - if (isDebugEnabled) - log.debug("DBGTRACE (5): authenticatedUser="+user.getName()+" -> "+Arrays.toString(user.getName().getBytes(StandardCharsets.UTF_8))); - - entry = LDAPAuthenticationBackend.exists(user.getName(), connection, settings, userBaseSettings, this.returnAttributes, this.shouldFollowReferrals); + if (isDebugEnabled) log.debug( + "DBGTRACE (5): authenticatedUser=" + + user.getName() + + " -> " + + Arrays.toString(user.getName().getBytes(StandardCharsets.UTF_8)) + ); + + entry = LDAPAuthenticationBackend.exists( + user.getName(), + connection, + settings, + userBaseSettings, + this.returnAttributes, + this.shouldFollowReferrals + ); if (isTraceEnabled) { log.trace("{} is not a valid DN and was resolved to {}", authenticatedUser, entry); @@ -759,8 +802,8 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) log.trace("User found with DN {}", dn); } - if (isDebugEnabled){ - log.debug("DBGTRACE (6): dn"+dn+" -> "+Arrays.toString(dn.getBytes(StandardCharsets.UTF_8))); + if (isDebugEnabled) { + log.debug("DBGTRACE (6): dn" + dn + " -> " + Arrays.toString(dn.getBytes(StandardCharsets.UTF_8))); } } @@ -784,8 +827,8 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) final Collection userRoles = entry.getAttribute(roleName).getStringValues(); for (final String possibleRoleDN : userRoles) { - if (isDebugEnabled){ - log.debug("DBGTRACE (7): possibleRoleDN"+possibleRoleDN); + if (isDebugEnabled) { + log.debug("DBGTRACE (7): possibleRoleDN" + possibleRoleDN); } if (isValidDn(possibleRoleDN)) { @@ -838,8 +881,8 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) if (rolesearchEnabled) { String escapedDn = dn; - if (isDebugEnabled){ - log.debug("DBGTRACE (8): escapedDn"+escapedDn); + if (isDebugEnabled) { + log.debug("DBGTRACE (8): escapedDn" + escapedDn); } for (Map.Entry roleSearchSettingsEntry : roleBaseSettings) { @@ -849,16 +892,24 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) f.setFilter(roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_SEARCH, DEFAULT_ROLESEARCH)); f.setParameter(LDAPAuthenticationBackend.ZERO_PLACEHOLDER, escapedDn); f.setParameter(ONE_PLACEHOLDER, originalUserName); - f.setParameter(TWO_PLACEHOLDER, - userRoleAttributeValue == null ? TWO_PLACEHOLDER : userRoleAttributeValue); + f.setParameter(TWO_PLACEHOLDER, userRoleAttributeValue == null ? TWO_PLACEHOLDER : userRoleAttributeValue); - List rolesResult = LdapHelper.search(connection, - roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE), - f, - SearchScope.SUBTREE, this.returnAttributes, this.shouldFollowReferrals); + List rolesResult = LdapHelper.search( + connection, + roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE), + f, + SearchScope.SUBTREE, + this.returnAttributes, + this.shouldFollowReferrals + ); if (isTraceEnabled) { - log.trace("Results for LDAP group search for {} in base {}:\n{}", escapedDn, roleSearchSettingsEntry.getKey(), rolesResult); + log.trace( + "Results for LDAP group search for {} in base {}:\n{}", + escapedDn, + roleSearchSettingsEntry.getKey(), + rolesResult + ); } if (rolesResult != null && !rolesResult.isEmpty()) { @@ -886,17 +937,21 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) final Set nestedReturn = new HashSet<>(ldapRoles); for (final LdapName roleLdapName : ldapRoles) { - Set> nameRoleSearchBaseKeys = resultRoleSearchBaseKeys - .get(roleLdapName); + Set> nameRoleSearchBaseKeys = resultRoleSearchBaseKeys.get(roleLdapName); if (nameRoleSearchBaseKeys == null) { - log.error("Could not find roleSearchBaseKeys for " + roleLdapName + "; existing: " - + resultRoleSearchBaseKeys); + log.error("Could not find roleSearchBaseKeys for " + roleLdapName + "; existing: " + resultRoleSearchBaseKeys); continue; } - final Set nestedRoles = resolveNestedRoles(roleLdapName, connection, userRoleNames, 0, - rolesearchEnabled, nameRoleSearchBaseKeys); + final Set nestedRoles = resolveNestedRoles( + roleLdapName, + connection, + userRoleNames, + 0, + rolesearchEnabled, + nameRoleSearchBaseKeys + ); if (isTraceEnabled) { log.trace("{} nested roles for {}", nestedRoles.size(), roleLdapName); @@ -953,10 +1008,14 @@ public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) } - protected Set resolveNestedRoles(final LdapName roleDn, final Connection ldapConnection, - String userRoleName, int depth, final boolean rolesearchEnabled, - Set> roleSearchBaseSettingsSet) - throws OpenSearchSecurityException, LdapException { + protected Set resolveNestedRoles( + final LdapName roleDn, + final Connection ldapConnection, + String userRoleName, + int depth, + final boolean rolesearchEnabled, + Set> roleSearchBaseSettingsSet + ) throws OpenSearchSecurityException, LdapException { if (nestedRoleMatcher.test(roleDn.toString())) { @@ -980,8 +1039,8 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti for (final String possibleRoleDN : userRoles) { - if (isDebugEnabled){ - log.debug("DBGTRACE (10): possibleRoleDN"+possibleRoleDN); + if (isDebugEnabled) { + log.debug("DBGTRACE (10): possibleRoleDN" + possibleRoleDN); } if (isValidDn(possibleRoleDN)) { @@ -1008,13 +1067,11 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti if (rolesearchEnabled) { String escapedDn = roleDn.toString(); - if (isDebugEnabled){ + if (isDebugEnabled) { log.debug("DBGTRACE (10): escapedDn {}", escapedDn); } - - for (Map.Entry roleSearchBaseSettingsEntry : Utils - .getOrderedBaseSettings(roleSearchBaseSettingsSet)) { + for (Map.Entry roleSearchBaseSettingsEntry : Utils.getOrderedBaseSettings(roleSearchBaseSettingsSet)) { Settings roleSearchSettings = roleSearchBaseSettingsEntry.getValue(); SearchFilter f = new SearchFilter(); @@ -1022,14 +1079,22 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti f.setParameter(LDAPAuthenticationBackend.ZERO_PLACEHOLDER, escapedDn); f.setParameter(ONE_PLACEHOLDER, escapedDn); - List foundEntries = LdapHelper.search(ldapConnection, - roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE), - f, - SearchScope.SUBTREE, - this.returnAttributes, this.shouldFollowReferrals); + List foundEntries = LdapHelper.search( + ldapConnection, + roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE), + f, + SearchScope.SUBTREE, + this.returnAttributes, + this.shouldFollowReferrals + ); if (isTraceEnabled) { - log.trace("Results for LDAP group search for {} in base {}:\n{}", escapedDn, roleSearchBaseSettingsEntry.getKey(), foundEntries); + log.trace( + "Results for LDAP group search for {} in base {}:\n{}", + escapedDn, + roleSearchBaseSettingsEntry.getKey(), + foundEntries + ); } if (foundEntries != null) { @@ -1048,8 +1113,7 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti int maxDepth = ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH_DEFAULT; try { - maxDepth = settings.getAsInt(ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH, - ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH_DEFAULT); + maxDepth = settings.getAsInt(ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH, ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH_DEFAULT); } catch (Exception e) { log.error(ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH + " is not parseable: " + e, e); } @@ -1059,13 +1123,18 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti Set> nameRoleSearchBaseKeys = resultRoleSearchBaseKeys.get(nm); if (nameRoleSearchBaseKeys == null) { - log.error( - "Could not find roleSearchBaseKeys for " + nm + "; existing: " + resultRoleSearchBaseKeys); + log.error("Could not find roleSearchBaseKeys for " + nm + "; existing: " + resultRoleSearchBaseKeys); continue; } - final Set in = resolveNestedRoles(nm, ldapConnection, userRoleName, depth, rolesearchEnabled, - nameRoleSearchBaseKeys); + final Set in = resolveNestedRoles( + nm, + ldapConnection, + userRoleName, + depth, + rolesearchEnabled, + nameRoleSearchBaseKeys + ); result.addAll(in); } } @@ -1099,16 +1168,21 @@ private String getRoleFromEntry(final Connection ldapConnection, final LdapName return null; } - if("dn".equalsIgnoreCase(role)) { + if ("dn".equalsIgnoreCase(role)) { return ldapName.toString(); } try { - final LdapEntry roleEntry = LdapHelper.lookup(ldapConnection, ldapName.toString(), this.returnAttributes, this.shouldFollowReferrals); - - if(roleEntry != null) { + final LdapEntry roleEntry = LdapHelper.lookup( + ldapConnection, + ldapName.toString(), + this.returnAttributes, + this.shouldFollowReferrals + ); + + if (roleEntry != null) { final LdapAttribute roleAttribute = roleEntry.getAttribute(role); - if(roleAttribute != null) { + if (roleAttribute != null) { return Utils.getSingleStringValue(roleAttribute); } } diff --git a/src/main/java/com/amazon/dlic/auth/ldap/util/ConfigConstants.java b/src/main/java/com/amazon/dlic/auth/ldap/util/ConfigConstants.java index bdd9f39a8e..4854f80332 100755 --- a/src/main/java/com/amazon/dlic/auth/ldap/util/ConfigConstants.java +++ b/src/main/java/com/amazon/dlic/auth/ldap/util/ConfigConstants.java @@ -14,7 +14,7 @@ public final class ConfigConstants { public static final String LDAP_AUTHC_USERBASE = "userbase"; - public static final String LDAP_AUTHC_USERNAME_ATTRIBUTE = "username_attribute";//multi-value + public static final String LDAP_AUTHC_USERNAME_ATTRIBUTE = "username_attribute";// multi-value public static final String LDAP_AUTHC_USERSEARCH = "usersearch"; public static final String LDAP_AUTHCZ_USERS = "users"; @@ -22,13 +22,12 @@ public final class ConfigConstants { public static final String LDAP_AUTHCZ_BASE = "base"; public static final String LDAP_AUTHCZ_SEARCH = "search"; - public static final String LDAP_AUTHZ_RESOLVE_NESTED_ROLES = "resolve_nested_roles"; public static final String LDAP_AUTHZ_ROLEBASE = "rolebase"; - public static final String LDAP_AUTHZ_ROLENAME = "rolename";//multi-value + public static final String LDAP_AUTHZ_ROLENAME = "rolename";// multi-value public static final String LDAP_AUTHZ_ROLESEARCH = "rolesearch"; - public static final String LDAP_AUTHZ_USERROLEATTRIBUTE = "userroleattribute";//multi-value - public static final String LDAP_AUTHZ_USERROLENAME = "userrolename";//multi-value + public static final String LDAP_AUTHZ_USERROLEATTRIBUTE = "userroleattribute";// multi-value + public static final String LDAP_AUTHZ_USERROLENAME = "userrolename";// multi-value public static final String LDAP_AUTHZ_SKIP_USERS = "skip_users"; public static final String LDAP_AUTHZ_ROLESEARCH_ENABLED = "rolesearch_enabled"; public static final String LDAP_AUTHZ_NESTEDROLEFILTER = "nested_role_filter"; diff --git a/src/main/java/com/amazon/dlic/auth/ldap/util/LdapHelper.java b/src/main/java/com/amazon/dlic/auth/ldap/util/LdapHelper.java index db737ca5c5..f06c7d59d7 100644 --- a/src/main/java/com/amazon/dlic/auth/ldap/util/LdapHelper.java +++ b/src/main/java/com/amazon/dlic/auth/ldap/util/LdapHelper.java @@ -38,9 +38,16 @@ public class LdapHelper { private static SearchFilter ALL = new SearchFilter("(objectClass=*)"); + @SuppressWarnings("removal") - public static List search(final Connection conn, final String unescapedDn, SearchFilter filter, - final SearchScope searchScope, final String[] returnAttributes, boolean shouldFollowReferrals) throws LdapException { + public static List search( + final Connection conn, + final String unescapedDn, + SearchFilter filter, + final SearchScope searchScope, + final String[] returnAttributes, + boolean shouldFollowReferrals + ) throws LdapException { final SecurityManager sm = System.getSecurityManager(); @@ -61,7 +68,7 @@ public List run() throws Exception { final SearchOperation search = new SearchOperation(conn); if (shouldFollowReferrals) { - // referrals will be followed to build the response + // referrals will be followed to build the response request.setReferralHandler(new SearchReferralHandler()); } @@ -80,12 +87,17 @@ public List run() throws Exception { } else { throw new RuntimeException(e); } - }catch (InvalidNameException e) { + } catch (InvalidNameException e) { throw new RuntimeException(e); } } - public static LdapEntry lookup(final Connection conn, final String unescapedDn, final String[] returnAttributes, boolean shouldFollowReferrals) throws LdapException { + public static LdapEntry lookup( + final Connection conn, + final String unescapedDn, + final String[] returnAttributes, + boolean shouldFollowReferrals + ) throws LdapException { final List entries = search(conn, unescapedDn, ALL, SearchScope.OBJECT, returnAttributes, shouldFollowReferrals); @@ -99,15 +111,15 @@ public static LdapEntry lookup(final Connection conn, final String unescapedDn, private static String escapeDn(String dn) throws InvalidNameException { final LdapName dnName = new LdapName(dn); final List escaped = new ArrayList<>(dnName.size()); - for(Rdn rdn: dnName.getRdns()) { + for (Rdn rdn : dnName.getRdns()) { escaped.add(new Rdn(rdn.getType(), escapeForwardSlash(rdn.getValue()))); } return new LdapName(escaped).toString(); } private static Object escapeForwardSlash(Object input) { - if(input != null && input instanceof String) { - return ((String)input).replace("/", "\\2f"); + if (input != null && input instanceof String) { + return ((String) input).replace("/", "\\2f"); } else { return input; } diff --git a/src/main/java/com/amazon/dlic/auth/ldap/util/Utils.java b/src/main/java/com/amazon/dlic/auth/ldap/util/Utils.java index f10452f410..743705eee5 100644 --- a/src/main/java/com/amazon/dlic/auth/ldap/util/Utils.java +++ b/src/main/java/com/amazon/dlic/auth/ldap/util/Utils.java @@ -83,8 +83,10 @@ private static void sortBaseSettings(List> list) { @Override public int compare(Map.Entry o1, Map.Entry o2) { - int attributeOrder = Integer.compare(o1.getValue().getAsInt("order", Integer.MAX_VALUE), - o2.getValue().getAsInt("order", Integer.MAX_VALUE)); + int attributeOrder = Integer.compare( + o1.getValue().getAsInt("order", Integer.MAX_VALUE), + o2.getValue().getAsInt("order", Integer.MAX_VALUE) + ); if (attributeOrder != 0) { return attributeOrder; @@ -96,12 +98,12 @@ public int compare(Map.Entry o1, Map.Entry o } public static String getSingleStringValue(LdapAttribute attribute) { - if(attribute == null) { + if (attribute == null) { return null; } - if(attribute.size() > 1) { - if(log.isDebugEnabled()) { + if (attribute.size() > 1) { + if (log.isDebugEnabled()) { log.debug("Multiple values found for {} ({})", attribute.getName(), attribute); } } diff --git a/src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthenticationBackend2.java b/src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthenticationBackend2.java index f64f3fc0b4..74184de0eb 100755 --- a/src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthenticationBackend2.java +++ b/src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthenticationBackend2.java @@ -65,8 +65,7 @@ public class LDAPAuthenticationBackend2 implements AuthenticationBackend, Destro public LDAPAuthenticationBackend2(final Settings settings, final Path configPath) throws SSLConfigException { this.settings = settings; - LDAPConnectionFactoryFactory ldapConnectionFactoryFactory = new LDAPConnectionFactoryFactory(settings, - configPath); + LDAPConnectionFactoryFactory ldapConnectionFactoryFactory = new LDAPConnectionFactoryFactory(settings, configPath); this.connectionPool = ldapConnectionFactoryFactory.createConnectionPool(); this.connectionFactory = ldapConnectionFactoryFactory.createConnectionFactory(this.connectionPool); @@ -78,11 +77,13 @@ public LDAPAuthenticationBackend2(final Settings settings, final Path configPath } this.userSearcher = new LDAPUserSearcher(settings); - this.returnAttributes = settings.getAsList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, Arrays.asList(ReturnAttributes.ALL.value())).toArray(new String[0]); + this.returnAttributes = settings.getAsList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, Arrays.asList(ReturnAttributes.ALL.value())) + .toArray(new String[0]); this.shouldFollowReferrals = settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT); customAttrMaxValueLen = settings.getAsInt(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 36); - whitelistedCustomLdapAttrMatcher = WildcardMatcher.from(settings.getAsList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, - Collections.singletonList("*"))); + whitelistedCustomLdapAttrMatcher = WildcardMatcher.from( + settings.getAsList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, Collections.singletonList("*")) + ); } @Override @@ -112,7 +113,6 @@ public User run() throws Exception { } } - private User authenticate0(final AuthCredentials credentials) throws OpenSearchSecurityException { Connection ldapConnection = null; @@ -130,11 +130,12 @@ private User authenticate0(final AuthCredentials credentials) throws OpenSearchS // makes guessing if a user exists or not harder when looking on the // authentication delay time if (entry == null && settings.getAsBoolean(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, false)) { - String fakeLognDn = settings.get(ConfigConstants.LDAP_FAKE_LOGIN_DN, - "CN=faketomakebindfail,DC=" + UUID.randomUUID().toString()); + String fakeLognDn = settings.get( + ConfigConstants.LDAP_FAKE_LOGIN_DN, + "CN=faketomakebindfail,DC=" + UUID.randomUUID().toString() + ); entry = new LdapEntry(fakeLognDn); - password = settings.get(ConfigConstants.LDAP_FAKE_LOGIN_PASSWORD, "fakeLoginPwd123") - .getBytes(StandardCharsets.UTF_8); + password = settings.get(ConfigConstants.LDAP_FAKE_LOGIN_PASSWORD, "fakeLoginPwd123").getBytes(StandardCharsets.UTF_8); } else if (entry == null) { throw new OpenSearchSecurityException("No user " + user + " found"); } @@ -195,7 +196,6 @@ public boolean exists(final User user) { sm.checkPermission(new SpecialPermission()); } - return AccessController.doPrivileged(new PrivilegedAction() { @Override public Boolean run() { @@ -217,13 +217,15 @@ private boolean exists0(final User user) { ldapConnection = this.connectionFactory.getConnection(); ldapConnection.open(); LdapEntry userEntry = this.userSearcher.exists(ldapConnection, userName, this.returnAttributes, this.shouldFollowReferrals); - + boolean exists = userEntry != null; - - if(exists) { - user.addAttributes(LdapUser.extractLdapAttributes(userName, userEntry, customAttrMaxValueLen, whitelistedCustomLdapAttrMatcher)); + + if (exists) { + user.addAttributes( + LdapUser.extractLdapAttributes(userName, userEntry, customAttrMaxValueLen, whitelistedCustomLdapAttrMatcher) + ); } - + return exists; } catch (final Exception e) { log.warn("User {} does not exist due to exception", userName, e); @@ -234,8 +236,7 @@ private boolean exists0(final User user) { } @SuppressWarnings("removal") - private void authenticateByLdapServer(final Connection connection, final String dn, byte[] password) - throws LdapException { + private void authenticateByLdapServer(final Connection connection, final String dn, byte[] password) throws LdapException { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { diff --git a/src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthorizationBackend2.java b/src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthorizationBackend2.java index c140dbb6f9..d8d27de7da 100755 --- a/src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthorizationBackend2.java +++ b/src/main/java/com/amazon/dlic/auth/ldap2/LDAPAuthorizationBackend2.java @@ -81,17 +81,18 @@ public class LDAPAuthorizationBackend2 implements AuthorizationBackend, Destroya public LDAPAuthorizationBackend2(final Settings settings, final Path configPath) throws SSLConfigException { this.settings = settings; this.skipUsersMatcher = WildcardMatcher.from(settings.getAsList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS)); - this.nestedRoleMatcher = settings.getAsBoolean(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) ? - WildcardMatcher.from(settings.getAsList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER)) : null; + this.nestedRoleMatcher = settings.getAsBoolean(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) + ? WildcardMatcher.from(settings.getAsList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER)) + : null; this.roleBaseSettings = getRoleSearchSettings(settings); - LDAPConnectionFactoryFactory ldapConnectionFactoryFactory = new LDAPConnectionFactoryFactory(settings, - configPath); + LDAPConnectionFactoryFactory ldapConnectionFactoryFactory = new LDAPConnectionFactoryFactory(settings, configPath); this.connectionPool = ldapConnectionFactoryFactory.createConnectionPool(); this.connectionFactory = ldapConnectionFactoryFactory.createConnectionFactory(this.connectionPool); this.userSearcher = new LDAPUserSearcher(settings); - this.returnAttributes = settings.getAsList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, Arrays.asList(ReturnAttributes.ALL.value())).toArray(new String[0]); + this.returnAttributes = settings.getAsList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, Arrays.asList(ReturnAttributes.ALL.value())) + .toArray(new String[0]); this.shouldFollowReferrals = settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT); } @@ -112,10 +113,8 @@ private static List> convertOldStyleSettingsToNewSty Settings.Builder settingsBuilder = Settings.builder(); - settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_BASE, - settings.get(ConfigConstants.LDAP_AUTHZ_ROLEBASE, DEFAULT_ROLEBASE)); - settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_SEARCH, - settings.get(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, DEFAULT_ROLESEARCH)); + settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_BASE, settings.get(ConfigConstants.LDAP_AUTHZ_ROLEBASE, DEFAULT_ROLEBASE)); + settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_SEARCH, settings.get(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, DEFAULT_ROLESEARCH)); result.put("convertedOldStyleSettings", settingsBuilder.build()); @@ -124,8 +123,7 @@ private static List> convertOldStyleSettingsToNewSty @SuppressWarnings("removal") @Override - public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) - throws OpenSearchSecurityException { + public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) throws OpenSearchSecurityException { final SecurityManager sm = System.getSecurityManager(); @@ -152,8 +150,7 @@ public Void run() throws Exception { } } - private void fillRoles0(final User user, final AuthCredentials optionalAuthCreds) - throws OpenSearchSecurityException { + private void fillRoles0(final User user, final AuthCredentials optionalAuthCreds) throws OpenSearchSecurityException { if (user == null) { return; @@ -170,7 +167,7 @@ private void fillRoles0(final User user, final AuthCredentials optionalAuthCreds authenticatedUser = entry.getDn(); originalUserName = ((LdapUser) user).getOriginalUsername(); } else { - authenticatedUser =user.getName(); + authenticatedUser = user.getName(); originalUserName = user.getName(); } @@ -309,17 +306,24 @@ private void fillRoles0(final User user, final AuthCredentials optionalAuthCreds f.setFilter(roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_SEARCH, DEFAULT_ROLESEARCH)); f.setParameter(ZERO_PLACEHOLDER, escapedDn); f.setParameter(ONE_PLACEHOLDER, originalUserName); - f.setParameter(TWO_PLACEHOLDER, - userRoleAttributeValue == null ? TWO_PLACEHOLDER : userRoleAttributeValue); + f.setParameter(TWO_PLACEHOLDER, userRoleAttributeValue == null ? TWO_PLACEHOLDER : userRoleAttributeValue); - List rolesResult = LdapHelper.search(connection, - roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE), - f, - SearchScope.SUBTREE, - this.returnAttributes, this.shouldFollowReferrals); + List rolesResult = LdapHelper.search( + connection, + roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE), + f, + SearchScope.SUBTREE, + this.returnAttributes, + this.shouldFollowReferrals + ); if (isTraceEnabled) { - log.trace("Results for LDAP group search for {} in base {}:\n{}", escapedDn, roleSearchSettingsEntry.getKey(), rolesResult); + log.trace( + "Results for LDAP group search for {} in base {}:\n{}", + escapedDn, + roleSearchSettingsEntry.getKey(), + rolesResult + ); } if (rolesResult != null && !rolesResult.isEmpty()) { @@ -347,17 +351,21 @@ private void fillRoles0(final User user, final AuthCredentials optionalAuthCreds final Set nestedReturn = new HashSet<>(ldapRoles); for (final LdapName roleLdapName : ldapRoles) { - Set> nameRoleSearchBaseKeys = resultRoleSearchBaseKeys - .get(roleLdapName); + Set> nameRoleSearchBaseKeys = resultRoleSearchBaseKeys.get(roleLdapName); if (nameRoleSearchBaseKeys == null) { - log.error("Could not find roleSearchBaseKeys for {}; existing: {}", - roleLdapName, resultRoleSearchBaseKeys); + log.error("Could not find roleSearchBaseKeys for {}; existing: {}", roleLdapName, resultRoleSearchBaseKeys); continue; } - final Set nestedRoles = resolveNestedRoles(roleLdapName, connection, userRoleNames, 0, - rolesearchEnabled, nameRoleSearchBaseKeys); + final Set nestedRoles = resolveNestedRoles( + roleLdapName, + connection, + userRoleNames, + 0, + rolesearchEnabled, + nameRoleSearchBaseKeys + ); if (isTraceEnabled) { log.trace("{} nested roles for {}", nestedRoles.size(), roleLdapName); @@ -412,10 +420,14 @@ private void fillRoles0(final User user, final AuthCredentials optionalAuthCreds } - protected Set resolveNestedRoles(final LdapName roleDn, final Connection ldapConnection, - String userRoleName, int depth, final boolean rolesearchEnabled, - Set> roleSearchBaseSettingsSet) - throws OpenSearchSecurityException, LdapException { + protected Set resolveNestedRoles( + final LdapName roleDn, + final Connection ldapConnection, + String userRoleName, + int depth, + final boolean rolesearchEnabled, + Set> roleSearchBaseSettingsSet + ) throws OpenSearchSecurityException, LdapException { final boolean isTraceEnabled = log.isTraceEnabled(); if (nestedRoleMatcher.test(roleDn.toString())) { @@ -461,8 +473,7 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti if (rolesearchEnabled) { String escapedDn = roleDn.toString(); - for (Map.Entry roleSearchBaseSettingsEntry : Utils - .getOrderedBaseSettings(roleSearchBaseSettingsSet)) { + for (Map.Entry roleSearchBaseSettingsEntry : Utils.getOrderedBaseSettings(roleSearchBaseSettingsSet)) { Settings roleSearchSettings = roleSearchBaseSettingsEntry.getValue(); SearchFilter f = new SearchFilter(); @@ -470,14 +481,22 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti f.setParameter(ZERO_PLACEHOLDER, escapedDn); f.setParameter(ONE_PLACEHOLDER, escapedDn); - List foundEntries = LdapHelper.search(ldapConnection, - roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE), - f, - SearchScope.SUBTREE, - this.returnAttributes, this.shouldFollowReferrals); + List foundEntries = LdapHelper.search( + ldapConnection, + roleSearchSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_ROLEBASE), + f, + SearchScope.SUBTREE, + this.returnAttributes, + this.shouldFollowReferrals + ); if (isTraceEnabled) { - log.trace("Results for LDAP group search for {} in base {}:\n{}", escapedDn, roleSearchBaseSettingsEntry.getKey(), foundEntries); + log.trace( + "Results for LDAP group search for {} in base {}:\n{}", + escapedDn, + roleSearchBaseSettingsEntry.getKey(), + foundEntries + ); } if (foundEntries != null) { @@ -496,8 +515,7 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti int maxDepth = ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH_DEFAULT; try { - maxDepth = settings.getAsInt(ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH, - ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH_DEFAULT); + maxDepth = settings.getAsInt(ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH, ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH_DEFAULT); } catch (Exception e) { log.error(ConfigConstants.LDAP_AUTHZ_MAX_NESTED_DEPTH + " is not parseable: ", e); } @@ -507,13 +525,18 @@ protected Set resolveNestedRoles(final LdapName roleDn, final Connecti Set> nameRoleSearchBaseKeys = resultRoleSearchBaseKeys.get(nm); if (nameRoleSearchBaseKeys == null) { - log.error( - "Could not find roleSearchBaseKeys for {}; existing: {}", nm, resultRoleSearchBaseKeys); + log.error("Could not find roleSearchBaseKeys for {}; existing: {}", nm, resultRoleSearchBaseKeys); continue; } - final Set in = resolveNestedRoles(nm, ldapConnection, userRoleName, depth, rolesearchEnabled, - nameRoleSearchBaseKeys); + final Set in = resolveNestedRoles( + nm, + ldapConnection, + userRoleName, + depth, + rolesearchEnabled, + nameRoleSearchBaseKeys + ); result.addAll(in); } } @@ -547,21 +570,26 @@ private String getRoleFromEntry(final Connection ldapConnection, final LdapName return null; } - if("dn".equalsIgnoreCase(role)) { + if ("dn".equalsIgnoreCase(role)) { return ldapName.toString(); } try { - final LdapEntry roleEntry = LdapHelper.lookup(ldapConnection, ldapName.toString(), this.returnAttributes, this.shouldFollowReferrals); - - if(roleEntry != null) { + final LdapEntry roleEntry = LdapHelper.lookup( + ldapConnection, + ldapName.toString(), + this.returnAttributes, + this.shouldFollowReferrals + ); + + if (roleEntry != null) { final LdapAttribute roleAttribute = roleEntry.getAttribute(role); - if(roleAttribute != null) { + if (roleAttribute != null) { return Utils.getSingleStringValue(roleAttribute); } } } catch (LdapException e) { - log.error("Unable to handle role {} because of ",ldapName, e); + log.error("Unable to handle role {} because of ", ldapName, e); } return null; diff --git a/src/main/java/com/amazon/dlic/auth/ldap2/LDAPConnectionFactoryFactory.java b/src/main/java/com/amazon/dlic/auth/ldap2/LDAPConnectionFactoryFactory.java index f711e41982..877c4160da 100644 --- a/src/main/java/com/amazon/dlic/auth/ldap2/LDAPConnectionFactoryFactory.java +++ b/src/main/java/com/amazon/dlic/auth/ldap2/LDAPConnectionFactoryFactory.java @@ -132,10 +132,22 @@ public ConnectionPool createConnectionPool() { checkForDeprecatedSetting(settings, ConfigConstants.LDAP_LEGACY_POOL_PRUNING_PERIOD, ConfigConstants.LDAP_POOL_PRUNING_PERIOD); checkForDeprecatedSetting(settings, ConfigConstants.LDAP_LEGACY_POOL_IDLE_TIME, ConfigConstants.LDAP_POOL_IDLE_TIME); - - result.setPruneStrategy(new IdlePruneStrategy( - Duration.ofMinutes(this.settings.getAsLong(ConfigConstants.LDAP_POOL_PRUNING_PERIOD, this.settings.getAsLong(ConfigConstants.LDAP_LEGACY_POOL_PRUNING_PERIOD, 5l))), - Duration.ofMinutes(this.settings.getAsLong(ConfigConstants.LDAP_POOL_IDLE_TIME, this.settings.getAsLong(ConfigConstants.LDAP_LEGACY_POOL_IDLE_TIME, 10l)))) + + result.setPruneStrategy( + new IdlePruneStrategy( + Duration.ofMinutes( + this.settings.getAsLong( + ConfigConstants.LDAP_POOL_PRUNING_PERIOD, + this.settings.getAsLong(ConfigConstants.LDAP_LEGACY_POOL_PRUNING_PERIOD, 5l) + ) + ), + Duration.ofMinutes( + this.settings.getAsLong( + ConfigConstants.LDAP_POOL_IDLE_TIME, + this.settings.getAsLong(ConfigConstants.LDAP_LEGACY_POOL_IDLE_TIME, 10l) + ) + ) + ) ); result.initialize(); @@ -186,8 +198,10 @@ private ConnectionInitializer getConnectionInitializer() { log.error("No password given for bind_dn {}. Will try to authenticate anonymously to ldap", bindDn); } - boolean enableClientAuth = settings.getAsBoolean(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, - ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH_DEFAULT); + boolean enableClientAuth = settings.getAsBoolean( + ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, + ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH_DEFAULT + ); if (bindDn != null && password != null) { log.debug("Will perform simple bind with bind dn"); @@ -195,8 +209,7 @@ private ConnectionInitializer getConnectionInitializer() { result.setBindCredential(new Credential(password)); if (enableClientAuth) { - log.warn( - "Will perform simple bind with bind dn because to bind dn is given and overrides client cert authentication"); + log.warn("Will perform simple bind with bind dn because to bind dn is given and overrides client cert authentication"); } } else if (enableClientAuth) { log.debug("Will perform External SASL bind because client cert authentication is enabled"); @@ -210,12 +223,12 @@ private ConnectionInitializer getConnectionInitializer() { private ConnectionStrategy getConnectionStrategy() { switch (this.settings.get(ConfigConstants.LDAP_CONNECTION_STRATEGY, "active_passive").toLowerCase()) { - case "round_robin": - return new RoundRobinConnectionStrategy(); - case "random": - return new RandomConnectionStrategy(); - default: - return new ActivePassiveConnectionStrategy(); + case "round_robin": + return new RoundRobinConnectionStrategy(); + case "random": + return new RandomConnectionStrategy(); + default: + return new ActivePassiveConnectionStrategy(); } } @@ -228,14 +241,19 @@ private Validator getConnectionValidator() { Validator result = null; if ("compare".equalsIgnoreCase(validationStrategy)) { - result = new CompareValidator(new CompareRequest(this.settings.get("validation.compare.dn", ""), - new LdapAttribute(this.settings.get("validation.compare.attribute", "objectClass"), - this.settings.get("validation.compare.value", "top")))); + result = new CompareValidator( + new CompareRequest( + this.settings.get("validation.compare.dn", ""), + new LdapAttribute( + this.settings.get("validation.compare.attribute", "objectClass"), + this.settings.get("validation.compare.value", "top") + ) + ) + ); } else { SearchRequest searchRequest = new SearchRequest(); searchRequest.setBaseDn(this.settings.get("validation.search.base_dn", "")); - searchRequest.setSearchFilter( - new SearchFilter(this.settings.get("validation.search.filter", "(objectClass=*)"))); + searchRequest.setSearchFilter(new SearchFilter(this.settings.get("validation.search.filter", "(objectClass=*)"))); searchRequest.setReturnAttributes(ReturnAttributes.NONE.value()); searchRequest.setSearchScope(SearchScope.OBJECT); searchRequest.setSizeLimit(1); @@ -250,8 +268,7 @@ private String getLdapUrlString() { // It's a bit weird that we create from structured data a plain string which is // later parsed again by ldaptive. But that's the way the API wants it to be. - List ldapHosts = this.settings.getAsList(ConfigConstants.LDAP_HOSTS, - Collections.singletonList("localhost")); + List ldapHosts = this.settings.getAsList(ConfigConstants.LDAP_HOSTS, Collections.singletonList("localhost")); boolean enableSSL = settings.getAsBoolean(ConfigConstants.LDAPS_ENABLE_SSL, false); StringBuilder result = new StringBuilder(); @@ -282,9 +299,12 @@ private void configureSSL(ConnectionConfig config) { SslConfig ldaptiveSslConfig = new SslConfig(); CredentialConfig cc = CredentialConfigFactory.createKeyStoreCredentialConfig( - this.sslConfig.getEffectiveTruststore(), this.sslConfig.getEffectiveTruststoreAliasesArray(), - this.sslConfig.getEffectiveKeystore(), this.sslConfig.getEffectiveKeyPasswordString(), - this.sslConfig.getEffectiveKeyAliasesArray()); + this.sslConfig.getEffectiveTruststore(), + this.sslConfig.getEffectiveTruststoreAliasesArray(), + this.sslConfig.getEffectiveKeystore(), + this.sslConfig.getEffectiveKeyPasswordString(), + this.sslConfig.getEffectiveKeyAliasesArray() + ); ldaptiveSslConfig.setCredentialConfig(cc); @@ -292,9 +312,11 @@ private void configureSSL(ConnectionConfig config) { ldaptiveSslConfig.setHostnameVerifier(new AllowAnyHostnameVerifier()); if (!Boolean.parseBoolean(System.getProperty("com.sun.jndi.ldap.object.disableEndpointIdentification"))) { - log.warn("In order to disable host name verification for LDAP connections (verify_hostnames: true), " + log.warn( + "In order to disable host name verification for LDAP connections (verify_hostnames: true), " + "you also need to set set the system property com.sun.jndi.ldap.object.disableEndpointIdentification to true when starting the JVM running OpenSearch. " - + "This applies for all Java versions released since July 2018."); + + "This applies for all Java versions released since July 2018." + ); // See: // https://www.oracle.com/technetwork/java/javase/8u181-relnotes-4479407.html // https://www.oracle.com/technetwork/java/javase/10-0-2-relnotes-4477557.html diff --git a/src/main/java/com/amazon/dlic/auth/ldap2/LDAPUserSearcher.java b/src/main/java/com/amazon/dlic/auth/ldap2/LDAPUserSearcher.java index 81da81647f..966555daff 100644 --- a/src/main/java/com/amazon/dlic/auth/ldap2/LDAPUserSearcher.java +++ b/src/main/java/com/amazon/dlic/auth/ldap2/LDAPUserSearcher.java @@ -48,33 +48,34 @@ public LDAPUserSearcher(Settings settings) { } static List> getUserBaseSettings(Settings settings) { - Map userBaseSettingsMap = new HashMap<>( - settings.getGroups(ConfigConstants.LDAP_AUTHCZ_USERS)); + Map userBaseSettingsMap = new HashMap<>(settings.getGroups(ConfigConstants.LDAP_AUTHCZ_USERS)); if (!userBaseSettingsMap.isEmpty()) { if (settings.hasValue(ConfigConstants.LDAP_AUTHC_USERBASE)) { throw new RuntimeException( - "Both old-style and new-style configuration defined for LDAP authentication backend: " - + settings); + "Both old-style and new-style configuration defined for LDAP authentication backend: " + settings + ); } return Utils.getOrderedBaseSettings(userBaseSettingsMap); } else { Settings.Builder settingsBuilder = Settings.builder(); - settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_BASE, - settings.get(ConfigConstants.LDAP_AUTHC_USERBASE, DEFAULT_USERBASE)); - settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_SEARCH, - settings.get(ConfigConstants.LDAP_AUTHC_USERSEARCH, DEFAULT_USERSEARCH_PATTERN)); + settingsBuilder.put(ConfigConstants.LDAP_AUTHCZ_BASE, settings.get(ConfigConstants.LDAP_AUTHC_USERBASE, DEFAULT_USERBASE)); + settingsBuilder.put( + ConfigConstants.LDAP_AUTHCZ_SEARCH, + settings.get(ConfigConstants.LDAP_AUTHC_USERSEARCH, DEFAULT_USERSEARCH_PATTERN) + ); return Collections.singletonList(Pair.of("_legacyConfig", settingsBuilder.build())); } } - LdapEntry exists(Connection ldapConnection, String user, final String[] returnAttributes, final boolean shouldFollowReferrals) throws Exception { + LdapEntry exists(Connection ldapConnection, String user, final String[] returnAttributes, final boolean shouldFollowReferrals) + throws Exception { if (settings.getAsBoolean(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, false) - || settings.getAsBoolean(ConfigConstants.LDAP_SEARCH_ALL_BASES, false) - || settings.hasValue(ConfigConstants.LDAP_AUTHC_USERBASE)) { + || settings.getAsBoolean(ConfigConstants.LDAP_SEARCH_ALL_BASES, false) + || settings.hasValue(ConfigConstants.LDAP_AUTHC_USERBASE)) { return existsSearchingAllBases(ldapConnection, user, returnAttributes, shouldFollowReferrals); } else { return existsSearchingUntilFirstHit(ldapConnection, user, returnAttributes, shouldFollowReferrals); @@ -82,7 +83,12 @@ LdapEntry exists(Connection ldapConnection, String user, final String[] returnAt } - private LdapEntry existsSearchingUntilFirstHit(Connection ldapConnection, String user, final String[] returnAttributes, final boolean shouldFollowReferrals) throws Exception { + private LdapEntry existsSearchingUntilFirstHit( + Connection ldapConnection, + String user, + final String[] returnAttributes, + final boolean shouldFollowReferrals + ) throws Exception { final String username = user; final boolean isDebugEnabled = log.isDebugEnabled(); for (Map.Entry entry : userBaseSettings) { @@ -92,11 +98,14 @@ private LdapEntry existsSearchingUntilFirstHit(Connection ldapConnection, String f.setFilter(baseSettings.get(ConfigConstants.LDAP_AUTHCZ_SEARCH, DEFAULT_USERSEARCH_PATTERN)); f.setParameter(ZERO_PLACEHOLDER, username); - List result = LdapHelper.search(ldapConnection, - baseSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_USERBASE), - f, - SearchScope.SUBTREE, - returnAttributes, shouldFollowReferrals); + List result = LdapHelper.search( + ldapConnection, + baseSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_USERBASE), + f, + SearchScope.SUBTREE, + returnAttributes, + shouldFollowReferrals + ); if (isDebugEnabled) { log.debug("Results for LDAP search for {} in base {}:\n{}", user, entry.getKey(), result); @@ -110,7 +119,12 @@ private LdapEntry existsSearchingUntilFirstHit(Connection ldapConnection, String return null; } - private LdapEntry existsSearchingAllBases(Connection ldapConnection, String user, final String[] returnAttributes, final boolean shouldFollowReferrals) throws Exception { + private LdapEntry existsSearchingAllBases( + Connection ldapConnection, + String user, + final String[] returnAttributes, + final boolean shouldFollowReferrals + ) throws Exception { final String username = user; Set result = new HashSet<>(); final boolean isDebugEnabled = log.isDebugEnabled(); @@ -121,11 +135,14 @@ private LdapEntry existsSearchingAllBases(Connection ldapConnection, String user f.setFilter(baseSettings.get(ConfigConstants.LDAP_AUTHCZ_SEARCH, DEFAULT_USERSEARCH_PATTERN)); f.setParameter(ZERO_PLACEHOLDER, username); - List foundEntries = LdapHelper.search(ldapConnection, - baseSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_USERBASE), - f, - SearchScope.SUBTREE, - returnAttributes, shouldFollowReferrals); + List foundEntries = LdapHelper.search( + ldapConnection, + baseSettings.get(ConfigConstants.LDAP_AUTHCZ_BASE, DEFAULT_USERBASE), + f, + SearchScope.SUBTREE, + returnAttributes, + shouldFollowReferrals + ); if (isDebugEnabled) { log.debug("Results for LDAP search for {} in base {}:\n{}", user, entry.getKey(), result); diff --git a/src/main/java/com/amazon/dlic/util/SettingsBasedSSLConfigurator.java b/src/main/java/com/amazon/dlic/util/SettingsBasedSSLConfigurator.java index ea99625e6b..ed42117a04 100644 --- a/src/main/java/com/amazon/dlic/util/SettingsBasedSSLConfigurator.java +++ b/src/main/java/com/amazon/dlic/util/SettingsBasedSSLConfigurator.java @@ -95,8 +95,7 @@ public class SettingsBasedSSLConfigurator { private String effectiveKeyAlias; private List effectiveTruststoreAliases; - public SettingsBasedSSLConfigurator(Settings settings, Path configPath, String settingsKeyPrefix, - String clientName) { + public SettingsBasedSSLConfigurator(Settings settings, Path configPath, String settingsKeyPrefix, String clientName) { this.settings = settings; this.configPath = configPath; this.settingsKeyPrefix = normalizeSettingsKeyPrefix(settingsKeyPrefix); @@ -136,10 +135,20 @@ public SSLConfig buildSSLConfig() throws SSLConfigException { return null; } - return new SSLConfig(sslContext, getSupportedProtocols(), getSupportedCipherSuites(), getHostnameVerifier(), - isHostnameVerificationEnabled(), isTrustAllEnabled(), isStartTlsEnabled(), this.effectiveTruststore, - this.effectiveTruststoreAliases, this.effectiveKeystore, this.effectiveKeyPassword, - this.effectiveKeyAlias); + return new SSLConfig( + sslContext, + getSupportedProtocols(), + getSupportedCipherSuites(), + getHostnameVerifier(), + isHostnameVerificationEnabled(), + isTrustAllEnabled(), + isStartTlsEnabled(), + this.effectiveTruststore, + this.effectiveTruststoreAliases, + this.effectiveKeystore, + this.effectiveKeyPassword, + this.effectiveKeyAlias + ); } private boolean isHostnameVerificationEnabled() { @@ -181,7 +190,7 @@ private void configureWithSettings() throws SSLConfigException, NoSuchAlgorithmE this.enableSslClientAuth = getSettingAsBoolean(ENABLE_SSL_CLIENT_AUTH, false); if (settings.get(settingsKeyPrefix + PEMTRUSTEDCAS_FILEPATH, null) != null - || settings.get(settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT, null) != null) { + || settings.get(settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT, null) != null) { initFromPem(); } else { initFromKeyStore(); @@ -194,22 +203,21 @@ private void configureWithSettings() throws SSLConfigException, NoSuchAlgorithmE if (enableSslClientAuth) { if (effectiveKeystore != null) { try { - sslContextBuilder.loadKeyMaterial(effectiveKeystore, effectiveKeyPassword, - new PrivateKeyStrategy() { - - @Override - public String chooseAlias(Map aliases, SSLParameters sslParameters) { - if (aliases == null || aliases.isEmpty()) { - return effectiveKeyAlias; - } - - if (effectiveKeyAlias == null || effectiveKeyAlias.isEmpty()) { - return aliases.keySet().iterator().next(); - } - - return effectiveKeyAlias; - } - }); + sslContextBuilder.loadKeyMaterial(effectiveKeystore, effectiveKeyPassword, new PrivateKeyStrategy() { + + @Override + public String chooseAlias(Map aliases, SSLParameters sslParameters) { + if (aliases == null || aliases.isEmpty()) { + return effectiveKeyAlias; + } + + if (effectiveKeyAlias == null || effectiveKeyAlias.isEmpty()) { + return aliases.keySet().iterator().next(); + } + + return effectiveKeyAlias; + } + }); } catch (UnrecoverableKeyException e) { throw new RuntimeException(e); } @@ -223,22 +231,25 @@ private void initFromPem() throws SSLConfigException { try { trustCertificates = PemKeyReader.loadCertificatesFromStream( - PemKeyReader.resolveStream(settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT, settings)); + PemKeyReader.resolveStream(settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT, settings) + ); } catch (Exception e) { throw new SSLConfigException( - "Error loading PEM from " + settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT + " for " + this.clientName, - e); + "Error loading PEM from " + settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT + " for " + this.clientName, + e + ); } if (trustCertificates == null) { - String path = PemKeyReader.resolve(settingsKeyPrefix + PEMTRUSTEDCAS_FILEPATH, settings, configPath, - !isTrustAllEnabled()); + String path = PemKeyReader.resolve(settingsKeyPrefix + PEMTRUSTEDCAS_FILEPATH, settings, configPath, !isTrustAllEnabled()); try { trustCertificates = PemKeyReader.loadCertificatesFromFile(path); } catch (Exception e) { - throw new SSLConfigException("Error loading PEM from " + path + " (" + settingsKeyPrefix - + PEMTRUSTEDCAS_FILEPATH + ") for " + this.clientName, e); + throw new SSLConfigException( + "Error loading PEM from " + path + " (" + settingsKeyPrefix + PEMTRUSTEDCAS_FILEPATH + ") for " + this.clientName, + e + ); } } @@ -247,21 +258,22 @@ private void initFromPem() throws SSLConfigException { try { authenticationCertificate = PemKeyReader.loadCertificatesFromStream( - PemKeyReader.resolveStream(settingsKeyPrefix + PEMCERT_CONTENT, settings)); + PemKeyReader.resolveStream(settingsKeyPrefix + PEMCERT_CONTENT, settings) + ); } catch (Exception e) { - throw new SSLConfigException( - "Error loading PEM from " + settingsKeyPrefix + PEMCERT_CONTENT + " for " + this.clientName, e); + throw new SSLConfigException("Error loading PEM from " + settingsKeyPrefix + PEMCERT_CONTENT + " for " + this.clientName, e); } if (authenticationCertificate == null) { - String path = PemKeyReader.resolve(settingsKeyPrefix + PEMCERT_FILEPATH, settings, configPath, - enableSslClientAuth); + String path = PemKeyReader.resolve(settingsKeyPrefix + PEMCERT_FILEPATH, settings, configPath, enableSslClientAuth); try { authenticationCertificate = PemKeyReader.loadCertificatesFromFile(path); } catch (Exception e) { - throw new SSLConfigException("Error loading PEM from " + path + " (" + settingsKeyPrefix - + PEMCERT_FILEPATH + ") for " + this.clientName, e); + throw new SSLConfigException( + "Error loading PEM from " + path + " (" + settingsKeyPrefix + PEMCERT_FILEPATH + ") for " + this.clientName, + e + ); } } @@ -269,22 +281,24 @@ private void initFromPem() throws SSLConfigException { PrivateKey authenticationKey; try { - authenticationKey = PemKeyReader.loadKeyFromStream(getSetting(PEMKEY_PASSWORD), - PemKeyReader.resolveStream(settingsKeyPrefix + PEMKEY_CONTENT, settings)); + authenticationKey = PemKeyReader.loadKeyFromStream( + getSetting(PEMKEY_PASSWORD), + PemKeyReader.resolveStream(settingsKeyPrefix + PEMKEY_CONTENT, settings) + ); } catch (Exception e) { - throw new SSLConfigException( - "Error loading PEM from " + settingsKeyPrefix + PEMKEY_CONTENT + " for " + this.clientName, e); + throw new SSLConfigException("Error loading PEM from " + settingsKeyPrefix + PEMKEY_CONTENT + " for " + this.clientName, e); } if (authenticationKey == null) { - String path = PemKeyReader.resolve(settingsKeyPrefix + PEMKEY_FILEPATH, settings, configPath, - enableSslClientAuth); + String path = PemKeyReader.resolve(settingsKeyPrefix + PEMKEY_FILEPATH, settings, configPath, enableSslClientAuth); try { authenticationKey = PemKeyReader.loadKeyFromFile(getSetting(PEMKEY_PASSWORD), path); } catch (Exception e) { - throw new SSLConfigException("Error loading PEM from " + path + " (" + settingsKeyPrefix - + PEMKEY_FILEPATH + ") for " + this.clientName, e); + throw new SSLConfigException( + "Error loading PEM from " + path + " (" + settingsKeyPrefix + PEMKEY_FILEPATH + ") for " + this.clientName, + e + ); } } @@ -292,8 +306,12 @@ private void initFromPem() throws SSLConfigException { effectiveKeyPassword = PemKeyReader.randomChars(12); effectiveKeyAlias = "al"; effectiveTruststore = PemKeyReader.toTruststore(effectiveKeyAlias, trustCertificates); - effectiveKeystore = PemKeyReader.toKeystore(effectiveKeyAlias, effectiveKeyPassword, - authenticationCertificate, authenticationKey); + effectiveKeystore = PemKeyReader.toKeystore( + effectiveKeyAlias, + effectiveKeyPassword, + authenticationCertificate, + authenticationKey + ); } catch (Exception e) { throw new SSLConfigException("Error initializing SSLConfig for " + this.clientName, e); } @@ -306,13 +324,20 @@ private void initFromKeyStore() throws SSLConfigException { try { trustStore = PemKeyReader.loadKeyStore( - PemKeyReader.resolve(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, settings, - configPath, !isTrustAllEnabled()), - SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.getSetting(settings), - settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_TYPE)); + PemKeyReader.resolve( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + settings, + configPath, + !isTrustAllEnabled() + ), + SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.getSetting(settings), + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_TYPE) + ); } catch (Exception e) { - throw new SSLConfigException("Error loading trust store from " - + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH), e); + throw new SSLConfigException( + "Error loading trust store from " + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH), + e + ); } effectiveTruststoreAliases = getSettingAsList(CA_ALIAS, null); @@ -321,20 +346,24 @@ private void initFromKeyStore() throws SSLConfigException { try { keyStore = PemKeyReader.loadKeyStore( - PemKeyReader.resolve(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, settings, - configPath, enableSslClientAuth), - SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, - SSLConfigConstants.DEFAULT_STORE_PASSWORD), - settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE)); + PemKeyReader.resolve( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + settings, + configPath, + enableSslClientAuth + ), + SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, SSLConfigConstants.DEFAULT_STORE_PASSWORD), + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE) + ); } catch (Exception e) { - throw new SSLConfigException("Error loading key store from " - + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH), e); + throw new SSLConfigException( + "Error loading key store from " + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH), + e + ); } - String keyStorePassword = SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, - SSLConfigConstants.DEFAULT_STORE_PASSWORD); - effectiveKeyPassword = keyStorePassword == null || keyStorePassword.isEmpty() ? null - : keyStorePassword.toCharArray(); + String keyStorePassword = SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, SSLConfigConstants.DEFAULT_STORE_PASSWORD); + effectiveKeyPassword = keyStorePassword == null || keyStorePassword.isEmpty() ? null : keyStorePassword.toCharArray(); effectiveKeyAlias = getSetting(CERT_ALIAS); if (enableSslClientAuth && effectiveKeyAlias == null) { @@ -393,10 +422,20 @@ public static class SSLConfig { private final char[] effectiveKeyPassword; private final String effectiveKeyAlias; - public SSLConfig(SSLContext sslContext, String[] supportedProtocols, String[] supportedCipherSuites, - HostnameVerifier hostnameVerifier, boolean hostnameVerificationEnabled, boolean trustAll, - boolean startTlsEnabled, KeyStore effectiveTruststore, List effectiveTruststoreAliases, - KeyStore effectiveKeystore, char[] effectiveKeyPassword, String effectiveKeyAlias) { + public SSLConfig( + SSLContext sslContext, + String[] supportedProtocols, + String[] supportedCipherSuites, + HostnameVerifier hostnameVerifier, + boolean hostnameVerificationEnabled, + boolean trustAll, + boolean startTlsEnabled, + KeyStore effectiveTruststore, + List effectiveTruststoreAliases, + KeyStore effectiveKeystore, + char[] effectiveKeyPassword, + String effectiveKeyAlias + ) { this.sslContext = sslContext; this.supportedProtocols = supportedProtocols; this.supportedCipherSuites = supportedCipherSuites; @@ -432,8 +471,7 @@ public HostnameVerifier getHostnameVerifier() { } public SSLConnectionSocketFactory toSSLConnectionSocketFactory() { - return new SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, - hostnameVerifier); + return new SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifier); } public boolean isStartTlsEnabled() { @@ -490,12 +528,29 @@ public String[] getEffectiveKeyAliasesArray() { @Override public String toString() { - return "SSLConfig [sslContext=" + sslContext + ", supportedProtocols=" + Arrays.toString(supportedProtocols) - + ", supportedCipherSuites=" + Arrays.toString(supportedCipherSuites) + ", hostnameVerifier=" - + hostnameVerifier + ", startTlsEnabled=" + startTlsEnabled + ", hostnameVerificationEnabled=" - + hostnameVerificationEnabled + ", trustAll=" + trustAll + ", effectiveTruststore=" - + effectiveTruststore + ", effectiveTruststoreAliases=" + effectiveTruststoreAliases - + ", effectiveKeystore=" + effectiveKeystore + ", effectiveKeyAlias=" + effectiveKeyAlias + "]"; + return "SSLConfig [sslContext=" + + sslContext + + ", supportedProtocols=" + + Arrays.toString(supportedProtocols) + + ", supportedCipherSuites=" + + Arrays.toString(supportedCipherSuites) + + ", hostnameVerifier=" + + hostnameVerifier + + ", startTlsEnabled=" + + startTlsEnabled + + ", hostnameVerificationEnabled=" + + hostnameVerificationEnabled + + ", trustAll=" + + trustAll + + ", effectiveTruststore=" + + effectiveTruststore + + ", effectiveTruststoreAliases=" + + effectiveTruststoreAliases + + ", effectiveKeystore=" + + effectiveKeystore + + ", effectiveKeyAlias=" + + effectiveKeyAlias + + "]"; } public boolean isTrustAllEnabled() { @@ -511,8 +566,7 @@ public SSLConfigException() { super(); } - public SSLConfigException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { + public SSLConfigException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } @@ -532,23 +586,26 @@ public SSLConfigException(Throwable cause) { private static class OverlyTrustfulSSLContextBuilder extends SSLContextBuilder { @Override - protected void initSSLContext(SSLContext sslContext, Collection keyManagers, - Collection trustManagers, SecureRandom secureRandom) throws KeyManagementException { - sslContext.init(!keyManagers.isEmpty() ? keyManagers.toArray(new KeyManager[keyManagers.size()]) : null, - new TrustManager[] { new OverlyTrustfulTrustManager() }, secureRandom); + protected void initSSLContext( + SSLContext sslContext, + Collection keyManagers, + Collection trustManagers, + SecureRandom secureRandom + ) throws KeyManagementException { + sslContext.init( + !keyManagers.isEmpty() ? keyManagers.toArray(new KeyManager[keyManagers.size()]) : null, + new TrustManager[] { new OverlyTrustfulTrustManager() }, + secureRandom + ); } } private static class OverlyTrustfulTrustManager implements X509TrustManager { @Override - public void checkClientTrusted(final X509Certificate[] chain, final String authType) - throws CertificateException { - } + public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {} @Override - public void checkServerTrusted(final X509Certificate[] chain, final String authType) - throws CertificateException { - } + public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {} @Override public X509Certificate[] getAcceptedIssuers() { diff --git a/src/main/java/com/amazon/dlic/util/SettingsBasedSSLConfiguratorV4.java b/src/main/java/com/amazon/dlic/util/SettingsBasedSSLConfiguratorV4.java index 013d8b70d7..c2de5d95a2 100644 --- a/src/main/java/com/amazon/dlic/util/SettingsBasedSSLConfiguratorV4.java +++ b/src/main/java/com/amazon/dlic/util/SettingsBasedSSLConfiguratorV4.java @@ -96,8 +96,7 @@ public class SettingsBasedSSLConfiguratorV4 { private String effectiveKeyAlias; private List effectiveTruststoreAliases; - public SettingsBasedSSLConfiguratorV4(Settings settings, Path configPath, String settingsKeyPrefix, - String clientName) { + public SettingsBasedSSLConfiguratorV4(Settings settings, Path configPath, String settingsKeyPrefix, String clientName) { this.settings = settings; this.configPath = configPath; this.settingsKeyPrefix = normalizeSettingsKeyPrefix(settingsKeyPrefix); @@ -137,10 +136,20 @@ public SSLConfig buildSSLConfig() throws SSLConfigException { return null; } - return new SSLConfig(sslContext, getSupportedProtocols(), getSupportedCipherSuites(), getHostnameVerifier(), - isHostnameVerificationEnabled(), isTrustAllEnabled(), isStartTlsEnabled(), this.effectiveTruststore, - this.effectiveTruststoreAliases, this.effectiveKeystore, this.effectiveKeyPassword, - this.effectiveKeyAlias); + return new SSLConfig( + sslContext, + getSupportedProtocols(), + getSupportedCipherSuites(), + getHostnameVerifier(), + isHostnameVerificationEnabled(), + isTrustAllEnabled(), + isStartTlsEnabled(), + this.effectiveTruststore, + this.effectiveTruststoreAliases, + this.effectiveKeystore, + this.effectiveKeyPassword, + this.effectiveKeyAlias + ); } private boolean isHostnameVerificationEnabled() { @@ -182,7 +191,7 @@ private void configureWithSettings() throws SSLConfigException, NoSuchAlgorithmE this.enableSslClientAuth = getSettingAsBoolean(ENABLE_SSL_CLIENT_AUTH, false); if (settings.get(settingsKeyPrefix + PEMTRUSTEDCAS_FILEPATH, null) != null - || settings.get(settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT, null) != null) { + || settings.get(settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT, null) != null) { initFromPem(); } else { initFromKeyStore(); @@ -195,22 +204,21 @@ private void configureWithSettings() throws SSLConfigException, NoSuchAlgorithmE if (enableSslClientAuth) { if (effectiveKeystore != null) { try { - sslContextBuilder.loadKeyMaterial(effectiveKeystore, effectiveKeyPassword, - new PrivateKeyStrategy() { - - @Override - public String chooseAlias(Map aliases, Socket socket) { - if (aliases == null || aliases.isEmpty()) { - return effectiveKeyAlias; - } - - if (effectiveKeyAlias == null || effectiveKeyAlias.isEmpty()) { - return aliases.keySet().iterator().next(); - } - - return effectiveKeyAlias; - } - }); + sslContextBuilder.loadKeyMaterial(effectiveKeystore, effectiveKeyPassword, new PrivateKeyStrategy() { + + @Override + public String chooseAlias(Map aliases, Socket socket) { + if (aliases == null || aliases.isEmpty()) { + return effectiveKeyAlias; + } + + if (effectiveKeyAlias == null || effectiveKeyAlias.isEmpty()) { + return aliases.keySet().iterator().next(); + } + + return effectiveKeyAlias; + } + }); } catch (UnrecoverableKeyException e) { throw new RuntimeException(e); } @@ -224,22 +232,25 @@ private void initFromPem() throws SSLConfigException { try { trustCertificates = PemKeyReader.loadCertificatesFromStream( - PemKeyReader.resolveStream(settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT, settings)); + PemKeyReader.resolveStream(settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT, settings) + ); } catch (Exception e) { throw new SSLConfigException( - "Error loading PEM from " + settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT + " for " + this.clientName, - e); + "Error loading PEM from " + settingsKeyPrefix + PEMTRUSTEDCAS_CONTENT + " for " + this.clientName, + e + ); } if (trustCertificates == null) { - String path = PemKeyReader.resolve(settingsKeyPrefix + PEMTRUSTEDCAS_FILEPATH, settings, configPath, - !isTrustAllEnabled()); + String path = PemKeyReader.resolve(settingsKeyPrefix + PEMTRUSTEDCAS_FILEPATH, settings, configPath, !isTrustAllEnabled()); try { trustCertificates = PemKeyReader.loadCertificatesFromFile(path); } catch (Exception e) { - throw new SSLConfigException("Error loading PEM from " + path + " (" + settingsKeyPrefix - + PEMTRUSTEDCAS_FILEPATH + ") for " + this.clientName, e); + throw new SSLConfigException( + "Error loading PEM from " + path + " (" + settingsKeyPrefix + PEMTRUSTEDCAS_FILEPATH + ") for " + this.clientName, + e + ); } } @@ -248,21 +259,22 @@ private void initFromPem() throws SSLConfigException { try { authenticationCertificate = PemKeyReader.loadCertificatesFromStream( - PemKeyReader.resolveStream(settingsKeyPrefix + PEMCERT_CONTENT, settings)); + PemKeyReader.resolveStream(settingsKeyPrefix + PEMCERT_CONTENT, settings) + ); } catch (Exception e) { - throw new SSLConfigException( - "Error loading PEM from " + settingsKeyPrefix + PEMCERT_CONTENT + " for " + this.clientName, e); + throw new SSLConfigException("Error loading PEM from " + settingsKeyPrefix + PEMCERT_CONTENT + " for " + this.clientName, e); } if (authenticationCertificate == null) { - String path = PemKeyReader.resolve(settingsKeyPrefix + PEMCERT_FILEPATH, settings, configPath, - enableSslClientAuth); + String path = PemKeyReader.resolve(settingsKeyPrefix + PEMCERT_FILEPATH, settings, configPath, enableSslClientAuth); try { authenticationCertificate = PemKeyReader.loadCertificatesFromFile(path); } catch (Exception e) { - throw new SSLConfigException("Error loading PEM from " + path + " (" + settingsKeyPrefix - + PEMCERT_FILEPATH + ") for " + this.clientName, e); + throw new SSLConfigException( + "Error loading PEM from " + path + " (" + settingsKeyPrefix + PEMCERT_FILEPATH + ") for " + this.clientName, + e + ); } } @@ -270,22 +282,24 @@ private void initFromPem() throws SSLConfigException { PrivateKey authenticationKey; try { - authenticationKey = PemKeyReader.loadKeyFromStream(getSetting(PEMKEY_PASSWORD), - PemKeyReader.resolveStream(settingsKeyPrefix + PEMKEY_CONTENT, settings)); + authenticationKey = PemKeyReader.loadKeyFromStream( + getSetting(PEMKEY_PASSWORD), + PemKeyReader.resolveStream(settingsKeyPrefix + PEMKEY_CONTENT, settings) + ); } catch (Exception e) { - throw new SSLConfigException( - "Error loading PEM from " + settingsKeyPrefix + PEMKEY_CONTENT + " for " + this.clientName, e); + throw new SSLConfigException("Error loading PEM from " + settingsKeyPrefix + PEMKEY_CONTENT + " for " + this.clientName, e); } if (authenticationKey == null) { - String path = PemKeyReader.resolve(settingsKeyPrefix + PEMKEY_FILEPATH, settings, configPath, - enableSslClientAuth); + String path = PemKeyReader.resolve(settingsKeyPrefix + PEMKEY_FILEPATH, settings, configPath, enableSslClientAuth); try { authenticationKey = PemKeyReader.loadKeyFromFile(getSetting(PEMKEY_PASSWORD), path); } catch (Exception e) { - throw new SSLConfigException("Error loading PEM from " + path + " (" + settingsKeyPrefix - + PEMKEY_FILEPATH + ") for " + this.clientName, e); + throw new SSLConfigException( + "Error loading PEM from " + path + " (" + settingsKeyPrefix + PEMKEY_FILEPATH + ") for " + this.clientName, + e + ); } } @@ -293,8 +307,12 @@ private void initFromPem() throws SSLConfigException { effectiveKeyPassword = PemKeyReader.randomChars(12); effectiveKeyAlias = "al"; effectiveTruststore = PemKeyReader.toTruststore(effectiveKeyAlias, trustCertificates); - effectiveKeystore = PemKeyReader.toKeystore(effectiveKeyAlias, effectiveKeyPassword, - authenticationCertificate, authenticationKey); + effectiveKeystore = PemKeyReader.toKeystore( + effectiveKeyAlias, + effectiveKeyPassword, + authenticationCertificate, + authenticationKey + ); } catch (Exception e) { throw new SSLConfigException("Error initializing SSLConfig for " + this.clientName, e); } @@ -307,13 +325,20 @@ private void initFromKeyStore() throws SSLConfigException { try { trustStore = PemKeyReader.loadKeyStore( - PemKeyReader.resolve(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, settings, - configPath, !isTrustAllEnabled()), - SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.getSetting(settings), - settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_TYPE)); + PemKeyReader.resolve( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + settings, + configPath, + !isTrustAllEnabled() + ), + SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.getSetting(settings), + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_TYPE) + ); } catch (Exception e) { - throw new SSLConfigException("Error loading trust store from " - + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH), e); + throw new SSLConfigException( + "Error loading trust store from " + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH), + e + ); } effectiveTruststoreAliases = getSettingAsList(CA_ALIAS, null); @@ -322,20 +347,24 @@ private void initFromKeyStore() throws SSLConfigException { try { keyStore = PemKeyReader.loadKeyStore( - PemKeyReader.resolve(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, settings, - configPath, enableSslClientAuth), - SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, - SSLConfigConstants.DEFAULT_STORE_PASSWORD), - settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE)); + PemKeyReader.resolve( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + settings, + configPath, + enableSslClientAuth + ), + SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, SSLConfigConstants.DEFAULT_STORE_PASSWORD), + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE) + ); } catch (Exception e) { - throw new SSLConfigException("Error loading key store from " - + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH), e); + throw new SSLConfigException( + "Error loading key store from " + settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH), + e + ); } - String keyStorePassword = SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD - .getSetting(settings, SSLConfigConstants.DEFAULT_STORE_PASSWORD); - effectiveKeyPassword = keyStorePassword == null || keyStorePassword.isEmpty() ? null - : keyStorePassword.toCharArray(); + String keyStorePassword = SECURITY_SSL_TRANSPORT_KEYSTORE_PASSWORD.getSetting(settings, SSLConfigConstants.DEFAULT_STORE_PASSWORD); + effectiveKeyPassword = keyStorePassword == null || keyStorePassword.isEmpty() ? null : keyStorePassword.toCharArray(); effectiveKeyAlias = getSetting(CERT_ALIAS); if (enableSslClientAuth && effectiveKeyAlias == null) { @@ -394,10 +423,20 @@ public static class SSLConfig { private final char[] effectiveKeyPassword; private final String effectiveKeyAlias; - public SSLConfig(SSLContext sslContext, String[] supportedProtocols, String[] supportedCipherSuites, - HostnameVerifier hostnameVerifier, boolean hostnameVerificationEnabled, boolean trustAll, - boolean startTlsEnabled, KeyStore effectiveTruststore, List effectiveTruststoreAliases, - KeyStore effectiveKeystore, char[] effectiveKeyPassword, String effectiveKeyAlias) { + public SSLConfig( + SSLContext sslContext, + String[] supportedProtocols, + String[] supportedCipherSuites, + HostnameVerifier hostnameVerifier, + boolean hostnameVerificationEnabled, + boolean trustAll, + boolean startTlsEnabled, + KeyStore effectiveTruststore, + List effectiveTruststoreAliases, + KeyStore effectiveKeystore, + char[] effectiveKeyPassword, + String effectiveKeyAlias + ) { this.sslContext = sslContext; this.supportedProtocols = supportedProtocols; this.supportedCipherSuites = supportedCipherSuites; @@ -437,8 +476,7 @@ public SSLIOSessionStrategy toSSLIOSessionStrategy() { } public SSLConnectionSocketFactory toSSLConnectionSocketFactory() { - return new SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, - hostnameVerifier); + return new SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifier); } public boolean isStartTlsEnabled() { @@ -495,12 +533,29 @@ public String[] getEffectiveKeyAliasesArray() { @Override public String toString() { - return "SSLConfig [sslContext=" + sslContext + ", supportedProtocols=" + Arrays.toString(supportedProtocols) - + ", supportedCipherSuites=" + Arrays.toString(supportedCipherSuites) + ", hostnameVerifier=" - + hostnameVerifier + ", startTlsEnabled=" + startTlsEnabled + ", hostnameVerificationEnabled=" - + hostnameVerificationEnabled + ", trustAll=" + trustAll + ", effectiveTruststore=" - + effectiveTruststore + ", effectiveTruststoreAliases=" + effectiveTruststoreAliases - + ", effectiveKeystore=" + effectiveKeystore + ", effectiveKeyAlias=" + effectiveKeyAlias + "]"; + return "SSLConfig [sslContext=" + + sslContext + + ", supportedProtocols=" + + Arrays.toString(supportedProtocols) + + ", supportedCipherSuites=" + + Arrays.toString(supportedCipherSuites) + + ", hostnameVerifier=" + + hostnameVerifier + + ", startTlsEnabled=" + + startTlsEnabled + + ", hostnameVerificationEnabled=" + + hostnameVerificationEnabled + + ", trustAll=" + + trustAll + + ", effectiveTruststore=" + + effectiveTruststore + + ", effectiveTruststoreAliases=" + + effectiveTruststoreAliases + + ", effectiveKeystore=" + + effectiveKeystore + + ", effectiveKeyAlias=" + + effectiveKeyAlias + + "]"; } public boolean isTrustAllEnabled() { @@ -516,8 +571,7 @@ public SSLConfigException() { super(); } - public SSLConfigException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { + public SSLConfigException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } @@ -537,23 +591,26 @@ public SSLConfigException(Throwable cause) { private static class OverlyTrustfulSSLContextBuilder extends SSLContextBuilder { @Override - protected void initSSLContext(SSLContext sslContext, Collection keyManagers, - Collection trustManagers, SecureRandom secureRandom) throws KeyManagementException { - sslContext.init(!keyManagers.isEmpty() ? keyManagers.toArray(new KeyManager[keyManagers.size()]) : null, - new TrustManager[] { new OverlyTrustfulTrustManager() }, secureRandom); + protected void initSSLContext( + SSLContext sslContext, + Collection keyManagers, + Collection trustManagers, + SecureRandom secureRandom + ) throws KeyManagementException { + sslContext.init( + !keyManagers.isEmpty() ? keyManagers.toArray(new KeyManager[keyManagers.size()]) : null, + new TrustManager[] { new OverlyTrustfulTrustManager() }, + secureRandom + ); } } private static class OverlyTrustfulTrustManager implements X509TrustManager { @Override - public void checkClientTrusted(final X509Certificate[] chain, final String authType) - throws CertificateException { - } + public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {} @Override - public void checkServerTrusted(final X509Certificate[] chain, final String authType) - throws CertificateException { - } + public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {} @Override public X509Certificate[] getAcceptedIssuers() { diff --git a/src/main/java/org/opensearch/security/DefaultObjectMapper.java b/src/main/java/org/opensearch/security/DefaultObjectMapper.java index 7c3168c68a..774af04bfa 100644 --- a/src/main/java/org/opensearch/security/DefaultObjectMapper.java +++ b/src/main/java/org/opensearch/security/DefaultObjectMapper.java @@ -54,7 +54,7 @@ public class DefaultObjectMapper { public static final ObjectMapper objectMapper = new ObjectMapper(); public final static ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory()); private static final ObjectMapper defaulOmittingObjectMapper = new ObjectMapper(); - + static { objectMapper.setSerializationInclusion(Include.NON_NULL); //objectMapper.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); @@ -116,7 +116,7 @@ public T run() throws Exception { throw (IOException) e.getCause(); } } - + @SuppressWarnings("removal") public static T readValue(String string, Class clazz) throws IOException { @@ -137,7 +137,7 @@ public T run() throws Exception { throw (IOException) e.getCause(); } } - + @SuppressWarnings("removal") public static JsonNode readTree(String string) throws IOException { diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 9bf13957da..85b6798410 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -838,7 +838,7 @@ public Collection createComponents(Client localClient, ClusterService cl securityRestHandler = new SecurityRestFilter(backendRegistry, auditLog, threadPool, principalExtractor, settings, configPath, compatConfig); - + HTTPOnBehalfOfJwtAuthenticator acInstance = new HTTPOnBehalfOfJwtAuthenticator(); final DynamicConfigFactory dcf = new DynamicConfigFactory(cr, settings, configPath, localClient, threadPool, cih); diff --git a/src/main/java/org/opensearch/security/action/configupdate/ConfigUpdateNodeResponse.java b/src/main/java/org/opensearch/security/action/configupdate/ConfigUpdateNodeResponse.java index 29c5b6c9a1..0e6944e9c4 100644 --- a/src/main/java/org/opensearch/security/action/configupdate/ConfigUpdateNodeResponse.java +++ b/src/main/java/org/opensearch/security/action/configupdate/ConfigUpdateNodeResponse.java @@ -37,10 +37,10 @@ import org.opensearch.core.xcontent.XContentBuilder; public class ConfigUpdateNodeResponse extends BaseNodeResponse implements ToXContentObject { - + private String[] updatedConfigTypes; private String message; - + public ConfigUpdateNodeResponse(StreamInput in) throws IOException { super(in); this.updatedConfigTypes = in.readStringArray(); @@ -52,11 +52,11 @@ public ConfigUpdateNodeResponse(final DiscoveryNode node, String[] updatedConfig this.updatedConfigTypes = updatedConfigTypes; this.message = message; } - + public static ConfigUpdateNodeResponse readNodeResponse(StreamInput in) throws IOException { return new ConfigUpdateNodeResponse(in); } - + public String[] getUpdatedConfigTypes() { return updatedConfigTypes==null?null:Arrays.copyOf(updatedConfigTypes, updatedConfigTypes.length); } @@ -64,7 +64,7 @@ public String[] getUpdatedConfigTypes() { public String getMessage() { return message; } - + @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); diff --git a/src/main/java/org/opensearch/security/action/configupdate/TransportConfigUpdateAction.java b/src/main/java/org/opensearch/security/action/configupdate/TransportConfigUpdateAction.java index 42879a8b6c..c5c60cf8a6 100644 --- a/src/main/java/org/opensearch/security/action/configupdate/TransportConfigUpdateAction.java +++ b/src/main/java/org/opensearch/security/action/configupdate/TransportConfigUpdateAction.java @@ -57,12 +57,12 @@ public class TransportConfigUpdateAction private final Provider backendRegistry; private final ConfigurationRepository configurationRepository; private DynamicConfigFactory dynamicConfigFactory; - + @Inject public TransportConfigUpdateAction(final Settings settings, final ThreadPool threadPool, final ClusterService clusterService, final TransportService transportService, final ConfigurationRepository configurationRepository, final ActionFilters actionFilters, - Provider backendRegistry, DynamicConfigFactory dynamicConfigFactory) { + Provider backendRegistry, DynamicConfigFactory dynamicConfigFactory) { super(ConfigUpdateAction.NAME, threadPool, clusterService, transportService, actionFilters, ConfigUpdateRequest::new, TransportConfigUpdateAction.NodeConfigUpdateRequest::new, ThreadPool.Names.MANAGEMENT, ConfigUpdateNodeResponse.class); @@ -96,14 +96,14 @@ public void writeTo(final StreamOutput out) throws IOException { protected ConfigUpdateNodeResponse newNodeResponse(StreamInput in) throws IOException { return new ConfigUpdateNodeResponse(in); } - + @Override protected ConfigUpdateResponse newResponse(ConfigUpdateRequest request, List responses, List failures) { return new ConfigUpdateResponse(this.clusterService.getClusterName(), responses, failures); } - + @Override protected ConfigUpdateNodeResponse nodeOperation(final NodeConfigUpdateRequest request) { configurationRepository.reloadConfiguration(CType.fromStringValues((request.request.getConfigTypes()))); diff --git a/src/main/java/org/opensearch/security/action/whoami/TransportWhoAmIAction.java b/src/main/java/org/opensearch/security/action/whoami/TransportWhoAmIAction.java index 897843ca92..901800f0a2 100644 --- a/src/main/java/org/opensearch/security/action/whoami/TransportWhoAmIAction.java +++ b/src/main/java/org/opensearch/security/action/whoami/TransportWhoAmIAction.java @@ -65,10 +65,10 @@ protected void doExecute(Task task, WhoAmIRequest request, ActionListener { +ActionRequestBuilder { public WhoAmIRequestBuilder(final ClusterAdminClient client) throws IOException { this(client, WhoAmIAction.INSTANCE); } diff --git a/src/main/java/org/opensearch/security/action/whoami/WhoAmIResponse.java b/src/main/java/org/opensearch/security/action/whoami/WhoAmIResponse.java index 876079dced..2b25344f76 100644 --- a/src/main/java/org/opensearch/security/action/whoami/WhoAmIResponse.java +++ b/src/main/java/org/opensearch/security/action/whoami/WhoAmIResponse.java @@ -37,12 +37,12 @@ import org.opensearch.core.xcontent.XContentBuilder; public class WhoAmIResponse extends ActionResponse implements ToXContent { - + private String dn; private boolean isAdmin; private boolean isAuthenticated; private boolean isNodeCertificateRequest; - + public WhoAmIResponse(String dn, boolean isAdmin, boolean isAuthenticated, boolean isNodeCertificateRequest) { this.dn = dn; this.isAdmin = isAdmin; @@ -93,8 +93,8 @@ public boolean isNodeCertificateRequest() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - - builder.startObject("whoami"); + + builder.startObject("whoami"); builder.field("dn", dn); builder.field("is_admin", isAdmin); builder.field("is_authenticated", isAuthenticated); diff --git a/src/main/java/org/opensearch/security/auditlog/AuditLog.java b/src/main/java/org/opensearch/security/auditlog/AuditLog.java index a35bfaa209..128944e387 100644 --- a/src/main/java/org/opensearch/security/auditlog/AuditLog.java +++ b/src/main/java/org/opensearch/security/auditlog/AuditLog.java @@ -74,7 +74,7 @@ public interface AuditLog extends Closeable { // set config void setConfig(AuditConfig auditConfig); - + public enum Origin { REST, TRANSPORT, LOCAL } diff --git a/src/main/java/org/opensearch/security/auditlog/config/AuditConfig.java b/src/main/java/org/opensearch/security/auditlog/config/AuditConfig.java index 5fb11102a8..1152abe89e 100644 --- a/src/main/java/org/opensearch/security/auditlog/config/AuditConfig.java +++ b/src/main/java/org/opensearch/security/auditlog/config/AuditConfig.java @@ -275,7 +275,7 @@ static Set fromSettingStringSet(final Settings settings, FilterEntries f final boolean foundDefault = stringSetOfKey.stream().anyMatch(defaultDetectorValue::equals); if (!foundDefault) { - return stringSetOfKey; + return stringSetOfKey; } // Fallback to the legacy keyname diff --git a/src/main/java/org/opensearch/security/auth/AuthFailureListener.java b/src/main/java/org/opensearch/security/auth/AuthFailureListener.java index 6495c8e2c9..b835078aa3 100644 --- a/src/main/java/org/opensearch/security/auth/AuthFailureListener.java +++ b/src/main/java/org/opensearch/security/auth/AuthFailureListener.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth; diff --git a/src/main/java/org/opensearch/security/auth/AuthenticationBackend.java b/src/main/java/org/opensearch/security/auth/AuthenticationBackend.java index 5762cd371a..0296f56a4a 100644 --- a/src/main/java/org/opensearch/security/auth/AuthenticationBackend.java +++ b/src/main/java/org/opensearch/security/auth/AuthenticationBackend.java @@ -43,13 +43,13 @@ * Instead catch all exceptions and log a appropriate error message. A logger can be instantiated like: *

* {@code private final Logger log = LogManager.getLogger(this.getClass());} - * + * *

*/ public interface AuthenticationBackend { /** - * The type (name) of the authenticator. Only for logging. + * The type (name) of the authenticator. Only for logging. * @return the type */ String getType(); @@ -58,20 +58,20 @@ public interface AuthenticationBackend { * Validate credentials and return an authenticated user (or throw an OpenSearchSecurityException) *

* Results of this method are normally cached so that we not need to query the backend for every authentication attempt. - *

+ *

* @param The credentials to be validated, never null * @return the authenticated User, never null * @throws OpenSearchSecurityException in case an authentication failure * (when credentials are incorrect, the user does not exist or the backend is not reachable) */ User authenticate(AuthCredentials credentials) throws OpenSearchSecurityException; - + /** - * + * * Lookup for a specific user in the authentication backend - * + * * @param user The user for which the authentication backend should be queried. If the authentication backend supports - * user attributes in combination with impersonation the attributes needs to be added to user by calling {@code user.addAttributes()} + * user attributes in combination with impersonation the attributes needs to be added to user by calling {@code user.addAttributes()} * @return true if the user exists in the authentication backend, false otherwise. Before return call {@code user.addAttributes()} as explained above. */ boolean exists(User user); diff --git a/src/main/java/org/opensearch/security/auth/AuthorizationBackend.java b/src/main/java/org/opensearch/security/auth/AuthorizationBackend.java index 83bf131a62..3aea412e69 100644 --- a/src/main/java/org/opensearch/security/auth/AuthorizationBackend.java +++ b/src/main/java/org/opensearch/security/auth/AuthorizationBackend.java @@ -49,7 +49,7 @@ public interface AuthorizationBackend { /** - * The type (name) of the authorizer. Only for logging. + * The type (name) of the authorizer. Only for logging. * @return the type */ String getType(); @@ -61,7 +61,7 @@ public interface AuthorizationBackend { *

* @param user The authenticated user to populate with backend roles, never null * @param credentials Credentials to authenticate to the authorization backend, maybe null. - * This parameter is for future usage, currently always empty credentials are passed! + * This parameter is for future usage, currently always empty credentials are passed! * @throws OpenSearchSecurityException in case when the authorization backend cannot be reached * or the {@code credentials} are insufficient to authenticate to the authorization backend. */ diff --git a/src/main/java/org/opensearch/security/auth/BackendRegistry.java b/src/main/java/org/opensearch/security/auth/BackendRegistry.java index a36aced5e1..9e8154230a 100644 --- a/src/main/java/org/opensearch/security/auth/BackendRegistry.java +++ b/src/main/java/org/opensearch/security/auth/BackendRegistry.java @@ -181,7 +181,7 @@ public boolean authenticate(final RestRequest request, final RestChannel channel if (isDebugEnabled) { log.debug("Rejecting REST request because of blocked address: {}", request.getHttpChannel().getRemoteAddress()); } - + channel.sendResponse(new BytesRestResponse(RestStatus.UNAUTHORIZED, "Authentication finally failed")); return false; @@ -200,14 +200,14 @@ public boolean authenticate(final RestRequest request, final RestChannel channel // ThreadContext injected user return true; } - + if (!isInitialized()) { log.error("Not yet initialized (you may need to run securityadmin)"); channel.sendResponse(new BytesRestResponse(RestStatus.SERVICE_UNAVAILABLE, "OpenSearch Security not initialized.")); return false; } - + final TransportAddress remoteAddress = xffResolver.resolve(request); final boolean isTraceEnabled = log.isTraceEnabled(); if (isTraceEnabled) { @@ -293,7 +293,7 @@ public boolean authenticate(final RestRequest request, final RestChannel channel } } - //http completed + //http completed authenticatedUser = authcz(userCache, restRoleCache, ac, authDomain.getBackend(), restAuthorizers); if(authenticatedUser == null) { @@ -481,7 +481,7 @@ private User authcz(final Cache cache, Cache * A HTTP authenticator extracts {@link AuthCredentials} from a {@link RestRequest} *

- * + * * Implementation classes must provide a public constructor *

* {@code public MyHTTPAuthenticator(org.opensearch.common.settings.Settings settings, java.nio.file.Path configPath)} @@ -51,14 +51,14 @@ public interface HTTPAuthenticator { /** - * The type (name) of the authenticator. Only for logging. + * The type (name) of the authenticator. Only for logging. * @return the type */ String getType(); - + /** * Extract {@link AuthCredentials} from {@link RestRequest} - * + * * @param request The rest request * @param context The current thread context * @return The authentication credentials (complete or incomplete) or null when no credentials are found in the request @@ -68,17 +68,17 @@ public interface HTTPAuthenticator { * @throws OpenSearchSecurityException */ AuthCredentials extractCredentials(RestRequest request, ThreadContext context) throws OpenSearchSecurityException; - + /** * If the {@code extractCredentials()} call was not successful or the authentication flow needs another roundtrip this method * will be called. If the custom HTTP authenticator does not support this method is a no-op and false should be returned. - * + * * If the custom HTTP authenticator does support re-request authentication or supports authentication flows with multiple roundtrips * then the response should be sent (through the channel) and true must be returned. - * + * * @param channel The rest channel to sent back the response via {@code channel.sendResponse()} * @param credentials The credentials from the prior authentication attempt - * @return false if re-request is not supported/necessary, true otherwise. + * @return false if re-request is not supported/necessary, true otherwise. * If true is returned {@code channel.sendResponse()} must be called so that the request completes. */ boolean reRequestAuthentication(final RestChannel channel, AuthCredentials credentials); diff --git a/src/main/java/org/opensearch/security/auth/blocking/ClientBlockRegistry.java b/src/main/java/org/opensearch/security/auth/blocking/ClientBlockRegistry.java index a5eba40353..e74c3ad70a 100644 --- a/src/main/java/org/opensearch/security/auth/blocking/ClientBlockRegistry.java +++ b/src/main/java/org/opensearch/security/auth/blocking/ClientBlockRegistry.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.blocking; diff --git a/src/main/java/org/opensearch/security/auth/blocking/HeapBasedClientBlockRegistry.java b/src/main/java/org/opensearch/security/auth/blocking/HeapBasedClientBlockRegistry.java index 363645cd90..450dda54db 100644 --- a/src/main/java/org/opensearch/security/auth/blocking/HeapBasedClientBlockRegistry.java +++ b/src/main/java/org/opensearch/security/auth/blocking/HeapBasedClientBlockRegistry.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.blocking; diff --git a/src/main/java/org/opensearch/security/auth/limiting/AbstractRateLimiter.java b/src/main/java/org/opensearch/security/auth/limiting/AbstractRateLimiter.java index 3f603437a0..a4d596b61d 100644 --- a/src/main/java/org/opensearch/security/auth/limiting/AbstractRateLimiter.java +++ b/src/main/java/org/opensearch/security/auth/limiting/AbstractRateLimiter.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.limiting; diff --git a/src/main/java/org/opensearch/security/auth/limiting/AddressBasedRateLimiter.java b/src/main/java/org/opensearch/security/auth/limiting/AddressBasedRateLimiter.java index 42f1d1f165..35a6571f8f 100644 --- a/src/main/java/org/opensearch/security/auth/limiting/AddressBasedRateLimiter.java +++ b/src/main/java/org/opensearch/security/auth/limiting/AddressBasedRateLimiter.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.limiting; diff --git a/src/main/java/org/opensearch/security/auth/limiting/UserNameBasedRateLimiter.java b/src/main/java/org/opensearch/security/auth/limiting/UserNameBasedRateLimiter.java index 7fe5ac05d6..3fd0c12246 100644 --- a/src/main/java/org/opensearch/security/auth/limiting/UserNameBasedRateLimiter.java +++ b/src/main/java/org/opensearch/security/auth/limiting/UserNameBasedRateLimiter.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.limiting; diff --git a/src/main/java/org/opensearch/security/configuration/AdminDNs.java b/src/main/java/org/opensearch/security/configuration/AdminDNs.java index ced262d543..72a4485e9f 100644 --- a/src/main/java/org/opensearch/security/configuration/AdminDNs.java +++ b/src/main/java/org/opensearch/security/configuration/AdminDNs.java @@ -62,7 +62,7 @@ public AdminDNs(final Settings settings) { this.injectAdminUserEnabled = settings.getAsBoolean(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_ADMIN_USER_ENABLED, false); final List adminDnsA = settings.getAsList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, Collections.emptyList()); - + for (String dn:adminDnsA) { try { log.debug("{} is registered as an admin dn", dn); @@ -73,13 +73,13 @@ public AdminDNs(final Settings settings) { if (log.isDebugEnabled()) { log.debug("Admin DN not an LDAP name, but admin user injection enabled. Will add {} to admin usernames", dn); } - adminUsernames.add(dn); + adminUsernames.add(dn); } else { - log.error("Unable to parse admin dn {}",dn, e); + log.error("Unable to parse admin dn {}",dn, e); } } } - + log.debug("Loaded {} admin DN's {}",adminDn.size(), adminDn); final Settings impersonationDns = settings.getByPrefix(ConfigConstants.SECURITY_AUTHCZ_IMPERSONATION_DN+"."); @@ -95,7 +95,7 @@ public AdminDNs(final Settings settings) { ); log.debug("Loaded {} impersonation DN's {}", allowedDnsImpersonations.size(), allowedDnsImpersonations); - + final Settings impersonationUsersRest = settings.getByPrefix(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+"."); allowedRestImpersonations = impersonationUsersRest.keySet().stream() @@ -103,9 +103,9 @@ public AdminDNs(final Settings settings) { ImmutableMap.toImmutableMap( Function.identity(), user -> WildcardMatcher.from(settings.getAsList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+"."+user)) - ) - ); - + ) + ); + log.debug("Loaded {} impersonation users for REST {}",allowedRestImpersonations.size(), allowedRestImpersonations); } @@ -129,11 +129,11 @@ public boolean isAdmin(User user) { } return false; } - + public boolean isAdminDN(String dn) { - + if(dn == null) return false; - + try { return isAdminDN(new LdapName(dn)); } catch (InvalidNameException e) { @@ -143,16 +143,16 @@ public boolean isAdminDN(String dn) { private boolean isAdminDN(LdapName dn) { if(dn == null) return false; - + boolean isAdmin = adminDn.contains(dn); - + if (log.isTraceEnabled()) { log.trace("Is principal {} an admin cert? {}", dn.toString(), isAdmin); } - + return isAdmin; } - + public boolean isRestImpersonationAllowed(final String originalUser, final String impersonated) { return (originalUser != null) ? allowedRestImpersonations.getOrDefault(originalUser, WildcardMatcher.NONE).test(impersonated) : false; } diff --git a/src/main/java/org/opensearch/security/configuration/ClusterInfoHolder.java b/src/main/java/org/opensearch/security/configuration/ClusterInfoHolder.java index 61877f2bf2..1c42321986 100644 --- a/src/main/java/org/opensearch/security/configuration/ClusterInfoHolder.java +++ b/src/main/java/org/opensearch/security/configuration/ClusterInfoHolder.java @@ -40,7 +40,7 @@ public class ClusterInfoHolder implements ClusterStateListener { private volatile DiscoveryNodes nodes = null; private volatile Boolean isLocalNodeElectedClusterManager = null; private volatile boolean initialized; - + @Override public void clusterChanged(ClusterChangedEvent event) { if(nodes == null || event.nodesChanged()) { @@ -50,7 +50,7 @@ public void clusterChanged(ClusterChangedEvent event) { } initialized = true; } - + isLocalNodeElectedClusterManager = event.localNodeClusterManager()?Boolean.TRUE:Boolean.FALSE; } @@ -69,7 +69,7 @@ public Boolean hasNode(DiscoveryNode node) { } return null; } - + return nodes.nodeExists(node)?Boolean.TRUE:Boolean.FALSE; } } diff --git a/src/main/java/org/opensearch/security/configuration/CompatConfig.java b/src/main/java/org/opensearch/security/configuration/CompatConfig.java index 6912cb4fbb..48f91b10be 100644 --- a/src/main/java/org/opensearch/security/configuration/CompatConfig.java +++ b/src/main/java/org/opensearch/security/configuration/CompatConfig.java @@ -50,13 +50,13 @@ public CompatConfig(final Environment environment, final OpensearchDynamicSettin this.staticSettings = environment.settings(); this.transportPassiveAuthSetting = transportPassiveAuthSetting; } - + @Subscribe public void onDynamicConfigModelChanged(DynamicConfigModel dcm) { this.dcm = dcm; log.debug("dynamicSecurityConfig updated?: {}", (dcm != null)); } - + //true is default public boolean restAuthEnabled() { final boolean restInitiallyDisabled = staticSettings.getAsBoolean(ConfigConstants.SECURITY_UNSUPPORTED_DISABLE_REST_AUTH_INITIALLY, false); @@ -79,7 +79,7 @@ public boolean restAuthEnabled() { } } - + //true is default public boolean transportInterClusterAuthEnabled() { final boolean interClusterAuthInitiallyDisabled = staticSettings.getAsBoolean(ConfigConstants.SECURITY_UNSUPPORTED_DISABLE_INTERTRANSPORT_AUTH_INITIALLY, false); diff --git a/src/main/java/org/opensearch/security/configuration/ConfigCallback.java b/src/main/java/org/opensearch/security/configuration/ConfigCallback.java index d7d1ed0cee..cb8fc1eedf 100644 --- a/src/main/java/org/opensearch/security/configuration/ConfigCallback.java +++ b/src/main/java/org/opensearch/security/configuration/ConfigCallback.java @@ -30,7 +30,7 @@ import org.opensearch.security.securityconf.impl.SecurityDynamicConfiguration; public interface ConfigCallback { - + void success(SecurityDynamicConfiguration dConf); void noData(String id); void singleFailure(Failure failure); diff --git a/src/main/java/org/opensearch/security/configuration/ConfigUpdateAlreadyInProgressException.java b/src/main/java/org/opensearch/security/configuration/ConfigUpdateAlreadyInProgressException.java index ea7799e014..c628a3156e 100644 --- a/src/main/java/org/opensearch/security/configuration/ConfigUpdateAlreadyInProgressException.java +++ b/src/main/java/org/opensearch/security/configuration/ConfigUpdateAlreadyInProgressException.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.configuration; diff --git a/src/main/java/org/opensearch/security/configuration/DlsFlsRequestValve.java b/src/main/java/org/opensearch/security/configuration/DlsFlsRequestValve.java index 4aa9fadcae..f5751efcae 100644 --- a/src/main/java/org/opensearch/security/configuration/DlsFlsRequestValve.java +++ b/src/main/java/org/opensearch/security/configuration/DlsFlsRequestValve.java @@ -36,7 +36,7 @@ import org.opensearch.threadpool.ThreadPool; public interface DlsFlsRequestValve { - + boolean invoke(String action, ActionRequest request, ActionListener listener, EvaluatedDlsFlsConfig evaluatedDlsFlsConfig, Resolved resolved); void handleSearchContext(SearchContext context, ThreadPool threadPool, NamedXContentRegistry namedXContentRegistry); @@ -61,5 +61,5 @@ public void onQueryPhase(QuerySearchResult queryResult) { } } - + } diff --git a/src/main/java/org/opensearch/security/configuration/DlsFlsValveImpl.java b/src/main/java/org/opensearch/security/configuration/DlsFlsValveImpl.java index 532f820210..947557d342 100644 --- a/src/main/java/org/opensearch/security/configuration/DlsFlsValveImpl.java +++ b/src/main/java/org/opensearch/security/configuration/DlsFlsValveImpl.java @@ -266,7 +266,7 @@ public boolean invoke(String action, ActionRequest request, final ActionListener RestStatus.FORBIDDEN)); return false; } - + if (evaluatedDlsFlsConfig.hasDls()) { if (request instanceof SearchRequest) { @@ -317,7 +317,7 @@ public void handleSearchContext(SearchContext context, ThreadPool threadPool, Na assert context.parsedQuery() != null; final Set unparsedDlsQueries = queries.get(dlsEval); - + if (unparsedDlsQueries != null && !unparsedDlsQueries.isEmpty()) { BooleanQuery.Builder queryBuilder = dlsQueryParser.parse(unparsedDlsQueries, context.getQueryShardContext(), (q) -> new ConstantScoreQuery(q)); @@ -390,7 +390,7 @@ private void setDlsHeaders(EvaluatedDlsFlsConfig dlsFls, ActionRequest request) } else { if (threadContext.getHeader(ConfigConstants.OPENDISTRO_SECURITY_DLS_QUERY_HEADER) != null) { Object deserializedDlsQueries = Base64Helper.deserializeObject(threadContext.getHeader(ConfigConstants.OPENDISTRO_SECURITY_DLS_QUERY_HEADER)); - if (!dlsQueries.equals(deserializedDlsQueries)) { + if (!dlsQueries.equals(deserializedDlsQueries)) { throw new OpenSearchSecurityException(ConfigConstants.OPENDISTRO_SECURITY_DLS_QUERY_HEADER + " does not match (SG 900D)"); } } else { diff --git a/src/main/java/org/opensearch/security/configuration/DlsQueryParser.java b/src/main/java/org/opensearch/security/configuration/DlsQueryParser.java index fd3b3aee98..a5f07541c8 100644 --- a/src/main/java/org/opensearch/security/configuration/DlsQueryParser.java +++ b/src/main/java/org/opensearch/security/configuration/DlsQueryParser.java @@ -99,7 +99,7 @@ public BooleanQuery.Builder parse(Set unparsedDlsQueries, QueryShardCont return dlsQueryBuilder; } - + private static void handleNested(final QueryShardContext queryShardContext, final BooleanQuery.Builder dlsQueryBuilder, final Query parentQuery) { final BitSetProducer parentDocumentsFilter = queryShardContext.bitsetFilter(NON_NESTED_QUERY); @@ -131,7 +131,7 @@ boolean containsTermLookupQuery(Set unparsedQueries) { if (log.isDebugEnabled()) { log.debug("containsTermLookupQuery() returns true due to " + query + "\nqueries: " + unparsedQueries); } - + return true; } } @@ -139,7 +139,7 @@ boolean containsTermLookupQuery(Set unparsedQueries) { if (log.isDebugEnabled()) { log.debug("containsTermLookupQuery() returns false\nqueries: " + unparsedQueries); } - + return false; } @@ -156,5 +156,5 @@ boolean containsTermLookupQuery(String query) { } } - + } diff --git a/src/main/java/org/opensearch/security/configuration/EmptyFilterLeafReader.java b/src/main/java/org/opensearch/security/configuration/EmptyFilterLeafReader.java index 4b603fa804..79069ef53e 100644 --- a/src/main/java/org/opensearch/security/configuration/EmptyFilterLeafReader.java +++ b/src/main/java/org/opensearch/security/configuration/EmptyFilterLeafReader.java @@ -102,7 +102,7 @@ public EmptyDirectoryReader(final DirectoryReader in) throws IOException { protected DirectoryReader doWrapDirectoryReader(final DirectoryReader in) throws IOException { return new EmptyDirectoryReader(in); } - + @Override public CacheHelper getReaderCacheHelper() { return in.getReaderCacheHelper(); diff --git a/src/main/java/org/opensearch/security/configuration/InvalidConfigException.java b/src/main/java/org/opensearch/security/configuration/InvalidConfigException.java index 5e96af6449..ba6a29b08a 100644 --- a/src/main/java/org/opensearch/security/configuration/InvalidConfigException.java +++ b/src/main/java/org/opensearch/security/configuration/InvalidConfigException.java @@ -29,7 +29,7 @@ public class InvalidConfigException extends Exception { /** - * + * */ private static final long serialVersionUID = 1L; diff --git a/src/main/java/org/opensearch/security/configuration/StaticResourceException.java b/src/main/java/org/opensearch/security/configuration/StaticResourceException.java index b4d787aa0f..8574a170bb 100644 --- a/src/main/java/org/opensearch/security/configuration/StaticResourceException.java +++ b/src/main/java/org/opensearch/security/configuration/StaticResourceException.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.configuration; diff --git a/src/main/java/org/opensearch/security/filter/SecurityFilter.java b/src/main/java/org/opensearch/security/filter/SecurityFilter.java index 7bdd5946d5..4dd629c010 100644 --- a/src/main/java/org/opensearch/security/filter/SecurityFilter.java +++ b/src/main/java/org/opensearch/security/filter/SecurityFilter.java @@ -192,7 +192,7 @@ private void ap if (user != null) { org.apache.logging.log4j.ThreadContext.put("user", user.getName()); } - + if (isActionTraceEnabled()) { String count = ""; @@ -232,12 +232,12 @@ private void ap chain.proceed(task, action, request, listener); return; } - - + + if(immutableIndicesMatcher != WildcardMatcher.NONE) { - + boolean isImmutable = false; - + if(request instanceof BulkShardRequest) { for(BulkItemRequest bsr: ((BulkShardRequest) request).items()) { isImmutable = checkImmutableIndices(bsr.request(), listener); @@ -248,7 +248,7 @@ private void ap } else { isImmutable = checkImmutableIndices(request, listener); } - + if(isImmutable) { return; } @@ -301,7 +301,7 @@ private void ap } final PrivilegesEvaluatorResponse pres = eval.evaluate(user, action, request, task, injectedRoles); - + if (log.isDebugEnabled()) { log.debug(pres.toString()); } @@ -384,7 +384,7 @@ private static boolean isUserAdmin(User user, final AdminDNs adminDns) { } private void attachSourceFieldContext(ActionRequest request) { - + if(request instanceof SearchRequest && SourceFieldsContext.isNeeded((SearchRequest) request)) { if(threadContext.getHeader("_opendistro_security_source_field_context") == null) { final String serializedSourceFieldContext = Base64Helper.serializeObject(new SourceFieldsContext((SearchRequest) request)); @@ -397,7 +397,7 @@ private void attachSourceFieldContext(ActionRequest request) { } } } - + @SuppressWarnings("rawtypes") private boolean checkImmutableIndices(Object request, ActionListener listener) { final boolean isModifyIndexRequest = request instanceof DeleteRequest @@ -413,11 +413,11 @@ private boolean checkImmutableIndices(Object request, ActionListener listener) { listener.onFailure(new OpenSearchSecurityException("Index is immutable", RestStatus.FORBIDDEN)); return true; } - + if ((request instanceof IndexRequest) && isRequestIndexImmutable(request)) { ((IndexRequest) request).opType(OpType.CREATE); } - + return false; } diff --git a/src/main/java/org/opensearch/security/filter/SecurityRestFilter.java b/src/main/java/org/opensearch/security/filter/SecurityRestFilter.java index ebd2e8d633..25926dab32 100644 --- a/src/main/java/org/opensearch/security/filter/SecurityRestFilter.java +++ b/src/main/java/org/opensearch/security/filter/SecurityRestFilter.java @@ -117,7 +117,7 @@ public SecurityRestFilter(final BackendRegistry registry, final AuditLog auditLo */ public RestHandler wrap(RestHandler original, AdminDNs adminDNs) { return new RestHandler() { - + @Override public void handleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception { org.apache.logging.log4j.ThreadContext.clearAll(); @@ -143,7 +143,7 @@ private boolean checkAndAuthenticateRequest(RestRequest request, RestChannel cha NodeClient client) throws Exception { threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_ORIGIN, Origin.REST.toString()); - + if(HTTPHelper.containsBadHeader(request)) { final OpenSearchException exception = ExceptionUtils.createBadHeaderException(); log.error(exception.toString()); @@ -151,7 +151,7 @@ private boolean checkAndAuthenticateRequest(RestRequest request, RestChannel cha channel.sendResponse(new BytesRestResponse(channel, RestStatus.FORBIDDEN, exception)); return true; } - + if(SSLRequestHelper.containsBadHeader(threadContext, ConfigConstants.OPENDISTRO_SECURITY_CONFIG_PREFIX)) { final OpenSearchException exception = ExceptionUtils.createBadHeaderException(); log.error(exception.toString()); @@ -166,7 +166,7 @@ private boolean checkAndAuthenticateRequest(RestRequest request, RestChannel cha if(sslInfo.getPrincipal() != null) { threadContext.putTransient("_opendistro_security_ssl_principal", sslInfo.getPrincipal()); } - + if(sslInfo.getX509Certs() != null) { threadContext.putTransient("_opendistro_security_ssl_peer_certificates", sslInfo.getX509Certs()); } @@ -179,7 +179,7 @@ private boolean checkAndAuthenticateRequest(RestRequest request, RestChannel cha channel.sendResponse(new BytesRestResponse(channel, RestStatus.FORBIDDEN, e)); return true; } - + if(!compatConfig.restAuthEnabled()) { return false; } @@ -198,7 +198,7 @@ private boolean checkAndAuthenticateRequest(RestRequest request, RestChannel cha org.apache.logging.log4j.ThreadContext.put("user", ((User)threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER)).getName()); } } - + return false; } diff --git a/src/main/java/org/opensearch/security/http/HTTPBasicAuthenticator.java b/src/main/java/org/opensearch/security/http/HTTPBasicAuthenticator.java index 35278d261f..30e6134381 100644 --- a/src/main/java/org/opensearch/security/http/HTTPBasicAuthenticator.java +++ b/src/main/java/org/opensearch/security/http/HTTPBasicAuthenticator.java @@ -47,20 +47,20 @@ public class HTTPBasicAuthenticator implements HTTPAuthenticator { protected final Logger log = LogManager.getLogger(this.getClass()); public HTTPBasicAuthenticator(final Settings settings, final Path configPath) { - + } @Override public AuthCredentials extractCredentials(final RestRequest request, ThreadContext threadContext) { final boolean forceLogin = request.paramAsBoolean("force_login", false); - + if(forceLogin) { return null; } - + final String authorizationHeader = request.header("Authorization"); - + return HTTPHelper.extractCredentials(authorizationHeader, log); } diff --git a/src/main/java/org/opensearch/security/http/HTTPClientCertAuthenticator.java b/src/main/java/org/opensearch/security/http/HTTPClientCertAuthenticator.java index 51ff6304b1..373919669d 100644 --- a/src/main/java/org/opensearch/security/http/HTTPClientCertAuthenticator.java +++ b/src/main/java/org/opensearch/security/http/HTTPClientCertAuthenticator.java @@ -48,7 +48,7 @@ import org.opensearch.security.user.AuthCredentials; public class HTTPClientCertAuthenticator implements HTTPAuthenticator { - + protected final Logger log = LogManager.getLogger(this.getClass()); protected final Settings settings; @@ -62,29 +62,29 @@ public AuthCredentials extractCredentials(final RestRequest request, final Threa final String principal = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_PRINCIPAL); if (!Strings.isNullOrEmpty(principal)) { - + final String usernameAttribute = settings.get("username_attribute"); final String rolesAttribute = settings.get("roles_attribute"); - + try { final LdapName rfc2253dn = new LdapName(principal); String username = principal.trim(); String[] backendRoles = null; - + if(usernameAttribute != null && usernameAttribute.length() > 0) { final List usernames = getDnAttribute(rfc2253dn, usernameAttribute); if(usernames.isEmpty() == false) { username = usernames.get(0); } } - + if(rolesAttribute != null && rolesAttribute.length() > 0) { final List roles = getDnAttribute(rfc2253dn, rolesAttribute); if(roles.isEmpty() == false) { backendRoles = roles.toArray(new String[0]); } } - + return new AuthCredentials(username, backendRoles).markComplete(); } catch (InvalidNameException e) { log.error("Client cert had no properly formed DN (was: {})", principal); @@ -106,8 +106,8 @@ public boolean reRequestAuthentication(final RestChannel channel, AuthCredential public String getType() { return "clientcert"; } - - private List getDnAttribute(LdapName rfc2253dn, String attribute) { + + private List getDnAttribute(LdapName rfc2253dn, String attribute) { final List attrValues = new ArrayList<>(rfc2253dn.size()); final List reverseRdn = new ArrayList<>(rfc2253dn.getRdns()); Collections.reverse(reverseRdn); @@ -117,7 +117,7 @@ private List getDnAttribute(LdapName rfc2253dn, String attribute) { attrValues.add(rdn.getValue().toString()); } } - + return Collections.unmodifiableList(attrValues); } } diff --git a/src/main/java/org/opensearch/security/http/HTTPProxyAuthenticator.java b/src/main/java/org/opensearch/security/http/HTTPProxyAuthenticator.java index 28fb80e0db..348811b694 100644 --- a/src/main/java/org/opensearch/security/http/HTTPProxyAuthenticator.java +++ b/src/main/java/org/opensearch/security/http/HTTPProxyAuthenticator.java @@ -57,14 +57,14 @@ public HTTPProxyAuthenticator(Settings settings, final Path configPath) { @Override public AuthCredentials extractCredentials(final RestRequest request, ThreadContext context) { - + if(context.getTransient(ConfigConstants.OPENDISTRO_SECURITY_XFF_DONE) != Boolean.TRUE) { throw new OpenSearchSecurityException("xff not done"); } - + final String userHeader = settings.get("user_header"); final String rolesHeader = settings.get("roles_header"); - + if (log.isDebugEnabled()) { log.debug("Headers {}", request.getHeaders()); log.debug("UserHeader {}, value {}", userHeader, userHeader == null ? null : request.header(userHeader)); diff --git a/src/main/java/org/opensearch/security/http/RemoteIpDetector.java b/src/main/java/org/opensearch/security/http/RemoteIpDetector.java index 404fd2dcc2..5d9e933c8f 100644 --- a/src/main/java/org/opensearch/security/http/RemoteIpDetector.java +++ b/src/main/java/org/opensearch/security/http/RemoteIpDetector.java @@ -120,23 +120,23 @@ String detect(RestRequest request, ThreadContext threadContext){ if (isTraceEnabled) { log.trace("originalRemoteAddr {}", originalRemoteAddr); } - + //X-Forwarded-For: client1, proxy1, proxy2 // ^^^^^^ originalRemoteAddr - + //originalRemoteAddr need to be in the list of internalProxies if (internalProxies !=null && internalProxies.matcher(originalRemoteAddr).matches()) { String remoteIp = null; final StringBuilder concatRemoteIpHeaderValue = new StringBuilder(); - + //client1, proxy1, proxy2 final List remoteIpHeaders = request.getHeaders().get(remoteIpHeader); //X-Forwarded-For if(remoteIpHeaders == null || remoteIpHeaders.isEmpty()) { return originalRemoteAddr; } - + for (String rh:remoteIpHeaders) { if (concatRemoteIpHeaderValue.length() > 0) { concatRemoteIpHeaderValue.append(", "); @@ -144,7 +144,7 @@ String detect(RestRequest request, ThreadContext threadContext){ concatRemoteIpHeaderValue.append(rh); } - + if (isTraceEnabled) { log.trace("concatRemoteIpHeaderValue {}", concatRemoteIpHeaderValue.toString()); } @@ -162,14 +162,14 @@ String detect(RestRequest request, ThreadContext threadContext){ break; } } - + // continue to loop on remoteIpHeaderValue to build the new value of the remoteIpHeader final LinkedList newRemoteIpHeaderValue = new LinkedList<>(); for (; idx >= 0; idx--) { String currentRemoteIp = remoteIpHeaderValue[idx]; newRemoteIpHeaderValue.addFirst(currentRemoteIp); } - + if (remoteIp != null) { if (isTraceEnabled) { final String originalRemoteHost = ((InetSocketAddress)request.getHttpChannel().getRemoteAddress()).getAddress().getHostName(); @@ -178,17 +178,17 @@ String detect(RestRequest request, ThreadContext threadContext){ threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_XFF_DONE, Boolean.TRUE); return remoteIp; - + } else { log.warn("Remote ip could not be detected, this should normally not happen"); } - + } else { if (isTraceEnabled) { log.trace("Skip RemoteIpDetector for request {} with originalRemoteAddr '{}' cause no internal proxy matches", request.uri(), request.getHttpChannel().getRemoteAddress()); } } - + return originalRemoteAddr; } diff --git a/src/main/java/org/opensearch/security/http/SecurityHttpServerTransport.java b/src/main/java/org/opensearch/security/http/SecurityHttpServerTransport.java index 3d977dcc7e..6f2f57053f 100644 --- a/src/main/java/org/opensearch/security/http/SecurityHttpServerTransport.java +++ b/src/main/java/org/opensearch/security/http/SecurityHttpServerTransport.java @@ -39,7 +39,7 @@ import org.opensearch.transport.SharedGroupFactory; public class SecurityHttpServerTransport extends SecuritySSLNettyHttpServerTransport { - + public SecurityHttpServerTransport(final Settings settings, final NetworkService networkService, final BigArrays bigArrays, final ThreadPool threadPool, final SecurityKeyStore odsks, final SslExceptionHandler sslExceptionHandler, final NamedXContentRegistry namedXContentRegistry, final ValidatingDispatcher dispatcher, final ClusterSettings clusterSettings, SharedGroupFactory sharedGroupFactory) { diff --git a/src/main/java/org/opensearch/security/http/SecurityNonSslHttpServerTransport.java b/src/main/java/org/opensearch/security/http/SecurityNonSslHttpServerTransport.java index b05153db4c..3c1dedc55e 100644 --- a/src/main/java/org/opensearch/security/http/SecurityNonSslHttpServerTransport.java +++ b/src/main/java/org/opensearch/security/http/SecurityNonSslHttpServerTransport.java @@ -54,7 +54,7 @@ public ChannelHandler configureServerChannelHandler() { } protected class NonSslHttpChannelHandler extends Netty4HttpServerTransport.HttpChannelHandler { - + protected NonSslHttpChannelHandler(Netty4HttpServerTransport transport, final HttpHandlingSettings handlingSettings) { super(transport, handlingSettings); } diff --git a/src/main/java/org/opensearch/security/http/XFFResolver.java b/src/main/java/org/opensearch/security/http/XFFResolver.java index 23de8e3676..c44e98537d 100644 --- a/src/main/java/org/opensearch/security/http/XFFResolver.java +++ b/src/main/java/org/opensearch/security/http/XFFResolver.java @@ -47,7 +47,7 @@ public class XFFResolver { private volatile boolean enabled; private volatile RemoteIpDetector detector; private final ThreadContext threadContext; - + public XFFResolver(final ThreadPool threadPool) { super(); this.threadContext = threadPool.getThreadContext(); @@ -58,16 +58,16 @@ public TransportAddress resolve(final RestRequest request) throws OpenSearchSecu if (isTraceEnabled) { log.trace("resolve {}", request.getHttpChannel().getRemoteAddress()); } - + if(enabled && request.getHttpChannel().getRemoteAddress() instanceof InetSocketAddress && request.getHttpChannel() instanceof Netty4HttpChannel) { final InetSocketAddress isa = new InetSocketAddress(detector.detect(request, threadContext), ((InetSocketAddress)request.getHttpChannel().getRemoteAddress()).getPort()); - - if(isa.isUnresolved()) { + + if(isa.isUnresolved()) { throw new OpenSearchSecurityException("Cannot resolve address "+isa.getHostString()); } - - + + if (isTraceEnabled) { if(threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_XFF_DONE) == Boolean.TRUE) { log.trace("xff resolved {} to {}", request.getHttpChannel().getRemoteAddress(), isa); @@ -77,7 +77,7 @@ public TransportAddress resolve(final RestRequest request) throws OpenSearchSecu } return new TransportAddress(isa); } else if(request.getHttpChannel().getRemoteAddress() instanceof InetSocketAddress){ - + if (isTraceEnabled) { log.trace("no xff done (enabled or no netty request) {},{},{},{}",enabled, request.getClass()); diff --git a/src/main/java/org/opensearch/security/http/proxy/HTTPExtendedProxyAuthenticator.java b/src/main/java/org/opensearch/security/http/proxy/HTTPExtendedProxyAuthenticator.java index d792158fea..e98f26d85a 100644 --- a/src/main/java/org/opensearch/security/http/proxy/HTTPExtendedProxyAuthenticator.java +++ b/src/main/java/org/opensearch/security/http/proxy/HTTPExtendedProxyAuthenticator.java @@ -60,7 +60,7 @@ public AuthCredentials extractCredentials(final RestRequest request, ThreadConte if(credentials == null) { return null; } - + String attrHeaderPrefix = settings.get("attr_header_prefix"); if(Strings.isNullOrEmpty(attrHeaderPrefix)) { log.debug("attr_header_prefix is null. Skipping additional attribute extraction"); @@ -68,7 +68,7 @@ public AuthCredentials extractCredentials(final RestRequest request, ThreadConte } else if(log.isDebugEnabled()) { log.debug("attrHeaderPrefix {}", attrHeaderPrefix); } - + credentials.addAttribute(ATTR_PROXY_USERNAME, credentials.getUsername()); attrHeaderPrefix = attrHeaderPrefix.toLowerCase(); for (Entry> entry : request.getHeaders().entrySet()) { diff --git a/src/main/java/org/opensearch/security/httpclient/HttpClient.java b/src/main/java/org/opensearch/security/httpclient/HttpClient.java index d032ca3544..ad507ea47c 100644 --- a/src/main/java/org/opensearch/security/httpclient/HttpClient.java +++ b/src/main/java/org/opensearch/security/httpclient/HttpClient.java @@ -195,7 +195,7 @@ public boolean index(final String content, final String index, final String type try { final IndexRequest ir = new IndexRequest(index); - + final IndexResponse response = rclient.index(ir .setRefreshPolicy(refresh?RefreshPolicy.IMMEDIATE:RefreshPolicy.NONE) .source(content, XContentType.JSON), RequestOptions.DEFAULT); diff --git a/src/main/java/org/opensearch/security/privileges/DocumentAllowList.java b/src/main/java/org/opensearch/security/privileges/DocumentAllowList.java index 8bfbb7c0db..129233a007 100644 --- a/src/main/java/org/opensearch/security/privileges/DocumentAllowList.java +++ b/src/main/java/org/opensearch/security/privileges/DocumentAllowList.java @@ -193,7 +193,7 @@ public static class Entry { if (index.indexOf('/') != -1 || index.indexOf('|') != -1) { throw new IllegalArgumentException("Invalid index name: " + index); } - + this.index = index; this.id = id; } diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index 36d53b2a9e..278dc86b7c 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -134,7 +134,7 @@ public class PrivilegesEvaluator { private final boolean dfmEmptyOverwritesAll; private DynamicConfigModel dcm; private final NamedXContentRegistry namedXContentRegistry; - + public PrivilegesEvaluator(final ClusterService clusterService, final ThreadPool threadPool, final ConfigurationRepository configurationRepository, final IndexNameExpressionResolver resolver, AuditLog auditLog, final Settings settings, final PrivilegesInterceptor privilegesInterceptor, final ClusterInfoHolder clusterInfoHolder, @@ -309,7 +309,7 @@ public PrivilegesEvaluatorResponse evaluate(final User user, String action0, fin } presponse.evaluatedDlsFlsConfig = getSecurityRoles(mappedRoles).getDlsFls(user, dfmEmptyOverwritesAll, resolver, clusterService, namedXContentRegistry); - + if (isClusterPerm(action0)) { if(!securityRoles.impliesClusterPermissionPermission(action0)) { @@ -384,7 +384,7 @@ public PrivilegesEvaluatorResponse evaluate(final User user, String action0, fin presponse.allowed = true; return presponse; } - + // term aggregations if (termsAggregationEvaluator.evaluate(requestedResolved, request, clusterService, user, securityRoles, resolver, presponse) .isComplete()) { return presponse; @@ -728,7 +728,7 @@ private boolean checkDocAllowListHeader(User user, String action, ActionRequest if (log.isDebugEnabled()) { log.debug("Request " + request + " is allowed by " + documentAllowList); } - + return true; } else { return false; @@ -739,7 +739,7 @@ private boolean checkDocAllowListHeader(User user, String action, ActionRequest return false; } } - + private List toString(List aliases) { if(aliases == null || aliases.size() == 0) { return Collections.emptyList(); diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluatorResponse.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluatorResponse.java index 8b3e51f045..31ce7095d2 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluatorResponse.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluatorResponse.java @@ -42,11 +42,11 @@ public class PrivilegesEvaluatorResponse { PrivilegesEvaluatorResponseState state = PrivilegesEvaluatorResponseState.PENDING; Resolved resolved; CreateIndexRequestBuilder createIndexRequestBuilder; - + public Resolved getResolved() { return resolved; } - + public boolean isAllowed() { return allowed; } @@ -61,11 +61,11 @@ public Set getMissingPrivileges() { public EvaluatedDlsFlsConfig getEvaluatedDlsFlsConfig() { return evaluatedDlsFlsConfig; } - + public CreateIndexRequestBuilder getCreateIndexRequestBuilder() { return createIndexRequestBuilder; } - + public PrivilegesEvaluatorResponse markComplete() { this.state = PrivilegesEvaluatorResponseState.COMPLETE; return this; @@ -89,10 +89,10 @@ public String toString() { return "PrivEvalResponse [allowed=" + allowed + ", missingPrivileges=" + missingPrivileges + ", evaluatedDlsFlsConfig=" + evaluatedDlsFlsConfig + "]"; } - + public static enum PrivilegesEvaluatorResponseState { PENDING, COMPLETE; } - + } diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesInterceptor.java b/src/main/java/org/opensearch/security/privileges/PrivilegesInterceptor.java index c76910474f..dd569b05fb 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesInterceptor.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesInterceptor.java @@ -65,7 +65,7 @@ protected static ReplaceResult newAccessGrantedReplaceResult(CreateIndexRequestB protected final Client client; protected final ThreadPool threadPool; - public PrivilegesInterceptor(final IndexNameExpressionResolver resolver, final ClusterService clusterService, + public PrivilegesInterceptor(final IndexNameExpressionResolver resolver, final ClusterService clusterService, final Client client, ThreadPool threadPool) { this.resolver = resolver; this.clusterService = clusterService; @@ -77,7 +77,7 @@ public ReplaceResult replaceDashboardsIndex(final ActionRequest request, final S final Resolved requestedResolved, final Map tenants) { throw new RuntimeException("not implemented"); } - + protected final ThreadContext getThreadContext() { return threadPool.getThreadContext(); } diff --git a/src/main/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluator.java b/src/main/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluator.java index 60456a4eb3..a74ea17ccd 100644 --- a/src/main/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluator.java @@ -47,9 +47,9 @@ import org.opensearch.tasks.Task; public class SecurityIndexAccessEvaluator { - + Logger log = LogManager.getLogger(this.getClass()); - + private final String securityIndex; private final AuditLog auditLog; private final WildcardMatcher securityDeniedActionMatcher; @@ -86,7 +86,7 @@ public SecurityIndexAccessEvaluator(final Settings settings, AuditLog auditLog, securityDeniedActionMatcher = WildcardMatcher.from(restoreSecurityIndexEnabled ? securityIndexDeniedActionPatternsList : securityIndexDeniedActionPatternsListNoSnapshot); } - + public PrivilegesEvaluatorResponse evaluate(final ActionRequest request, final Task task, final String action, final Resolved requestedResolved, final PrivilegesEvaluatorResponse presponse) { final boolean isDebugEnabled = log.isDebugEnabled(); diff --git a/src/main/java/org/opensearch/security/privileges/SnapshotRestoreEvaluator.java b/src/main/java/org/opensearch/security/privileges/SnapshotRestoreEvaluator.java index c457b42624..c536ae2d2e 100644 --- a/src/main/java/org/opensearch/security/privileges/SnapshotRestoreEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/SnapshotRestoreEvaluator.java @@ -47,7 +47,7 @@ public class SnapshotRestoreEvaluator { private final String securityIndex; private final AuditLog auditLog; private final boolean restoreSecurityIndexEnabled; - + public SnapshotRestoreEvaluator(final Settings settings, AuditLog auditLog) { this.enableSnapshotRestorePrivilege = settings.getAsBoolean(ConfigConstants.SECURITY_ENABLE_SNAPSHOT_RESTORE_PRIVILEGE, ConfigConstants.SECURITY_DEFAULT_ENABLE_SNAPSHOT_RESTORE_PRIVILEGE); @@ -63,27 +63,27 @@ public PrivilegesEvaluatorResponse evaluate(final ActionRequest request, final T if (!(request instanceof RestoreSnapshotRequest)) { return presponse; } - + // snapshot restore for regular users not enabled if (!enableSnapshotRestorePrivilege) { log.warn("{} is not allowed for a regular user", action); presponse.allowed = false; - return presponse.markComplete(); + return presponse.markComplete(); } // if this feature is enabled, users can also snapshot and restore // the Security index and the global state if (restoreSecurityIndexEnabled) { presponse.allowed = true; - return presponse; + return presponse; } - + if (clusterInfoHolder.isLocalNodeElectedClusterManager() == Boolean.FALSE) { presponse.allowed = true; - return presponse.markComplete(); + return presponse.markComplete(); } - + final RestoreSnapshotRequest restoreRequest = (RestoreSnapshotRequest) request; // Do not allow restore of global state @@ -91,7 +91,7 @@ public PrivilegesEvaluatorResponse evaluate(final ActionRequest request, final T auditLog.logSecurityIndexAttempt(request, action, task); log.warn("{} with 'include_global_state' enabled is not allowed", action); presponse.allowed = false; - return presponse.markComplete(); + return presponse.markComplete(); } final List rs = SnapshotRestoreHelper.resolveOriginalIndices(restoreRequest); @@ -100,7 +100,7 @@ public PrivilegesEvaluatorResponse evaluate(final ActionRequest request, final T auditLog.logSecurityIndexAttempt(request, action, task); log.warn("{} for '{}' as source index is not allowed", action, securityIndex); presponse.allowed = false; - return presponse.markComplete(); + return presponse.markComplete(); } return presponse; } diff --git a/src/main/java/org/opensearch/security/privileges/TermsAggregationEvaluator.java b/src/main/java/org/opensearch/security/privileges/TermsAggregationEvaluator.java index 1d1d048350..53709458fd 100644 --- a/src/main/java/org/opensearch/security/privileges/TermsAggregationEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/TermsAggregationEvaluator.java @@ -56,12 +56,12 @@ public class TermsAggregationEvaluator { "indices:data/read/field_caps*" //"indices:admin/mappings/fields/get*" }; - + private static final QueryBuilder NONE_QUERY = new MatchNoneQueryBuilder(); - + public TermsAggregationEvaluator() { } - + public PrivilegesEvaluatorResponse evaluate(final Resolved resolved, final ActionRequest request, ClusterService clusterService, User user, SecurityRoles securityRoles, IndexNameExpressionResolver resolver, PrivilegesEvaluatorResponse presponse) { try { if(request instanceof SearchRequest) { @@ -81,14 +81,14 @@ public PrivilegesEvaluatorResponse evaluate(final Resolved resolved, final Actio && ab.getPipelineAggregations().isEmpty() && ab.getSubAggregations().isEmpty()) { - + final Set allPermittedIndices = securityRoles.getAllPermittedIndicesForDashboards(resolved, user, READ_ACTIONS, resolver, clusterService); if(allPermittedIndices == null || allPermittedIndices.isEmpty()) { sr.source().query(NONE_QUERY); } else { sr.source().query(new TermsQueryBuilder("_index", allPermittedIndices)); - } - + } + presponse.allowed = true; return presponse.markComplete(); } @@ -99,7 +99,7 @@ public PrivilegesEvaluatorResponse evaluate(final Resolved resolved, final Actio log.warn("Unable to evaluate terms aggregation",e); return presponse; } - + return presponse; } } diff --git a/src/main/java/org/opensearch/security/resolver/IndexResolverReplacer.java b/src/main/java/org/opensearch/security/resolver/IndexResolverReplacer.java index d2d0685860..5892a91a30 100644 --- a/src/main/java/org/opensearch/security/resolver/IndexResolverReplacer.java +++ b/src/main/java/org/opensearch/security/resolver/IndexResolverReplacer.java @@ -369,7 +369,7 @@ public final static class Resolved { private final Set remoteIndices; private final boolean isLocalAll; private final IndicesOptions indicesOptions; - + public Resolved(final ImmutableSet aliases, final ImmutableSet allIndices, final ImmutableSet originalRequested, @@ -394,15 +394,15 @@ public Set getAliases() { public Set getAllIndices() { return allIndices; } - + public Set getAllIndicesResolved(ClusterService clusterService, IndexNameExpressionResolver resolver) { - if (isLocalAll) { + if (isLocalAll) { return new HashSet<>(Arrays.asList(resolver.concreteIndexNames(clusterService.state(), indicesOptions, "*"))); - } else { + } else { return allIndices; } } - + public boolean isAllIndicesEmpty() { return allIndices.isEmpty(); } @@ -711,7 +711,7 @@ private boolean getOrReplaceAllIndices(final Object request, final IndicesProvid } private IndicesOptions indicesOptionsFrom(Object localRequest) { - + if(!respectRequestIndicesOptions) { return IndicesOptions.fromOptions(false, true, true, false, true); } diff --git a/src/main/java/org/opensearch/security/rest/DashboardsInfoAction.java b/src/main/java/org/opensearch/security/rest/DashboardsInfoAction.java index 0fd88e7565..a7620f6bdc 100644 --- a/src/main/java/org/opensearch/security/rest/DashboardsInfoAction.java +++ b/src/main/java/org/opensearch/security/rest/DashboardsInfoAction.java @@ -92,9 +92,9 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli public void accept(RestChannel channel) throws Exception { XContentBuilder builder = channel.newBuilder(); //NOSONAR BytesRestResponse response = null; - + try { - + final User user = (User)threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); builder.startObject(); @@ -131,6 +131,6 @@ public void accept(RestChannel channel) throws Exception { public String getName() { return "Kibana Info Action"; } - - + + } diff --git a/src/main/java/org/opensearch/security/rest/SecurityHealthAction.java b/src/main/java/org/opensearch/security/rest/SecurityHealthAction.java index b88d2700c9..17d5ee122f 100644 --- a/src/main/java/org/opensearch/security/rest/SecurityHealthAction.java +++ b/src/main/java/org/opensearch/security/rest/SecurityHealthAction.java @@ -67,7 +67,7 @@ public List routes() { @Override protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { return new RestChannelConsumer() { - + final String mode = request.param("mode","strict"); @Override @@ -76,8 +76,8 @@ public void accept(RestChannel channel) throws Exception { RestStatus restStatus = RestStatus.OK; BytesRestResponse response = null; try { - - + + String status = "UP"; String message = null; @@ -98,12 +98,12 @@ public void accept(RestChannel channel) throws Exception { } finally { builder.close(); } - - + + channel.sendResponse(response); } - - + + }; } diff --git a/src/main/java/org/opensearch/security/rest/SecurityInfoAction.java b/src/main/java/org/opensearch/security/rest/SecurityInfoAction.java index f8e03da5d2..7867e8790d 100644 --- a/src/main/java/org/opensearch/security/rest/SecurityInfoAction.java +++ b/src/main/java/org/opensearch/security/rest/SecurityInfoAction.java @@ -88,12 +88,12 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli public void accept(RestChannel channel) throws Exception { XContentBuilder builder = channel.newBuilder(); //NOSONAR BytesRestResponse response = null; - + try { - + final boolean verbose = request.paramAsBoolean("verbose", false); - + final X509Certificate[] certs = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_PEER_CERTIFICATES); final User user = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); final TransportAddress remoteAddress = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS); @@ -112,7 +112,7 @@ public void accept(RestChannel channel) throws Exception { builder.field("principal", (String)threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_PRINCIPAL)); builder.field("peer_certificates", certs != null && certs.length > 0 ? certs.length + "" : "0"); builder.field("sso_logout_url", (String)threadContext.getTransient(ConfigConstants.SSO_LOGOUT_URL)); - + if(user != null && verbose) { try { builder.field("size_of_user", RamUsageEstimator.humanReadableUnits(Base64Helper.serializeObject(user).length())); @@ -122,8 +122,8 @@ public void accept(RestChannel channel) throws Exception { //ignore } } - - + + builder.endObject(); response = new BytesRestResponse(RestStatus.OK, builder); @@ -144,7 +144,7 @@ public void accept(RestChannel channel) throws Exception { } }; } - + @Override public String getName() { return "OpenSearch Security Info Action"; diff --git a/src/main/java/org/opensearch/security/rest/TenantInfoAction.java b/src/main/java/org/opensearch/security/rest/TenantInfoAction.java index 266d2edf49..f7b2a606c6 100644 --- a/src/main/java/org/opensearch/security/rest/TenantInfoAction.java +++ b/src/main/java/org/opensearch/security/rest/TenantInfoAction.java @@ -78,7 +78,7 @@ public class TenantInfoAction extends BaseRestHandler { private final AdminDNs adminDns; private final ConfigurationRepository configurationRepository; - public TenantInfoAction(final Settings settings, final RestController controller, + public TenantInfoAction(final Settings settings, final RestController controller, final PrivilegesEvaluator evaluator, final ThreadPool threadPool, final ClusterService clusterService, final AdminDNs adminDns, final ConfigurationRepository configurationRepository) { super(); @@ -102,18 +102,18 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli public void accept(RestChannel channel) throws Exception { XContentBuilder builder = channel.newBuilder(); //NOSONAR BytesRestResponse response = null; - + try { final User user = (User)threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_USER); - + //only allowed for admins or the kibanaserveruser if(!isAuthorized()) { response = new BytesRestResponse(RestStatus.FORBIDDEN,""); } else { builder.startObject(); - + final SortedMap lookup = clusterService.state().metadata().getIndicesLookup(); for(final String indexOrAlias: lookup.keySet()) { final String tenant = tenantNameForIndex(indexOrAlias); @@ -123,7 +123,7 @@ public void accept(RestChannel channel) throws Exception { } builder.endObject(); - + response = new BytesRestResponse(RestStatus.OK, builder); } } catch (final Exception e1) { @@ -179,21 +179,21 @@ private final SecurityDynamicConfiguration load(final CType config, boolean l private String tenantNameForIndex(String index) { String[] indexParts; - if(index == null + if(index == null || (indexParts = index.split("_")).length != 3 ) { return null; } - - + + if(!indexParts[0].equals(evaluator.dashboardsIndex())) { return null; } - + try { final int expectedHash = Integer.parseInt(indexParts[1]); final String sanitizedName = indexParts[2]; - + for(String tenant: evaluator.getAllConfiguredTenantNames()) { if(tenant.hashCode() == expectedHash && sanitizedName.equals(tenant.toLowerCase().replaceAll("[^a-z0-9]+",""))) { return tenant; @@ -211,6 +211,6 @@ private String tenantNameForIndex(String index) { public String getName() { return "Tenant Info Action"; } - - + + } diff --git a/src/main/java/org/opensearch/security/securityconf/ConfigModelV6.java b/src/main/java/org/opensearch/security/securityconf/ConfigModelV6.java index 987b8fac64..7a978034f1 100644 --- a/src/main/java/org/opensearch/security/securityconf/ConfigModelV6.java +++ b/src/main/java/org/opensearch/security/securityconf/ConfigModelV6.java @@ -83,9 +83,9 @@ public ConfigModelV6( SecurityDynamicConfiguration rolesmapping, DynamicConfigModel dcm, Settings opensearchSettings) { - + this.roles = roles; - + try { rolesMappingResolution = ConfigConstants.RolesMappingResolution.valueOf( opensearchSettings.get(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, ConfigConstants.RolesMappingResolution.MAPPING_ONLY.toString()) @@ -94,13 +94,13 @@ public ConfigModelV6( log.error("Cannot apply roles mapping resolution", e); rolesMappingResolution = ConfigConstants.RolesMappingResolution.MAPPING_ONLY; } - + agr = reloadActionGroups(actiongroups); securityRoles = reload(roles); tenantHolder = new TenantHolder(roles); roleMappingHolder = new RoleMappingHolder(rolesmapping, dcm.getHostsResolverMode()); } - + public Set getAllConfiguredTenantNames() { final Set configuredTenants = new HashSet<>(); for (Entry securityRole : roles.getCEntries().entrySet()) { @@ -114,18 +114,18 @@ public Set getAllConfiguredTenantNames() { return Collections.unmodifiableSet(configuredTenants); } - + public SecurityRoles getSecurityRoles() { return securityRoles; } - + private static interface ActionGroupResolver { Set resolvedActions(final List actions); } - + private ActionGroupResolver reloadActionGroups(SecurityDynamicConfiguration actionGroups) { return new ActionGroupResolver() { - + private Set getGroupMembers(final String groupname) { if (actionGroups == null) { @@ -134,27 +134,27 @@ private Set getGroupMembers(final String groupname) { return Collections.unmodifiableSet(resolve(actionGroups, groupname)); } - + private Set resolve(final SecurityDynamicConfiguration actionGroups, final String entry) { - + // SG5 format, plain array //List en = actionGroups.getAsList(DotPath.of(entry)); //if (en.isEmpty()) { // try SG6 format including readonly and permissions key // en = actionGroups.getAsList(DotPath.of(entry + "." + ConfigConstants.CONFIGKEY_ACTION_GROUPS_PERMISSIONS)); //} - + if(!actionGroups.getCEntries().containsKey(entry)) { return Collections.emptySet(); } - + final Set ret = new HashSet(); - + final Object actionGroupAsObject = actionGroups.getCEntries().get(entry); - + if(actionGroupAsObject != null && actionGroupAsObject instanceof List) { - + for (final String perm: ((List) actionGroupAsObject)) { if (actionGroups.getCEntries().keySet().contains(perm)) { ret.addAll(resolve(actionGroups,perm)); @@ -162,8 +162,8 @@ private Set resolve(final SecurityDynamicConfiguration actionGroups, ret.add(perm); } } - - + + } else if(actionGroupAsObject != null && actionGroupAsObject instanceof ActionGroupsV6) { for (final String perm: ((ActionGroupsV6) actionGroupAsObject).getPermissions()) { if (actionGroups.getCEntries().keySet().contains(perm)) { @@ -175,10 +175,10 @@ private Set resolve(final SecurityDynamicConfiguration actionGroups, } else { throw new RuntimeException("Unable to handle "+actionGroupAsObject); } - + return Collections.unmodifiableSet(ret); } - + @Override public Set resolvedActions(final List actions) { final Set resolvedActions = new HashSet(); @@ -208,7 +208,7 @@ private SecurityRoles reload(SecurityDynamicConfiguration settings) { @Override public SecurityRole call() throws Exception { SecurityRole _securityRole = new SecurityRole(securityRole.getKey()); - + if(securityRole.getValue() == null) { return null; } @@ -261,8 +261,8 @@ public SecurityRole call() throws Exception { _securityRole.addIndexPattern(_indexPattern); } - - + + return _securityRole; } }); @@ -352,7 +352,7 @@ public Set getRoles() { public Set getRoleNames() { return getRoles().stream().map(r -> r.getName()).collect(Collectors.toSet()); } - + public SecurityRoles filter(Set keep) { final SecurityRoles retVal = new SecurityRoles(roles.size()); for (SecurityRole sr : roles) { @@ -371,7 +371,7 @@ public EvaluatedDlsFlsConfig getDlsFls(User user, boolean dfmEmptyOverwritesAll, final Map> dlsQueries = new HashMap>(); final Map> flsFields = new HashMap>(); final Map> maskedFieldsMap = new HashMap>(); - + for (SecurityRole sr : roles) { for (IndexPattern ip : sr.getIpatterns()) { final Set fls = ip.getFls(); @@ -423,7 +423,7 @@ public EvaluatedDlsFlsConfig getDlsFls(User user, boolean dfmEmptyOverwritesAll, } } } - + if (maskedFields != null && maskedFields.size() > 0) { if (maskedFieldsMap.containsKey(indexPattern)) { @@ -444,7 +444,7 @@ public EvaluatedDlsFlsConfig getDlsFls(User user, boolean dfmEmptyOverwritesAll, } } } - + return new EvaluatedDlsFlsConfig(dlsQueries, flsFields, maskedFieldsMap); } @@ -1010,10 +1010,10 @@ private static boolean impliesTypePerm(Set ipatterns, Resolved res ); } - - + + //####### - + private class TenantHolder { private SetMultimap> tenantsMM = null; @@ -1024,7 +1024,7 @@ public TenantHolder(SecurityDynamicConfiguration roles) { final ExecutorService execs = Executors.newFixedThreadPool(10); for(Entry securityRole: roles.getCEntries().entrySet()) { - + if(securityRole.getValue() == null) { continue; } @@ -1036,7 +1036,7 @@ public Tuple>> call() throws Exception { final Map tenants = securityRole.getValue().getTenants(); if (tenants != null) { - + for (String tenant : tenants.keySet()) { if ("RW".equalsIgnoreCase(tenants.get(tenant))) { @@ -1125,7 +1125,7 @@ private class RoleMappingHolder { private RoleMappingHolder(final SecurityDynamicConfiguration rolesMapping, final String hostResolverMode) { this.hostResolverMode = hostResolverMode; - + if (rolesMapping != null) { users = ArrayListMultimap.create(); @@ -1228,10 +1228,10 @@ private Set map(final User user, final TransportAddress caller) { } } - - - - + + + + public Map mapTenants(User user, Set roles) { return tenantHolder.mapTenants(user, roles); diff --git a/src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java b/src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java index 1e2adee1db..560cfb8a6d 100644 --- a/src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java +++ b/src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java @@ -92,7 +92,7 @@ public ConfigModelV7( this.roles = roles; this.tenants = tenants; - + try { rolesMappingResolution = ConfigConstants.RolesMappingResolution.valueOf( opensearchSettings.get(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, ConfigConstants.RolesMappingResolution.MAPPING_ONLY.toString()) @@ -111,18 +111,18 @@ public ConfigModelV7( public Set getAllConfiguredTenantNames() { return Collections.unmodifiableSet(tenants.getCEntries().keySet()); } - + public SecurityRoles getSecurityRoles() { return securityRoles; } - + private static interface ActionGroupResolver { Set resolvedActions(final List actions); } private ActionGroupResolver reloadActionGroups(SecurityDynamicConfiguration actionGroups) { return new ActionGroupResolver() { - + private Set getGroupMembers(final String groupname) { if (actionGroups == null) { @@ -131,27 +131,27 @@ private Set getGroupMembers(final String groupname) { return Collections.unmodifiableSet(resolve(actionGroups, groupname)); } - + private Set resolve(final SecurityDynamicConfiguration actionGroups, final String entry) { - + // SG5 format, plain array //List en = actionGroups.getAsList(DotPath.of(entry)); //if (en.isEmpty()) { // try SG6 format including readonly and permissions key // en = actionGroups.getAsList(DotPath.of(entry + "." + ConfigConstants.CONFIGKEY_ACTION_GROUPS_PERMISSIONS)); //} - + if(!actionGroups.getCEntries().containsKey(entry)) { return Collections.emptySet(); } - + final Set ret = new HashSet(); - + final Object actionGroupAsObject = actionGroups.getCEntries().get(entry); - + if(actionGroupAsObject != null && actionGroupAsObject instanceof List) { - + for (final String perm: ((List) actionGroupAsObject)) { if (actionGroups.getCEntries().keySet().contains(perm)) { ret.addAll(resolve(actionGroups,perm)); @@ -159,8 +159,8 @@ private Set resolve(final SecurityDynamicConfiguration actionGroups, ret.add(perm); } } - - + + } else if(actionGroupAsObject != null && actionGroupAsObject instanceof ActionGroupsV7) { for (final String perm: ((ActionGroupsV7) actionGroupAsObject).getAllowed_actions()) { if (actionGroups.getCEntries().keySet().contains(perm)) { @@ -172,10 +172,10 @@ private Set resolve(final SecurityDynamicConfiguration actionGroups, } else { throw new RuntimeException("Unable to handle "+actionGroupAsObject); } - + return Collections.unmodifiableSet(ret); } - + @Override public Set resolvedActions(final List actions) { final Set resolvedActions = new HashSet(); @@ -205,7 +205,7 @@ private SecurityRoles reload(SecurityDynamicConfiguration settings) { @Override public SecurityRole call() throws Exception { SecurityRole.Builder _securityRole = new SecurityRole.Builder(securityRole.getKey()); - + if(securityRole.getValue() == null) { return null; } @@ -238,21 +238,21 @@ public SecurityRole call() throws Exception { _indexPattern.addFlsFields(fls); _indexPattern.addMaskedFields(maskedFields); _indexPattern.addPerm(agr.resolvedActions(permittedAliasesIndex.getAllowed_actions())); - + /*for(Entry> type: permittedAliasesIndex.getValue().getTypes(-).entrySet()) { TypePerm typePerm = new TypePerm(type.getKey()); final List perms = type.getValue(); typePerm.addPerms(agr.resolvedActions(perms)); _indexPattern.addTypePerms(typePerm); }*/ - + _securityRole.addIndexPattern(_indexPattern); - + } } - - + + return _securityRole.build(); } }); @@ -339,7 +339,7 @@ public String toString() { public Set getRoles() { return Collections.unmodifiableSet(roles); } - + public Set getRoleNames() { return getRoles().stream().map(r -> r.getName()).collect(Collectors.toSet()); } @@ -367,8 +367,8 @@ public EvaluatedDlsFlsConfig getDlsFls(User user, boolean dfmEmptyOverwritesAll, return EvaluatedDlsFlsConfig.EMPTY; } - - Map> dlsQueriesByIndex = new HashMap>(); + + Map> dlsQueriesByIndex = new HashMap>(); Map> flsFields = new HashMap>(); Map> maskedFieldsMap = new HashMap>(); @@ -379,7 +379,7 @@ public EvaluatedDlsFlsConfig getDlsFls(User user, boolean dfmEmptyOverwritesAll, Set noDlsConcreteIndices = new HashSet<>(); Set noFlsConcreteIndices = new HashSet<>(); Set noMaskedFieldConcreteIndices = new HashSet<>(); - + for (SecurityRole role : roles) { for (IndexPattern ip : role.getIpatterns()) { final Set concreteIndices = ip.concreteIndexNames(user, resolver, cs); @@ -409,12 +409,12 @@ public EvaluatedDlsFlsConfig getDlsFls(User user, boolean dfmEmptyOverwritesAll, } else if (dfmEmptyOverwritesAll) { noFlsConcreteIndices.addAll(concreteIndices); } - + Set maskedFields = ip.getMaskedFields(); if (maskedFields != null && maskedFields.size() > 0) { - for (String concreteIndex : concreteIndices) { + for (String concreteIndex : concreteIndices) { if (maskedFieldsMap.containsKey(concreteIndex)) { maskedFieldsMap.get(concreteIndex).addAll(Sets.newHashSet(maskedFields)); } else { @@ -498,7 +498,7 @@ public boolean impliesTypePermGlobal(Resolved resolved, User user, String[] acti roles.stream().forEach(p -> ipatterns.addAll(p.getIpatterns())); return ConfigModelV7.impliesTypePerm(ipatterns, resolved, user, actions, resolver, cs); } - + private boolean containsDlsFlsConfig() { for (SecurityRole role : roles) { for (IndexPattern ip : role.getIpatterns()) { @@ -562,7 +562,7 @@ private Set getAllResolvedPermittedIndices(Resolved resolved, User user, for (IndexPattern p : ipatterns) { //what if we cannot resolve one (for create purposes) final boolean patternMatch = p.getPerms().matchAll(actions); - + // final Set tperms = p.getTypePerms(); // for (TypePerm tp : tperms) { // if (WildcardMatcher.matchAny(tp.typePattern, resolved.getTypes(-).toArray(new String[0]))) { @@ -810,7 +810,7 @@ public String getDlsQuery(User user) { public boolean hasDlsQuery() { return dlsQuery != null && !dlsQuery.isEmpty(); } - + public Set getFls() { return Collections.unmodifiableSet(fls); } @@ -818,7 +818,7 @@ public Set getFls() { public boolean hasFlsFields() { return fls != null && !fls.isEmpty(); } - + public Set getMaskedFields() { return Collections.unmodifiableSet(maskedFields); } @@ -826,12 +826,12 @@ public Set getMaskedFields() { public boolean hasMaskedFields() { return maskedFields != null && !maskedFields.isEmpty(); } - + public WildcardMatcher getPerms() { return WildcardMatcher.from(perms); } - + } /*public static class TypePerm { @@ -1033,7 +1033,7 @@ private static boolean impliesTypePerm(Set ipatterns, Resolved res ) ); } - + private class TenantHolder { private SetMultimap> tenantsMM = null; @@ -1055,7 +1055,7 @@ public Tuple>> call() throws Exception { final Set> tuples = new HashSet<>(); final List tenants = securityRole.getValue().getTenant_permissions(); if (tenants != null) { - + for (RoleV7.Tenant tenant : tenants) { // find Wildcarded tenant patterns @@ -1166,7 +1166,7 @@ private class RoleMappingHolder { private RoleMappingHolder(final SecurityDynamicConfiguration rolemappings, final String hostResolverMode) { this.hostResolverMode = hostResolverMode; - + if (roles != null) { users = ArrayListMultimap.create(); @@ -1267,10 +1267,10 @@ private Set map(final User user, final TransportAddress caller) { } } - - - - + + + + public Map mapTenants(User user, Set roles) { return tenantHolder.mapTenants(user, roles); diff --git a/src/main/java/org/opensearch/security/securityconf/DynamicConfigFactory.java b/src/main/java/org/opensearch/security/securityconf/DynamicConfigFactory.java index 262eb37cf8..9d8c36576c 100644 --- a/src/main/java/org/opensearch/security/securityconf/DynamicConfigFactory.java +++ b/src/main/java/org/opensearch/security/securityconf/DynamicConfigFactory.java @@ -117,7 +117,7 @@ public final static SecurityDynamicConfiguration addStatics(SecurityDynamicCo return original; } - + protected final Logger log = LogManager.getLogger(this.getClass()); private final ConfigurationRepository cr; private final AtomicBoolean initialized = new AtomicBoolean(); @@ -127,7 +127,7 @@ public final static SecurityDynamicConfiguration addStatics(SecurityDynamicCo private final InternalAuthenticationBackend iab = new InternalAuthenticationBackend(); SecurityDynamicConfiguration config; - + public DynamicConfigFactory(ConfigurationRepository cr, final Settings opensearchSettings, final Path configPath, Client client, ThreadPool threadPool, ClusterInfoHolder cih) { super(); @@ -144,11 +144,11 @@ public DynamicConfigFactory(ConfigurationRepository cr, final Settings opensearc } else { log.info("Static resources will not be loaded."); } - + registerDCFListener(this.iab); this.cr.subscribeOnChange(this); } - + @Override public void onChange(Map> typeToConfig) { @@ -187,7 +187,7 @@ public void onChange(Map> typeToConfig) { if(config.getImplementingClass() == ConfigV7.class) { //statics - + if(roles.containsAny(staticRoles)) { throw new StaticResourceException("Cannot override static roles"); } @@ -205,24 +205,24 @@ public void onChange(Map> typeToConfig) { if(!actionGroups.add(staticActionGroups) && !staticActionGroups.getCEntries().isEmpty()) { throw new StaticResourceException("Unable to load static action groups"); } - + log.debug("Static action groups loaded ({})", staticActionGroups.getCEntries().size()); - + if(tenants.containsAny(staticTenants)) { throw new StaticResourceException("Cannot override static tenants"); } if(!tenants.add(staticTenants) && !staticTenants.getCEntries().isEmpty()) { throw new StaticResourceException("Unable to load static tenants"); } - + log.debug("Static tenants loaded ({})", staticTenants.getCEntries().size()); log.debug("Static configuration loaded (total roles: {}/total action groups: {}/total tenants: {})", roles.getCEntries().size(), actionGroups.getCEntries().size(), tenants.getCEntries().size()); - + //rebuild v7 Models dcm = new DynamicConfigModelV7(getConfigV7(config), opensearchSettings, configPath, iab); @@ -252,26 +252,26 @@ public void onChange(Map> typeToConfig) { } initialized.set(true); - + } - + private static ConfigV6 getConfigV6(SecurityDynamicConfiguration sdc) { @SuppressWarnings("unchecked") SecurityDynamicConfiguration c = (SecurityDynamicConfiguration) sdc; return c.getCEntry("opendistro_security"); } - + private static ConfigV7 getConfigV7(SecurityDynamicConfiguration sdc) { @SuppressWarnings("unchecked") SecurityDynamicConfiguration c = (SecurityDynamicConfiguration) sdc; return c.getCEntry("config"); } - + @Override public final boolean isInitialized() { return initialized.get(); } - + public void registerDCFListener(Object listener) { eventBus.register(listener); } @@ -279,15 +279,15 @@ public void registerDCFListener(Object listener) { public void unregisterDCFListener(Object listener) { eventBus.unregister(listener); } - + private static class InternalUsersModelV7 extends InternalUsersModel { - + private final SecurityDynamicConfiguration internalUserV7SecurityDynamicConfiguration; private final SecurityDynamicConfiguration rolesV7SecurityDynamicConfiguration; private final SecurityDynamicConfiguration rolesMappingsV7SecurityDynamicConfiguration; - + public InternalUsersModelV7(SecurityDynamicConfiguration internalUserV7SecurityDynamicConfiguration, SecurityDynamicConfiguration rolesV7SecurityDynamicConfiguration, SecurityDynamicConfiguration rolesMappingsV7SecurityDynamicConfiguration) { @@ -325,7 +325,7 @@ public String getHash(String user) { InternalUserV7 tmp = internalUserV7SecurityDynamicConfiguration.getCEntry(user); return tmp==null?null:tmp.getHash(); } - + public List getSecurityRoles(String user) { InternalUserV7 tmp = internalUserV7SecurityDynamicConfiguration.getCEntry(user); @@ -341,11 +341,11 @@ private boolean isRolesMappingHidden(String rolename) { return roleMapping!=null && roleMapping.isHidden(); } } - + private static class InternalUsersModelV6 extends InternalUsersModel { - + SecurityDynamicConfiguration configuration; - + public InternalUsersModelV6(SecurityDynamicConfiguration configuration) { super(); @@ -379,7 +379,7 @@ public String getHash(String user) { InternalUserV6 tmp = configuration.getCEntry(user); return tmp==null?null:tmp.getHash(); } - + public List getSecurityRoles(String user) { return Collections.emptyList(); } diff --git a/src/main/java/org/opensearch/security/securityconf/DynamicConfigModel.java b/src/main/java/org/opensearch/security/securityconf/DynamicConfigModel.java index 8b273be122..959679cf85 100644 --- a/src/main/java/org/opensearch/security/securityconf/DynamicConfigModel.java +++ b/src/main/java/org/opensearch/security/securityconf/DynamicConfigModel.java @@ -54,7 +54,7 @@ import org.opensearch.security.http.proxy.HTTPExtendedProxyAuthenticator; public abstract class DynamicConfigModel { - + protected final Logger log = LogManager.getLogger(this.getClass()); public abstract SortedSet getRestAuthDomains(); public abstract Set getRestAuthorizers(); @@ -76,17 +76,18 @@ public abstract class DynamicConfigModel { public abstract String getFilteredAliasMode(); public abstract String getHostsResolverMode(); public abstract boolean isDnfofForEmptyResultsEnabled(); - + public abstract List getIpAuthFailureListeners(); public abstract Multimap getAuthBackendFailureListeners(); public abstract List> getIpClientBlockRegistries(); public abstract Multimap> getAuthBackendClientBlockRegistries(); public abstract Settings getDynamicOnBehalfOfSettings(); + protected final Map authImplMap = new HashMap<>(); public DynamicConfigModel() { super(); - + authImplMap.put("intern_c", InternalAuthenticationBackend.class.getName()); authImplMap.put("intern_z", NoOpAuthorizationBackend.class.getName()); @@ -98,7 +99,7 @@ public DynamicConfigModel() { authImplMap.put("ldap_c", "com.amazon.dlic.auth.ldap.backend.LDAPAuthenticationBackend"); authImplMap.put("ldap_z", "com.amazon.dlic.auth.ldap.backend.LDAPAuthorizationBackend"); - + authImplMap.put("ldap2_c", "com.amazon.dlic.auth.ldap2.LDAPAuthenticationBackend2"); authImplMap.put("ldap2_z", "com.amazon.dlic.auth.ldap2.LDAPAuthorizationBackend2"); @@ -110,11 +111,11 @@ public DynamicConfigModel() { authImplMap.put("jwt_h", "com.amazon.dlic.auth.http.jwt.HTTPJwtAuthenticator"); authImplMap.put("openid_h", "com.amazon.dlic.auth.http.jwt.keybyoidc.HTTPJwtKeyByOpenIdConnectAuthenticator"); authImplMap.put("saml_h", "com.amazon.dlic.auth.http.saml.HTTPSamlAuthenticator"); - + authImplMap.put("ip_authFailureListener", AddressBasedRateLimiter.class.getName()); authImplMap.put("username_authFailureListener", UserNameBasedRateLimiter.class.getName()); } - - - + + + } diff --git a/src/main/java/org/opensearch/security/securityconf/DynamicConfigModelV6.java b/src/main/java/org/opensearch/security/securityconf/DynamicConfigModelV6.java index 1e6467ae6f..3255bb4de4 100644 --- a/src/main/java/org/opensearch/security/securityconf/DynamicConfigModelV6.java +++ b/src/main/java/org/opensearch/security/securityconf/DynamicConfigModelV6.java @@ -62,7 +62,7 @@ import org.opensearch.security.support.ReflectionHelper; public class DynamicConfigModelV6 extends DynamicConfigModel { - + private final ConfigV6 config; private final Settings opensearchSettings; private final Path configPath; @@ -72,12 +72,12 @@ public class DynamicConfigModelV6 extends DynamicConfigModel { private Set transportAuthorizers; private List destroyableComponents; private final InternalAuthenticationBackend iab; - + private List ipAuthFailureListeners; private Multimap authBackendFailureListeners; private List> ipClientBlockRegistries; private Multimap> authBackendClientBlockRegistries; - + public DynamicConfigModelV6(ConfigV6 config, Settings opensearchSettings, Path configPath, InternalAuthenticationBackend iab) { super(); this.config = config; @@ -158,7 +158,7 @@ public boolean isMultiRolespanEnabled() { public String getFilteredAliasMode() { return config.dynamic.filtered_alias_mode; } - + @Override public boolean isDnfofForEmptyResultsEnabled() { return config.dynamic.do_not_fail_on_forbidden_empty; @@ -168,22 +168,22 @@ public boolean isDnfofForEmptyResultsEnabled() { public String getHostsResolverMode() { return config.dynamic.hosts_resolver_mode; } - + @Override public List getIpAuthFailureListeners() { return Collections.unmodifiableList(ipAuthFailureListeners); } - + @Override public Multimap getAuthBackendFailureListeners() { return Multimaps.unmodifiableMultimap(authBackendFailureListeners); } - + @Override public List> getIpClientBlockRegistries() { return Collections.unmodifiableList(ipClientBlockRegistries); } - + @Override public Multimap> getAuthBackendClientBlockRegistries() { return Multimaps.unmodifiableMultimap(authBackendClientBlockRegistries); @@ -195,7 +195,7 @@ public Settings getDynamicOnBehalfOfSettings() { } private void buildAAA() { - + final SortedSet restAuthDomains0 = new TreeSet<>(); final Set restAuthorizers0 = new HashSet<>(); final SortedSet transportAuthDomains0 = new TreeSet<>(); @@ -219,7 +219,7 @@ private void buildAAA() { final String authzBackendClazz = ad.getValue().authorization_backend.type; final AuthorizationBackend authorizationBackend; - + if(authzBackendClazz.equals(InternalAuthenticationBackend.class.getName()) //NOSONAR || authzBackendClazz.equals("internal") || authzBackendClazz.equals("intern")) { @@ -234,7 +234,7 @@ private void buildAAA() { .put(Settings.builder().loadFromSource(ad.getValue().authorization_backend.configAsJson(), XContentType.JSON).build()).build() , configPath); } - + if (httpEnabled) { restAuthorizers0.add(authorizationBackend); } @@ -242,7 +242,7 @@ private void buildAAA() { if (transportEnabled) { transportAuthorizers0.add(authorizationBackend); } - + if (authorizationBackend instanceof Destroyable) { destroyableComponents0.add((Destroyable) authorizationBackend); } @@ -281,7 +281,7 @@ private void buildAAA() { String httpAuthenticatorType = ad.getValue().http_authenticator.type; //no default HTTPAuthenticator httpAuthenticator = httpAuthenticatorType==null?null: (HTTPAuthenticator) newInstance(httpAuthenticatorType,"h", Settings.builder().put(opensearchSettings) - //.putProperties(ads.getAsStringMap(DotPath.of("http_authenticator.config")), DynamicConfiguration.checkKeyFunction()).build(), + //.putProperties(ads.getAsStringMap(DotPath.of("http_authenticator.config")), DynamicConfiguration.checkKeyFunction()).build(), .put(Settings.builder().loadFromSource(ad.getValue().http_authenticator.configAsJson(), XContentType.JSON).build()).build() , configPath); @@ -296,15 +296,15 @@ private void buildAAA() { if (transportEnabled) { transportAuthDomains0.add(_ad); } - + if (httpAuthenticator instanceof Destroyable) { destroyableComponents0.add((Destroyable) httpAuthenticator); } - + if (authenticationBackend instanceof Destroyable) { destroyableComponents0.add((Destroyable) authenticationBackend); } - + } catch (final Exception e) { log.error("Unable to initialize auth domain {} due to {}", ad, e.toString(), e); } @@ -313,30 +313,30 @@ private void buildAAA() { } List originalDestroyableComponents = destroyableComponents; - + restAuthDomains = Collections.unmodifiableSortedSet(restAuthDomains0); transportAuthDomains = Collections.unmodifiableSortedSet(transportAuthDomains0); restAuthorizers = Collections.unmodifiableSet(restAuthorizers0); transportAuthorizers = Collections.unmodifiableSet(transportAuthorizers0); - + destroyableComponents = Collections.unmodifiableList(destroyableComponents0); - + if(originalDestroyableComponents != null) { destroyDestroyables(originalDestroyableComponents); } - + originalDestroyableComponents = null; - + createAuthFailureListeners(ipAuthFailureListeners0, authBackendFailureListeners0, ipClientBlockRegistries0, authBackendClientBlockRegistries0, destroyableComponents0); - + ipAuthFailureListeners = Collections.unmodifiableList(ipAuthFailureListeners0); ipClientBlockRegistries = Collections.unmodifiableList(ipClientBlockRegistries0); authBackendClientBlockRegistries = Multimaps.unmodifiableMultimap(authBackendClientBlockRegistries0); authBackendFailureListeners = Multimaps.unmodifiableMultimap(authBackendFailureListeners0); } - + private void destroyDestroyables(List destroyableComponents) { for (Destroyable destroyable : destroyableComponents) { try { @@ -346,7 +346,7 @@ private void destroyDestroyables(List destroyableComponents) { } } } - + private T newInstance(final String clazzOrShortcut, String type, final Settings settings, final Path configPath) { String clazz = clazzOrShortcut; @@ -357,7 +357,7 @@ private T newInstance(final String clazzOrShortcut, String type, final Setti return ReflectionHelper.instantiateAAA(clazz, settings, configPath); } - + private String translateShortcutToClassName(final String clazzOrShortcut, final String type) { if (authImplMap.containsKey(clazzOrShortcut + "_" + type)) { @@ -366,17 +366,17 @@ private String translateShortcutToClassName(final String clazzOrShortcut, final return clazzOrShortcut; } } - + private void createAuthFailureListeners(List ipAuthFailureListeners, Multimap authBackendFailureListeners, List> ipClientBlockRegistries, Multimap> authBackendUserClientBlockRegistries, List destroyableComponents0) { for (Entry entry : config.dynamic.auth_failure_listeners.getListeners().entrySet()) { - + Settings entrySettings = Settings.builder() .put(opensearchSettings) .put(Settings.builder().loadFromSource(entry.getValue().asJson(), XContentType.JSON).build()).build(); - + String type = entry.getValue().type; String authenticationBackend = entry.getValue().authentication_backend; diff --git a/src/main/java/org/opensearch/security/securityconf/DynamicConfigModelV7.java b/src/main/java/org/opensearch/security/securityconf/DynamicConfigModelV7.java index c3e3792c5c..0b66d9a306 100644 --- a/src/main/java/org/opensearch/security/securityconf/DynamicConfigModelV7.java +++ b/src/main/java/org/opensearch/security/securityconf/DynamicConfigModelV7.java @@ -62,7 +62,7 @@ import org.opensearch.security.support.ReflectionHelper; public class DynamicConfigModelV7 extends DynamicConfigModel { - + private final ConfigV7 config; private final Settings opensearchSettings; private final Path configPath; @@ -77,7 +77,7 @@ public class DynamicConfigModelV7 extends DynamicConfigModel { private Multimap authBackendFailureListeners; private List> ipClientBlockRegistries; private Multimap> authBackendClientBlockRegistries; - + public DynamicConfigModelV7(ConfigV7 config, Settings opensearchSettings, Path configPath, InternalAuthenticationBackend iab) { super(); this.config = config; @@ -163,27 +163,27 @@ public String getFilteredAliasMode() { public String getHostsResolverMode() { return config.dynamic.hosts_resolver_mode; } - + @Override public boolean isDnfofForEmptyResultsEnabled() { return config.dynamic.do_not_fail_on_forbidden_empty; } - + @Override public List getIpAuthFailureListeners() { return Collections.unmodifiableList(ipAuthFailureListeners); } - + @Override public Multimap getAuthBackendFailureListeners() { return Multimaps.unmodifiableMultimap(authBackendFailureListeners); } - + @Override public List> getIpClientBlockRegistries() { return Collections.unmodifiableList(ipClientBlockRegistries); } - + @Override public Multimap> getAuthBackendClientBlockRegistries() { return Multimaps.unmodifiableMultimap(authBackendClientBlockRegistries); @@ -195,9 +195,9 @@ public Settings getDynamicOnBehalfOfSettings() { .put(Settings.builder().loadFromSource(config.dynamic.on_behalf_of.configAsJson(), XContentType.JSON).build()) .build(); } - + private void buildAAA() { - + final SortedSet restAuthDomains0 = new TreeSet<>(); final Set restAuthorizers0 = new HashSet<>(); final SortedSet transportAuthDomains0 = new TreeSet<>(); @@ -220,7 +220,7 @@ private void buildAAA() { final String authzBackendClazz = ad.getValue().authorization_backend.type; final AuthorizationBackend authorizationBackend; - + if(authzBackendClazz.equals(InternalAuthenticationBackend.class.getName()) //NOSONAR || authzBackendClazz.equals("internal") || authzBackendClazz.equals("intern")) { @@ -235,7 +235,7 @@ private void buildAAA() { .put(Settings.builder().loadFromSource(ad.getValue().authorization_backend.configAsJson(), XContentType.JSON).build()).build() , configPath); } - + if (httpEnabled) { restAuthorizers0.add(authorizationBackend); } @@ -243,7 +243,7 @@ private void buildAAA() { if (transportEnabled) { transportAuthorizers0.add(authorizationBackend); } - + if (authorizationBackend instanceof Destroyable) { destroyableComponents0.add((Destroyable) authorizationBackend); } @@ -281,7 +281,7 @@ private void buildAAA() { String httpAuthenticatorType = ad.getValue().http_authenticator.type; //no default HTTPAuthenticator httpAuthenticator = httpAuthenticatorType==null?null: (HTTPAuthenticator) newInstance(httpAuthenticatorType,"h", Settings.builder().put(opensearchSettings) - //.putProperties(ads.getAsStringMap(DotPath.of("http_authenticator.config")), DynamicConfiguration.checkKeyFunction()).build(), + //.putProperties(ads.getAsStringMap(DotPath.of("http_authenticator.config")), DynamicConfiguration.checkKeyFunction()).build(), .put(Settings.builder().loadFromSource(ad.getValue().http_authenticator.configAsJson(), XContentType.JSON).build()).build() , configPath); @@ -296,15 +296,15 @@ private void buildAAA() { if (transportEnabled) { transportAuthDomains0.add(_ad); } - + if (httpAuthenticator instanceof Destroyable) { destroyableComponents0.add((Destroyable) httpAuthenticator); } - + if (authenticationBackend instanceof Destroyable) { destroyableComponents0.add((Destroyable) authenticationBackend); } - + } catch (final Exception e) { log.error("Unable to initialize auth domain {} due to {}", ad, e.toString(), e); } @@ -313,23 +313,23 @@ private void buildAAA() { } List originalDestroyableComponents = destroyableComponents; - + restAuthDomains = Collections.unmodifiableSortedSet(restAuthDomains0); transportAuthDomains = Collections.unmodifiableSortedSet(transportAuthDomains0); restAuthorizers = Collections.unmodifiableSet(restAuthorizers0); transportAuthorizers = Collections.unmodifiableSet(transportAuthorizers0); - + destroyableComponents = Collections.unmodifiableList(destroyableComponents0); - + if(originalDestroyableComponents != null) { destroyDestroyables(originalDestroyableComponents); } - + originalDestroyableComponents = null; createAuthFailureListeners(ipAuthFailureListeners0, authBackendFailureListeners0, ipClientBlockRegistries0, authBackendClientBlockRegistries0, destroyableComponents0); - + ipAuthFailureListeners = Collections.unmodifiableList(ipAuthFailureListeners0); ipClientBlockRegistries = Collections.unmodifiableList(ipClientBlockRegistries0); authBackendClientBlockRegistries = Multimaps.unmodifiableMultimap(authBackendClientBlockRegistries0); @@ -346,7 +346,7 @@ private void destroyDestroyables(List destroyableComponents) { } } } - + private T newInstance(final String clazzOrShortcut, String type, final Settings settings, final Path configPath) { String clazz = clazzOrShortcut; @@ -357,7 +357,7 @@ private T newInstance(final String clazzOrShortcut, String type, final Setti return ReflectionHelper.instantiateAAA(clazz, settings, configPath); } - + private String translateShortcutToClassName(final String clazzOrShortcut, final String type) { if (authImplMap.containsKey(clazzOrShortcut + "_" + type)) { @@ -366,17 +366,17 @@ private String translateShortcutToClassName(final String clazzOrShortcut, final return clazzOrShortcut; } } - + private void createAuthFailureListeners(List ipAuthFailureListeners, Multimap authBackendFailureListeners, List> ipClientBlockRegistries, Multimap> authBackendUserClientBlockRegistries, List destroyableComponents0) { for (Entry entry : config.dynamic.auth_failure_listeners.getListeners().entrySet()) { - + Settings entrySettings = Settings.builder() .put(opensearchSettings) .put(Settings.builder().loadFromSource(entry.getValue().asJson(), XContentType.JSON).build()).build(); - + String type = entry.getValue().type; String authenticationBackend = entry.getValue().authentication_backend; diff --git a/src/main/java/org/opensearch/security/securityconf/EvaluatedDlsFlsConfig.java b/src/main/java/org/opensearch/security/securityconf/EvaluatedDlsFlsConfig.java index 9100e7dd02..8870cb3aad 100644 --- a/src/main/java/org/opensearch/security/securityconf/EvaluatedDlsFlsConfig.java +++ b/src/main/java/org/opensearch/security/securityconf/EvaluatedDlsFlsConfig.java @@ -87,7 +87,7 @@ public EvaluatedDlsFlsConfig filter(Resolved indices) { return this; } else { Set allIndices = indices.getAllIndices(); - + return new EvaluatedDlsFlsConfig(filter(dlsQueriesByIndex, allIndices), filter(flsByIndex, allIndices), filter(fieldMaskingByIndex, allIndices)); } @@ -108,7 +108,7 @@ private Map> filter(Map> map, Set> result = new HashMap<>(map.size()); - for (Map.Entry> entry : map.entrySet()) { + for (Map.Entry> entry : map.entrySet()) { if (WildcardMatcher.from(entry.getKey(), false).matchAny(allIndices)) { result.put(entry.getKey(), entry.getValue()); } diff --git a/src/main/java/org/opensearch/security/securityconf/Hideable.java b/src/main/java/org/opensearch/security/securityconf/Hideable.java index 9b1df8f157..8744575d64 100644 --- a/src/main/java/org/opensearch/security/securityconf/Hideable.java +++ b/src/main/java/org/opensearch/security/securityconf/Hideable.java @@ -28,7 +28,7 @@ package org.opensearch.security.securityconf; public interface Hideable { - + boolean isHidden(); boolean isReserved(); diff --git a/src/main/java/org/opensearch/security/securityconf/Initializable.java b/src/main/java/org/opensearch/security/securityconf/Initializable.java index fafc717866..ab1a1ebd4a 100644 --- a/src/main/java/org/opensearch/security/securityconf/Initializable.java +++ b/src/main/java/org/opensearch/security/securityconf/Initializable.java @@ -28,7 +28,7 @@ package org.opensearch.security.securityconf; public interface Initializable { - + boolean isInitialized(); } diff --git a/src/main/java/org/opensearch/security/securityconf/InternalUsersModel.java b/src/main/java/org/opensearch/security/securityconf/InternalUsersModel.java index 3ff1554a94..41c3116874 100644 --- a/src/main/java/org/opensearch/security/securityconf/InternalUsersModel.java +++ b/src/main/java/org/opensearch/security/securityconf/InternalUsersModel.java @@ -31,7 +31,7 @@ import java.util.Map; public abstract class InternalUsersModel { - + public abstract boolean exists(String user); public abstract List getBackenRoles(String user); public abstract Map getAttributes(String user); diff --git a/src/main/java/org/opensearch/security/securityconf/Migration.java b/src/main/java/org/opensearch/security/securityconf/Migration.java index 3cb111f11c..ec6a5525b9 100644 --- a/src/main/java/org/opensearch/security/securityconf/Migration.java +++ b/src/main/java/org/opensearch/security/securityconf/Migration.java @@ -55,15 +55,15 @@ public class Migration { - + public static Tuple,SecurityDynamicConfiguration> migrateRoles(SecurityDynamicConfiguration r6cs, SecurityDynamicConfiguration rms6) throws MigrationException { - + final SecurityDynamicConfiguration r7 = SecurityDynamicConfiguration.empty(); r7.setCType(r6cs.getCType()); r7.set_meta(new Meta()); r7.get_meta().setConfig_version(2); r7.get_meta().setType("roles"); - + final SecurityDynamicConfiguration t7 = SecurityDynamicConfiguration.empty(); t7.setCType(CType.TENANTS); t7.set_meta(new Meta()); @@ -71,11 +71,11 @@ public static Tuple,SecurityDynamicConfigur t7.get_meta().setType("tenants"); Set dedupTenants = new HashSet<>(); - + for(final Entry r6e: r6cs.getCEntries().entrySet()) { final String roleName = r6e.getKey(); final RoleV6 r6 = r6e.getValue(); - + if(r6 == null) { RoleV7 noPermRole = new RoleV7(); noPermRole.setDescription("Migrated from v6, was empty"); @@ -84,52 +84,52 @@ public static Tuple,SecurityDynamicConfigur } r7.putCEntry(roleName, new RoleV7(r6)); - + for(Entry tenant: r6.getTenants().entrySet()) { dedupTenants.add(tenant.getKey()); } } - + if(rms6 != null) { for(final Entry r6m: rms6.getCEntries().entrySet()) { final String roleName = r6m.getKey(); //final RoleMappingsV6 r6 = r6m.getValue(); - + if(!r7.exists(roleName)) { //rolemapping but role does not exists RoleV7 noPermRole = new RoleV7(); noPermRole.setDescription("Migrated from v6, was in rolemappings but no role existed"); r7.putCEntry(roleName, noPermRole); } - + } } - + for(String tenantName: dedupTenants) { TenantV7 entry = new TenantV7(); entry.setDescription("Migrated from v6"); t7.putCEntry(tenantName, entry); } - + return new Tuple, SecurityDynamicConfiguration>(r7, t7); - + } - + public static SecurityDynamicConfiguration migrateConfig(SecurityDynamicConfiguration r6cs) throws MigrationException { final SecurityDynamicConfiguration c7 = SecurityDynamicConfiguration.empty(); c7.setCType(r6cs.getCType()); c7.set_meta(new Meta()); c7.get_meta().setConfig_version(2); c7.get_meta().setType("config"); - + if(r6cs.getCEntries().size() != 1) { throw new MigrationException("Unable to migrate config because expected size was 1 but actual size is "+r6cs.getCEntries().size()); } - + if(r6cs.getCEntries().get("opendistro_security") == null) { throw new MigrationException("Unable to migrate config because 'opendistro_security' key not found"); } - + for(final Entry r6c: r6cs.getCEntries().entrySet()) { c7.putCEntry("config", new ConfigV7(r6c.getValue())); } @@ -181,23 +181,23 @@ public static SecurityDynamicConfiguration migrateInternalUsers i7.set_meta(new Meta()); i7.get_meta().setConfig_version(2); i7.get_meta().setType("internalusers"); - + for(final Entry r6i: r6is.getCEntries().entrySet()) { final String username = !Strings.isNullOrEmpty(r6i.getValue().getUsername())?r6i.getValue().getUsername():r6i.getKey(); i7.putCEntry(username, new InternalUserV7(r6i.getValue())); } - + return i7; } - + public static SecurityDynamicConfiguration migrateActionGroups(SecurityDynamicConfiguration r6as) throws MigrationException { - + final SecurityDynamicConfiguration a7 = SecurityDynamicConfiguration.empty(); a7.setCType(r6as.getCType()); a7.set_meta(new Meta()); a7.get_meta().setConfig_version(2); a7.get_meta().setType("actiongroups"); - + if(r6as.getImplementingClass().isAssignableFrom(List.class)) { for(final Entry r6a: r6as.getCEntries().entrySet()) { a7.putCEntry(r6a.getKey(), new ActionGroupsV7(r6a.getKey(), (List) r6a.getValue())); @@ -210,18 +210,18 @@ public static SecurityDynamicConfiguration migrateActionGroups( return a7; } - + public static SecurityDynamicConfiguration migrateRoleMappings(SecurityDynamicConfiguration r6rms) throws MigrationException { final SecurityDynamicConfiguration rms7 = SecurityDynamicConfiguration.empty(); rms7.setCType(r6rms.getCType()); rms7.set_meta(new Meta()); rms7.get_meta().setConfig_version(2); rms7.get_meta().setType("rolesmapping"); - + for(final Entry r6m: r6rms.getCEntries().entrySet()) { rms7.putCEntry(r6m.getKey(), new RoleMappingsV7(r6m.getValue())); } - + return rms7; } diff --git a/src/main/java/org/opensearch/security/securityconf/StaticDefinable.java b/src/main/java/org/opensearch/security/securityconf/StaticDefinable.java index d6ffb106cf..06b92100fa 100644 --- a/src/main/java/org/opensearch/security/securityconf/StaticDefinable.java +++ b/src/main/java/org/opensearch/security/securityconf/StaticDefinable.java @@ -28,7 +28,7 @@ package org.opensearch.security.securityconf; public interface StaticDefinable { - + boolean isStatic(); } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/Meta.java b/src/main/java/org/opensearch/security/securityconf/impl/Meta.java index 42912c1dda..1e9060efa1 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/Meta.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/Meta.java @@ -30,17 +30,17 @@ import com.fasterxml.jackson.annotation.JsonIgnore; public class Meta { - - + + private String type; private int config_version; - + private CType cType; - + public String getType() { return type; } - + public void setType(String type) { this.type = type; cType = CType.fromString(type); @@ -51,7 +51,7 @@ public int getConfig_version() { public void setConfig_version(int config_version) { this.config_version = config_version; } - + @JsonIgnore public CType getCType() { return cType; @@ -61,6 +61,6 @@ public CType getCType() { public String toString() { return "Meta [type=" + type + ", config_version=" + config_version + ", cType=" + cType + "]"; } - - + + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/SecurityDynamicConfiguration.java b/src/main/java/org/opensearch/security/securityconf/impl/SecurityDynamicConfiguration.java index 09eeee41e3..c282f439e8 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/SecurityDynamicConfiguration.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/SecurityDynamicConfiguration.java @@ -52,7 +52,7 @@ import org.opensearch.security.securityconf.StaticDefinable; public class SecurityDynamicConfiguration implements ToXContent { - + private static final TypeReference> typeRefMSO = new TypeReference>() {}; @JsonIgnore @@ -61,7 +61,7 @@ public class SecurityDynamicConfiguration implements ToXContent { private long primaryTerm= -1; private CType ctype; private int version = -1; - + public static SecurityDynamicConfiguration empty() { return new SecurityDynamicConfiguration(); } @@ -83,11 +83,11 @@ public static SecurityDynamicConfiguration fromJson(String json, CType ct sdc = DefaultObjectMapper.readValue(json, DefaultObjectMapper.getTypeFactory().constructParametricType(SecurityDynamicConfiguration.class, implementationClass)); } validate(sdc, version, ctype); - + } else { sdc = new SecurityDynamicConfiguration(); } - + sdc.ctype = ctype; sdc.seqNo = seqNo; sdc.primaryTerm = primaryTerm; @@ -95,35 +95,35 @@ public static SecurityDynamicConfiguration fromJson(String json, CType ct return sdc; } - + public static void validate(SecurityDynamicConfiguration sdc, int version, CType ctype) throws IOException { if(version < 2 && sdc.get_meta() != null) { throw new IOException("A version of "+version+" can not have a _meta key for "+ctype); } - + if(version >= 2 && sdc.get_meta() == null) { throw new IOException("A version of "+version+" must have a _meta key for "+ctype); } - + if(version < 2 && ctype == CType.CONFIG && (sdc.getCEntries().size() != 1 || !sdc.getCEntries().keySet().contains("opendistro_security"))) { throw new IOException("A version of "+version+" must have a single toplevel key named 'opendistro_security' for "+ctype); } - + if(version >= 2 && ctype == CType.CONFIG && (sdc.getCEntries().size() != 1 || !sdc.getCEntries().keySet().contains("config"))) { throw new IOException("A version of "+version+" must have a single toplevel key named 'config' for "+ctype); } - + } public static SecurityDynamicConfiguration fromNode(JsonNode json, CType ctype, int version, long seqNo, long primaryTerm) throws IOException { return fromJson(DefaultObjectMapper.writeValueAsString(json, false), ctype, version, seqNo, primaryTerm); } - + //for Jackson private SecurityDynamicConfiguration() { super(); } - + private Meta _meta; public Meta get_meta() { @@ -134,17 +134,17 @@ public void set_meta(Meta _meta) { this._meta = _meta; } - + @JsonAnySetter void setCEntries(String key, T value) { putCEntry(key, value); } - + @JsonAnyGetter public Map getCEntries() { return centries; } - + @JsonIgnore public void removeHidden() { for(Entry entry: new HashMap(centries).entrySet()) { @@ -153,7 +153,7 @@ public void removeHidden() { } } } - + @JsonIgnore public void removeStatic() { for(Entry entry: new HashMap(centries).entrySet()) { @@ -162,38 +162,38 @@ public void removeStatic() { } } } - + @JsonIgnore public void clearHashes() { for(Entry entry: centries.entrySet()) { if(entry.getValue() instanceof Hashed) { - ((Hashed) entry.getValue()).clearHash(); + ((Hashed) entry.getValue()).clearHash(); } } } - + public void removeOthers(String key) { T tmp = this.centries.get(key); this.centries.clear(); this.centries.put(key, tmp); } - + @JsonIgnore public T putCEntry(String key, T value) { return centries.put(key, value); } - + @JsonIgnore public void putCObject(String key, Object value) { centries.put(key, (T) value); } - + @JsonIgnore public T getCEntry(String key) { return centries.get(key); } - + @JsonIgnore public boolean exists(String key) { return centries.containsKey(key); @@ -216,7 +216,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws final boolean omitDefaults = params != null && params.paramAsBoolean("omit_defaults", false); return builder.map(DefaultObjectMapper.readValue(DefaultObjectMapper.writeValueAsString(this, omitDefaults), typeRefMSO)); } - + @Override @JsonIgnore public boolean isFragment() { @@ -237,7 +237,7 @@ public long getPrimaryTerm() { public CType getCType() { return ctype; } - + @JsonIgnore public void setCType(CType ctype) { this.ctype = ctype; @@ -247,7 +247,7 @@ public void setCType(CType ctype) { public int getVersion() { return version; } - + @JsonIgnore public Class getImplementingClass() { return ctype==null?null:ctype.getImplementationClass().get(getVersion()); @@ -265,7 +265,7 @@ public SecurityDynamicConfiguration deepClone() { @JsonIgnore public void remove(String key) { centries.remove(key); - + } @SuppressWarnings({ "rawtypes", "unchecked" }) @@ -273,19 +273,19 @@ public boolean add(SecurityDynamicConfiguration other) { if(other.ctype == null || !other.ctype.equals(this.ctype)) { return false; } - + if(other.getImplementingClass() == null || !other.getImplementingClass().equals(this.getImplementingClass())) { return false; } - + if(other.version != this.version) { return false; } - + this.centries.putAll(other.centries); return true; } - + @JsonIgnore @SuppressWarnings({ "rawtypes" }) public boolean containsAny(SecurityDynamicConfiguration other) { diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v6/ActionGroupsV6.java b/src/main/java/org/opensearch/security/securityconf/impl/v6/ActionGroupsV6.java index b64becf0a4..99bef31505 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v6/ActionGroupsV6.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v6/ActionGroupsV6.java @@ -35,7 +35,7 @@ public class ActionGroupsV6 implements Hideable { - + private boolean readonly; private boolean hidden; private List permissions = Collections.emptyList(); @@ -43,7 +43,7 @@ public class ActionGroupsV6 implements Hideable { public ActionGroupsV6() { super(); } - + @JsonIgnore public boolean isReserved() { return readonly; @@ -70,6 +70,6 @@ public void setPermissions(List permissions) { public String toString() { return "ActionGroups [readonly=" + readonly + ", hidden=" + hidden + ", permissions=" + permissions + "]"; } - - + + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v6/ConfigV6.java b/src/main/java/org/opensearch/security/securityconf/impl/v6/ConfigV6.java index 301cb68219..3692bb59ca 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v6/ConfigV6.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v6/ConfigV6.java @@ -47,8 +47,8 @@ public class ConfigV6 { public Dynamic dynamic; - - + + @Override public String toString() { return "Config [dynamic=" + dynamic + "]"; @@ -73,7 +73,7 @@ public static class Dynamic { public String transport_userrname_attribute; public boolean do_not_fail_on_forbidden_empty; public OnBehalfOf on_behalf_of = new OnBehalfOf() { - + }; @Override @@ -100,9 +100,9 @@ public String toString() { return "Kibana [multitenancy_enabled=" + multitenancy_enabled + ", server_username=" + server_username + ", opendistro_role=" + opendistro_role + ", index=" + index + ", do_not_fail_on_forbidden=" + do_not_fail_on_forbidden + "]"; } - - - + + + } public static class Http { @@ -112,8 +112,8 @@ public static class Http { public String toString() { return "Http [anonymous_auth_enabled=" + anonymous_auth_enabled + ", xff=" + xff + "]"; } - - + + } public static class AuthFailureListeners { @@ -130,7 +130,7 @@ public Map getListeners() { return listeners; } - + } public static class AuthFailureListener { @@ -141,11 +141,11 @@ public static class AuthFailureListener { public int block_expiry_seconds = 60 * 10; public int max_blocked_clients = 100_000; public int max_tracked_clients = 100_000; - + public AuthFailureListener() { super(); } - + @JsonIgnore public String asJson() { try { @@ -175,12 +175,12 @@ public String toString() { return "Xff [enabled=" + enabled + ", internalProxies=" + internalProxies + ", remoteIpHeader=" + remoteIpHeader + ", proxiesHeader=" + proxiesHeader + ", trustedProxies=" + trustedProxies + "]"; } - - + + } public static class Authc { - + @JsonIgnore private final Map domains = new HashMap<>(); @@ -198,8 +198,8 @@ public Map getDomains() { public String toString() { return "Authc [domains=" + domains + "]"; } - - + + } public static class AuthcDomain { @@ -217,8 +217,8 @@ public String toString() { return "AuthcDomain [http_enabled=" + http_enabled + ", transport_enabled=" + transport_enabled + ", enabled=" + enabled + ", order=" + order + ", http_authenticator=" + http_authenticator + ", authentication_backend=" + authentication_backend + "]"; } - - + + } public static class HttpAuthenticator { @@ -226,7 +226,7 @@ public static class HttpAuthenticator { public boolean challenge = true; public String type; public Map config = Collections.emptyMap(); - + @JsonIgnore public String configAsJson() { try { @@ -240,14 +240,14 @@ public String configAsJson() { public String toString() { return "HttpAuthenticator [challenge=" + challenge + ", type=" + type + ", config=" + config + "]"; } - - + + } public static class AuthzBackend { public String type = "noop"; public Map config = Collections.emptyMap(); - + @JsonIgnore public String configAsJson() { try { @@ -261,14 +261,14 @@ public String configAsJson() { public String toString() { return "AuthzBackend [type=" + type + ", config=" + config + "]"; } - - + + } public static class AuthcBackend { public String type = InternalAuthenticationBackend.class.getName(); public Map config = Collections.emptyMap(); - + @JsonIgnore public String configAsJson() { try { @@ -282,8 +282,8 @@ public String configAsJson() { public String toString() { return "AuthcBackend [type=" + type + ", config=" + config + "]"; } - - + + } public static class Authz { @@ -304,8 +304,8 @@ public Map getDomains() { public String toString() { return "Authz [domains=" + domains + "]"; } - - + + } public static class AuthzDomain { @@ -320,8 +320,8 @@ public static class AuthzDomain { public String toString() { return "AuthzDomain [http_enabled=" + http_enabled + ", transport_enabled=" + transport_enabled + ", enabled=" + enabled + ", authorization_backend=" + authorization_backend + "]"; } - - + + } public static class OnBehalfOf { @@ -351,4 +351,5 @@ public String toString() { return "OnBehalfOf [signing_key=" + signingKey + ", encryption_key=" + encryptionKey +"]"; } } + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v6/InternalUserV6.java b/src/main/java/org/opensearch/security/securityconf/impl/v6/InternalUserV6.java index 827e573a3a..f650101b64 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v6/InternalUserV6.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v6/InternalUserV6.java @@ -37,7 +37,7 @@ import org.opensearch.security.securityconf.Hideable; public class InternalUserV6 implements Hideable, Hashed { - + private String hash; private boolean readonly; private boolean hidden; @@ -45,7 +45,7 @@ public class InternalUserV6 implements Hideable, Hashed { private Map attributes = Collections.emptyMap(); private String username; - + public InternalUserV6(String hash, boolean readonly, boolean hidden, List roles, Map attributes, String username) { super(); @@ -69,7 +69,7 @@ public InternalUserV6() { super(); //default constructor } - + public String getHash() { return hash; } @@ -80,7 +80,7 @@ public void setHash(String hash) { public void setPassword(String password){ // no-op setter. Due to a bug in 6.x, empty "password" may be saved to the internalusers doc. Ignore it. } - + public boolean isReadonly() { return readonly; } @@ -111,7 +111,7 @@ public String toString() { return "SgInternalUser [hash=" + hash + ", readonly=" + readonly + ", hidden=" + hidden + ", roles=" + roles + ", attributes=" + attributes + "]"; } - + @JsonIgnore public boolean isReserved() { return readonly; @@ -122,7 +122,7 @@ public boolean isReserved() { public void clearHash() { hash = ""; } - - + + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v6/RoleMappingsV6.java b/src/main/java/org/opensearch/security/securityconf/impl/v6/RoleMappingsV6.java index 1c28f99113..bb10fd8812 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v6/RoleMappingsV6.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v6/RoleMappingsV6.java @@ -82,7 +82,7 @@ public String toString() { return "RoleMappings [readonly=" + readonly + ", hidden=" + hidden + ", backendroles=" + backendroles + ", hosts=" + getHosts() + ", users=" + getUsers() + ", andBackendroles=" + andBackendroles + "]"; } - + @JsonIgnore public boolean isReserved() { return readonly; diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v6/RoleV6.java b/src/main/java/org/opensearch/security/securityconf/impl/v6/RoleV6.java index f0377f797b..e8254d4530 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v6/RoleV6.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v6/RoleV6.java @@ -60,13 +60,13 @@ void setTypes0(String key, List value) { public Map> getTypes() { return types; } - + private String _dls_; private List _fls_; private List _masked_fields_; - - + + public String get_dls_() { return _dls_; } @@ -84,7 +84,7 @@ public String toString() { return "Index [types=" + types + ", _dls_=" + _dls_ + ", _fls_=" + _fls_ + ", _masked_fields_=" + _masked_fields_ + "]"; } - + } @@ -132,7 +132,7 @@ public void setIndices(Map indices) { public String toString() { return "Role [readonly=" + readonly + ", hidden=" + hidden + ", cluster=" + cluster + ", tenants=" + tenants + ", indices=" + indices + "]"; } - + @JsonIgnore public boolean isReserved() { return readonly; diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v7/ActionGroupsV7.java b/src/main/java/org/opensearch/security/securityconf/impl/v7/ActionGroupsV7.java index d728dfb8cf..f38978eec2 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v7/ActionGroupsV7.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v7/ActionGroupsV7.java @@ -38,8 +38,8 @@ public class ActionGroupsV7 implements Hideable, StaticDefinable { - - + + private boolean reserved; private boolean hidden; @JsonProperty(value = "static") @@ -47,7 +47,7 @@ public class ActionGroupsV7 implements Hideable, StaticDefinable { private List allowed_actions = Collections.emptyList(); private String type; private String description; - + public ActionGroupsV7() { super(); } @@ -76,8 +76,8 @@ public String getDescription() { public void setDescription(String description) { this.description = description; } - - + + public boolean isReserved() { return reserved; } @@ -109,8 +109,8 @@ public String toString() { return "ActionGroupsV7 [reserved=" + reserved + ", hidden=" + hidden + ", _static=" + _static + ", allowed_actions=" + allowed_actions + ", type=" + type + ", description=" + description + "]"; } - - - - + + + + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v7/ConfigV7.java b/src/main/java/org/opensearch/security/securityconf/impl/v7/ConfigV7.java index 9a39979909..f426af2d70 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v7/ConfigV7.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v7/ConfigV7.java @@ -54,7 +54,7 @@ public ConfigV7() { public ConfigV7(ConfigV6 c6) { dynamic = new Dynamic(); - + dynamic.filtered_alias_mode = c6.dynamic.filtered_alias_mode; dynamic.disable_rest_auth = c6.dynamic.disable_rest_auth; dynamic.disable_intertransport_auth = c6.dynamic.disable_intertransport_auth; @@ -65,40 +65,40 @@ public ConfigV7(ConfigV6 c6) { dynamic.multi_rolespan_enabled = c6.dynamic.multi_rolespan_enabled; dynamic.hosts_resolver_mode = c6.dynamic.hosts_resolver_mode; dynamic.transport_userrname_attribute = c6.dynamic.transport_userrname_attribute; - + dynamic.kibana = new Kibana(); - + dynamic.kibana.index = c6.dynamic.kibana.index; dynamic.kibana.multitenancy_enabled = c6.dynamic.kibana.multitenancy_enabled; dynamic.kibana.private_tenant_enabled = true; dynamic.kibana.default_tenant = ""; dynamic.kibana.server_username = c6.dynamic.kibana.server_username; - + dynamic.http = new Http(); - + dynamic.http.anonymous_auth_enabled = c6.dynamic.http.anonymous_auth_enabled; - + dynamic.http.xff = new Xff(); - + dynamic.http.xff.enabled = c6.dynamic.http.xff.enabled; dynamic.http.xff.internalProxies = c6.dynamic.http.xff.internalProxies; dynamic.http.xff.remoteIpHeader = c6.dynamic.http.xff.remoteIpHeader; - + dynamic.authc = new Authc(); - + dynamic.authc.domains.putAll(c6.dynamic.authc.getDomains().entrySet().stream().collect(Collectors.toMap( - entry -> entry.getKey(), + entry -> entry.getKey(), entry -> new AuthcDomain(entry.getValue())))); - + dynamic.authz = new Authz(); - + dynamic.authz.domains.putAll(c6.dynamic.authz.getDomains().entrySet().stream().collect(Collectors.toMap( - entry -> entry.getKey(), + entry -> entry.getKey(), entry -> new AuthzDomain(entry.getValue())))); - + dynamic.auth_failure_listeners = new AuthFailureListeners(); dynamic.auth_failure_listeners.listeners.putAll(c6.dynamic.auth_failure_listeners.getListeners().entrySet().stream().collect(Collectors.toMap( - entry -> entry.getKey(), + entry -> entry.getKey(), entry -> new AuthFailureListener(entry.getValue())))); } @@ -127,7 +127,7 @@ public static class Dynamic { public String transport_userrname_attribute; public boolean do_not_fail_on_forbidden_empty; public OnBehalfOf on_behalf_of = new OnBehalfOf(); - + @Override public String toString() { return "Dynamic [filtered_alias_mode=" + filtered_alias_mode + ", kibana=" + kibana + ", http=" + http + ", authc=" + authc + ", authz=" @@ -153,9 +153,9 @@ public String toString() { server_username + ", opendistro_role=" + opendistro_role + ", index=" + index + "]"; } - - - + + + } public static class Http { @@ -165,8 +165,8 @@ public static class Http { public String toString() { return "Http [anonymous_auth_enabled=" + anonymous_auth_enabled + ", xff=" + xff + "]"; } - - + + } public static class AuthFailureListeners { @@ -183,7 +183,7 @@ public Map getListeners() { return listeners; } - + } public static class AuthFailureListener { @@ -194,9 +194,9 @@ public static class AuthFailureListener { public int block_expiry_seconds = 60 * 10; public int max_blocked_clients = 100_000; public int max_tracked_clients = 100_000; - - - + + + public AuthFailureListener() { super(); } @@ -211,7 +211,7 @@ public AuthFailureListener(ConfigV6.AuthFailureListener v6) { this.max_blocked_clients = v6.max_blocked_clients; this.max_tracked_clients = v6.max_tracked_clients; } - + @JsonIgnore public String asJson() { try { @@ -237,12 +237,12 @@ public static class Xff { public String toString() { return "Xff [enabled=" + enabled + ", internalProxies=" + internalProxies + ", remoteIpHeader=" + remoteIpHeader+"]"; } - - + + } public static class Authc { - + @JsonIgnore private final Map domains = new HashMap<>(); @@ -260,9 +260,9 @@ public Map getDomains() { public String toString() { return "Authc [domains=" + domains + "]"; } - - - + + + } public static class AuthcDomain { @@ -276,11 +276,11 @@ public static class AuthcDomain { public HttpAuthenticator http_authenticator = new HttpAuthenticator(); public AuthcBackend authentication_backend = new AuthcBackend(); public String description; - + public AuthcDomain() { super(); } - + public AuthcDomain(ConfigV6.AuthcDomain v6) { super(); http_enabled = v6.http_enabled && v6.enabled; @@ -301,8 +301,8 @@ public String toString() { + ", http_authenticator=" + http_authenticator + ", authentication_backend=" + authentication_backend + ", description=" + description + "]"; } - - + + } public static class HttpAuthenticator { @@ -310,7 +310,7 @@ public static class HttpAuthenticator { public boolean challenge = true; public String type; public Map config = Collections.emptyMap(); - + public HttpAuthenticator() { super(); } @@ -337,16 +337,16 @@ public String configAsJson() { public String toString() { return "HttpAuthenticator [challenge=" + challenge + ", type=" + type + ", config=" + config + "]"; } - - + + } public static class AuthzBackend { public String type = "noop"; public Map config = Collections.emptyMap(); - - - + + + public AuthzBackend() { super(); } @@ -375,16 +375,16 @@ public String configAsJson() { public String toString() { return "AuthzBackend [type=" + type + ", config=" + config + "]"; } - - + + } public static class AuthcBackend { public String type = InternalAuthenticationBackend.class.getName(); public Map config = Collections.emptyMap(); - - - + + + public AuthcBackend() { super(); } @@ -413,8 +413,8 @@ public String configAsJson() { public String toString() { return "AuthcBackend [type=" + type + ", config=" + config + "]"; } - - + + } public static class Authz { @@ -435,8 +435,8 @@ public Map getDomains() { public String toString() { return "Authz [domains=" + domains + "]"; } - - + + } public static class AuthzDomain { @@ -446,11 +446,11 @@ public static class AuthzDomain { public boolean transport_enabled = true; public AuthzBackend authorization_backend = new AuthzBackend(); public String description; - + public AuthzDomain() { super(); } - + public AuthzDomain(ConfigV6.AuthzDomain v6) { http_enabled = v6.http_enabled && v6.enabled; transport_enabled = v6.transport_enabled && v6.enabled; @@ -502,4 +502,5 @@ public String toString() { return "OnBehalfOf [signing_key=" + signingKey + ", encryption_key=" + encryptionKey +"]"; } } + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v7/InternalUserV7.java b/src/main/java/org/opensearch/security/securityconf/impl/v7/InternalUserV7.java index b697a9485b..a7aed05cc1 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v7/InternalUserV7.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v7/InternalUserV7.java @@ -40,7 +40,7 @@ import org.opensearch.security.securityconf.impl.v6.InternalUserV6; public class InternalUserV7 implements Hideable, Hashed, StaticDefinable { - + private String hash; private boolean reserved; private boolean hidden; @@ -79,7 +79,7 @@ public InternalUserV7() { super(); //default constructor } - + public InternalUserV7(InternalUserV6 u6) { hash = u6.getHash(); reserved = u6.isReserved(); @@ -95,15 +95,15 @@ public String getHash() { public void setHash(String hash) { this.hash = hash; } - - + + public boolean isHidden() { return hidden; } public void setHidden(boolean hidden) { this.hidden = hidden; } - + public List getBackend_roles() { return backend_roles; @@ -171,7 +171,7 @@ public boolean isReserved() { public void setReserved(boolean reserved) { this.reserved = reserved; } - + @JsonProperty(value = "static") public boolean isStatic() { return _static; @@ -180,6 +180,6 @@ public boolean isStatic() { public void setStatic(boolean _static) { this._static = _static; } - - + + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v7/RoleMappingsV7.java b/src/main/java/org/opensearch/security/securityconf/impl/v7/RoleMappingsV7.java index c97ad2f92f..364d524497 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v7/RoleMappingsV7.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v7/RoleMappingsV7.java @@ -124,6 +124,6 @@ public String toString() { } - + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v7/RoleV7.java b/src/main/java/org/opensearch/security/securityconf/impl/v7/RoleV7.java index 262f8ed21d..dce4652d63 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v7/RoleV7.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v7/RoleV7.java @@ -51,11 +51,11 @@ public class RoleV7 implements Hideable, StaticDefinable { private List cluster_permissions = Collections.emptyList(); private List index_permissions = Collections.emptyList(); private List tenant_permissions = Collections.emptyList(); - + public RoleV7() { - + } - + public RoleV7(RoleV6 roleV6) { this.reserved = roleV6.isReserved(); this.hidden = roleV6.isHidden(); @@ -63,24 +63,24 @@ public RoleV7(RoleV6 roleV6) { this.cluster_permissions = roleV6.getCluster(); index_permissions = new ArrayList<>(); tenant_permissions = new ArrayList<>(); - + for(Entry v6i: roleV6.getIndices().entrySet()) { index_permissions.add(new Index(v6i.getKey(), v6i.getValue())); } - + //rw tenants List rwTenants = roleV6.getTenants().entrySet().stream().filter(e-> "rw".equalsIgnoreCase(e.getValue())).map(e->e.getKey()).collect(Collectors.toList()); - + if(rwTenants != null && !rwTenants.isEmpty()) { Tenant t = new Tenant(); t.setAllowed_actions(Collections.singletonList("kibana_all_write")); t.setTenant_patterns(rwTenants); tenant_permissions.add(t); } - - + + List roTenants = roleV6.getTenants().entrySet().stream().filter(e-> "ro".equalsIgnoreCase(e.getValue())).map(e->e.getKey()).collect(Collectors.toList()); - + if(roTenants != null && !roTenants.isEmpty()) { Tenant t = new Tenant(); t.setAllowed_actions(Collections.singletonList("kibana_all_read")); @@ -97,25 +97,25 @@ public static class Index { private List fls = Collections.emptyList(); private List masked_fields = Collections.emptyList(); private List allowed_actions = Collections.emptyList(); - + public Index(String pattern, RoleV6.Index v6Index) { super(); index_patterns = Collections.singletonList(pattern); dls = v6Index.get_dls_(); fls = v6Index.get_fls_(); masked_fields = v6Index.get_masked_fields_(); - Set tmpActions = new HashSet<>(); + Set tmpActions = new HashSet<>(); for(Entry> type: v6Index.getTypes().entrySet()) { tmpActions.addAll(type.getValue()); } allowed_actions = new ArrayList<>(tmpActions); } - - + + public Index() { super(); } - + public List getIndex_patterns() { return index_patterns; } @@ -152,27 +152,27 @@ public String toString() { + ", allowed_actions=" + allowed_actions + "]"; } } - - + + public static class Tenant { private List tenant_patterns = Collections.emptyList(); private List allowed_actions = Collections.emptyList(); - + /*public Index(String pattern, RoleV6.Index v6Index) { super(); index_patterns = Collections.singletonList(pattern); dls = v6Index.get_dls_(); fls = v6Index.get_fls_(); masked_fields = v6Index.get_masked_fields_(); - Set tmpActions = new HashSet<>(); + Set tmpActions = new HashSet<>(); for(Entry> type: v6Index.getTypes().entrySet()) { tmpActions.addAll(type.getValue()); } allowed_actions = new ArrayList<>(tmpActions); }*/ - - + + public Tenant() { super(); } @@ -197,10 +197,10 @@ public void setAllowed_actions(List allowed_actions) { public String toString() { return "Tenant [tenant_patterns=" + tenant_patterns + ", allowed_actions=" + allowed_actions + "]"; } - - + + } - + public boolean isHidden() { return hidden; @@ -226,7 +226,7 @@ public void setCluster_permissions(List cluster_permissions) { this.cluster_permissions = cluster_permissions; } - + public List getIndex_permissions() { return index_permissions; @@ -267,9 +267,9 @@ public String toString() { + ", cluster_permissions=" + cluster_permissions + ", index_permissions=" + index_permissions + ", tenant_permissions=" + tenant_permissions + "]"; } - - - + + + } diff --git a/src/main/java/org/opensearch/security/securityconf/impl/v7/TenantV7.java b/src/main/java/org/opensearch/security/securityconf/impl/v7/TenantV7.java index 210fada185..1c55d0cd95 100644 --- a/src/main/java/org/opensearch/security/securityconf/impl/v7/TenantV7.java +++ b/src/main/java/org/opensearch/security/securityconf/impl/v7/TenantV7.java @@ -39,7 +39,7 @@ public class TenantV7 implements Hideable, StaticDefinable { @JsonProperty(value = "static") private boolean _static; private String description; - + public boolean isHidden() { return hidden; } @@ -58,8 +58,8 @@ public boolean isReserved() { public void setReserved(boolean reserved) { this.reserved = reserved; } - - + + @JsonProperty(value = "static") public boolean isStatic() { return _static; @@ -72,6 +72,6 @@ public void setStatic(boolean _static) { public String toString() { return "TenantV7 [reserved=" + reserved + ", hidden=" + hidden + ", _static=" + _static + ", description=" + description + "]"; } - - + + } diff --git a/src/main/java/org/opensearch/security/ssl/ExternalSecurityKeyStore.java b/src/main/java/org/opensearch/security/ssl/ExternalSecurityKeyStore.java index 3fbbab69d6..87713a1d3a 100644 --- a/src/main/java/org/opensearch/security/ssl/ExternalSecurityKeyStore.java +++ b/src/main/java/org/opensearch/security/ssl/ExternalSecurityKeyStore.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl; @@ -45,13 +45,13 @@ public ExternalSecurityKeyStore(final Settings settings) { this.settings = Objects.requireNonNull(settings); final String externalContextId = settings .get(SSLConfigConstants.SECURITY_SSL_CLIENT_EXTERNAL_CONTEXT_ID, null); - + if(externalContextId == null || externalContextId.length() == 0) { throw new OpenSearchException("no external ssl context id was set"); } - + externalSslContext = contextMap.get(externalContextId); - + if(externalSslContext == null) { throw new OpenSearchException("no external ssl context for id "+externalContextId); } @@ -70,7 +70,7 @@ public SSLEngine createServerTransportSSLEngine() throws SSLException { @Override public SSLEngine createClientTransportSSLEngine(final String peerHost, final int peerPort) throws SSLException { if (peerHost != null) { - final SSLEngine engine = externalSslContext.createSSLEngine(peerHost, peerPort); + final SSLEngine engine = externalSslContext.createSSLEngine(peerHost, peerPort); final SSLParameters sslParams = new SSLParameters(); sslParams.setEndpointIdentificationAlgorithm("HTTPS"); engine.setSSLParameters(sslParams); @@ -135,31 +135,31 @@ public String getSubjectAlternativeNames(X509Certificate cert) { public static void registerExternalSslContext(String id, SSLContext externalSsslContext) { contextMap.put(Objects.requireNonNull(id), Objects.requireNonNull(externalSsslContext)); } - + public static boolean hasExternalSslContext(Settings settings) { - + final String externalContextId = settings .get(SSLConfigConstants.SECURITY_SSL_CLIENT_EXTERNAL_CONTEXT_ID, null); - + if(externalContextId == null || externalContextId.length() == 0) { return false; } - + return contextMap.containsKey(externalContextId); } - + public static boolean hasExternalSslContext(String id) { return contextMap.containsKey(id); } - + public static void removeExternalSslContext(String id) { contextMap.remove(id); } - + public static void removeAllExternalSslContexts() { contextMap.clear(); } - + private String[] evalSecure(String[] engineEnabled, String[] secure) { List tmp = new ArrayList<>(Arrays.asList(engineEnabled)); tmp.retainAll(Arrays.asList(secure)); diff --git a/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java b/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java index 755a2b188f..ab96c7bb3e 100644 --- a/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java +++ b/src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl; @@ -122,7 +122,7 @@ protected OpenSearchSecuritySSLPlugin(final Settings settings, final Path config this.sks = null; this.configPath = null; SSLConfig = new SSLConfig(false, false); - + AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { @@ -130,36 +130,36 @@ public Object run() { return null; } }); - - + + return; } SSLConfig = new SSLConfig(settings); this.configPath = configPath; - + if(this.configPath != null) { log.info("OpenSearch Config path is {}", this.configPath.toAbsolutePath()); } else { log.info("OpenSearch Config path is not set"); } - + final boolean allowClientInitiatedRenegotiation = settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_ALLOW_CLIENT_INITIATED_RENEGOTIATION, false); final boolean rejectClientInitiatedRenegotiation = Boolean.parseBoolean(System.getProperty(SSLConfigConstants.JDK_TLS_REJECT_CLIENT_INITIATED_RENEGOTIATION)); - + if(allowClientInitiatedRenegotiation && !rejectClientInitiatedRenegotiation) { final String renegoMsg = "Client side initiated TLS renegotiation enabled. This can open a vulnerablity for DoS attacks through client side initiated TLS renegotiation."; log.warn(renegoMsg); System.out.println(renegoMsg); System.err.println(renegoMsg); - } else { + } else { if(!rejectClientInitiatedRenegotiation) { - + final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new SpecialPermission()); } - + AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { @@ -198,7 +198,7 @@ public Object run() { NonValidatingObjectMapper.inject(injectableValues); client = !"node".equals(this.settings.get(OpenSearchSecuritySSLPlugin.CLIENT_TYPE)); - + httpSSLEnabled = settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_DEFAULT); transportSSLEnabled = settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, @@ -211,7 +211,7 @@ public Object run() { System.out.println("SSL not activated for http and/or transport."); System.err.println("SSL not activated for http and/or transport."); } - + if(ExternalSecurityKeyStore.hasExternalSslContext(settings)) { this.sks = new ExternalSecurityKeyStore(settings); } else { @@ -223,9 +223,9 @@ public Object run() { public Map> getHttpTransports(Settings settings, ThreadPool threadPool, BigArrays bigArrays, PageCacheRecycler pageCacheRecycler, CircuitBreakerService circuitBreakerService, NamedXContentRegistry xContentRegistry, NetworkService networkService, Dispatcher dispatcher, ClusterSettings clusterSettings) { - + if (!client && httpSSLEnabled) { - + final ValidatingDispatcher validatingDispatcher = new ValidatingDispatcher(threadPool.getThreadContext(), dispatcher, settings, configPath, NOOP_SSL_EXCEPTION_HANDLER); final SecuritySSLNettyHttpServerTransport sgsnht = new SecuritySSLNettyHttpServerTransport(settings, networkService, bigArrays, threadPool, @@ -233,7 +233,7 @@ public Map> getHttpTransports(Settings set sharedGroupFactory); return Collections.singletonMap("org.opensearch.security.ssl.http.netty.SecuritySSLNettyHttpServerTransport", () -> sgsnht); - + } return Collections.emptyMap(); @@ -243,35 +243,35 @@ public Map> getHttpTransports(Settings set public List getRestHandlers(Settings settings, RestController restController, ClusterSettings clusterSettings, IndexScopedSettings indexScopedSettings, SettingsFilter settingsFilter, IndexNameExpressionResolver indexNameExpressionResolver, Supplier nodesInCluster) { - + final List handlers = new ArrayList(1); - + if (!client) { handlers.add(new SecuritySSLInfoAction(settings, configPath, restController, sks, Objects.requireNonNull(principalExtractor))); } - + return handlers; } - - - + + + @Override public List getTransportInterceptors(NamedWriteableRegistry namedWriteableRegistry, ThreadContext threadContext) { List interceptors = new ArrayList(1); - + if(transportSSLEnabled && !client) { interceptors.add(new SecuritySSLTransportInterceptor(settings, null, null, SSLConfig, NOOP_SSL_EXCEPTION_HANDLER)); } - + return interceptors; } - - + + @Override public Map> getTransports(Settings settings, ThreadPool threadPool, PageCacheRecycler pageCacheRecycler, CircuitBreakerService circuitBreakerService, NamedWriteableRegistry namedWriteableRegistry, NetworkService networkService) { - + Map> transports = new HashMap>(); if (transportSSLEnabled) { transports.put("org.opensearch.security.ssl.http.netty.SecuritySSLNettyTransport", @@ -290,11 +290,11 @@ public Collection createComponents(Client localClient, ClusterService cl IndexNameExpressionResolver indexNameExpressionResolver, Supplier repositoriesServiceSupplier) { final List components = new ArrayList<>(1); - + if(client) { return components; } - + final String principalExtractorClass = settings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PRINCIPAL_EXTRACTOR_CLASS, null); if(principalExtractorClass == null) { @@ -309,9 +309,9 @@ public Collection createComponents(Client localClient, ClusterService cl throw new OpenSearchException(e); } } - + components.add(principalExtractor); - + return components; } @@ -389,24 +389,24 @@ public List> getSettings() { @Override public Settings additionalSettings() { final Settings.Builder builder = Settings.builder(); - + if(!client && httpSSLEnabled) { - + if(settings.get("http.compression") == null) { builder.put("http.compression", false); log.info("Disabled https compression by default to mitigate BREACH attacks. You can enable it by setting 'http.compression: true' in opensearch.yml"); } - + builder.put(NetworkModule.HTTP_TYPE_KEY, "org.opensearch.security.ssl.http.netty.SecuritySSLNettyHttpServerTransport"); } - + if (transportSSLEnabled) { builder.put(NetworkModule.TRANSPORT_TYPE_KEY, "org.opensearch.security.ssl.http.netty.SecuritySSLNettyTransport"); } - + return builder.build(); } - + @Override public List getSettingsFilter() { List settingsFilter = new ArrayList<>(); diff --git a/src/main/java/org/opensearch/security/ssl/SecurityKeyStore.java b/src/main/java/org/opensearch/security/ssl/SecurityKeyStore.java index a14e8e7df1..107c48f0f5 100644 --- a/src/main/java/org/opensearch/security/ssl/SecurityKeyStore.java +++ b/src/main/java/org/opensearch/security/ssl/SecurityKeyStore.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl; @@ -33,7 +33,7 @@ public interface SecurityKeyStore { public String getHTTPProviderName(); public String getTransportServerProviderName(); public String getTransportClientProviderName(); - public String getSubjectAlternativeNames(X509Certificate cert); + public String getSubjectAlternativeNames(X509Certificate cert); public void initHttpSSLConfig(); public void initTransportSSLConfig(); diff --git a/src/main/java/org/opensearch/security/ssl/SslExceptionHandler.java b/src/main/java/org/opensearch/security/ssl/SslExceptionHandler.java index 531711dc54..427debfdba 100644 --- a/src/main/java/org/opensearch/security/ssl/SslExceptionHandler.java +++ b/src/main/java/org/opensearch/security/ssl/SslExceptionHandler.java @@ -1,10 +1,10 @@ /* * Copyright 2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl; @@ -22,15 +22,15 @@ import org.opensearch.transport.TransportRequest; public interface SslExceptionHandler { - + default void logError(Throwable t, RestRequest request, int type) { //no-op } - + default void logError(Throwable t, boolean isRest) { //no-op } - + default void logError(Throwable t, final TransportRequest request, String action, Task task, int type) { //no-op } diff --git a/src/main/java/org/opensearch/security/ssl/http/netty/SecuritySSLNettyHttpServerTransport.java b/src/main/java/org/opensearch/security/ssl/http/netty/SecuritySSLNettyHttpServerTransport.java index 7c53b6268a..b6012f036e 100644 --- a/src/main/java/org/opensearch/security/ssl/http/netty/SecuritySSLNettyHttpServerTransport.java +++ b/src/main/java/org/opensearch/security/ssl/http/netty/SecuritySSLNettyHttpServerTransport.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.http.netty; @@ -45,7 +45,7 @@ public class SecuritySSLNettyHttpServerTransport extends Netty4HttpServerTranspo private static final Logger logger = LogManager.getLogger(SecuritySSLNettyHttpServerTransport.class); private final SecurityKeyStore sks; private final SslExceptionHandler errorHandler; - + public SecuritySSLNettyHttpServerTransport(final Settings settings, final NetworkService networkService, final BigArrays bigArrays, final ThreadPool threadPool, final SecurityKeyStore sks, final NamedXContentRegistry namedXContentRegistry, final ValidatingDispatcher dispatcher, final SslExceptionHandler errorHandler, ClusterSettings clusterSettings, SharedGroupFactory sharedGroupFactory) { @@ -94,7 +94,7 @@ protected void configurePipeline(ChannelHandlerContext ctx, String protocol) thr throw new IllegalStateException("Unknown application protocol: " + protocol); } } - + @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { super.exceptionCaught(ctx, cause); @@ -119,7 +119,7 @@ protected void initChannel(Channel ch) throws Exception { final SslHandler sslHandler = new SslHandler(SecuritySSLNettyHttpServerTransport.this.sks.createHTTPSSLEngine()); ch.pipeline().addFirst("ssl_http", sslHandler); } - + @Override protected void configurePipeline(Channel ch) { ch.pipeline().addLast(new Http2OrHttpHandler()); diff --git a/src/main/java/org/opensearch/security/ssl/http/netty/ValidatingDispatcher.java b/src/main/java/org/opensearch/security/ssl/http/netty/ValidatingDispatcher.java index 66976a930b..32a1f73568 100644 --- a/src/main/java/org/opensearch/security/ssl/http/netty/ValidatingDispatcher.java +++ b/src/main/java/org/opensearch/security/ssl/http/netty/ValidatingDispatcher.java @@ -1,10 +1,10 @@ /* * Copyright 2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.http.netty; @@ -47,7 +47,7 @@ public class ValidatingDispatcher implements Dispatcher { private final Settings settings; private final Path configPath; - public ValidatingDispatcher(final ThreadContext threadContext, final Dispatcher originalDispatcher, + public ValidatingDispatcher(final ThreadContext threadContext, final Dispatcher originalDispatcher, final Settings settings, final Path configPath, final SslExceptionHandler errorHandler) { super(); this.threadContext = threadContext; @@ -68,15 +68,15 @@ public void dispatchBadRequest(RestChannel channel, ThreadContext threadContext, checkRequest(channel.request(), channel); originalDispatcher.dispatchBadRequest(channel, threadContext, cause); } - + protected void checkRequest(final RestRequest request, final RestChannel channel) { - + if(SSLRequestHelper.containsBadHeader(threadContext, "_opendistro_security_ssl_")) { final OpenSearchException exception = ExceptionUtils.createBadHeaderException(); errorHandler.logError(exception, request, 1); throw exception; } - + try { if(SSLRequestHelper.getSSLInfo(settings, configPath, request, null) == null) { logger.error("Not an SSL request"); diff --git a/src/main/java/org/opensearch/security/ssl/rest/SecuritySSLInfoAction.java b/src/main/java/org/opensearch/security/ssl/rest/SecuritySSLInfoAction.java index f5050d3242..5b1fae01e5 100644 --- a/src/main/java/org/opensearch/security/ssl/rest/SecuritySSLInfoAction.java +++ b/src/main/java/org/opensearch/security/ssl/rest/SecuritySSLInfoAction.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.rest; @@ -68,11 +68,11 @@ public SecuritySSLInfoAction(final Settings settings, final Path configPath, fin public List routes() { return routes; } - + @Override protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { return new RestChannelConsumer() { - + final Boolean showDn = request.paramAsBoolean("show_dn", Boolean.FALSE); @Override @@ -81,7 +81,7 @@ public void accept(RestChannel channel) throws Exception { BytesRestResponse response = null; try { - + SSLInfo sslInfo = SSLRequestHelper.getSSLInfo(settings, configPath, request, principalExtractor); X509Certificate[] certs = sslInfo == null?null:sslInfo.getX509Certs(); X509Certificate[] localCerts = sslInfo == null?null:sslInfo.getLocalCertificates(); @@ -123,7 +123,7 @@ public void accept(RestChannel channel) throws Exception { builder.close(); } } - + channel.sendResponse(response); } }; diff --git a/src/main/java/org/opensearch/security/ssl/transport/DefaultPrincipalExtractor.java b/src/main/java/org/opensearch/security/ssl/transport/DefaultPrincipalExtractor.java index d717df2da6..001059eefa 100644 --- a/src/main/java/org/opensearch/security/ssl/transport/DefaultPrincipalExtractor.java +++ b/src/main/java/org/opensearch/security/ssl/transport/DefaultPrincipalExtractor.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.transport; @@ -38,7 +38,7 @@ public class DefaultPrincipalExtractor implements PrincipalExtractor { protected final Logger log = LogManager.getLogger(this.getClass()); - + @Override @SuppressWarnings("removal") public String extractPrincipal(final X509Certificate x509Certificate, final Type type) { @@ -54,7 +54,7 @@ public String extractPrincipal(final X509Certificate x509Certificate, final Type String dnString = AccessController.doPrivileged(new PrivilegedAction() { @Override - public String run() { + public String run() { final X500Principal principal = x509Certificate.getSubjectX500Principal(); return principal.toString(); } @@ -69,12 +69,12 @@ public String run() { } catch (InvalidNameException e) { log.error("Unable to parse: {}",dnString, e); } - - + + if(log.isTraceEnabled()) { log.trace("principal: {}", dnString); } - + return dnString; } diff --git a/src/main/java/org/opensearch/security/ssl/transport/PrincipalExtractor.java b/src/main/java/org/opensearch/security/ssl/transport/PrincipalExtractor.java index 06213af642..cccca06e0c 100644 --- a/src/main/java/org/opensearch/security/ssl/transport/PrincipalExtractor.java +++ b/src/main/java/org/opensearch/security/ssl/transport/PrincipalExtractor.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.transport; @@ -20,7 +20,7 @@ import java.security.cert.X509Certificate; public interface PrincipalExtractor { - + public enum Type { HTTP, TRANSPORT @@ -28,13 +28,13 @@ public enum Type { /** * Extract the principal name - * + * * Please note that this method gets called for principal extraction of other nodes * as well as transport clients. It's up to the implementer to distinguish between them * and handle them appropriately. - * + * * Implementations must be public classes with a default public default constructor. - * + * * @param x509Certificate The first X509 certificate in the peer certificate chain * This can be null, in this case the method must also return null. * @return The principal as string. This may be null in case where x509Certificate is null diff --git a/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLNettyTransport.java b/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLNettyTransport.java index 58da4cb55e..5a38909f81 100644 --- a/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLNettyTransport.java +++ b/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLNettyTransport.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ /* @@ -101,7 +101,7 @@ public void onException(TcpChannel channel, Exception e) { protected ChannelHandler getServerChannelInitializer(String name) { return new SSLServerChannelInitializer(name); } - + @Override protected ChannelHandler getClientChannelInitializer(DiscoveryNode node) { return new SSLClientChannelInitializer(node); @@ -127,7 +127,7 @@ protected void initChannel(Channel ch) throws Exception { ch.pipeline().addFirst("ssl_server", sslHandler); } } - + @Override public final void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { if (cause instanceof DecoderException && cause != null) { @@ -147,7 +147,7 @@ protected static class ClientSSLHandler extends ChannelOutboundHandlerAdapter { private final boolean hostnameVerificationEnabled; private final boolean hostnameVerificationResovleHostName; private final SslExceptionHandler errorHandler; - + private ClientSSLHandler(final SecurityKeyStore sks, final boolean hostnameVerificationEnabled, final boolean hostnameVerificationResovleHostName, final SslExceptionHandler errorHandler) { @@ -156,14 +156,14 @@ private ClientSSLHandler(final SecurityKeyStore sks, final boolean hostnameVerif this.hostnameVerificationResovleHostName = hostnameVerificationResovleHostName; this.errorHandler = errorHandler; } - + @Override public final void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { if (cause instanceof DecoderException && cause != null) { cause = cause.getCause(); } - + errorHandler.logError(cause, false); logger.error("Exception during establishing a SSL connection: " + cause, cause); @@ -186,7 +186,7 @@ public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, Sock if(log.isDebugEnabled()) { log.debug("Hostname of peer is {} ({}/{}) with hostnameVerificationResovleHostName: {}", hostname, inetSocketAddress.getHostName(), inetSocketAddress.getHostString(), hostnameVerificationResovleHostName); } - + engine = sks.createClientTransportSSLEngine(hostname, inetSocketAddress.getPort()); } else { engine = sks.createClientTransportSSLEngine(null, -1); @@ -239,7 +239,7 @@ protected void initChannel(Channel ch) throws Exception { logger.debug("Connection to {} needs to be non ssl", node.getHostName()); } } - + @Override public final void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { if (cause instanceof DecoderException && cause != null) { @@ -249,7 +249,7 @@ public final void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) th errorHandler.logError(cause, false); logger.error("Exception during establishing a SSL connection: " + cause, cause); - + super.exceptionCaught(ctx, cause); } } diff --git a/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLRequestHandler.java b/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLRequestHandler.java index 925f5cf0e9..53877df0f0 100644 --- a/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLRequestHandler.java +++ b/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLRequestHandler.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.transport; @@ -47,7 +47,7 @@ public class SecuritySSLRequestHandler implements TransportRequestHandler { - + private final String action; private final TransportRequestHandler actualHandler; private final ThreadPool threadPool; @@ -68,7 +68,7 @@ public SecuritySSLRequestHandler(String action, TransportRequestHandler actua this.SSLConfig = SSLConfig; this.errorHandler = errorHandler; } - + protected ThreadContext getThreadContext() { if(threadPool == null) { return null; @@ -80,7 +80,7 @@ protected ThreadContext getThreadContext() { @Override public final void messageReceived(T request, TransportChannel channel, Task task) throws Exception { ThreadContext threadContext = getThreadContext() ; - + if(SSLRequestHelper.containsBadHeader(threadContext, "_opendistro_security_ssl_")) { final Exception exception = ExceptionUtils.createBadHeaderException(); channel.sendResponse(exception); @@ -91,12 +91,12 @@ public final void messageReceived(T request, TransportChannel channel, Task task if (!channelType.equals("direct") && !channelType.equals("transport")) { channel = getInnerChannel(channel); } - + if (!"transport".equals(channel.getChannelType())) { //netty4 messageReceivedDecorate(request, actualHandler, channel, task); return; } - + try { Netty4TcpChannel nettyChannel = null; @@ -111,7 +111,7 @@ public final void messageReceived(T request, TransportChannel channel, Task task } else { throw new Exception("Invalid channel of type "+channel.getClass()+ " ("+channel.getChannelType()+")"); } - + final SslHandler sslhandler = (SslHandler) nettyChannel.getNettyChannel().pipeline().get("ssl_server"); if (sslhandler == null) { @@ -131,11 +131,11 @@ public final void messageReceived(T request, TransportChannel channel, Task task final Certificate[] peerCerts = sslhandler.engine().getSession().getPeerCertificates(); final Certificate[] localCerts = sslhandler.engine().getSession().getLocalCertificates(); - - if (peerCerts != null - && peerCerts.length > 0 - && peerCerts[0] instanceof X509Certificate - && localCerts != null && localCerts.length > 0 + + if (peerCerts != null + && peerCerts.length > 0 + && peerCerts[0] instanceof X509Certificate + && localCerts != null && localCerts.length > 0 && localCerts[0] instanceof X509Certificate) { final X509Certificate[] x509PeerCerts = Arrays.copyOf(peerCerts, peerCerts.length, X509Certificate[].class); final X509Certificate[] x509LocalCerts = Arrays.copyOf(localCerts, localCerts.length, X509Certificate[].class); @@ -168,7 +168,7 @@ public final void messageReceived(T request, TransportChannel channel, Task task errorHandler.logError(e, request, action, task, 0); throw e; } - + } protected TransportChannel getInnerChannel(TransportChannel transportChannel) throws Exception { @@ -182,12 +182,12 @@ protected TransportChannel getInnerChannel(TransportChannel transportChannel) th throw new RuntimeException("Unknown channel type " + transportChannel.getChannelType() + " does not implement getInnerChannel method."); } } - + protected void addAdditionalContextValues(final String action, final TransportRequest request, final X509Certificate[] localCerts, final X509Certificate[] peerCerts, final String principal) throws Exception { // no-op } - + protected void messageReceivedDecorate(final T request, final TransportRequestHandler actualHandler, final TransportChannel transportChannel, Task task) throws Exception { actualHandler.messageReceived(request, transportChannel, task); } diff --git a/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLTransportInterceptor.java b/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLTransportInterceptor.java index 165662d429..aa83265125 100644 --- a/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLTransportInterceptor.java +++ b/src/main/java/org/opensearch/security/ssl/transport/SecuritySSLTransportInterceptor.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.transport; @@ -28,7 +28,7 @@ import org.opensearch.transport.TransportRequestHandler; public final class SecuritySSLTransportInterceptor implements TransportInterceptor { - + protected final Logger log = LogManager.getLogger(this.getClass()); protected final ThreadPool threadPool; protected final PrincipalExtractor principalExtractor; @@ -49,6 +49,6 @@ public TransportRequestHandler interceptHandler( TransportRequestHandler actualHandler) { return new SecuritySSLRequestHandler(action, actualHandler, threadPool, principalExtractor, SSLConfig, errorHandler); } - - + + } diff --git a/src/main/java/org/opensearch/security/ssl/util/CertificateValidator.java b/src/main/java/org/opensearch/security/ssl/util/CertificateValidator.java index 0a12ffc2b5..b0a975b618 100644 --- a/src/main/java/org/opensearch/security/ssl/util/CertificateValidator.java +++ b/src/main/java/org/opensearch/security/ssl/util/CertificateValidator.java @@ -59,14 +59,14 @@ * Allows specifying Certificate Revocation List (CRL), as well as enabling * CRL Distribution Points Protocol (CRLDP) certificate extension support, * and also enabling On-Line Certificate Status Protocol (OCSP) support. - * + * * IMPORTANT: at least one of the above mechanisms *MUST* be configured and * operational, otherwise certificate validation *WILL FAIL* unconditionally. */ // CS-ENFORCE-SINGLE public class CertificateValidator { - + boolean isPreferCrl() { return preferCrl; } @@ -95,16 +95,16 @@ void setCheckOnlyEndEntities(boolean checkOnlyEndEntities) { private boolean _enableOCSP = false; /** Location of OCSP Responder */ private String _ocspResponderURL; - + private boolean preferCrl = false; private boolean checkOnlyEndEntities = true; private Date date = null; //current date - + /** - * creates an instance of the certificate validator + * creates an instance of the certificate validator * - * @param trustStore the truststore to use - * @param crls the Certificate Revocation List to use + * @param trustStore the truststore to use + * @param crls the Certificate Revocation List to use */ public CertificateValidator(KeyStore trustStore, Collection crls) { @@ -112,18 +112,18 @@ public CertificateValidator(KeyStore trustStore, Collection crls) { throw new InvalidParameterException("TrustStore must be specified for CertificateValidator."); } - + _trustStore = trustStore; _crls = crls; } - + public CertificateValidator(X509Certificate[] trustedCert, Collection crls) { if (trustedCert == null || trustedCert.length == 0) { throw new InvalidParameterException("trustedCert must be specified for CertificateValidator."); } - + _trustedCert = trustedCert; _crls = crls; } @@ -137,7 +137,7 @@ public void validate(Certificate[] certChain) throws CertificateException { if (item == null) continue; - + if (!(item instanceof X509Certificate)) { throw new IllegalStateException("Invalid certificate type in chain"); @@ -149,34 +149,34 @@ public void validate(Certificate[] certChain) throws CertificateException if (certList.isEmpty()) { throw new IllegalStateException("Invalid certificate chain"); - + } - + X509CertSelector certSelect = new X509CertSelector(); certSelect.setCertificate(certList.get(0)); - + CertPathBuilder certPathBuilder = CertPathBuilder.getInstance("PKIX"); PKIXRevocationChecker revocationChecker = (PKIXRevocationChecker) certPathBuilder.getRevocationChecker(); Set opts = new HashSet<>(); - + if(preferCrl) { opts.add(PKIXRevocationChecker.Option.PREFER_CRLS); } - + //opts.add(PKIXRevocationChecker.Option.SOFT_FAIL); - + //opts.add(PKIXRevocationChecker.Option.NO_FALLBACK); - + if(checkOnlyEndEntities) { opts.add(PKIXRevocationChecker.Option.ONLY_END_ENTITY); } - + revocationChecker.setOptions(opts); // Configure certification path builder parameters PKIXBuilderParameters pbParams = null; - + if(_trustStore != null) { pbParams = new PKIXBuilderParameters(_trustStore, certSelect); } else { @@ -189,25 +189,25 @@ public void validate(Certificate[] certChain) throws CertificateException pbParams = new PKIXBuilderParameters(trustAnchors, certSelect); } - + pbParams.addCertPathChecker(revocationChecker); - + pbParams.setDate(date); - + pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList))); - + // Set maximum certification path length pbParams.setMaxPathLength(_maxCertPathLength); - + // Enable revocation checking pbParams.setRevocationEnabled(true); - + // Set static Certificate Revocation List if (_crls != null && !_crls.isEmpty()) { pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(_crls))); } - + // Enable On-Line Certificate Status Protocol (OCSP) support if (_enableOCSP) { @@ -218,10 +218,10 @@ public void validate(Certificate[] certChain) throws CertificateException { System.setProperty("com.sun.security.enableCRLDP","true"); } - + // Build certification path - CertPathBuilderResult buildResult = CertPathBuilder.getInstance("PKIX").build(pbParams); - + CertPathBuilderResult buildResult = CertPathBuilder.getInstance("PKIX").build(pbParams); + // Validate certification path CertPathValidator.getInstance("PKIX").validate(buildResult.getCertPath(),pbParams); } @@ -255,9 +255,9 @@ public void setMaxCertPathLength(int maxCertPathLength) { _maxCertPathLength = maxCertPathLength; } - + /* ------------------------------------------------------------ */ - /** + /** * @return true if CRL Distribution Points support is enabled */ public boolean isEnableCRLDP() @@ -275,7 +275,7 @@ public void setEnableCRLDP(boolean enableCRLDP) } /* ------------------------------------------------------------ */ - /** + /** * @return true if On-Line Certificate Status Protocol support is enabled */ public boolean isEnableOCSP() @@ -293,7 +293,7 @@ public void setEnableOCSP(boolean enableOCSP) } /* ------------------------------------------------------------ */ - /** + /** * @return Location of the OCSP Responder */ public String getOcspResponderURL() diff --git a/src/main/java/org/opensearch/security/ssl/util/ExceptionUtils.java b/src/main/java/org/opensearch/security/ssl/util/ExceptionUtils.java index f06c4d9808..e2af22844f 100644 --- a/src/main/java/org/opensearch/security/ssl/util/ExceptionUtils.java +++ b/src/main/java/org/opensearch/security/ssl/util/ExceptionUtils.java @@ -1,10 +1,10 @@ /* * Copyright 2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.util; @@ -20,30 +20,30 @@ import org.opensearch.OpenSearchException; public class ExceptionUtils { - + public static Throwable getRootCause(final Throwable e) { - + if(e == null) { return null; } - + final Throwable cause = e.getCause(); if(cause == null) { return e; } return getRootCause(cause); } - + public static Throwable findMsg(final Throwable e, String msg) { - + if(e == null) { return null; } - + if(e.getMessage() != null && e.getMessage().contains(msg)) { return e; } - + final Throwable cause = e.getCause(); if(cause == null) { return null; diff --git a/src/main/java/org/opensearch/security/ssl/util/SSLCertificateHelper.java b/src/main/java/org/opensearch/security/ssl/util/SSLCertificateHelper.java index ff36cc40a8..42b44a3817 100644 --- a/src/main/java/org/opensearch/security/ssl/util/SSLCertificateHelper.java +++ b/src/main/java/org/opensearch/security/ssl/util/SSLCertificateHelper.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.util; @@ -40,20 +40,20 @@ public class SSLCertificateHelper { private static final Logger log = LogManager.getLogger(SSLCertificateHelper.class); private static boolean stripRootFromChain = true; //TODO check - + public static X509Certificate[] exportRootCertificates(final KeyStore ks, final String alias) throws KeyStoreException { logKeyStore(ks); - + final List trustedCerts = new ArrayList(); - + if (Strings.isNullOrEmpty(alias)) { - + if(log.isDebugEnabled()) { log.debug("No alias given, will trust all of the certificates in the store"); } - + final List aliases = toList(ks.aliases()); - + for (final String _alias : aliases) { if (ks.isCertificateEntry(_alias)) { @@ -79,12 +79,12 @@ public static X509Certificate[] exportRootCertificates(final KeyStore ks, final } return trustedCerts.toArray(new X509Certificate[0]); - } - + } + public static X509Certificate[] exportServerCertChain(final KeyStore ks, String alias) throws KeyStoreException { logKeyStore(ks); final List aliases = toList(ks.aliases()); - + if (Strings.isNullOrEmpty(alias)) { if(aliases.isEmpty()) { log.error("Keystore does not contain any aliases"); @@ -92,7 +92,7 @@ public static X509Certificate[] exportServerCertChain(final KeyStore ks, String alias = aliases.get(0); log.info("No alias given, use the first one: {}", alias); } - } + } final Certificate[] certs = ks.getCertificateChain(alias); if (certs != null && certs.length > 0) { @@ -103,7 +103,7 @@ public static X509Certificate[] exportServerCertChain(final KeyStore ks, String if (lastCertificate.getBasicConstraints() > -1 && lastCertificate.getSubjectX500Principal().equals(lastCertificate.getIssuerX500Principal())) { log.warn("Certificate chain for alias {} contains a root certificate", alias); - + if(stripRootFromChain ) { x509Certs = Arrays.copyOf(certs, certs.length-1, X509Certificate[].class); } @@ -143,7 +143,7 @@ public static PrivateKey exportDecryptedKey(final KeyStore ks, final String alia return null; } - + private static void logKeyStore(final KeyStore ks) { try { final List aliases = toList(ks.aliases()); @@ -175,14 +175,14 @@ private static void logKeyStore(final KeyStore ks) { log.error("Error logging keystore due to "+e, e); } } - + private static List toList(final Enumeration enumeration) { final List aliases = new ArrayList<>(); while (enumeration.hasMoreElements()) { aliases.add(enumeration.nextElement()); } - + return Collections.unmodifiableList(aliases); } } diff --git a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java index 65eaec238a..63b2ae5502 100644 --- a/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java +++ b/src/main/java/org/opensearch/security/ssl/util/SSLConfigConstants.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.util; @@ -88,15 +88,15 @@ public final class SSLConfigConstants { public static final String SECURITY_SSL_ALLOW_CLIENT_INITIATED_RENEGOTIATION = "plugins.security.ssl.allow_client_initiated_renegotiation"; public static final String DEFAULT_STORE_PASSWORD = "changeit"; //#16 - + public static final String JDK_TLS_REJECT_CLIENT_INITIATED_RENEGOTIATION = "jdk.tls.rejectClientInitiatedRenegotiation"; - + private static final String[] _SECURE_SSL_PROTOCOLS = {"TLSv1.3", "TLSv1.2", "TLSv1.1"}; - + public static final String[] getSecureSSLProtocols(Settings settings, boolean http) { List configuredProtocols = null; - + if(settings != null) { if(http) { configuredProtocols = settings.getAsList(SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, Collections.emptyList()); @@ -104,26 +104,26 @@ public static final String[] getSecureSSLProtocols(Settings settings, boolean ht configuredProtocols = settings.getAsList(SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, Collections.emptyList()); } } - + if(configuredProtocols != null && configuredProtocols.size() > 0) { return configuredProtocols.toArray(new String[0]); } - + return _SECURE_SSL_PROTOCOLS.clone(); } - + // @formatter:off - private static final String[] _SECURE_SSL_CIPHERS = + private static final String[] _SECURE_SSL_CIPHERS = { //TLS__WITH_ - + //Example (including unsafe ones) //Protocol: TLS, SSL //Key Exchange RSA, Diffie-Hellman, ECDH, SRP, PSK //Authentication RSA, DSA, ECDSA //Bulk Ciphers RC4, 3DES, AES //Message Authentication HMAC-SHA256, HMAC-SHA1, HMAC-MD5 - + //thats what chrome 48 supports (https://cc.dcsec.uni-hannover.de/) //(c0,2b)ECDHE-ECDSA-AES128-GCM-SHA256128 BitKey exchange: ECDH, encryption: AES, MAC: SHA256. @@ -141,7 +141,7 @@ public static final String[] getSecureSSLProtocols(Settings settings, boolean ht //(00,35)RSA-AES256-SHA256 BitKey exchange: RSA, encryption: AES, MAC: SHA1. //(00,2f)RSA-AES128-SHA128 BitKey exchange: RSA, encryption: AES, MAC: SHA1. //(00,0a)RSA-3DES-EDE-SHA168 BitKey exchange: RSA, encryption: 3DES, MAC: SHA1. - + //thats what firefox 42 supports (https://cc.dcsec.uni-hannover.de/) //(c0,2b) ECDHE-ECDSA-AES128-GCM-SHA256 //(c0,2f) ECDHE-RSA-AES128-GCM-SHA256 @@ -176,18 +176,18 @@ public static final String[] getSecureSSLProtocols(Settings settings, boolean ht "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", - + //TLS 1.3 "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256", //Open SSL >= 1.1.1 and Java >= 12 - + //TLS 1.2 CHACHA20 POLY1305 supported by Java >= 12 and //OpenSSL >= 1.1.0 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", - + //IBM "SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "SSL_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", @@ -211,14 +211,14 @@ public static final String[] getSecureSSLProtocols(Settings settings, boolean ht "SSL_DHE_RSA_WITH_AES_256_CBC_SHA256", "SSL_DHE_DSS_WITH_AES_256_CBC_SHA", "SSL_DHE_RSA_WITH_AES_256_CBC_SHA" - + //some others //"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", //"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", - //"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - //"TLS_DHE_RSA_WITH_AES_256_CBC_SHA", + //"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + //"TLS_DHE_RSA_WITH_AES_256_CBC_SHA", //"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", - //"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + //"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", //"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", //"TLS_DHE_RSA_WITH_AES_128_CBC_SHA", //"TLS_RSA_WITH_AES_128_CBC_SHA256", @@ -227,11 +227,11 @@ public static final String[] getSecureSSLProtocols(Settings settings, boolean ht //"TLS_RSA_WITH_AES_256_CBC_SHA", }; // @formatter:on - + public static final List getSecureSSLCiphers(Settings settings, boolean http) { - + List configuredCiphers = null; - + if(settings != null) { if(http) { configuredCiphers = settings.getAsList(SECURITY_SSL_HTTP_ENABLED_CIPHERS, Collections.emptyList()); @@ -239,14 +239,14 @@ public static final List getSecureSSLCiphers(Settings settings, boolean configuredCiphers = settings.getAsList(SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, Collections.emptyList()); } } - + if(configuredCiphers != null && configuredCiphers.size() > 0) { return configuredCiphers; } return Collections.unmodifiableList(Arrays.asList(_SECURE_SSL_CIPHERS)); } - + private SSLConfigConstants() { } diff --git a/src/main/java/org/opensearch/security/ssl/util/SSLRequestHelper.java b/src/main/java/org/opensearch/security/ssl/util/SSLRequestHelper.java index 87452f8a9c..42aad19a09 100644 --- a/src/main/java/org/opensearch/security/ssl/util/SSLRequestHelper.java +++ b/src/main/java/org/opensearch/security/ssl/util/SSLRequestHelper.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.util; @@ -55,7 +55,7 @@ public class SSLRequestHelper { private static final Logger log = LogManager.getLogger(SSLRequestHelper.class); - + public static class SSLInfo { private final X509Certificate[] x509Certs; private final X509Certificate[] localCertificates; @@ -79,7 +79,7 @@ public SSLInfo(final X509Certificate[] x509Certs, final String principal, final public X509Certificate[] getX509Certs() { return x509Certs == null ? null : x509Certs.clone(); } - + public X509Certificate[] getLocalCertificates() { return localCertificates == null ? null : localCertificates.clone(); } @@ -106,7 +106,7 @@ public String toString() { @SuppressWarnings("removal") public static SSLInfo getSSLInfo(final Settings settings, final Path configPath, final RestRequest request, PrincipalExtractor principalExtractor) throws SSLPeerUnverifiedException { - + if(request == null || request.getHttpChannel() == null || !(request.getHttpChannel() instanceof Netty4HttpChannel)) { return null; } @@ -138,7 +138,7 @@ public static SSLInfo getSSLInfo(final Settings settings, final Path configPath, if (certs != null && certs.length > 0 && certs[0] instanceof X509Certificate) { x509Certs = Arrays.copyOf(certs, certs.length, X509Certificate[].class); final X509Certificate[] x509CertsF = x509Certs; - + final SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -147,7 +147,7 @@ public static SSLInfo getSSLInfo(final Settings settings, final Path configPath, validationFailure = AccessController.doPrivileged(new PrivilegedAction() { @Override - public Boolean run() { + public Boolean run() { return !validate(x509CertsF, settings, configPath); } }); @@ -171,7 +171,7 @@ public Boolean run() { Certificate[] localCerts = session.getLocalCertificates(); return new SSLInfo(x509Certs, principal, protocol, cipher, localCerts==null?null:Arrays.copyOf(localCerts, localCerts.length, X509Certificate[].class)); } - + public static boolean containsBadHeader(final ThreadContext context, String prefix) { if (context != null) { for (final Entry header : context.getHeaders().entrySet()) { @@ -180,27 +180,27 @@ public static boolean containsBadHeader(final ThreadContext context, String pref } } } - + return false; } - + private static boolean validate(X509Certificate[] x509Certs, final Settings settings, final Path configPath) { - + final boolean validateCrl = settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATE, false); final boolean isTraceEnabled = log.isTraceEnabled(); if (isTraceEnabled) { log.trace("validateCrl: {}", validateCrl); } - + if(!validateCrl) { return true; } - + final Environment env = new Environment(settings, configPath); - + try { - + Collection crls = null; final String crlFile = settings.get(SSLConfigConstants.SSECURITY_SSL_HTTP_CRL_FILE); @@ -209,7 +209,7 @@ private static boolean validate(X509Certificate[] x509Certs, final Settings sett try(FileInputStream crlin = new FileInputStream(crl)) { crls = CertificateFactory.getInstance("X.509").generateCRLs(crlin); } - + if (isTraceEnabled) { log.trace("crls from file: {}", crls.size()); } @@ -218,15 +218,15 @@ private static boolean validate(X509Certificate[] x509Certs, final Settings sett log.trace("no crl file configured"); } } - + final String truststore = settings.get(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH); CertificateValidator validator = null; - + if(truststore != null) { final String truststoreType = settings.get(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_TYPE, "JKS"); final String truststorePassword = SECURITY_SSL_HTTP_TRUSTSTORE_PASSWORD.getSetting(settings); //final String truststoreAlias = settings.get(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_ALIAS, null); - + final KeyStore ts = KeyStore.getInstance(truststoreType); try(FileInputStream fin = new FileInputStream(new File(env.configDir().resolve(truststore).toAbsolutePath().toString()))) { ts.load(fin, (truststorePassword == null || truststorePassword.length() == 0) ?null:truststorePassword.toCharArray()); @@ -237,9 +237,9 @@ private static boolean validate(X509Certificate[] x509Certs, final Settings sett try(FileInputStream trin = new FileInputStream(trustedCas)) { Collection cert = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); validator = new CertificateValidator(cert.toArray(new X509Certificate[0]), crls); - } + } } - + validator.setEnableCRLDP(!settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_DISABLE_CRLDP, false)); validator.setEnableOCSP(!settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_DISABLE_OCSP, false)); validator.setCheckOnlyEndEntities(settings.getAsBoolean(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_CHECK_ONLY_END_ENTITIES, true)); @@ -250,13 +250,13 @@ private static boolean validate(X509Certificate[] x509Certs, final Settings sett } validator.setDate(dateTimestamp==null?null:new Date(dateTimestamp.longValue())); validator.validate(x509Certs); - + return true; - + } catch (Exception e) { log.warn("Unable to validate CRL: ", ExceptionUtils.getRootCause(e)); } - + return false; } } diff --git a/src/main/java/org/opensearch/security/ssl/util/Utils.java b/src/main/java/org/opensearch/security/ssl/util/Utils.java index 2035c4fb1e..2a6fcd2550 100644 --- a/src/main/java/org/opensearch/security/ssl/util/Utils.java +++ b/src/main/java/org/opensearch/security/ssl/util/Utils.java @@ -1,10 +1,10 @@ /* * Copyright 2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl.util; @@ -23,18 +23,18 @@ public static T coalesce(T first, T... more) { if (first != null) { return first; } - + if(more == null || more.length == 0) { return null; } - + for (int i = 0; i < more.length; i++) { T t = more[i]; if(t != null) { return t; } } - + return null; } diff --git a/src/main/java/org/opensearch/security/support/ConfigConstants.java b/src/main/java/org/opensearch/security/support/ConfigConstants.java index 83281c9d0b..f5c64bccd3 100644 --- a/src/main/java/org/opensearch/security/support/ConfigConstants.java +++ b/src/main/java/org/opensearch/security/support/ConfigConstants.java @@ -49,7 +49,7 @@ public class ConfigConstants { public static final String OPENDISTRO_SECURITY_ORIGIN_HEADER = OPENDISTRO_SECURITY_CONFIG_PREFIX+"origin_header"; public static final String OPENDISTRO_SECURITY_DLS_QUERY_HEADER = OPENDISTRO_SECURITY_CONFIG_PREFIX+"dls_query"; - + public static final String OPENDISTRO_SECURITY_DLS_FILTER_LEVEL_QUERY_HEADER = OPENDISTRO_SECURITY_CONFIG_PREFIX+"dls_filter_level_query"; public static final String OPENDISTRO_SECURITY_DLS_FILTER_LEVEL_QUERY_TRANSIENT = OPENDISTRO_SECURITY_CONFIG_PREFIX+"dls_filter_level_query_t"; @@ -57,7 +57,7 @@ public class ConfigConstants { public static final String OPENDISTRO_SECURITY_DLS_MODE_TRANSIENT = OPENDISTRO_SECURITY_CONFIG_PREFIX+"dls_mode_t"; public static final String OPENDISTRO_SECURITY_FLS_FIELDS_HEADER = OPENDISTRO_SECURITY_CONFIG_PREFIX+"fls_fields"; - + public static final String OPENDISTRO_SECURITY_MASKED_FIELD_HEADER = OPENDISTRO_SECURITY_CONFIG_PREFIX+"masked_fields"; @@ -65,7 +65,7 @@ public class ConfigConstants { public static final String OPENDISTRO_SECURITY_DOC_ALLOWLIST_TRANSIENT = OPENDISTRO_SECURITY_CONFIG_PREFIX+"doc_allowlist_t"; public static final String OPENDISTRO_SECURITY_FILTER_LEVEL_DLS_DONE = OPENDISTRO_SECURITY_CONFIG_PREFIX+"filter_level_dls_done"; - + public static final String OPENDISTRO_SECURITY_DLS_QUERY_CCS = OPENDISTRO_SECURITY_CONFIG_PREFIX+"dls_query_ccs"; public static final String OPENDISTRO_SECURITY_FLS_FIELDS_CCS = OPENDISTRO_SECURITY_CONFIG_PREFIX+"fls_fields_ccs"; @@ -76,7 +76,7 @@ public class ConfigConstants { public static final String OPENDISTRO_SECURITY_REMOTE_ADDRESS = OPENDISTRO_SECURITY_CONFIG_PREFIX+"remote_address"; public static final String OPENDISTRO_SECURITY_REMOTE_ADDRESS_HEADER = OPENDISTRO_SECURITY_CONFIG_PREFIX+"remote_address_header"; - + public static final String OPENDISTRO_SECURITY_INITIAL_ACTION_CLASS_HEADER = OPENDISTRO_SECURITY_CONFIG_PREFIX+"initial_action_class_header"; /** @@ -118,7 +118,7 @@ public class ConfigConstants { public static final String SSO_LOGOUT_URL = OPENDISTRO_SECURITY_CONFIG_PREFIX+"sso_logout_url"; - + public static final String OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX = ".opendistro_security"; public static final String SECURITY_ENABLE_SNAPSHOT_RESTORE_PRIVILEGE = "plugins.security.enable_snapshot_restore_privilege"; @@ -141,7 +141,7 @@ public class ConfigConstants { public static final String SECURITY_CONFIG_INDEX_NAME = "plugins.security.config_index_name"; public static final String SECURITY_AUTHCZ_IMPERSONATION_DN = "plugins.security.authcz.impersonation_dn"; public static final String SECURITY_AUTHCZ_REST_IMPERSONATION_USERS="plugins.security.authcz.rest_impersonation_user"; - + public static final String SECURITY_AUDIT_TYPE_DEFAULT = "plugins.security.audit.type"; public static final String SECURITY_AUDIT_CONFIG_DEFAULT = "plugins.security.audit.config"; public static final String SECURITY_AUDIT_CONFIG_ROUTES = "plugins.security.audit.routes"; @@ -162,14 +162,14 @@ public class ConfigConstants { public static final boolean OPENDISTRO_SECURITY_AUDIT_SSL_VERIFY_HOSTNAMES_DEFAULT = true; public static final boolean OPENDISTRO_SECURITY_AUDIT_SSL_ENABLE_SSL_CLIENT_AUTH_DEFAULT = false; public static final String OPENDISTRO_SECURITY_AUDIT_EXCLUDE_SENSITIVE_HEADERS = "opendistro_security.audit.exclude_sensitive_headers"; - + public static final String SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX = "plugins.security.audit.config."; // Internal / External OpenSearch public static final String SECURITY_AUDIT_OPENSEARCH_INDEX = "index"; public static final String SECURITY_AUDIT_OPENSEARCH_TYPE = "type"; - + // External OpenSearch public static final String SECURITY_AUDIT_EXTERNAL_OPENSEARCH_HTTP_ENDPOINTS = "http_endpoints"; public static final String SECURITY_AUDIT_EXTERNAL_OPENSEARCH_USERNAME = "username"; @@ -188,22 +188,22 @@ public class ConfigConstants { public static final String SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLED_SSL_CIPHERS = "enabled_ssl_ciphers"; public static final String SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLED_SSL_PROTOCOLS = "enabled_ssl_protocols"; - // Webhooks + // Webhooks public static final String SECURITY_AUDIT_WEBHOOK_URL = "webhook.url"; public static final String SECURITY_AUDIT_WEBHOOK_FORMAT = "webhook.format"; public static final String SECURITY_AUDIT_WEBHOOK_SSL_VERIFY = "webhook.ssl.verify"; public static final String SECURITY_AUDIT_WEBHOOK_PEMTRUSTEDCAS_FILEPATH = "webhook.ssl.pemtrustedcas_filepath"; public static final String SECURITY_AUDIT_WEBHOOK_PEMTRUSTEDCAS_CONTENT = "webhook.ssl.pemtrustedcas_content"; - + // Log4j public static final String SECURITY_AUDIT_LOG4J_LOGGER_NAME = "log4j.logger_name"; public static final String SECURITY_AUDIT_LOG4J_LEVEL = "log4j.level"; - + //retry public static final String SECURITY_AUDIT_RETRY_COUNT = "plugins.security.audit.config.retry_count"; public static final String SECURITY_AUDIT_RETRY_DELAY_MS = "plugins.security.audit.config.retry_delay_ms"; - + public static final String SECURITY_KERBEROS_KRB5_FILEPATH = "plugins.security.kerberos.krb5_filepath"; public static final String SECURITY_KERBEROS_ACCEPTOR_KEYTAB_FILEPATH = "plugins.security.kerberos.acceptor_keytab_filepath"; public static final String SECURITY_KERBEROS_ACCEPTOR_PRINCIPAL = "plugins.security.kerberos.acceptor_principal"; diff --git a/src/main/java/org/opensearch/security/support/HTTPHelper.java b/src/main/java/org/opensearch/security/support/HTTPHelper.java index e7554f120d..5e9fc78f8c 100644 --- a/src/main/java/org/opensearch/security/support/HTTPHelper.java +++ b/src/main/java/org/opensearch/security/support/HTTPHelper.java @@ -55,7 +55,7 @@ public static AuthCredentials extractCredentials(String authorizationHeader, Log // username:pass:word //blank password // username: - + final int firstColonIndex = decodedBasicHeader.indexOf(':'); String username = null; @@ -63,7 +63,7 @@ public static AuthCredentials extractCredentials(String authorizationHeader, Log if (firstColonIndex > 0) { username = decodedBasicHeader.substring(0, firstColonIndex); - + if(decodedBasicHeader.length() - 1 != firstColonIndex) { password = decodedBasicHeader.substring(firstColonIndex + 1); } else { @@ -83,20 +83,20 @@ public static AuthCredentials extractCredentials(String authorizationHeader, Log return null; } } - + public static boolean containsBadHeader(final RestRequest request) { - + final Map> headers; - + if (request != null && ( headers = request.getHeaders()) != null) { for (final String key: headers.keySet()) { - if ( key != null + if ( key != null && key.trim().toLowerCase().startsWith(ConfigConstants.OPENDISTRO_SECURITY_CONFIG_PREFIX.toLowerCase())) { return true; } } } - + return false; } } diff --git a/src/main/java/org/opensearch/security/support/HeaderHelper.java b/src/main/java/org/opensearch/security/support/HeaderHelper.java index 1a7484a781..af8da305d4 100644 --- a/src/main/java/org/opensearch/security/support/HeaderHelper.java +++ b/src/main/java/org/opensearch/security/support/HeaderHelper.java @@ -39,7 +39,7 @@ public static boolean isInterClusterRequest(final ThreadContext context) { } public static boolean isDirectRequest(final ThreadContext context) { - + return "direct".equals(context.getTransient(ConfigConstants.OPENDISTRO_SECURITY_CHANNEL_TYPE)) || context.getTransient(ConfigConstants.OPENDISTRO_SECURITY_CHANNEL_TYPE) == null; } @@ -49,7 +49,7 @@ public static boolean isExtensionRequest(final ThreadContext context) { return context.getTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_EXTENSION_REQUEST) == Boolean.TRUE; } // CS-ENFORCE-SINGLE - + public static String getSafeFromHeader(final ThreadContext context, final String headerName) { if (context == null || headerName == null || headerName.isEmpty()) { @@ -73,7 +73,7 @@ public static Serializable deserializeSafeFromHeader(final ThreadContext context return null; } - + public static boolean isTrustedClusterRequest(final ThreadContext context) { return context.getTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_TRUSTED_CLUSTER_REQUEST) == Boolean.TRUE; } diff --git a/src/main/java/org/opensearch/security/support/MapUtils.java b/src/main/java/org/opensearch/security/support/MapUtils.java index 65aa6f7f9d..a50505eae9 100644 --- a/src/main/java/org/opensearch/security/support/MapUtils.java +++ b/src/main/java/org/opensearch/security/support/MapUtils.java @@ -32,11 +32,11 @@ import java.util.Map; public class MapUtils { - + public static void deepTraverseMap(final Map map, final Callback cb) { deepTraverseMap(map, cb, null); } - + private static void deepTraverseMap(final Map map, final Callback cb, final List stack) { final List localStack; if(stack == null) { @@ -58,7 +58,7 @@ private static void deepTraverseMap(final Map map, final Callbac } } } - + public static interface Callback { public void call(String key, Map map, List stack); } diff --git a/src/main/java/org/opensearch/security/support/ModuleInfo.java b/src/main/java/org/opensearch/security/support/ModuleInfo.java index 994e49046c..c8558b1c13 100644 --- a/src/main/java/org/opensearch/security/support/ModuleInfo.java +++ b/src/main/java/org/opensearch/security/support/ModuleInfo.java @@ -36,16 +36,16 @@ import org.opensearch.common.io.stream.Writeable; public class ModuleInfo implements Serializable, Writeable{ - + private static final long serialVersionUID = -1077651823194285138L; - + private ModuleType moduleType; private String classname; private String classpath = ""; private String version = ""; private String buildTime = ""; private String gitsha1 = ""; - + public ModuleInfo(ModuleType moduleType, String classname) { assert(moduleType != null); this.moduleType = moduleType; @@ -73,7 +73,7 @@ public void setVersion(String version) { public void setBuildTime(String buildTime) { this.buildTime = buildTime; } - + public String getGitsha1() { return gitsha1; } @@ -85,7 +85,7 @@ public void setGitsha1(String gitsha1) { public ModuleType getModuleType() { return moduleType; } - + public Map getAsMap() { Map infoMap = new HashMap<>(); infoMap.put("type", moduleType.name()); @@ -99,7 +99,7 @@ public Map getAsMap() { infoMap.put("gitsha1", this.gitsha1); return infoMap; } - + @Override public void writeTo(StreamOutput out) throws IOException { out.writeEnum(moduleType); @@ -109,8 +109,8 @@ public void writeTo(StreamOutput out) throws IOException { out.writeString(buildTime); out.writeString(gitsha1); } - - + + /* (non-Javadoc) * @see java.lang.Object#hashCode() @@ -180,5 +180,5 @@ public boolean equals(Object obj) { public String toString() { return "Module [type=" + this.moduleType.name() + ", implementing class=" + this.classname + "]"; } - + } diff --git a/src/main/java/org/opensearch/security/support/PemKeyReader.java b/src/main/java/org/opensearch/security/support/PemKeyReader.java index fb3a595f9e..7d37fee4f3 100644 --- a/src/main/java/org/opensearch/security/support/PemKeyReader.java +++ b/src/main/java/org/opensearch/security/support/PemKeyReader.java @@ -72,12 +72,12 @@ import org.opensearch.env.Environment; public final class PemKeyReader { - + //private static final String[] EMPTY_STRING_ARRAY = new String[0]; protected static final Logger log = LogManager.getLogger(PemKeyReader.class); static final String JKS = "JKS"; static final String PKCS12 = "PKCS12"; - + private static final Pattern KEY_PATTERN = Pattern.compile( "-+BEGIN\\s+.*PRIVATE\\s+KEY[^-]*-+(?:\\s|\\r|\\n)+" + // Header "([a-z0-9+/=\\r\\n]+)" + // Base64 text @@ -147,7 +147,7 @@ private static void safeClose(OutputStream out) { //ignore } } - + public static PrivateKey toPrivateKey(File keyFile, String keyPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidAlgorithmParameterException, KeyException, IOException { if (keyFile == null) { @@ -155,7 +155,7 @@ public static PrivateKey toPrivateKey(File keyFile, String keyPassword) throws N } return getPrivateKeyFromByteBuffer(PemKeyReader.readPrivateKey(keyFile), keyPassword); } - + public static PrivateKey toPrivateKey(InputStream in, String keyPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidAlgorithmParameterException, KeyException, IOException { if (in == null) { @@ -182,7 +182,7 @@ private static PrivateKey getPrivateKeyFromByteBuffer(byte[] encodedKey, String } } } - + private static PKCS8EncodedKeySpec generateKeySpec(char[] password, byte[] key) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException { @@ -201,27 +201,27 @@ private static PKCS8EncodedKeySpec generateKeySpec(char[] password, byte[] key) return encryptedPrivateKeyInfo.getKeySpec(cipher); } - + public static X509Certificate loadCertificateFromFile(String file) throws Exception { if(file == null) { return null; } - + CertificateFactory fact = CertificateFactory.getInstance("X.509"); try(FileInputStream is = new FileInputStream(file)) { return (X509Certificate) fact.generateCertificate(is); } } - + public static X509Certificate loadCertificateFromStream(InputStream in) throws Exception { if(in == null) { return null; } - + CertificateFactory fact = CertificateFactory.getInstance("X.509"); return (X509Certificate) fact.generateCertificate(in); } - + public static KeyStore loadKeyStore(String storePath, String keyStorePassword, String type) throws Exception { if(storePath == null) { return null; @@ -230,36 +230,36 @@ public static KeyStore loadKeyStore(String storePath, String keyStorePassword, S if(type == null || !type.toUpperCase().equals(JKS) || !type.toUpperCase().equals(PKCS12)) { type = JKS; } - + final KeyStore store = KeyStore.getInstance(type.toUpperCase()); store.load(new FileInputStream(storePath), keyStorePassword==null?null:keyStorePassword.toCharArray()); return store; } public static PrivateKey loadKeyFromFile(String password, String keyFile) throws Exception { - + if(keyFile == null) { return null; } - + return PemKeyReader.toPrivateKey(new File(keyFile), password); } - + public static PrivateKey loadKeyFromStream(String password, InputStream in) throws Exception { - + if(in == null) { return null; } - + return PemKeyReader.toPrivateKey(in, password); } - + public static void checkPath(String keystoreFilePath, String fileNameLogOnly) { - + if (keystoreFilePath == null || keystoreFilePath.length() == 0) { throw new OpenSearchException("Empty file path for "+fileNameLogOnly); } - + if (Files.isDirectory(Paths.get(keystoreFilePath), LinkOption.NOFOLLOW_LINKS)) { throw new OpenSearchException("Is a directory: " + keystoreFilePath+" Expected a file for "+fileNameLogOnly); } @@ -268,34 +268,34 @@ public static void checkPath(String keystoreFilePath, String fileNameLogOnly) { throw new OpenSearchException("Unable to read " + keystoreFilePath + " ("+Paths.get(keystoreFilePath)+"). Please make sure this files exists and is readable regarding to permissions. Property: "+fileNameLogOnly); } } - + public static X509Certificate[] loadCertificatesFromFile(String file) throws Exception { if(file == null) { return null; } - + try(FileInputStream is = new FileInputStream(file)) { return loadCertificatesFromStream(is); } - + } public static X509Certificate[] loadCertificatesFromFile(File file) throws Exception { if(file == null) { return null; } - + try(FileInputStream is = new FileInputStream(file)) { return loadCertificatesFromStream(is); } - + } - + public static X509Certificate[] loadCertificatesFromStream(InputStream in) throws Exception { if(in == null) { return null; } - + CertificateFactory fact = CertificateFactory.getInstance("X.509"); Collection certs = fact.generateCertificates(in); X509Certificate[] x509Certs = new X509Certificate[certs.size()]; @@ -304,21 +304,21 @@ public static X509Certificate[] loadCertificatesFromStream(InputStream in) throw x509Certs[i++] = (X509Certificate) cert; } return x509Certs; - + } - + public static InputStream resolveStream(String propName, Settings settings) { final String content = settings.get(propName, null); - + if(content == null) { return null; } return new ByteArrayInputStream(content.getBytes(StandardCharsets.US_ASCII)); } - - public static String resolve(String propName, Settings settings, Path configPath, boolean mustBeValid) { + + public static String resolve(String propName, Settings settings, Path configPath, boolean mustBeValid) { final String originalPath = settings.get(propName, null); return resolve(originalPath, propName, settings, configPath, mustBeValid); } @@ -327,32 +327,32 @@ public static String resolve(String originalPath, String propName, Settings sett log.debug("Path is is {}", originalPath); String path = originalPath; final Environment env = new Environment(settings, configPath); - + if(env != null && originalPath != null && originalPath.length() > 0) { path = env.configDir().resolve(originalPath).toAbsolutePath().toString(); log.debug("Resolved {} to {} against {}", originalPath, path, env.configDir().toAbsolutePath().toString()); } - + if(mustBeValid) { checkPath(path, propName); } - + if("".equals(path)) { path = null; } - - return path; + + return path; } - + public static KeyStore toTruststore(final String trustCertificatesAliasPrefix, final X509Certificate[] trustCertificates) throws Exception { - + if(trustCertificates == null) { return null; } - + KeyStore ks = KeyStore.getInstance(JKS); ks.load(null); - + if(trustCertificates != null && trustCertificates.length > 0) { for (int i = 0; i < trustCertificates.length; i++) { X509Certificate x509Certificate = trustCertificates[i]; @@ -361,10 +361,10 @@ public static KeyStore toTruststore(final String trustCertificatesAliasPrefix, f } return ks; } - + public static KeyStore toKeystore(final String authenticationCertificateAlias, final char[] password, final X509Certificate authenticationCertificate[], final PrivateKey authenticationKey) throws Exception { - if(authenticationCertificateAlias != null && authenticationCertificate != null && authenticationKey != null) { + if(authenticationCertificateAlias != null && authenticationCertificate != null && authenticationKey != null) { KeyStore ks = KeyStore.getInstance(JKS); ks.load(null, null); ks.setKeyEntry(authenticationCertificateAlias, authenticationKey, password, authenticationCertificate); @@ -374,7 +374,7 @@ public static KeyStore toKeystore(final String authenticationCertificateAlias, f } } - + public static char[] randomChars(int len) { final SecureRandom r = new SecureRandom(); final char[] ret = new char[len]; diff --git a/src/main/java/org/opensearch/security/support/ReflectiveAttributeAccessors.java b/src/main/java/org/opensearch/security/support/ReflectiveAttributeAccessors.java index 8f12ffaf61..8ddc52f428 100644 --- a/src/main/java/org/opensearch/security/support/ReflectiveAttributeAccessors.java +++ b/src/main/java/org/opensearch/security/support/ReflectiveAttributeAccessors.java @@ -28,7 +28,7 @@ public static Function objectAttr(String name) { public static Function objectAttr(String name, Class type) { return new ReflectiveAttributeGetter(name, type); } - + public static Function protectedObjectAttr(String name, Class type) { return new ProtectedReflectiveAttributeGetter(name, type); } @@ -114,7 +114,7 @@ public R apply(O object) { } } - + static class ReflectiveAttributeSetter implements BiFunction { private final String attribute; private final String methodName; diff --git a/src/main/java/org/opensearch/security/support/SecurityJsonNode.java b/src/main/java/org/opensearch/security/support/SecurityJsonNode.java index 472ab2bb86..d1e2f4d34e 100644 --- a/src/main/java/org/opensearch/security/support/SecurityJsonNode.java +++ b/src/main/java/org/opensearch/security/support/SecurityJsonNode.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2018 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.support; @@ -28,22 +28,22 @@ import org.opensearch.security.DefaultObjectMapper; public final class SecurityJsonNode { - + private final JsonNode node; public SecurityJsonNode(JsonNode node) { this.node = node; } - + public SecurityJsonNode get(String name) { if(isNull(node)) { return new SecurityJsonNode(null); } - + JsonNode val = node.get(name); return new SecurityJsonNode(val); } - + public String asString() { if(isNull(node)) { return null; @@ -51,11 +51,11 @@ public String asString() { return node.asText(null); } } - + private static boolean isNull(JsonNode node) { return node == null || node.isNull(); } - + public boolean isNull() { return isNull(this.node); } @@ -73,25 +73,25 @@ public SecurityJsonNode getDotted(String string) { for(String part: string.split("\\.")) { tmp = tmp.get(part); } - + return tmp; - + } public List asList() { if(isNull(node) || node.getNodeType() != JsonNodeType.ARRAY) { return null; } - + List retVal = new ArrayList(); - + for(int i=0; i> map, final String in .findAny() .orElse(null); } - + @SafeVarargs public static Map mapFromArray(T ... keyValues) { if(keyValues == null) { @@ -109,25 +109,25 @@ public static Map mapFromArray(T ... keyValues) { return null; } Map map = new HashMap<>(); - + for(int i = 0; i resolveOriginalIndices(RestoreSnapshotRequest restoreRequest) { final SnapshotInfo snapshotInfo = getSnapshotInfo(restoreRequest); @@ -57,17 +57,17 @@ public static List resolveOriginalIndices(RestoreSnapshotRequest restore return null; } else { return SnapshotUtils.filterIndices(snapshotInfo.indices(), restoreRequest.indices(), restoreRequest.indicesOptions()); - } - - + } + + } - + public static SnapshotInfo getSnapshotInfo(RestoreSnapshotRequest restoreRequest) { final RepositoriesService repositoriesService = Objects.requireNonNull(OpenSearchSecurityPlugin.GuiceHolder.getRepositoriesService(), "RepositoriesService not initialized"); final Repository repository = repositoriesService.repository(restoreRequest.repository()); final String threadName = Thread.currentThread().getName(); SnapshotInfo snapshotInfo = null; - + try { setCurrentThreadName("[" + ThreadPool.Names.GENERIC + "]"); for (SnapshotId snapshotId : PlainActionFuture.get(repository::getRepositoryData).getSnapshotIds()) { @@ -86,7 +86,7 @@ public static SnapshotInfo getSnapshotInfo(RestoreSnapshotRequest restoreRequest } return snapshotInfo; } - + @SuppressWarnings("removal") private static void setCurrentThreadName(final String name) { final SecurityManager sm = System.getSecurityManager(); @@ -94,7 +94,7 @@ private static void setCurrentThreadName(final String name) { if (sm != null) { sm.checkPermission(new SpecialPermission()); } - + AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { @@ -103,5 +103,5 @@ public Object run() { } }); } - + } diff --git a/src/main/java/org/opensearch/security/support/SourceFieldsContext.java b/src/main/java/org/opensearch/security/support/SourceFieldsContext.java index 175415a5b6..8f61bcbaf5 100644 --- a/src/main/java/org/opensearch/security/support/SourceFieldsContext.java +++ b/src/main/java/org/opensearch/security/support/SourceFieldsContext.java @@ -97,7 +97,7 @@ public String[] getExcludes() { public boolean hasIncludesOrExcludes() { return (includes != null && includes.length > 0) || (excludes != null && excludes.length > 0); } - + public boolean isFetchSource() { return fetchSource; } diff --git a/src/main/java/org/opensearch/security/support/WildcardMatcher.java b/src/main/java/org/opensearch/security/support/WildcardMatcher.java index f22f981fd2..302736fe67 100644 --- a/src/main/java/org/opensearch/security/support/WildcardMatcher.java +++ b/src/main/java/org/opensearch/security/support/WildcardMatcher.java @@ -296,7 +296,7 @@ public static List getAllMatchingPatterns(final Collection val = Migration.migrateConfig(SecurityDynamicConfiguration.fromNode(DefaultObjectMapper.YAML_MAPPER.readTree(file), CType.CONFIG, 1, 0, 0)); return backupAndWrite(file, val, backup); @@ -121,12 +121,12 @@ public static boolean migrateFile(File file, CType cType, boolean backup) { boolean roles = backupAndWrite(file, tup.v1(), backup); return roles && backupAndWrite(new File(file.getParent(),"tenants.yml"), tup.v2(), backup); } - + if(cType == CType.ROLESMAPPING) { SecurityDynamicConfiguration val = Migration.migrateRoleMappings(SecurityDynamicConfiguration.fromNode(DefaultObjectMapper.YAML_MAPPER.readTree(file), CType.ROLESMAPPING, 1, 0, 0)); return backupAndWrite(file, val, backup); } - + if(cType == CType.INTERNALUSERS) { SecurityDynamicConfiguration val = Migration.migrateInternalUsers(SecurityDynamicConfiguration.fromNode(DefaultObjectMapper.YAML_MAPPER.readTree(file), CType.INTERNALUSERS, 1, 0, 0)); return backupAndWrite(file, val, backup); @@ -147,11 +147,11 @@ public static boolean migrateFile(File file, CType cType, boolean backup) { } catch (Exception e) { System.out.println("Can not migrate "+file+" due to "+e); } - - + + return false; } - + private static boolean backupAndWrite(File file, SecurityDynamicConfiguration val, boolean backup) { try { if(val == null) { @@ -169,7 +169,7 @@ private static boolean backupAndWrite(File file, SecurityDynamicConfiguration System.out.println(" Details: "+e.getMessage()); e.printStackTrace(); } - + return false; } } diff --git a/src/main/java/org/opensearch/security/tools/SecurityAdmin.java b/src/main/java/org/opensearch/security/tools/SecurityAdmin.java index 2427a48f8a..738e0e6b20 100644 --- a/src/main/java/org/opensearch/security/tools/SecurityAdmin.java +++ b/src/main/java/org/opensearch/security/tools/SecurityAdmin.java @@ -162,7 +162,7 @@ public class SecurityAdmin { private static final Settings ENABLE_ALL_ALLOCATIONS_SETTINGS = Settings.builder() .put("cluster.routing.allocation.enable", "all") .build(); - + public static void main(final String[] args) { try { final int returnCode = execute(args); @@ -173,7 +173,7 @@ public static void main(final String[] args) { System.out.println(ExceptionsHelper.stackTrace(e)); System.out.println(); System.exit(-1); - } + } catch (IndexNotFoundException e) { System.out.println("ERR: No OpenSearch Security configuration index found. Please execute securityadmin with different command line parameters"); System.out.println("When you run it for the first time do not specify -us, -era, -dra or -rl"); @@ -181,16 +181,16 @@ public static void main(final String[] args) { System.exit(-1); } catch (Throwable e) { - + if (e instanceof OpenSearchException - && e.getMessage() != null + && e.getMessage() != null && e.getMessage().contains("no permissions")) { - System.out.println("ERR: You try to connect with a TLS node certificate instead of an admin client certificate"); + System.out.println("ERR: You try to connect with a TLS node certificate instead of an admin client certificate"); System.out.println(); System.exit(-1); } - + System.out.println("ERR: An unexpected "+e.getClass().getSimpleName()+" occured: "+e.getMessage()); System.out.println("Trace:"); System.out.println(ExceptionsHelper.stackTrace(e)); @@ -200,7 +200,7 @@ public static void main(final String[] args) { } public static int execute(final String[] args) throws Exception { - + System.out.println("Security Admin v7"); System.setProperty("security.nowarn.client","true"); System.setProperty("jdk.tls.rejectClientInitiatedRenegotiation","true"); @@ -256,16 +256,16 @@ public static int execute(final String[] args) throws Exception { options.addOption(Option.builder("backup").hasArg().argName("folder").desc("Backup configuration to folder").build()); options.addOption(Option.builder("migrate").hasArg().argName("folder").desc("Migrate and use folder to store migrated files").build()); - + options.addOption(Option.builder("rev").longOpt("resolve-env-vars").desc("Resolve/Substitute env vars in config with their value before uploading").build()); options.addOption(Option.builder("vc").numberOfArgs(1).optionalArg(true).argName("version").longOpt("validate-configs").desc("Validate config for version 6 or 7 (default 7)").build()); options.addOption(Option.builder("mo").longOpt("migrate-offline").hasArg().argName("folder").desc("Migrate and use folder to store migrated files").build()); - + //when adding new options also adjust validate(CommandLine line) - + String hostname = "localhost"; int port = 9200; String kspass = System.getenv(OPENDISTRO_SECURITY_KS_PASS); @@ -293,7 +293,7 @@ public static int execute(final String[] args) throws Exception { boolean deleteConfigIndex = false; boolean enableShardAllocation = false; boolean acceptRedCluster = false; - + String keypass = System.getenv(OPENDISTRO_SECURITY_KEYPASS); String cacert = null; String cert = null; @@ -316,28 +316,28 @@ public static int execute(final String[] args) throws Exception { CommandLineParser parser = new DefaultParser(); try { CommandLine line = parser.parse( options, args ); - + validate(line); - + hostname = line.getOptionValue("h", hostname); port = Integer.parseInt(line.getOptionValue("p", String.valueOf(port))); promptForPassword = line.hasOption("prompt"); - + if(kspass == null || kspass.isEmpty()) { kspass = line.getOptionValue("kspass",promptForPassword?null:"changeit"); } - + if(tspass == null || tspass.isEmpty()) { tspass = line.getOptionValue("tspass",promptForPassword?null:kspass); } cd = line.getOptionValue("cd", cd); - + if(!cd.endsWith(File.separator)) { cd += File.separator; } - + ks = line.getOptionValue("ks",ks); ts = line.getOptionValue("ts",ts); kst = line.getOptionValue("kst", kst); @@ -349,87 +349,87 @@ public static int execute(final String[] args) throws Exception { retrieve = line.hasOption("r"); ksAlias = line.getOptionValue("ksalias", ksAlias); index = line.getOptionValue("i", index); - + String enabledCiphersString = line.getOptionValue("ec", null); String enabledProtocolsString = line.getOptionValue("ep", null); - + if(enabledCiphersString != null) { enabledCiphers = enabledCiphersString.split(","); } - + if(enabledProtocolsString != null) { enabledProtocols = enabledProtocolsString.split(","); } - + updateSettings = line.hasOption("us")?Integer.parseInt(line.getOptionValue("us")):null; reload = line.hasOption("rl"); - + if(line.hasOption("era")) { replicaAutoExpand = true; } - + if(line.hasOption("dra")) { replicaAutoExpand = false; } - + failFast = line.hasOption("ff"); diagnose = line.hasOption("dg"); deleteConfigIndex = line.hasOption("dci"); enableShardAllocation = line.hasOption("esa"); acceptRedCluster = line.hasOption("arc"); - + cacert = line.getOptionValue("cacert"); cert = line.getOptionValue("cert"); key = line.getOptionValue("key"); keypass = line.getOptionValue("keypass", keypass); si = line.hasOption("si"); - + whoami = line.hasOption("w"); - + explicitReplicas = line.getOptionValue("er", explicitReplicas); - + backup = line.getOptionValue("backup"); - + migrate = line.getOptionValue("migrate"); - + resolveEnvVars = line.hasOption("rev"); - + validateConfig = !line.hasOption("vc")?null:Integer.parseInt(line.getOptionValue("vc", "7")); - + if(validateConfig != null && validateConfig.intValue() != 6 && validateConfig.intValue() != 7) { throw new ParseException("version must be 6 or 7"); } - + migrateOffline = line.getOptionValue("mo"); - + } catch( ParseException exp ) { System.out.println("ERR: Parsing failed. Reason: " + exp.getMessage()); formatter.printHelp("securityadmin.sh", options, true); return -1; } - + if(validateConfig != null) { System.out.println("Validate configuration for Version "+validateConfig.intValue()); return validateConfig(cd, file, type, validateConfig.intValue()); } - + if(migrateOffline != null) { System.out.println("Migrate "+migrateOffline+" offline"); final boolean retVal = Migrater.migrateDirectory(new File(migrateOffline), true); return retVal?0:-1; } - + System.out.print("Will connect to "+hostname+":"+port); Socket socket = new Socket(); - + try { - + socket.connect(new InetSocketAddress(hostname, port)); - + } catch (java.net.ConnectException ex) { System.out.println(); System.out.println("ERR: Seems there is no OpenSearch running on "+hostname+":"+port+" - Will exit"); @@ -450,13 +450,13 @@ public static int execute(final String[] args) throws Exception { kspass = promptForPassword("Keystore", "kspass", OPENDISTRO_SECURITY_KS_PASS); } } - + if(ts != null) { tst = tst==null?(ts.endsWith(".jks")?"JKS":"PKCS12"):tst; if(tspass == null && promptForPassword) { tspass = promptForPassword("Truststore", "tspass", OPENDISTRO_SECURITY_TS_PASS); } - } + } if(key != null) { @@ -549,7 +549,7 @@ public static int execute(final String[] args) throws Exception { System.out.println("Reload config on all nodes"); return 0; } - + if(si) { return (0); } @@ -558,9 +558,9 @@ public static int execute(final String[] args) throws Exception { System.out.println(whoAmIResNode.toPrettyString()); return (0); } - - - if(replicaAutoExpand != null) { + + + if(replicaAutoExpand != null) { Settings indexSettings = Settings.builder() .put("index.auto_expand_replicas", replicaAutoExpand?"0-all":"false") .build(); @@ -594,10 +594,10 @@ public static int execute(final String[] args) throws Exception { } else { System.out.println("ERR: Unable to enable shard allocation"); } - + return (successful?0:-1); - } - + } + if(failFast) { System.out.println("Fail-fast is activated"); } @@ -620,11 +620,11 @@ public static int execute(final String[] args) throws Exception { } catch (Exception e) { Throwable rootCause = ExceptionUtils.getRootCause(e); - + if(!failFast) { System.out.println("Cannot retrieve cluster state due to: "+e.getMessage()+". This is not an error, will keep on trying ..."); System.out.println(" Root cause: "+rootCause+" ("+e.getClass().getName()+"/"+rootCause.getClass().getName()+")"); - System.out.println(" * Try running securityadmin.sh with -icl (but no -cl) and -nhnv (If that works you need to check your clustername as well as hostnames in your TLS certificates)"); + System.out.println(" * Try running securityadmin.sh with -icl (but no -cl) and -nhnv (If that works you need to check your clustername as well as hostnames in your TLS certificates)"); System.out.println(" * Make sure that your keystore or PEM certificate is a client certificate (not a node certificate) and configured properly in opensearch.yml"); System.out.println(" * If this is not working, try running securityadmin.sh with --diagnose and see diagnose trace log file)"); System.out.println(" * Add --accept-red-cluster to allow securityadmin to operate on a red cluster."); @@ -634,12 +634,12 @@ public static int execute(final String[] args) throws Exception { System.out.println(" Root cause: "+rootCause+" ("+e.getClass().getName()+"/"+rootCause.getClass().getName()+")"); System.out.println(" * Try running securityadmin.sh with -icl (but no -cl) and -nhnv (If that works you need to check your clustername as well as hostnames in your TLS certificates)"); System.out.println(" * Make also sure that your keystore or PEM certificate is a client certificate (not a node certificate) and configured properly in opensearch.yml"); - System.out.println(" * If this is not working, try running securityadmin.sh with --diagnose and see diagnose trace log file)"); + System.out.println(" * If this is not working, try running securityadmin.sh with --diagnose and see diagnose trace log file)"); System.out.println(" * Add --accept-red-cluster to allow securityadmin to operate on a red cluster."); return (-1); } - + Thread.sleep(3000); continue; } @@ -651,7 +651,7 @@ public static int execute(final String[] args) throws Exception { System.out.println("ERR: Timed out while waiting for a green or yellow cluster state."); System.out.println(" * Try running securityadmin.sh with -icl (but no -cl) and -nhnv (If that works you need to check your clustername as well as hostnames in your TLS certificates)"); System.out.println(" * Make also sure that your keystore or PEM certificate is a client certificate (not a node certificate) and configured properly in opensearch.yml"); - System.out.println(" * If this is not working, try running securityadmin.sh with --diagnose and see diagnose trace log file)"); + System.out.println(" * If this is not working, try running securityadmin.sh with --diagnose and see diagnose trace log file)"); System.out.println(" * Add --accept-red-cluster to allow securityadmin to operate on a red cluster."); return (-1); } @@ -680,7 +680,7 @@ public static int execute(final String[] args) throws Exception { if(deleteConfigIndex) { return deleteConfigIndex(restHighLevelClient, index, indexExists); } - + if (!indexExists) { System.out.print(index +" index does not exists, attempt to create it ... "); final int created = createConfigIndex(restHighLevelClient, index, explicitReplicas); @@ -690,7 +690,7 @@ public static int execute(final String[] args) throws Exception { } else { System.out.println(index+" index already exists, so we do not need to create one."); - + try { ClusterHealthResponse clusterHealthResponse = restHighLevelClient.cluster().health(new ClusterHealthRequest(index), RequestOptions.DEFAULT); @@ -705,7 +705,7 @@ public static int execute(final String[] args) throws Exception { if (clusterHealthResponse.getStatus() == ClusterHealthStatus.YELLOW) { System.out.println("INFO: "+index+" index state is YELLOW, it seems you miss some replicas"); } - + } catch (Exception e) { if(!failFast) { System.out.println("Cannot retrieve "+index+" index state state due to "+e.getMessage()+". This is not an error, will keep on trying ..."); @@ -726,7 +726,7 @@ public static int execute(final String[] args) throws Exception { && securityIndex.getMappings() != null && securityIndex.getMappings().get(index) != null && securityIndex.getMappings().get(index).getSourceAsMap().containsKey("security")); - + if(legacy) { System.out.println("Legacy index '"+index+"' (ES 6) detected (or forced). You should migrate the configuration!"); } @@ -765,9 +765,9 @@ public static int execute(final String[] args) throws Exception { } boolean isCdAbs = new File(cd).isAbsolute(); - + System.out.println("Populate config from "+(isCdAbs?cd:new File(".", cd).getCanonicalPath())); - + if(file != null) { if(type != null) { System.out.println("Force type: "+type); @@ -828,7 +828,7 @@ private static boolean checkConfigUpdateResponse(Response response, int expected } else { System.out.println("SUCC: Expected " + expectedConfigCount + " config types for node " + n + " is " + n.get("updated_config_size").asInt() + " (" + n.get("updated_config_types") + ") due to: " + (n.get("message") == null ? "unknown reason" : n.get("message"))); } - + success = success && successNode; } @@ -843,7 +843,7 @@ private static boolean uploadFile(final RestHighLevelClient restHighLevelClient, final boolean populateEmptyIfMissing) { String id = _id; - + if(legacy) { id = _id; @@ -892,12 +892,12 @@ private static boolean retrieveFile(final RestHighLevelClient restHighLevelClien private static boolean retrieveFile(final RestHighLevelClient restHighLevelClient, final String filepath, final String index, final String _id, final boolean legacy, final boolean populateFileIfEmpty) { String id = _id; - + if(legacy) { id = _id; - + } - + System.out.println("Will retrieve '"+"/" +id+"' into "+filepath+" "+(legacy?"(legacy mode)":"")); try (Writer writer = new FileWriter(filepath, StandardCharsets.UTF_8)) { @@ -944,7 +944,7 @@ private static boolean retrieveFile(final RestHighLevelClient restHighLevelClien } catch (Exception e) { System.out.println(" FAIL: Get configuration for '"+_id+"' failed because of "+e.toString()); } - + return false; } @@ -962,23 +962,23 @@ private static BytesReference readXContent(final String content, final MediaType parser.close(); } } - + //validate return retVal; } - + private static String convertToYaml(String type, BytesReference bytes, boolean prettyPrint) throws IOException { - + try (XContentParser parser = JsonXContent.jsonXContent.createParser(NamedXContentRegistry.EMPTY, THROW_UNSUPPORTED_OPERATION, bytes.streamInput())) { parser.nextToken(); parser.nextToken(); - + if(!type.equals((parser.currentName()))) { return null; } - + parser.nextToken(); - + XContentBuilder builder = XContentFactory.yamlBuilder(); if (prettyPrint) { builder.prettyPrint(); @@ -991,7 +991,7 @@ private static String convertToYaml(String type, BytesReference bytes, boolean p protected static void generateDiagnoseTrace(final RestHighLevelClient restHighLevelClient) { final String date = DATE_FORMAT.format(new Date()); - + final StringBuilder sb = new StringBuilder(); sb.append("Diagnostic securityadmin trace"+System.lineSeparator()); sb.append("OpenSearch client version: "+Version.CURRENT+System.lineSeparator()); @@ -1061,19 +1061,19 @@ private static void validate(CommandLine line) throws ParseException { if(line.hasOption("ts") && line.hasOption("cacert")) { System.out.println("WARN: It makes no sense to specify -ts as well as -cacert"); } - + if(line.hasOption("ks") && line.hasOption("cert")) { System.out.println("WARN: It makes no sense to specify -ks as well as -cert"); } - + if(line.hasOption("ks") && line.hasOption("key")) { System.out.println("WARN: It makes no sense to specify -ks as well as -key"); } - + if(line.hasOption("cd") && line.hasOption("rl")) { System.out.println("WARN: It makes no sense to specify -cd as well as -r"); } - + if(line.hasOption("cd") && line.hasOption("f")) { System.out.println("WARN: It makes no sense to specify -cd as well as -f"); } @@ -1089,15 +1089,15 @@ private static void validate(CommandLine line) throws ParseException { if(!line.hasOption("vc") && !line.hasOption("ks") && !line.hasOption("cert") /*&& !line.hasOption("simple-auth")*/) { throw new ParseException("Specify at least -ks or -cert"); } - - if(!line.hasOption("vc") && !line.hasOption("mo") + + if(!line.hasOption("vc") && !line.hasOption("mo") && !line.hasOption("ts") && !line.hasOption("cacert")) { throw new ParseException("Specify at least -ts or -cacert"); } - + //TODO add more validation rules } - + private static String promptForPassword(String passwordName, String commandLineOption, String envVarName) throws Exception { final Console console = System.console(); if(console == null) { @@ -1132,7 +1132,7 @@ private static int issueWarnings(RestHighLevelClient restHighLevelClient) throws if(!ALLOW_MIXED) { return -1; } - + } else { System.out.println("OpenSearch Version: "+minVersion.toString()); } @@ -1161,14 +1161,14 @@ private static int deleteConfigIndex(RestHighLevelClient restHighLevelClient, St } else { System.out.print("No index '"+index+"' exists, so no need to delete it"); } - + return (success?0:-1); } private static int createConfigIndex(RestHighLevelClient restHighLevelClient, String index, String explicitReplicas) throws IOException { Map indexSettings = new HashMap<>(); indexSettings.put("index.number_of_shards", 1); - + if(explicitReplicas != null) { if(explicitReplicas.contains("-")) { indexSettings.put("index.auto_expand_replicas", explicitReplicas); @@ -1218,11 +1218,11 @@ private static int upload(RestHighLevelClient tc, String index, String cd, boole boolean success = uploadFile(tc, cd + "config.yml", index, "config", legacy, resolveEnvVars); success = uploadFile(tc, cd+"roles.yml", index, "roles", legacy, resolveEnvVars) && success; success = uploadFile(tc, cd+"roles_mapping.yml", index, "rolesmapping", legacy, resolveEnvVars) && success; - + success = uploadFile(tc, cd+"internal_users.yml", index, "internalusers", legacy, resolveEnvVars) && success; success = uploadFile(tc, cd+"action_groups.yml", index, "actiongroups", legacy, resolveEnvVars) && success; - + if(!legacy) { success = uploadFile(tc, cd+"tenants.yml", index, "tenants", legacy, resolveEnvVars) && success; } @@ -1252,18 +1252,18 @@ private static int migrate(RestHighLevelClient tc, String index, File backupDir, System.out.println("== Migration started =="); System.out.println("======================="); - + System.out.println("-> Backup current configuration to "+backupDir.getAbsolutePath()); - + if(backup(tc, index, backupDir, true) != 0) { return -1; } System.out.println(" done"); - + File v7Dir = new File(backupDir,"v7"); v7Dir.mkdirs(); - + try { System.out.println("-> Migrate configuration to new format and store it here: "+v7Dir.getAbsolutePath()); @@ -1303,13 +1303,13 @@ private static int migrate(RestHighLevelClient tc, String index, File backupDir, e.printStackTrace(); return -1; } - + System.out.println(" done"); - + System.out.println("-> Delete old "+index+" index"); deleteConfigIndex(tc, index, true); System.out.println(" done"); - + System.out.println("-> Upload new configuration into OpenSearch cluster"); int uploadResult = upload(tc, index, v7Dir.getAbsolutePath() + "/", false, expectedNodeCount, resolveEnvVars); @@ -1319,10 +1319,10 @@ private static int migrate(RestHighLevelClient tc, String index, File backupDir, }else { System.out.println(" ERR: unable to upload"); } - + return uploadResult; } - + private static String readTypeFromFile(File file) throws IOException { if(!file.exists() || !file.isFile()) { System.out.println("ERR: No such file "+file.getAbsolutePath()); @@ -1335,16 +1335,16 @@ private static String readTypeFromFile(File file) throws IOException { private static int validateConfig(String cd, String file, String type, int version) { if (file != null) { try { - + if(type == null) { type = readTypeFromFile(new File(file)); } - + if(type == null) { System.out.println("ERR: Unable to read type from "+file); return -1; } - + ConfigHelper.fromYamlFile(file, CType.fromString(type), version==7?2:1, 0, 0); return 0; } catch (Exception e) { @@ -1357,7 +1357,7 @@ private static int validateConfig(String cd, String file, String type, int versi success = validateConfigFile(cd+"roles.yml", CType.ROLES, version) && success; success = validateConfigFile(cd+"roles_mapping.yml", CType.ROLESMAPPING, version) && success; success = validateConfigFile(cd+"config.yml", CType.CONFIG, version) && success; - + if(new File(cd+"tenants.yml").exists() && version != 6) { success = validateConfigFile(cd+"tenants.yml", CType.TENANTS, version) && success; } @@ -1368,10 +1368,10 @@ private static int validateConfig(String cd, String file, String type, int versi return success?0:-1; } - + return -1; } - + private static boolean validateConfigFile(String file, CType cType, int version) { try { ConfigHelper.fromYamlFile(file, cType, version==7?2:1, 0, 0); diff --git a/src/main/java/org/opensearch/security/transport/DefaultInterClusterRequestEvaluator.java b/src/main/java/org/opensearch/security/transport/DefaultInterClusterRequestEvaluator.java index 6a7917b385..84087b5ed9 100644 --- a/src/main/java/org/opensearch/security/transport/DefaultInterClusterRequestEvaluator.java +++ b/src/main/java/org/opensearch/security/transport/DefaultInterClusterRequestEvaluator.java @@ -81,9 +81,9 @@ private WildcardMatcher getNodesDnToEvaluate() { @Override public boolean isInterClusterRequest(TransportRequest request, X509Certificate[] localCerts, X509Certificate[] peerCerts, final String principal) { - + String[] principals = new String[2]; - + if (principal != null && principal.length() > 0) { principals[0] = principal; principals[1] = principal.replace(" ",""); @@ -93,14 +93,14 @@ public boolean isInterClusterRequest(TransportRequest request, X509Certificate[] final boolean isTraceEnabled = log.isTraceEnabled(); if (principals[0] != null && nodesDn.matchAny(principals)) { - + if (isTraceEnabled) { log.trace("Treat certificate with principal {} as other node because of it matches one of {}", Arrays.toString(principals), nodesDn); } - + return true; - + } else { if (isTraceEnabled) { log.trace("Treat certificate with principal {} NOT as other node because we it does not matches one of {}", Arrays.toString(principals), diff --git a/src/main/java/org/opensearch/security/transport/InterClusterRequestEvaluator.java b/src/main/java/org/opensearch/security/transport/InterClusterRequestEvaluator.java index 38f4426420..81cfa9e345 100644 --- a/src/main/java/org/opensearch/security/transport/InterClusterRequestEvaluator.java +++ b/src/main/java/org/opensearch/security/transport/InterClusterRequestEvaluator.java @@ -42,18 +42,18 @@ public interface InterClusterRequestEvaluator { /** * Determine if request is a message from * another node in the cluster - * + * * @param request The transport request to evaluate * @param localCerts Local certs to use for evaluating the request which include criteria * specific to the implementation for confirming intercluster * communication - * + * * @param peerCerts Certs to use for evaluating the request which include criteria * specific to the implementation for confirming intercluster * communication - * + * * @param principal The principal evaluated by the configured principal extractor - * + * * @return True when determined to be intercluster, false otherwise */ boolean isInterClusterRequest(final TransportRequest request, final X509Certificate[] localCerts, final X509Certificate[] peerCerts, diff --git a/src/main/java/org/opensearch/security/transport/SecurityInterceptor.java b/src/main/java/org/opensearch/security/transport/SecurityInterceptor.java index e17560a000..5456d36d9c 100644 --- a/src/main/java/org/opensearch/security/transport/SecurityInterceptor.java +++ b/src/main/java/org/opensearch/security/transport/SecurityInterceptor.java @@ -142,7 +142,7 @@ public void sendRequestDecorate(AsyncSender sender || k.equals(ConfigConstants.OPENDISTRO_SECURITY_DOC_ALLOWLIST_HEADER) || k.equals(ConfigConstants.OPENDISTRO_SECURITY_FILTER_LEVEL_DLS_DONE) || k.equals(ConfigConstants.OPENDISTRO_SECURITY_DLS_MODE_HEADER) - || k.equals(ConfigConstants.OPENDISTRO_SECURITY_DLS_FILTER_LEVEL_QUERY_HEADER) + || k.equals(ConfigConstants.OPENDISTRO_SECURITY_DLS_FILTER_LEVEL_QUERY_HEADER) || (k.equals("_opendistro_security_source_field_context") && ! (request instanceof SearchRequest) && !(request instanceof GetRequest)) || k.startsWith("_opendistro_security_trace") || k.startsWith(ConfigConstants.OPENDISTRO_SECURITY_INITIAL_ACTION_CLASS_HEADER) @@ -269,18 +269,18 @@ public T read(StreamInput in) throws IOException { @Override public void handleResponse(T response) { - + ThreadContext threadContext = getThreadContext(); Map> responseHeaders = threadContext.getResponseHeaders(); List flsResponseHeader = responseHeaders.get(ConfigConstants.OPENDISTRO_SECURITY_FLS_FIELDS_HEADER); List dlsResponseHeader = responseHeaders.get(ConfigConstants.OPENDISTRO_SECURITY_DLS_QUERY_HEADER); List maskedFieldsResponseHeader = responseHeaders.get(ConfigConstants.OPENDISTRO_SECURITY_MASKED_FIELD_HEADER); - + contextToRestore.restore(); final boolean isDebugEnabled = log.isDebugEnabled(); - if (response instanceof ClusterSearchShardsResponse) { + if (response instanceof ClusterSearchShardsResponse) { if (flsResponseHeader != null && !flsResponseHeader.isEmpty()) { if (isDebugEnabled) { log.debug("add flsResponseHeader as transient"); diff --git a/src/main/java/org/opensearch/security/transport/SecurityRequestHandler.java b/src/main/java/org/opensearch/security/transport/SecurityRequestHandler.java index c6c80ba50e..4a2919fdb2 100644 --- a/src/main/java/org/opensearch/security/transport/SecurityRequestHandler.java +++ b/src/main/java/org/opensearch/security/transport/SecurityRequestHandler.java @@ -296,7 +296,7 @@ else if(!Strings.isNullOrEmpty(injectedUserHeader)) { } } } - + private void putInitialActionClassHeader(String initialActionClassValue, String resolvedActionClass) { if(initialActionClassValue == null) { if(getThreadContext().getHeader(ConfigConstants.OPENDISTRO_SECURITY_INITIAL_ACTION_CLASS_HEADER) == null) { diff --git a/src/main/java/org/opensearch/security/user/CustomAttributesAware.java b/src/main/java/org/opensearch/security/user/CustomAttributesAware.java index 89d62d3d5d..f5db96db8a 100644 --- a/src/main/java/org/opensearch/security/user/CustomAttributesAware.java +++ b/src/main/java/org/opensearch/security/user/CustomAttributesAware.java @@ -29,6 +29,6 @@ import java.util.Map; public interface CustomAttributesAware { - + Map getCustomAttributesMap(); } diff --git a/src/main/java/org/opensearch/security/user/User.java b/src/main/java/org/opensearch/security/user/User.java index 83c7ea2eb5..86089afd35 100644 --- a/src/main/java/org/opensearch/security/user/User.java +++ b/src/main/java/org/opensearch/security/user/User.java @@ -56,7 +56,7 @@ public class User implements Serializable, Writeable, CustomAttributesAware { // This is to be used in scenarios where some of the nodes do not have security enabled, and therefore do not pass any user information in threadcontext, yet we need the communication to not break between the nodes. // Attach the required permissions to either the user or the backend role. public static final User DEFAULT_TRANSPORT_USER = new User("opendistro_security_default_transport_user", Lists.newArrayList("opendistro_security_default_transport_backendrole"), null); - + private static final long serialVersionUID = -5500938501822658596L; private final String name; /** @@ -76,10 +76,10 @@ public User(final StreamInput in) throws IOException { attributes = Collections.synchronizedMap(in.readMap(StreamInput::readString, StreamInput::readString)); securityRoles.addAll(in.readList(StreamInput::readString)); } - + /** * Create a new authenticated user - * + * * @param name The username (must not be null or empty) * @param roles Roles of which the user is a member off (maybe null) * @param customAttributes Custom attributes associated with this (maybe null) @@ -97,7 +97,7 @@ public User(final String name, final Collection roles, final AuthCredent if (roles != null) { this.addRoles(roles); } - + if(customAttributes != null) { this.attributes.putAll(customAttributes.getAttributes()); } @@ -106,7 +106,7 @@ public User(final String name, final Collection roles, final AuthCredent /** * Create a new authenticated user without roles and attributes - * + * * @param name The username (must not be null or empty) * @throws IllegalArgumentException if name is null or empty */ @@ -119,7 +119,7 @@ public final String getName() { } /** - * + * * @return A unmodifiable set of the backend roles this user is a member of */ public final Set getRoles() { @@ -128,7 +128,7 @@ public final Set getRoles() { /** * Associate this user with a backend role - * + * * @param role The backend role */ public final void addRole(final String role) { @@ -137,7 +137,7 @@ public final void addRole(final String role) { /** * Associate this user with a set of backend roles - * + * * @param roles The backend roles */ public final void addRoles(final Collection roles) { @@ -148,7 +148,7 @@ public final void addRoles(final Collection roles) { /** * Check if this user is a member of a backend role - * + * * @param role The backend role * @return true if this user is a member of the backend role, false otherwise */ @@ -158,7 +158,7 @@ public final boolean isUserInRole(final String role) { /** * Associate this user with a set of backend roles - * + * * @param roles The backend roles */ public final void addAttributes(final Map attributes) { @@ -166,7 +166,7 @@ public final void addAttributes(final Map attributes) { this.attributes.putAll(attributes); } } - + public final String getRequestedTenant() { return requestedTenant; } @@ -174,8 +174,8 @@ public final String getRequestedTenant() { public final void setRequestedTenant(String requestedTenant) { this.requestedTenant = requestedTenant; } - - + + public boolean isInjected() { return isInjected; } @@ -225,7 +225,7 @@ public final boolean equals(final Object obj) { /** * Copy all backend roles from another user - * + * * @param user The user from which the backend roles should be copied over */ public final void copyRolesFrom(final User user) { @@ -245,7 +245,7 @@ public void writeTo(StreamOutput out) throws IOException { /** * Get the custom attributes associated with this user - * + * * @return A modifiable map with all the current custom attributes associated with this user */ public synchronized final Map getCustomAttributesMap() { @@ -254,13 +254,13 @@ public synchronized final Map getCustomAttributesMap() { } return attributes; } - + public final void addSecurityRoles(final Collection securityRoles) { if(securityRoles != null && this.securityRoles != null) { this.securityRoles.addAll(securityRoles); } } - + public final Set getSecurityRoles() { return this.securityRoles == null ? Collections.synchronizedSet(Collections.emptySet()) : Collections.unmodifiableSet(this.securityRoles); } diff --git a/src/main/java/org/opensearch/security/util/ratetracking/HeapBasedRateTracker.java b/src/main/java/org/opensearch/security/util/ratetracking/HeapBasedRateTracker.java index 37a9817b34..537d4d8fc7 100644 --- a/src/main/java/org/opensearch/security/util/ratetracking/HeapBasedRateTracker.java +++ b/src/main/java/org/opensearch/security/util/ratetracking/HeapBasedRateTracker.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.util.ratetracking; @@ -131,7 +131,7 @@ private void shiftFull(long timestamp) { this.startTime = timestamp; return; } - + int shiftOffset = this.timeOffsets[this.timeOffsetStart]; this.startTime += shiftOffset; diff --git a/src/main/java/org/opensearch/security/util/ratetracking/RateTracker.java b/src/main/java/org/opensearch/security/util/ratetracking/RateTracker.java index 5de531f0cb..c90680cd4a 100644 --- a/src/main/java/org/opensearch/security/util/ratetracking/RateTracker.java +++ b/src/main/java/org/opensearch/security/util/ratetracking/RateTracker.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.util.ratetracking; diff --git a/src/main/java/org/opensearch/security/util/ratetracking/SingleTryRateTracker.java b/src/main/java/org/opensearch/security/util/ratetracking/SingleTryRateTracker.java index c56639d04a..4f6bd371ed 100644 --- a/src/main/java/org/opensearch/security/util/ratetracking/SingleTryRateTracker.java +++ b/src/main/java/org/opensearch/security/util/ratetracking/SingleTryRateTracker.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.util.ratetracking; diff --git a/src/main/resources/static_config/static_roles.yml b/src/main/resources/static_config/static_roles.yml index 417e4f0ab7..dc80662d0e 100644 --- a/src/main/resources/static_config/static_roles.yml +++ b/src/main/resources/static_config/static_roles.yml @@ -62,7 +62,7 @@ own_index: allowed_actions: - "indices_all" - + manage_snapshots: reserved: true hidden: false @@ -76,7 +76,7 @@ manage_snapshots: allowed_actions: - "indices:data/write/index" - "indices:admin/create" - + kibana_server: reserved: true hidden: false @@ -141,7 +141,7 @@ logstash: allowed_actions: - "crud" - "create_index" - + readall_and_monitor: reserved: true hidden: false @@ -155,7 +155,7 @@ readall_and_monitor: - "*" allowed_actions: - "read" - + readall: reserved: true hidden: false @@ -168,4 +168,3 @@ readall: - "*" allowed_actions: - "read" - diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/HTTPJwtAuthenticatorTest.java b/src/test/java/com/amazon/dlic/auth/http/jwt/HTTPJwtAuthenticatorTest.java index 0aeb4df082..04a30ba2db 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/HTTPJwtAuthenticatorTest.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/HTTPJwtAuthenticatorTest.java @@ -41,7 +41,7 @@ public class HTTPJwtAuthenticatorTest { final static byte[] secretKeyBytes = new byte[1024]; final static SecretKey secretKey; - + static { new SecureRandom().nextBytes(secretKeyBytes); secretKey = Keys.hmacShaKeyFor(secretKeyBytes); @@ -50,29 +50,29 @@ public class HTTPJwtAuthenticatorTest { @Test public void testNoKey() throws Exception { - final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder(), - Jwts.builder().setSubject("Leonard McCoy")); + final AuthCredentials credentials = extractCredentialsFromJwtHeader(Settings.builder(), Jwts.builder().setSubject("Leonard McCoy")); Assert.assertNull(credentials); } @Test public void testEmptyKey() throws Exception { - + final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", ""), - Jwts.builder().setSubject("Leonard McCoy")); + Settings.builder().put("signing_key", ""), + Jwts.builder().setSubject("Leonard McCoy") + ); - Assert.assertNull(credentials); + Assert.assertNull(credentials); } @Test public void testBadKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(new byte[]{1,3,3,4,3,6,7,8,3,10})), - Jwts.builder().setSubject("Leonard McCoy")); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(new byte[] { 1, 3, 3, 4, 3, 6, 7, 8, 3, 10 })), + Jwts.builder().setSubject("Leonard McCoy") + ); Assert.assertNull(credentials); } @@ -99,7 +99,7 @@ public void testInvalid() throws Exception { HTTPJwtAuthenticator jwtAuth = new HTTPJwtAuthenticator(settings, null); Map headers = new HashMap(); - headers.put("Authorization", "Bearer "+jwsToken); + headers.put("Authorization", "Bearer " + jwsToken); AuthCredentials credentials = jwtAuth.extractCredentials(new FakeRestRequest(headers, new HashMap()), null); Assert.assertNull(credentials); @@ -110,11 +110,15 @@ public void testBearer() throws Exception { Settings settings = Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).build(); - String jwsToken = Jwts.builder().setSubject("Leonard McCoy").setAudience("myaud").signWith(secretKey, SignatureAlgorithm.HS512).compact(); + String jwsToken = Jwts.builder() + .setSubject("Leonard McCoy") + .setAudience("myaud") + .signWith(secretKey, SignatureAlgorithm.HS512) + .compact(); HTTPJwtAuthenticator jwtAuth = new HTTPJwtAuthenticator(settings, null); Map headers = new HashMap(); - headers.put("Authorization", "Bearer "+jwsToken); + headers.put("Authorization", "Bearer " + jwsToken); AuthCredentials credentials = jwtAuth.extractCredentials(new FakeRestRequest(headers, new HashMap()), null); @@ -140,7 +144,6 @@ public void testBearerWrongPosition() throws Exception { Assert.assertNull(credentials); } - @Test public void testBasicAuthHeader() throws Exception { Settings settings = Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).build(); @@ -157,8 +160,9 @@ public void testBasicAuthHeader() throws Exception { public void testRoles() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), - Jwts.builder().setSubject("Leonard McCoy").claim("roles", "role1,role2")); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), + Jwts.builder().setSubject("Leonard McCoy").claim("roles", "role1,role2") + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); @@ -169,8 +173,9 @@ public void testRoles() throws Exception { public void testNullClaim() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), - Jwts.builder().setSubject("Leonard McCoy").claim("roles", null)); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), + Jwts.builder().setSubject("Leonard McCoy").claim("roles", null) + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); @@ -181,21 +186,23 @@ public void testNullClaim() throws Exception { public void testNonStringClaim() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), - Jwts.builder().setSubject("Leonard McCoy").claim("roles", 123L)); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), + Jwts.builder().setSubject("Leonard McCoy").claim("roles", 123L) + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); Assert.assertEquals(1, credentials.getBackendRoles().size()); - Assert.assertTrue( credentials.getBackendRoles().contains("123")); + Assert.assertTrue(credentials.getBackendRoles().contains("123")); } @Test public void testRolesMissing() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), - Jwts.builder().setSubject("Leonard McCoy")); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), + Jwts.builder().setSubject("Leonard McCoy") + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); @@ -206,8 +213,9 @@ public void testRolesMissing() throws Exception { public void testWrongSubjectKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("subject_key", "missing"), - Jwts.builder().claim("roles", "role1,role2").claim("asub", "Dr. Who")); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("subject_key", "missing"), + Jwts.builder().claim("roles", "role1,role2").claim("asub", "Dr. Who") + ); Assert.assertNull(credentials); } @@ -216,8 +224,9 @@ public void testWrongSubjectKey() throws Exception { public void testAlternativeSubject() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("subject_key", "asub"), - Jwts.builder().setSubject("Leonard McCoy").claim("roles", "role1,role2").claim("asub", "Dr. Who")); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("subject_key", "asub"), + Jwts.builder().setSubject("Leonard McCoy").claim("roles", "role1,role2").claim("asub", "Dr. Who") + ); Assert.assertNotNull(credentials); Assert.assertEquals("Dr. Who", credentials.getUsername()); @@ -228,8 +237,9 @@ public void testAlternativeSubject() throws Exception { public void testNonStringAlternativeSubject() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("subject_key", "asub"), - Jwts.builder().setSubject("Leonard McCoy").claim("roles", "role1,role2").claim("asub", false)); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("subject_key", "asub"), + Jwts.builder().setSubject("Leonard McCoy").claim("roles", "role1,role2").claim("asub", false) + ); Assert.assertNotNull(credentials); Assert.assertEquals("false", credentials.getUsername()); @@ -239,7 +249,10 @@ public void testNonStringAlternativeSubject() throws Exception { @Test public void testUrlParam() throws Exception { - Settings settings = Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("jwt_url_parameter", "abc").build(); + Settings settings = Settings.builder() + .put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)) + .put("jwt_url_parameter", "abc") + .build(); String jwsToken = Jwts.builder().setSubject("Leonard McCoy").signWith(secretKey, SignatureAlgorithm.HS512).compact(); @@ -259,8 +272,9 @@ public void testUrlParam() throws Exception { public void testExp() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)), - Jwts.builder().setSubject("Expired").setExpiration(new Date(100))); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)), + Jwts.builder().setSubject("Expired").setExpiration(new Date(100)) + ); Assert.assertNull(credentials); } @@ -269,9 +283,10 @@ public void testExp() throws Exception { public void testNbf() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)), - Jwts.builder().setSubject("Expired").setNotBefore(new Date(System.currentTimeMillis()+(1000*36000)))); - + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)), + Jwts.builder().setSubject("Expired").setNotBefore(new Date(System.currentTimeMillis() + (1000 * 36000))) + ); + Assert.assertNull(credentials); } @@ -285,11 +300,16 @@ public void testRS256() throws Exception { PublicKey pub = pair.getPublic(); String jwsToken = Jwts.builder().setSubject("Leonard McCoy").signWith(priv, SignatureAlgorithm.RS256).compact(); - Settings settings = Settings.builder().put("signing_key", "-----BEGIN PUBLIC KEY-----\n"+BaseEncoding.base64().encode(pub.getEncoded())+"-----END PUBLIC KEY-----").build(); + Settings settings = Settings.builder() + .put( + "signing_key", + "-----BEGIN PUBLIC KEY-----\n" + BaseEncoding.base64().encode(pub.getEncoded()) + "-----END PUBLIC KEY-----" + ) + .build(); HTTPJwtAuthenticator jwtAuth = new HTTPJwtAuthenticator(settings, null); Map headers = new HashMap(); - headers.put("Authorization", "Bearer "+jwsToken); + headers.put("Authorization", "Bearer " + jwsToken); AuthCredentials creds = jwtAuth.extractCredentials(new FakeRestRequest(headers, new HashMap()), null); @@ -306,10 +326,10 @@ public void testES512() throws Exception { KeyPair pair = keyGen.generateKeyPair(); PrivateKey priv = pair.getPrivate(); PublicKey pub = pair.getPublic(); - + Settings settings = Settings.builder().put("signing_key", BaseEncoding.base64().encode(pub.getEncoded())).build(); String jwsToken = Jwts.builder().setSubject("Leonard McCoy").signWith(priv, SignatureAlgorithm.ES512).compact(); - + HTTPJwtAuthenticator jwtAuth = new HTTPJwtAuthenticator(settings, null); Map headers = new HashMap(); headers.put("Authorization", jwsToken); @@ -324,16 +344,13 @@ public void testES512() throws Exception { @Test public void testRolesArray() throws Exception { - JwtBuilder builder = Jwts.builder() - .setPayload("{"+ - "\"sub\": \"John Doe\","+ - "\"roles\": [\"a\",\"b\",\"3rd\"]"+ - "}"); + JwtBuilder builder = Jwts.builder().setPayload("{" + "\"sub\": \"John Doe\"," + "\"roles\": [\"a\",\"b\",\"3rd\"]" + "}"); final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), - builder); - + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("roles_key", "roles"), + builder + ); + Assert.assertNotNull(credentials); Assert.assertEquals("John Doe", credentials.getUsername()); Assert.assertEquals(3, credentials.getBackendRoles().size()); @@ -346,9 +363,10 @@ public void testRolesArray() throws Exception { public void testRequiredAudienceWithCorrectAudience() { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("required_audience", "test_audience"), - Jwts.builder().setSubject("Leonard McCoy").setAudience("test_audience")); - + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("required_audience", "test_audience"), + Jwts.builder().setSubject("Leonard McCoy").setAudience("test_audience") + ); + Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); } @@ -356,19 +374,21 @@ public void testRequiredAudienceWithCorrectAudience() { @Test public void testRequiredAudienceWithIncorrectAudience() { - final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("required_audience", "test_audience"), - Jwts.builder().setSubject("Leonard McCoy").setAudience("wrong_audience")); - + final AuthCredentials credentials = extractCredentialsFromJwtHeader( + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("required_audience", "test_audience"), + Jwts.builder().setSubject("Leonard McCoy").setAudience("wrong_audience") + ); + Assert.assertNull(credentials); } @Test public void testRequiredIssuerWithCorrectAudience() { - + final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("required_issuer", "test_issuer"), - Jwts.builder().setSubject("Leonard McCoy").setIssuer("test_issuer")); + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("required_issuer", "test_issuer"), + Jwts.builder().setSubject("Leonard McCoy").setIssuer("test_issuer") + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); @@ -376,18 +396,17 @@ public void testRequiredIssuerWithCorrectAudience() { @Test public void testRequiredIssuerWithIncorrectAudience() { - - final AuthCredentials credentials = extractCredentialsFromJwtHeader( - Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("required_issuer", "test_issuer"), - Jwts.builder().setSubject("Leonard McCoy").setIssuer("wrong_issuer")); - + + final AuthCredentials credentials = extractCredentialsFromJwtHeader( + Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).put("required_issuer", "test_issuer"), + Jwts.builder().setSubject("Leonard McCoy").setIssuer("wrong_issuer") + ); + Assert.assertNull(credentials); } /** extracts a default user credential from a request header */ - private AuthCredentials extractCredentialsFromJwtHeader( - final Settings.Builder settingsBuilder, - final JwtBuilder jwtBuilder) { + private AuthCredentials extractCredentialsFromJwtHeader(final Settings.Builder settingsBuilder, final JwtBuilder jwtBuilder) { final Settings settings = settingsBuilder.build(); final String jwsToken = jwtBuilder.signWith(secretKey, SignatureAlgorithm.HS512).compact(); final HTTPJwtAuthenticator jwtAuth = new HTTPJwtAuthenticator(settings, null); diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/CxfTestTools.java b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/CxfTestTools.java index e9920995ac..b2958193c2 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/CxfTestTools.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/CxfTestTools.java @@ -16,7 +16,7 @@ class CxfTestTools { - static String toJson(JsonMapObject jsonMapObject) { - return new JsonMapObjectReaderWriter().toJson(jsonMapObject); - } + static String toJson(JsonMapObject jsonMapObject) { + return new JsonMapObjectReaderWriter().toJson(jsonMapObject); + } } diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/HTTPJwtKeyByOpenIdConnectAuthenticatorTest.java b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/HTTPJwtKeyByOpenIdConnectAuthenticatorTest.java index 6419e84891..578fef7202 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/HTTPJwtKeyByOpenIdConnectAuthenticatorTest.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/HTTPJwtKeyByOpenIdConnectAuthenticatorTest.java @@ -18,222 +18,376 @@ import org.junit.BeforeClass; import org.junit.Test; +import org.opensearch.OpenSearchSecurityException; import org.opensearch.common.settings.Settings; import org.opensearch.security.user.AuthCredentials; import org.opensearch.security.util.FakeRestRequest; public class HTTPJwtKeyByOpenIdConnectAuthenticatorTest { - protected static MockIpdServer mockIdpServer; - - @BeforeClass - public static void setUp() throws Exception { - mockIdpServer = new MockIpdServer(TestJwk.Jwks.ALL); - } - - @AfterClass - public static void tearDown() { - if (mockIdpServer != null) { - try { - mockIdpServer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @Test - public void basicTest() { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials(new FakeRestRequest( - ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_OCT_1), new HashMap()), null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - } - - @Test - public void testEscapeKid() { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials(new FakeRestRequest( - ImmutableMap.of("Authorization", "Bearer " + TestJwts.MC_COY_SIGNED_OCT_1_INVALID_KID), new HashMap()), null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - } - - @Test - public void bearerTest() { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", "Bearer " + TestJwts.MC_COY_SIGNED_OCT_1), - new HashMap()), - null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - } - - @Test - public void testRoles() throws Exception { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()) - .put("roles_key", TestJwts.ROLES_CLAIM).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials(new FakeRestRequest( - ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_OCT_1), new HashMap()), null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_ROLES, creds.getBackendRoles()); - } - - @Test - public void testExp() throws Exception { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", "Bearer " + TestJwts.MC_COY_EXPIRED_SIGNED_OCT_1), - new HashMap()), - null); - - Assert.assertNull(creds); - } - - @Test - public void testExpInSkew() throws Exception { - Settings settings = Settings.builder() - .put("openid_connect_url", mockIdpServer.getDiscoverUri()) - .put("jwt_clock_skew_tolerance_seconds", "10") - .build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - long expiringDate = System.currentTimeMillis()/1000-5; - long notBeforeDate = System.currentTimeMillis()/1000-25; - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest( - ImmutableMap.of( - "Authorization", - "Bearer "+TestJwts.createMcCoySignedOct1(notBeforeDate, expiringDate)), - new HashMap()), - null); - - Assert.assertNotNull(creds); - } - - @Test - public void testNbf() throws Exception { - Settings settings = Settings.builder() - .put("openid_connect_url", mockIdpServer.getDiscoverUri()) - .put("jwt_clock_skew_tolerance_seconds", "0") - .build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - long expiringDate = 20+System.currentTimeMillis()/1000; - long notBeforeDate = 5+System.currentTimeMillis()/1000; - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest( - ImmutableMap.of( - "Authorization", - "Bearer "+TestJwts.createMcCoySignedOct1(notBeforeDate, expiringDate)), - new HashMap()), - null); - - Assert.assertNull(creds); - } - - @Test - public void testNbfInSkew() throws Exception { - Settings settings = Settings.builder() - .put("openid_connect_url", mockIdpServer.getDiscoverUri()) - .put("jwt_clock_skew_tolerance_seconds", "10") - .build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - long expiringDate = 20+System.currentTimeMillis()/1000; - long notBeforeDate = 5+System.currentTimeMillis()/1000;; - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest( - ImmutableMap.of("Authorization", "Bearer "+TestJwts.createMcCoySignedOct1(notBeforeDate, expiringDate)), - new HashMap()), - null); - - Assert.assertNotNull(creds); - } - - - @Test - public void testRS256() throws Exception { - - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials(new FakeRestRequest( - ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_RSA_1), new HashMap()), null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - } - - @Test - public void testBadSignature() throws Exception { - - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials(new FakeRestRequest( - ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_RSA_X), new HashMap()), null); - - Assert.assertNull(creds); - } - - @Test - public void testPeculiarJsonEscaping() { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.PeculiarEscaping.MC_COY_SIGNED_RSA_1), new HashMap()), - null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - } + protected static MockIpdServer mockIdpServer; + + @BeforeClass + public static void setUp() throws Exception { + mockIdpServer = new MockIpdServer(TestJwk.Jwks.ALL); + } + + @AfterClass + public static void tearDown() { + if (mockIdpServer != null) { + try { + mockIdpServer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Test + public void basicTest() { + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_OCT_1), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + } + + @Test + public void jwksUriTest() { + Settings settings = Settings.builder() + .put("jwks_uri", mockIdpServer.getJwksUri()) + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_OCT_2), new HashMap<>()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + } + + @Test + public void jwksMissingRequiredIssuerInClaimTest() { + Settings settings = Settings.builder() + .put("jwks_uri", mockIdpServer.getJwksUri()) + .put("required_issuer", TestJwts.TEST_ISSUER) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_NO_ISSUER_OCT_1), new HashMap<>()), + null + ); + + Assert.assertNull(creds); + } + + @Test + public void jwksNotMatchingRequiredIssuerInClaimTest() { + Settings settings = Settings.builder().put("jwks_uri", mockIdpServer.getJwksUri()).put("required_issuer", "Wrong Issuer").build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_OCT_2), new HashMap<>()), + null + ); + + Assert.assertNull(creds); + } + + @Test + public void jwksMissingRequiredAudienceInClaimTest() { + Settings settings = Settings.builder() + .put("jwks_uri", mockIdpServer.getJwksUri()) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_NO_AUDIENCE_OCT_1), new HashMap<>()), + null + ); + + Assert.assertNull(creds); + } + + @Test + public void jwksNotMatchingRequiredAudienceInClaimTest() { + Settings settings = Settings.builder() + .put("jwks_uri", mockIdpServer.getJwksUri()) + .put("required_audience", "Wrong Audience") + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_OCT_2), new HashMap<>()), + null + ); + + Assert.assertNull(creds); + } + + @Test + public void jwksUriMissingTest() { + var exception = Assert.assertThrows(Exception.class, () -> { + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(Settings.builder().build(), null); + jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_OCT_1), new HashMap<>()), + null + ); + }); + + Assert.assertEquals("Authentication backend failed", exception.getMessage()); + Assert.assertEquals(OpenSearchSecurityException.class, exception.getClass()); + } + + @Test + public void testEscapeKid() { + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest( + ImmutableMap.of("Authorization", "Bearer " + TestJwts.MC_COY_SIGNED_OCT_1_INVALID_KID), + new HashMap() + ), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + } + + @Test + public void bearerTest() { + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", "Bearer " + TestJwts.MC_COY_SIGNED_OCT_1), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + } + + @Test + public void testRoles() throws Exception { + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("roles_key", TestJwts.ROLES_CLAIM) + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_OCT_1), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_ROLES, creds.getBackendRoles()); + } + + @Test + public void testExp() throws Exception { + Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest( + ImmutableMap.of("Authorization", "Bearer " + TestJwts.MC_COY_EXPIRED_SIGNED_OCT_1), + new HashMap() + ), + null + ); + + Assert.assertNull(creds); + } + + @Test + public void testExpInSkew() throws Exception { + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("jwt_clock_skew_tolerance_seconds", "10") + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + long expiringDate = System.currentTimeMillis() / 1000 - 5; + long notBeforeDate = System.currentTimeMillis() / 1000 - 25; + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest( + ImmutableMap.of("Authorization", "Bearer " + TestJwts.createMcCoySignedOct1(notBeforeDate, expiringDate)), + new HashMap() + ), + null + ); + + Assert.assertNotNull(creds); + } + + @Test + public void testNbf() throws Exception { + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("jwt_clock_skew_tolerance_seconds", "0") + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + long expiringDate = 20 + System.currentTimeMillis() / 1000; + long notBeforeDate = 5 + System.currentTimeMillis() / 1000; + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest( + ImmutableMap.of("Authorization", "Bearer " + TestJwts.createMcCoySignedOct1(notBeforeDate, expiringDate)), + new HashMap() + ), + null + ); + + Assert.assertNull(creds); + } + + @Test + public void testNbfInSkew() throws Exception { + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("jwt_clock_skew_tolerance_seconds", "10") + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + long expiringDate = 20 + System.currentTimeMillis() / 1000; + long notBeforeDate = 5 + System.currentTimeMillis() / 1000; + ; + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest( + ImmutableMap.of("Authorization", "Bearer " + TestJwts.createMcCoySignedOct1(notBeforeDate, expiringDate)), + new HashMap() + ), + null + ); + + Assert.assertNotNull(creds); + } + + @Test + public void testRS256() throws Exception { + + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_RSA_1), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + } + + @Test + public void testBadSignature() throws Exception { + + Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_RSA_X), new HashMap()), + null + ); + + Assert.assertNull(creds); + } + + @Test + public void testPeculiarJsonEscaping() { + Settings settings = Settings.builder() + .put("openid_connect_url", mockIdpServer.getDiscoverUri()) + .put("required_issuer", TestJwts.TEST_ISSUER) + .put("required_audience", TestJwts.TEST_AUDIENCE) + .build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest( + ImmutableMap.of("Authorization", TestJwts.PeculiarEscaping.MC_COY_SIGNED_RSA_1), + new HashMap() + ), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + } } diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetRetrieverTest.java b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetRetrieverTest.java index b30a6326b6..07c0250504 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetRetrieverTest.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/KeySetRetrieverTest.java @@ -78,12 +78,10 @@ public void cacheTest() { @Test public void clientCertTest() throws Exception { - try (MockIpdServer sslMockIdpServer = new MockIpdServer(TestJwk.Jwks.ALL, SocketUtils.findAvailableTcpPort(), - true) { + try (MockIpdServer sslMockIdpServer = new MockIpdServer(TestJwk.Jwks.ALL, SocketUtils.findAvailableTcpPort(), true) { @Override - protected void handleDiscoverRequest(HttpRequest request, ClassicHttpResponse response, HttpContext context) - throws IOException, HttpException { - + protected void handleDiscoverRequest(HttpRequest request, ClassicHttpResponse response, HttpContext context) throws IOException, + HttpException { SSLSession sslSession = ((HttpCoreContext) context).getSSLSession(); @@ -92,8 +90,7 @@ protected void handleDiscoverRequest(HttpRequest request, ClassicHttpResponse re try { String sha256Fingerprint = Hashing.sha256().hashBytes(peerCert.getEncoded()).toString(); - Assert.assertEquals("04b2b8baea7a0a893f0223d95b72081e9a1e154a0f9b1b4e75998085972b1b68", - sha256Fingerprint); + Assert.assertEquals("04b2b8baea7a0a893f0223d95b72081e9a1e154a0f9b1b4e75998085972b1b68", sha256Fingerprint); } catch (CertificateEncodingException e) { throw new RuntimeException(e); @@ -105,13 +102,11 @@ protected void handleDiscoverRequest(HttpRequest request, ClassicHttpResponse re SSLContextBuilder sslContextBuilder = SSLContexts.custom(); KeyStore trustStore = KeyStore.getInstance("JKS"); - InputStream trustStream = new FileInputStream( - FileHelper.getAbsoluteFilePathFromClassPath("jwt/truststore.jks").toFile()); + InputStream trustStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("jwt/truststore.jks").toFile()); trustStore.load(trustStream, "changeit".toCharArray()); KeyStore keyStore = KeyStore.getInstance("JKS"); - InputStream keyStream = new FileInputStream( - FileHelper.getAbsoluteFilePathFromClassPath("jwt/spock-keystore.jks").toFile()); + InputStream keyStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("jwt/spock-keystore.jks").toFile()); keyStore.load(keyStream, "changeit".toCharArray()); @@ -126,8 +121,19 @@ public String chooseAlias(Map aliases, SSLParameters }); SettingsBasedSSLConfigurator.SSLConfig sslConfig = new SettingsBasedSSLConfigurator.SSLConfig( - sslContextBuilder.build(), new String[] { "TLSv1.2", "TLSv1.1" }, null, null, false, false, false, - trustStore, null, keyStore, null, null); + sslContextBuilder.build(), + new String[] { "TLSv1.2", "TLSv1.1" }, + null, + null, + false, + false, + false, + trustStore, + null, + keyStore, + null, + null + ); KeySetRetriever keySetRetriever = new KeySetRetriever(sslMockIdpServer.getDiscoverUri(), sslConfig, false); diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/MockIpdServer.java b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/MockIpdServer.java index 21a9d239c3..68f852da5c 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/MockIpdServer.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/MockIpdServer.java @@ -45,123 +45,131 @@ import static com.amazon.dlic.auth.http.jwt.keybyoidc.CxfTestTools.toJson; class MockIpdServer implements Closeable { - final static String CTX_DISCOVER = "/discover"; - final static String CTX_KEYS = "/api/oauth/keys"; - - private final HttpServer httpServer; - private final int port; - private final String uri; - private final boolean ssl; - private final JsonWebKeys jwks; - - MockIpdServer(JsonWebKeys jwks) throws IOException { - this(jwks, SocketUtils.findAvailableTcpPort(), false); - } - - MockIpdServer(JsonWebKeys jwks, int port, boolean ssl) throws IOException { - this.port = port; - this.uri = (ssl ? "https" : "http") + "://localhost:" + port; - this.ssl = ssl; - this.jwks = jwks; - - ServerBootstrap serverBootstrap = ServerBootstrap.bootstrap().setListenerPort(port) - .register(CTX_DISCOVER, new HttpRequestHandler() { - - @Override - public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, IOException { - handleDiscoverRequest(request, response, context); - } - }).register(CTX_KEYS, new HttpRequestHandler() { - - @Override - public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, IOException { - handleKeysRequest(request, response, context); - } - }); - - if (ssl) { - serverBootstrap = serverBootstrap.setSslContext(createSSLContext()) - .setSslSetupHandler(new Callback() { - @Override - public void execute(SSLParameters object) { - object.setNeedClientAuth(true); - } - }).setConnectionFactory(new HttpConnectionFactory() { - @Override - public DefaultBHttpServerConnection createConnection(final Socket socket) throws IOException { - final DefaultBHttpServerConnection conn = new DefaultBHttpServerConnection(ssl ? "https" : "http", Http1Config.DEFAULT); - conn.bind(socket); - return conn; - } - }); - } - - this.httpServer = serverBootstrap.create(); - - httpServer.start(); - } - - @Override - public void close() throws IOException { - httpServer.stop(); - } - - public HttpServer getHttpServer() { - return httpServer; - } - - public String getUri() { - return uri; - } - - public String getDiscoverUri() { - return uri + CTX_DISCOVER; - } - - public int getPort() { - return port; - } - - protected void handleDiscoverRequest(HttpRequest request, ClassicHttpResponse response, HttpContext context) - throws HttpException, IOException { - response.setCode(200); - response.setHeader("Cache-Control", "public, max-age=31536000"); - response.setEntity(new StringEntity("{\"jwks_uri\": \"" + uri + CTX_KEYS + "\",\n" + "\"issuer\": \"" + uri - + "\", \"unknownPropertyToBeIgnored\": 42}")); - } - - protected void handleKeysRequest(HttpRequest request, ClassicHttpResponse response, HttpContext context) - throws HttpException, IOException { - response.setCode(200); - response.setEntity(new StringEntity(toJson(jwks))); - } - - private SSLContext createSSLContext() { - if (!this.ssl) { - return null; - } - - try { - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - final KeyStore trustStore = KeyStore.getInstance("JKS"); - InputStream trustStream = new FileInputStream( - FileHelper.getAbsoluteFilePathFromClassPath("jwt/truststore.jks").toFile()); - trustStore.load(trustStream, "changeit".toCharArray()); - tmf.init(trustStore); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - final KeyStore keyStore = KeyStore.getInstance("JKS"); - InputStream keyStream = new FileInputStream( - FileHelper.getAbsoluteFilePathFromClassPath("jwt/node-0-keystore.jks").toFile()); - - keyStore.load(keyStream, "changeit".toCharArray()); - kmf.init(keyStore, "changeit".toCharArray()); - - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); - sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - return sslContext; - } catch (GeneralSecurityException | IOException e) { - throw new RuntimeException(e); - } - } + final static String CTX_DISCOVER = "/discover"; + final static String CTX_KEYS = "/api/oauth/keys"; + + private final HttpServer httpServer; + private final int port; + private final String uri; + private final boolean ssl; + private final JsonWebKeys jwks; + + MockIpdServer(JsonWebKeys jwks) throws IOException { + this(jwks, SocketUtils.findAvailableTcpPort(), false); + } + + MockIpdServer(JsonWebKeys jwks, int port, boolean ssl) throws IOException { + this.port = port; + this.uri = (ssl ? "https" : "http") + "://localhost:" + port; + this.ssl = ssl; + this.jwks = jwks; + + ServerBootstrap serverBootstrap = ServerBootstrap.bootstrap() + .setListenerPort(port) + .register(CTX_DISCOVER, new HttpRequestHandler() { + + @Override + public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, + IOException { + handleDiscoverRequest(request, response, context); + } + }) + .register(CTX_KEYS, new HttpRequestHandler() { + + @Override + public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, + IOException { + handleKeysRequest(request, response, context); + } + }); + + if (ssl) { + serverBootstrap = serverBootstrap.setSslContext(createSSLContext()).setSslSetupHandler(new Callback() { + @Override + public void execute(SSLParameters object) { + object.setNeedClientAuth(true); + } + }).setConnectionFactory(new HttpConnectionFactory() { + @Override + public DefaultBHttpServerConnection createConnection(final Socket socket) throws IOException { + final DefaultBHttpServerConnection conn = new DefaultBHttpServerConnection(ssl ? "https" : "http", Http1Config.DEFAULT); + conn.bind(socket); + return conn; + } + }); + } + + this.httpServer = serverBootstrap.create(); + + httpServer.start(); + } + + @Override + public void close() throws IOException { + httpServer.stop(); + } + + public HttpServer getHttpServer() { + return httpServer; + } + + public String getUri() { + return uri; + } + + public String getDiscoverUri() { + return uri + CTX_DISCOVER; + } + + public String getJwksUri() { + return uri + CTX_KEYS; + } + + public int getPort() { + return port; + } + + protected void handleDiscoverRequest(HttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, + IOException { + response.setCode(200); + response.setHeader("Cache-Control", "public, max-age=31536000"); + response.setEntity( + new StringEntity( + "{\"jwks_uri\": \"" + uri + CTX_KEYS + "\",\n" + "\"issuer\": \"" + uri + "\", \"unknownPropertyToBeIgnored\": 42}" + ) + ); + } + + protected void handleKeysRequest(HttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, + IOException { + response.setCode(200); + response.setEntity(new StringEntity(toJson(jwks))); + } + + private SSLContext createSSLContext() { + if (!this.ssl) { + return null; + } + + try { + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + final KeyStore trustStore = KeyStore.getInstance("JKS"); + InputStream trustStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("jwt/truststore.jks").toFile()); + trustStore.load(trustStream, "changeit".toCharArray()); + tmf.init(trustStore); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + final KeyStore keyStore = KeyStore.getInstance("JKS"); + InputStream keyStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("jwt/node-0-keystore.jks").toFile()); + + keyStore.load(keyStream, "changeit".toCharArray()); + kmf.init(keyStore, "changeit".toCharArray()); + + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + return sslContext; + } catch (GeneralSecurityException | IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SelfRefreshingKeySetTest.java b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SelfRefreshingKeySetTest.java index 50bd2fcc0e..6bbce7d85d 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SelfRefreshingKeySetTest.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SelfRefreshingKeySetTest.java @@ -22,100 +22,97 @@ public class SelfRefreshingKeySetTest { - @Test - public void basicTest() throws AuthenticatorUnavailableException, BadCredentialsException { - SelfRefreshingKeySet selfRefreshingKeySet = new SelfRefreshingKeySet(new MockKeySetProvider()); + @Test + public void basicTest() throws AuthenticatorUnavailableException, BadCredentialsException { + SelfRefreshingKeySet selfRefreshingKeySet = new SelfRefreshingKeySet(new MockKeySetProvider()); - JsonWebKey key1 = selfRefreshingKeySet.getKey("kid/a"); - Assert.assertEquals(TestJwk.OCT_1_K, key1.getProperty("k")); - Assert.assertEquals(1, selfRefreshingKeySet.getRefreshCount()); + JsonWebKey key1 = selfRefreshingKeySet.getKey("kid/a"); + Assert.assertEquals(TestJwk.OCT_1_K, key1.getProperty("k")); + Assert.assertEquals(1, selfRefreshingKeySet.getRefreshCount()); - JsonWebKey key2 = selfRefreshingKeySet.getKey("kid/b"); - Assert.assertEquals(TestJwk.OCT_2_K, key2.getProperty("k")); - Assert.assertEquals(1, selfRefreshingKeySet.getRefreshCount()); + JsonWebKey key2 = selfRefreshingKeySet.getKey("kid/b"); + Assert.assertEquals(TestJwk.OCT_2_K, key2.getProperty("k")); + Assert.assertEquals(1, selfRefreshingKeySet.getRefreshCount()); - try { - selfRefreshingKeySet.getKey("kid/X"); - Assert.fail("Expected a BadCredentialsException"); - } catch (BadCredentialsException e) { - Assert.assertEquals(2, selfRefreshingKeySet.getRefreshCount()); - } + try { + selfRefreshingKeySet.getKey("kid/X"); + Assert.fail("Expected a BadCredentialsException"); + } catch (BadCredentialsException e) { + Assert.assertEquals(2, selfRefreshingKeySet.getRefreshCount()); + } - } + } + @Test(timeout = 10000) + public void twoThreadedTest() throws Exception { + BlockingMockKeySetProvider provider = new BlockingMockKeySetProvider(); + final SelfRefreshingKeySet selfRefreshingKeySet = new SelfRefreshingKeySet(provider); - @Test(timeout = 10000) - public void twoThreadedTest() throws Exception { - BlockingMockKeySetProvider provider = new BlockingMockKeySetProvider(); + ExecutorService executorService = Executors.newCachedThreadPool(); - final SelfRefreshingKeySet selfRefreshingKeySet = new SelfRefreshingKeySet(provider); + Future f1 = executorService.submit(() -> selfRefreshingKeySet.getKey("kid/a")); - ExecutorService executorService = Executors.newCachedThreadPool(); + provider.waitForCalled(); - Future f1 = executorService.submit(() -> selfRefreshingKeySet.getKey("kid/a")); + Future f2 = executorService.submit(() -> selfRefreshingKeySet.getKey("kid/b")); - provider.waitForCalled(); + while (selfRefreshingKeySet.getQueuedGetCount() == 0) { + Thread.sleep(10); + } - Future f2 = executorService.submit(() -> selfRefreshingKeySet.getKey("kid/b")); + provider.unblock(); - while (selfRefreshingKeySet.getQueuedGetCount() == 0) { - Thread.sleep(10); - } + Assert.assertEquals(TestJwk.OCT_1_K, f1.get().getProperty("k")); + Assert.assertEquals(TestJwk.OCT_2_K, f2.get().getProperty("k")); - provider.unblock(); + Assert.assertEquals(1, selfRefreshingKeySet.getRefreshCount()); + Assert.assertEquals(1, selfRefreshingKeySet.getQueuedGetCount()); - Assert.assertEquals(TestJwk.OCT_1_K, f1.get().getProperty("k")); - Assert.assertEquals(TestJwk.OCT_2_K, f2.get().getProperty("k")); + } - Assert.assertEquals(1, selfRefreshingKeySet.getRefreshCount()); - Assert.assertEquals(1, selfRefreshingKeySet.getQueuedGetCount()); + static class MockKeySetProvider implements KeySetProvider { - } + @Override + public JsonWebKeys get() throws AuthenticatorUnavailableException { + return TestJwk.OCT_1_2_3; + } - static class MockKeySetProvider implements KeySetProvider { + } - @Override - public JsonWebKeys get() throws AuthenticatorUnavailableException { - return TestJwk.OCT_1_2_3; - } + static class BlockingMockKeySetProvider extends MockKeySetProvider { + private boolean blocked = true; + private boolean called = false; - } + @Override + public synchronized JsonWebKeys get() throws AuthenticatorUnavailableException { - static class BlockingMockKeySetProvider extends MockKeySetProvider { - private boolean blocked = true; - private boolean called = false; + called = true; + notifyAll(); - @Override - public synchronized JsonWebKeys get() throws AuthenticatorUnavailableException { + waitForUnblock(); - called = true; - notifyAll(); + return super.get(); + } - waitForUnblock(); + public synchronized void unblock() { + blocked = false; + notifyAll(); + } - return super.get(); - } + public synchronized void waitForCalled() throws InterruptedException { + while (!called) { + wait(); + } + } - public synchronized void unblock() { - blocked = false; - notifyAll(); - } + private synchronized void waitForUnblock() { + while (blocked) { + try { + wait(); + } catch (InterruptedException e) {} - public synchronized void waitForCalled() throws InterruptedException { - while (!called) { - wait(); - } - } - - private synchronized void waitForUnblock() { - while (blocked) { - try { - wait(); - } catch (InterruptedException e) { - } - - } - } - } + } + } + } } diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SingleKeyHTTPJwtKeyByOpenIdConnectAuthenticatorTest.java b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SingleKeyHTTPJwtKeyByOpenIdConnectAuthenticatorTest.java index 4400dd1cdc..21f0c362d9 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SingleKeyHTTPJwtKeyByOpenIdConnectAuthenticatorTest.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/SingleKeyHTTPJwtKeyByOpenIdConnectAuthenticatorTest.java @@ -23,186 +23,185 @@ public class SingleKeyHTTPJwtKeyByOpenIdConnectAuthenticatorTest { - @Test - public void basicTest() throws Exception { - MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1); - try { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_RSA_1), - new HashMap()), - null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - - } finally { - try { - mockIdpServer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @Test - public void wrongSigTest() throws Exception { - MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1); - try { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_X), - new HashMap()), - null); - - Assert.assertNull(creds); - - } finally { - try { - mockIdpServer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @Test - public void noAlgTest() throws Exception { - MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1_NO_ALG); - try { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_RSA_1), - new HashMap()), - null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - } finally { - try { - mockIdpServer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @Test - public void mismatchedAlgTest() throws Exception { - MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1_WRONG_ALG); - try { - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_1), - new HashMap()), - null); - - Assert.assertNull(creds); - - } finally { - try { - mockIdpServer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - - @Test - public void keyExchangeTest() throws Exception { - MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1); - - Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); - - HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - try { - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_1), - new HashMap()), - null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - - creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_2), - new HashMap()), - null); - - Assert.assertNull(creds); - - creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_X), - new HashMap()), - null); - - Assert.assertNull(creds); - - creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_1), - new HashMap()), - null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - - } finally { - try { - mockIdpServer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_2); - settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); //port changed - jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); - - try { - AuthCredentials creds = jwtAuth.extractCredentials( - new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_2), - new HashMap()), - null); - - Assert.assertNotNull(creds); - Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); - Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); - Assert.assertEquals(0, creds.getBackendRoles().size()); - Assert.assertEquals(3, creds.getAttributes().size()); - - } finally { - try { - mockIdpServer.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } + @Test + public void basicTest() throws Exception { + MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1); + try { + Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_RSA_1), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + + } finally { + try { + mockIdpServer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Test + public void wrongSigTest() throws Exception { + MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1); + try { + Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_X), new HashMap()), + null + ); + + Assert.assertNull(creds); + + } finally { + try { + mockIdpServer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Test + public void noAlgTest() throws Exception { + MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1_NO_ALG); + try { + Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.MC_COY_SIGNED_RSA_1), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + } finally { + try { + mockIdpServer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Test + public void mismatchedAlgTest() throws Exception { + MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1_WRONG_ALG); + try { + Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_1), new HashMap()), + null + ); + + Assert.assertNull(creds); + + } finally { + try { + mockIdpServer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Test + public void keyExchangeTest() throws Exception { + MockIpdServer mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_1); + + Settings settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); + + HTTPJwtKeyByOpenIdConnectAuthenticator jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + try { + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_1), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + + creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_2), new HashMap()), + null + ); + + Assert.assertNull(creds); + + creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_X), new HashMap()), + null + ); + + Assert.assertNull(creds); + + creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_1), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + + } finally { + try { + mockIdpServer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + mockIdpServer = new MockIpdServer(TestJwk.Jwks.RSA_2); + settings = Settings.builder().put("openid_connect_url", mockIdpServer.getDiscoverUri()).build(); // port changed + jwtAuth = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, null); + + try { + AuthCredentials creds = jwtAuth.extractCredentials( + new FakeRestRequest(ImmutableMap.of("Authorization", TestJwts.NoKid.MC_COY_SIGNED_RSA_2), new HashMap()), + null + ); + + Assert.assertNotNull(creds); + Assert.assertEquals(TestJwts.MCCOY_SUBJECT, creds.getUsername()); + Assert.assertEquals(TestJwts.TEST_AUDIENCE, creds.getAttributes().get("attr.jwt.aud")); + Assert.assertEquals(0, creds.getBackendRoles().size()); + Assert.assertEquals(4, creds.getAttributes().size()); + + } finally { + try { + mockIdpServer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } } diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/TestJwk.java b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/TestJwk.java index b0f996a03f..5b0d5738a3 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/TestJwk.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/TestJwk.java @@ -20,94 +20,102 @@ class TestJwk { - // Keys generated with https://mkjwk.org/ - - static final String OCT_1_K = "eTDZjSqRD9Abhod9iqeGX_7o93a-eElTeXWAF6FmzQshmRIrPD-C9ET3pFjJ_IBrzmWIZDk8ig-X_PIyGmKsxNMsrU-0BNWF5gJq5xOp4rYTl8z66Tw9wr8tHLxLxgJqkLSuUCRBZvlZlQ7jNdhBBxgM-hdSSzsN1T33qdIwhrUeJ-KXI5yKUXHjoWFYb9tETbYQ4NvONowkCsXK_flp-E3F_OcKe_z5iVUszAV8QfCod1zhbya540kDejXCL6N_XMmhWJqum7UJ3hgf6DEtroPSnVpHt4iR5w9ArKK-IBgluPght03gNcoNqwz7p77TFbdOmUKF_PWy1bcdbaUoSg"; - static final String OCT_2_K = "YP6Q3IF2qJEagV948dsicXKpG43Ci2W7ZxUpiVTBLZr1vFN9ZGUKxeXGgVWuMFYTmoHvv5AOC8BvoNOpcE3rcJNuNOqTMdujxD92CxjOykiLEKQ0Te_7xQ4LnSQjlqdIJ4U3S7qCnJLd1LxhKOGZcUhE_pjhwf7q2RUUpvC3UOyZZLog9yeflnp9nqqDy5yVqRYWZRcPI06kJTh3Z8IFi2JRJV14iUFQtOHQKuyJRMcsldKnfWl7YW3JdQ9IRN-c1lEYSEBmsavEejcqHZkbli2svqLfmCBJVWffXDRxhq0_VafiL83HC0bP9qeNKivhemw6foVmg8UMs7yJ6ao02A"; - static final String OCT_3_K = "r3aeW3OK7-B4Hs3hq9BmlT1D3jRiolH9PL82XUz9xAS7dniAdmvMnN5GkOc1vqibOe2T-CC_103UglDm9D0iU9S9zn6wTuQt1L5wfZIoHd9f5IjJ_YFEzZMvsoUY_-ji_0K_ugVvBPwi9JnBQHHS4zrgmP06dGjmcnZDcIf4W_iFas3lDYSXilL1V2QhNaynpSqTarpfBGSphKv4Zg2JhsX8xB0VSaTlEq4lF8pzvpWSxXCW9CtomhB80daSuTizrmSTEPpdN3XzQ2-Tovo1ieMOfDU4csvjEk7Bwc2ThjpnA8ucKQUYpUv9joBxKuCdUltssthWnetrogjYOn_xGA"; - - static final JsonWebKey OCT_1 = createOct("kid/a", "HS256", OCT_1_K); - static final JsonWebKey OCT_2 = createOct("kid/b", "HS256", OCT_2_K); - static final JsonWebKey OCT_3 = createOct("kid/c", "HS256", OCT_3_K); - static final JsonWebKey ESCAPED_SLASH_KID_OCT_1 = createOct("kid\\/_a", "HS256", OCT_1_K); - static final JsonWebKey FORWARD_SLASH_KID_OCT_1 = createOct("kid/_a", "HS256", OCT_1_K); - - static final JsonWebKeys OCT_1_2_3 = createJwks(OCT_1, OCT_2, OCT_3, FORWARD_SLASH_KID_OCT_1,ESCAPED_SLASH_KID_OCT_1); - - static final String RSA_1_D = "On8XGMmdM5Fm5hvuhQk-qAkIP2CoK5QMx0OH5m_WDzKXZv8lZ2eg89I4ehBiOKGdw1h_mjmWwTah-evpXV-BF5QpejPQqxkXS-8s5r2AvietQq32jl-gwIwZWTvfzjpT9On0YJZ4q01tMDj3r-YOLUW2xrz3za9tl6pPU_5kP63C-hoj1ybTwcC7ujbCPwhY6yAopMA1v10uVmCxsjsNikEjB6YePgHixez51wO3Z8mXNwefWukFWYJ5T7t4kHMSf5P_8FJZ14u5yvYZnngE_tJCyHFdIDb6UWsrgxomtlQU-SdZYK_NY6gw6mCkjjlqOoYqlsrRJ16kJ81Ds269oQ"; - static final String RSA_1_N = "hMSoV74FRtoaU7xpp0llsXbHE4oUseKoSNga-C_YIXuoGc3pajHh1WtJppZQNYM1Xy07nHchLJAdgqL2_q_Lk8cFHmmL1KTjwPflK9zZ9C0-8QTOrrqU9vkp3gT00jWWJ0HJbUvXIGxPGPnxoJoI--ToE0EWsYEWqWyx1TqYol--oUUPlY5r7vXRKIn5UZNz6VGkW8nI4fXaqDUpXH9uVM9A-nJX2B0Xjwu3VOn2zrgkCZeGTHjNgfLISOTFe9m8lHWLKcuxOWPuCZyCN0C6ZdWB1YP2NhxYFQwQfGV8yfnTImgL-DuV4WPSRVj7W_GJr213-oXBrBR0CnQEPbi_3w"; - static final String RSA_1_E = "AQAB"; - - static final String RSA_2_D = "QQ18k_buZHOSVYzkXL1FaqdodZVNZ_hrBtDcmCVUYjm3dfDVQYt70h8LUdLUCSUA2-_VEwqVdQ-L2FTg7NZVvZJXIyQXp3yrdY1vGKebs3oaIB_VQT8jt-64s12r_8V2ksK2myRrvfm2Fgqi32H5QkspuaQYb9s4NJwKSk7mVAz5dRWQdCx9JNVWknWDJxgHzh3Uku1tNwUOyvSYcRnSZ9X7oWNHaHkSGLEYE_mxD7YXs6HEdCDwc3WuvR5AiVKg2OGec0lL1hY_AWX5UxnR00mhAa0qPytFfaPe-Sc5tQ5regQRqRNDyDESVGIvqXsY8ePjZPOFyoxrcJ2wN3bt4Q"; - static final String RSA_2_N = "lt4EID7tbrE9E8l7VfVGhiwSx4O8nLO5AZo5pJNE1fUy4bM56wH_DeU3YspXh0UvH-vcn4uKjhwJdOCjzalBc2wXD0aRd3JXzWwbjveo6oBFz6kU7VnY8nFMYLMlb6FDcl066OZOtW4PIFtAStXj5rX_J94He3sfTClodpNljTi4qeQwoNsrnZ5Eq82pCp20zCgvbdes8HQBq_QgApvzhL3c-PXd2I_4pBnaPoZwAnufthk7-v8V0Zf5CrDuqEczKKr38pvwggnxZqsfUy2X0bXPBvDXh5B2ljWxWl8tHJbKXzOhfV5Nx5rllJnNabFoVxh3hnlxdOZ88zcaslWBLQ"; - static final String RSA_2_E = "AQAB"; - - static final String RSA_X_D = "iXym57VmwbWvcHtf--xSDPTagEJdnceuErjH6lbuabFXeBx42ZpuAICvo6_YpMcqLybD37ArIu2SD5J_ZBALp4v4KecMPFI5lZr7GKlGgqnForvcC7EWA_ZtZ9uY746cKun8NtemcOlAenn2dvc9NP2S4JtE3FHxmqs2MMmz-ki-ar8-zu0j0HLPLl_Wj2SZ9yCeFmmH3eocX5IRRiWwPnudQJM2t0kt9V-M88YzobqzoMEoFjTfi-owa-w6xGAgJxAUKk02vTiTivH3Qmkk-uAXyj-VtcyzYXD74ICN8EplcAEUKegDR59T4-u18GdpDbPU20XzxDaO4lZiQ7TIEQ"; - static final String RSA_X_N = "jDDVUMXOXDVcaRVAT5TtuiAsLxk7XAAwyyECfmySZul7D5XVLMtGe6rP2900q3nM4BaCEiuwXjmTCZDAGlFGs2a3eQ1vbBSv9_0KGHL-gZGFPNiv0v8aR7QzZ-abhGnRy5F52PlTWsypGgG_kQpF2t2TBotvYhvVPagAt4ljllDKvY1siOvS3nh4TqcUtWcbgQZEWPmaXuhx0eLmhQJca7UEw99YlGNew48AEzt7ZnfU0Qkz3JwSz7IcPx-NfIh6BN6LwAg_ASdoM3MR8rDOtLYavmJVhutrfOpE-4-fw1mf3eLYu7xrxIplSiOIsHunTUssnTiBkXAaGqGJs604Pw"; - static final String RSA_X_E = "AQAB"; - - static final JsonWebKey RSA_1 = createRsa("kid/1", "RS256", RSA_1_E, RSA_1_N, RSA_1_D); - static final JsonWebKey RSA_1_PUBLIC = createRsaPublic("kid/1", "RS256", RSA_1_E, RSA_1_N); - static final JsonWebKey RSA_1_PUBLIC_NO_ALG = createRsaPublic("kid/1", null, RSA_1_E, RSA_1_N); + // Keys generated with https://mkjwk.org/ + + static final String OCT_1_K = + "eTDZjSqRD9Abhod9iqeGX_7o93a-eElTeXWAF6FmzQshmRIrPD-C9ET3pFjJ_IBrzmWIZDk8ig-X_PIyGmKsxNMsrU-0BNWF5gJq5xOp4rYTl8z66Tw9wr8tHLxLxgJqkLSuUCRBZvlZlQ7jNdhBBxgM-hdSSzsN1T33qdIwhrUeJ-KXI5yKUXHjoWFYb9tETbYQ4NvONowkCsXK_flp-E3F_OcKe_z5iVUszAV8QfCod1zhbya540kDejXCL6N_XMmhWJqum7UJ3hgf6DEtroPSnVpHt4iR5w9ArKK-IBgluPght03gNcoNqwz7p77TFbdOmUKF_PWy1bcdbaUoSg"; + static final String OCT_2_K = + "YP6Q3IF2qJEagV948dsicXKpG43Ci2W7ZxUpiVTBLZr1vFN9ZGUKxeXGgVWuMFYTmoHvv5AOC8BvoNOpcE3rcJNuNOqTMdujxD92CxjOykiLEKQ0Te_7xQ4LnSQjlqdIJ4U3S7qCnJLd1LxhKOGZcUhE_pjhwf7q2RUUpvC3UOyZZLog9yeflnp9nqqDy5yVqRYWZRcPI06kJTh3Z8IFi2JRJV14iUFQtOHQKuyJRMcsldKnfWl7YW3JdQ9IRN-c1lEYSEBmsavEejcqHZkbli2svqLfmCBJVWffXDRxhq0_VafiL83HC0bP9qeNKivhemw6foVmg8UMs7yJ6ao02A"; + static final String OCT_3_K = + "r3aeW3OK7-B4Hs3hq9BmlT1D3jRiolH9PL82XUz9xAS7dniAdmvMnN5GkOc1vqibOe2T-CC_103UglDm9D0iU9S9zn6wTuQt1L5wfZIoHd9f5IjJ_YFEzZMvsoUY_-ji_0K_ugVvBPwi9JnBQHHS4zrgmP06dGjmcnZDcIf4W_iFas3lDYSXilL1V2QhNaynpSqTarpfBGSphKv4Zg2JhsX8xB0VSaTlEq4lF8pzvpWSxXCW9CtomhB80daSuTizrmSTEPpdN3XzQ2-Tovo1ieMOfDU4csvjEk7Bwc2ThjpnA8ucKQUYpUv9joBxKuCdUltssthWnetrogjYOn_xGA"; + + static final JsonWebKey OCT_1 = createOct("kid/a", "HS256", OCT_1_K); + static final JsonWebKey OCT_2 = createOct("kid/b", "HS256", OCT_2_K); + static final JsonWebKey OCT_3 = createOct("kid/c", "HS256", OCT_3_K); + static final JsonWebKey ESCAPED_SLASH_KID_OCT_1 = createOct("kid\\/_a", "HS256", OCT_1_K); + static final JsonWebKey FORWARD_SLASH_KID_OCT_1 = createOct("kid/_a", "HS256", OCT_1_K); + + static final JsonWebKeys OCT_1_2_3 = createJwks(OCT_1, OCT_2, OCT_3, FORWARD_SLASH_KID_OCT_1, ESCAPED_SLASH_KID_OCT_1); + + static final String RSA_1_D = + "On8XGMmdM5Fm5hvuhQk-qAkIP2CoK5QMx0OH5m_WDzKXZv8lZ2eg89I4ehBiOKGdw1h_mjmWwTah-evpXV-BF5QpejPQqxkXS-8s5r2AvietQq32jl-gwIwZWTvfzjpT9On0YJZ4q01tMDj3r-YOLUW2xrz3za9tl6pPU_5kP63C-hoj1ybTwcC7ujbCPwhY6yAopMA1v10uVmCxsjsNikEjB6YePgHixez51wO3Z8mXNwefWukFWYJ5T7t4kHMSf5P_8FJZ14u5yvYZnngE_tJCyHFdIDb6UWsrgxomtlQU-SdZYK_NY6gw6mCkjjlqOoYqlsrRJ16kJ81Ds269oQ"; + static final String RSA_1_N = + "hMSoV74FRtoaU7xpp0llsXbHE4oUseKoSNga-C_YIXuoGc3pajHh1WtJppZQNYM1Xy07nHchLJAdgqL2_q_Lk8cFHmmL1KTjwPflK9zZ9C0-8QTOrrqU9vkp3gT00jWWJ0HJbUvXIGxPGPnxoJoI--ToE0EWsYEWqWyx1TqYol--oUUPlY5r7vXRKIn5UZNz6VGkW8nI4fXaqDUpXH9uVM9A-nJX2B0Xjwu3VOn2zrgkCZeGTHjNgfLISOTFe9m8lHWLKcuxOWPuCZyCN0C6ZdWB1YP2NhxYFQwQfGV8yfnTImgL-DuV4WPSRVj7W_GJr213-oXBrBR0CnQEPbi_3w"; + static final String RSA_1_E = "AQAB"; + + static final String RSA_2_D = + "QQ18k_buZHOSVYzkXL1FaqdodZVNZ_hrBtDcmCVUYjm3dfDVQYt70h8LUdLUCSUA2-_VEwqVdQ-L2FTg7NZVvZJXIyQXp3yrdY1vGKebs3oaIB_VQT8jt-64s12r_8V2ksK2myRrvfm2Fgqi32H5QkspuaQYb9s4NJwKSk7mVAz5dRWQdCx9JNVWknWDJxgHzh3Uku1tNwUOyvSYcRnSZ9X7oWNHaHkSGLEYE_mxD7YXs6HEdCDwc3WuvR5AiVKg2OGec0lL1hY_AWX5UxnR00mhAa0qPytFfaPe-Sc5tQ5regQRqRNDyDESVGIvqXsY8ePjZPOFyoxrcJ2wN3bt4Q"; + static final String RSA_2_N = + "lt4EID7tbrE9E8l7VfVGhiwSx4O8nLO5AZo5pJNE1fUy4bM56wH_DeU3YspXh0UvH-vcn4uKjhwJdOCjzalBc2wXD0aRd3JXzWwbjveo6oBFz6kU7VnY8nFMYLMlb6FDcl066OZOtW4PIFtAStXj5rX_J94He3sfTClodpNljTi4qeQwoNsrnZ5Eq82pCp20zCgvbdes8HQBq_QgApvzhL3c-PXd2I_4pBnaPoZwAnufthk7-v8V0Zf5CrDuqEczKKr38pvwggnxZqsfUy2X0bXPBvDXh5B2ljWxWl8tHJbKXzOhfV5Nx5rllJnNabFoVxh3hnlxdOZ88zcaslWBLQ"; + static final String RSA_2_E = "AQAB"; + + static final String RSA_X_D = + "iXym57VmwbWvcHtf--xSDPTagEJdnceuErjH6lbuabFXeBx42ZpuAICvo6_YpMcqLybD37ArIu2SD5J_ZBALp4v4KecMPFI5lZr7GKlGgqnForvcC7EWA_ZtZ9uY746cKun8NtemcOlAenn2dvc9NP2S4JtE3FHxmqs2MMmz-ki-ar8-zu0j0HLPLl_Wj2SZ9yCeFmmH3eocX5IRRiWwPnudQJM2t0kt9V-M88YzobqzoMEoFjTfi-owa-w6xGAgJxAUKk02vTiTivH3Qmkk-uAXyj-VtcyzYXD74ICN8EplcAEUKegDR59T4-u18GdpDbPU20XzxDaO4lZiQ7TIEQ"; + static final String RSA_X_N = + "jDDVUMXOXDVcaRVAT5TtuiAsLxk7XAAwyyECfmySZul7D5XVLMtGe6rP2900q3nM4BaCEiuwXjmTCZDAGlFGs2a3eQ1vbBSv9_0KGHL-gZGFPNiv0v8aR7QzZ-abhGnRy5F52PlTWsypGgG_kQpF2t2TBotvYhvVPagAt4ljllDKvY1siOvS3nh4TqcUtWcbgQZEWPmaXuhx0eLmhQJca7UEw99YlGNew48AEzt7ZnfU0Qkz3JwSz7IcPx-NfIh6BN6LwAg_ASdoM3MR8rDOtLYavmJVhutrfOpE-4-fw1mf3eLYu7xrxIplSiOIsHunTUssnTiBkXAaGqGJs604Pw"; + static final String RSA_X_E = "AQAB"; + + static final JsonWebKey RSA_1 = createRsa("kid/1", "RS256", RSA_1_E, RSA_1_N, RSA_1_D); + static final JsonWebKey RSA_1_PUBLIC = createRsaPublic("kid/1", "RS256", RSA_1_E, RSA_1_N); + static final JsonWebKey RSA_1_PUBLIC_NO_ALG = createRsaPublic("kid/1", null, RSA_1_E, RSA_1_N); static final JsonWebKey RSA_1_PUBLIC_WRONG_ALG = createRsaPublic("kid/1", "HS256", RSA_1_E, RSA_1_N); - static final JsonWebKey RSA_2 = createRsa("kid/2", "RS256", RSA_2_E, RSA_2_N, RSA_2_D); - static final JsonWebKey RSA_2_PUBLIC = createRsaPublic("kid/2", "RS256", RSA_2_E, RSA_2_N); - - static final JsonWebKey RSA_X = createRsa("kid/2", "RS256", RSA_X_E, RSA_X_N, RSA_X_D); - static final JsonWebKey RSA_X_PUBLIC = createRsaPublic("kid/2", "RS256", RSA_X_E, RSA_X_N); + static final JsonWebKey RSA_2 = createRsa("kid/2", "RS256", RSA_2_E, RSA_2_N, RSA_2_D); + static final JsonWebKey RSA_2_PUBLIC = createRsaPublic("kid/2", "RS256", RSA_2_E, RSA_2_N); - static final JsonWebKeys RSA_1_2_PUBLIC = createJwks(RSA_1_PUBLIC, RSA_2_PUBLIC); + static final JsonWebKey RSA_X = createRsa("kid/2", "RS256", RSA_X_E, RSA_X_N, RSA_X_D); + static final JsonWebKey RSA_X_PUBLIC = createRsaPublic("kid/2", "RS256", RSA_X_E, RSA_X_N); - static class Jwks { - static final JsonWebKeys ALL = createJwks(OCT_1, OCT_2, OCT_3, FORWARD_SLASH_KID_OCT_1, RSA_1_PUBLIC, RSA_2_PUBLIC); - static final JsonWebKeys RSA_1 = createJwks(RSA_1_PUBLIC); - static final JsonWebKeys RSA_2 = createJwks(RSA_2_PUBLIC); - static final JsonWebKeys RSA_1_NO_ALG = createJwks(RSA_1_PUBLIC_NO_ALG); - static final JsonWebKeys RSA_1_WRONG_ALG = createJwks(RSA_1_PUBLIC_WRONG_ALG); - } + static final JsonWebKeys RSA_1_2_PUBLIC = createJwks(RSA_1_PUBLIC, RSA_2_PUBLIC); + static class Jwks { + static final JsonWebKeys ALL = createJwks(OCT_1, OCT_2, OCT_3, FORWARD_SLASH_KID_OCT_1, RSA_1_PUBLIC, RSA_2_PUBLIC); + static final JsonWebKeys RSA_1 = createJwks(RSA_1_PUBLIC); + static final JsonWebKeys RSA_2 = createJwks(RSA_2_PUBLIC); + static final JsonWebKeys RSA_1_NO_ALG = createJwks(RSA_1_PUBLIC_NO_ALG); + static final JsonWebKeys RSA_1_WRONG_ALG = createJwks(RSA_1_PUBLIC_WRONG_ALG); + } - private static JsonWebKey createOct(String keyId, String algorithm, String k) { - JsonWebKey result = new JsonWebKey(); + private static JsonWebKey createOct(String keyId, String algorithm, String k) { + JsonWebKey result = new JsonWebKey(); - result.setKeyId(keyId); - result.setKeyType(KeyType.OCTET); - result.setAlgorithm(algorithm); - result.setPublicKeyUse(PublicKeyUse.SIGN); - result.setProperty("k", k); + result.setKeyId(keyId); + result.setKeyType(KeyType.OCTET); + result.setAlgorithm(algorithm); + result.setPublicKeyUse(PublicKeyUse.SIGN); + result.setProperty("k", k); - return result; - } + return result; + } - private static JsonWebKey createRsa(String keyId, String algorithm, String e, String n, String d) { - JsonWebKey result = new JsonWebKey(); + private static JsonWebKey createRsa(String keyId, String algorithm, String e, String n, String d) { + JsonWebKey result = new JsonWebKey(); - result.setKeyId(keyId); - result.setKeyType(KeyType.RSA); - result.setAlgorithm(algorithm); - result.setPublicKeyUse(PublicKeyUse.SIGN); + result.setKeyId(keyId); + result.setKeyType(KeyType.RSA); + result.setAlgorithm(algorithm); + result.setPublicKeyUse(PublicKeyUse.SIGN); - if (d != null) { - result.setProperty("d", d); - } + if (d != null) { + result.setProperty("d", d); + } - result.setProperty("e", e); - result.setProperty("n", n); + result.setProperty("e", e); + result.setProperty("n", n); - return result; - } + return result; + } - private static JsonWebKey createRsaPublic(String keyId, String algorithm, String e, String n) { - return createRsa(keyId, algorithm, e, n, null); - } + private static JsonWebKey createRsaPublic(String keyId, String algorithm, String e, String n) { + return createRsa(keyId, algorithm, e, n, null); + } - private static JsonWebKeys createJwks(JsonWebKey... array) { - JsonWebKeys result = new JsonWebKeys(); + private static JsonWebKeys createJwks(JsonWebKey... array) { + JsonWebKeys result = new JsonWebKeys(); - result.setKeys(Arrays.asList(array)); + result.setKeys(Arrays.asList(array)); - return result; - } + return result; + } } diff --git a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/TestJwts.java b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/TestJwts.java index 217e64926c..292af6c014 100644 --- a/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/TestJwts.java +++ b/src/test/java/com/amazon/dlic/auth/http/jwt/keybyoidc/TestJwts.java @@ -25,95 +25,126 @@ import org.apache.logging.log4j.util.Strings; class TestJwts { - static final String ROLES_CLAIM = "roles"; - static final Set TEST_ROLES = ImmutableSet.of("role1", "role2"); - static final String TEST_ROLES_STRING = Strings.join(TEST_ROLES, ','); + static final String ROLES_CLAIM = "roles"; + static final Set TEST_ROLES = ImmutableSet.of("role1", "role2"); + static final String TEST_ROLES_STRING = Strings.join(TEST_ROLES, ','); - static final String TEST_AUDIENCE = "TestAudience"; + static final String TEST_AUDIENCE = "TestAudience"; - static final String MCCOY_SUBJECT = "Leonard McCoy"; + static final String MCCOY_SUBJECT = "Leonard McCoy"; - static final JwtToken MC_COY = create(MCCOY_SUBJECT, TEST_AUDIENCE, ROLES_CLAIM, TEST_ROLES_STRING); + static final String TEST_ISSUER = "TestIssuer"; - static final JwtToken MC_COY_EXPIRED = create(MCCOY_SUBJECT, TEST_AUDIENCE, ROLES_CLAIM, TEST_ROLES_STRING, JwtConstants.CLAIM_EXPIRY, 10); + static final JwtToken MC_COY = create(MCCOY_SUBJECT, TEST_AUDIENCE, TEST_ISSUER, ROLES_CLAIM, TEST_ROLES_STRING); - static final String MC_COY_SIGNED_OCT_1 = createSigned(MC_COY, TestJwk.OCT_1); + static final JwtToken MC_COY_2 = create(MCCOY_SUBJECT, TEST_AUDIENCE, TEST_ISSUER, ROLES_CLAIM, TEST_ROLES_STRING); - static final String MC_COY_SIGNED_OCT_1_INVALID_KID = createSigned(MC_COY, TestJwk.FORWARD_SLASH_KID_OCT_1); + static final JwtToken MC_COY_NO_AUDIENCE = create(MCCOY_SUBJECT, null, TEST_ISSUER, ROLES_CLAIM, TEST_ROLES_STRING); - static final String MC_COY_SIGNED_RSA_1 = createSigned(MC_COY, TestJwk.RSA_1); + static final JwtToken MC_COY_NO_ISSUER = create(MCCOY_SUBJECT, TEST_AUDIENCE, null, ROLES_CLAIM, TEST_ROLES_STRING); - static final String MC_COY_SIGNED_RSA_X = createSigned(MC_COY, TestJwk.RSA_X); + static final JwtToken MC_COY_EXPIRED = create( + MCCOY_SUBJECT, + TEST_AUDIENCE, + TEST_ISSUER, + ROLES_CLAIM, + TEST_ROLES_STRING, + JwtConstants.CLAIM_EXPIRY, + 10 + ); - static final String MC_COY_EXPIRED_SIGNED_OCT_1 = createSigned(MC_COY_EXPIRED, TestJwk.OCT_1); + static final String MC_COY_SIGNED_OCT_1 = createSigned(MC_COY, TestJwk.OCT_1); - static class NoKid { - static final String MC_COY_SIGNED_RSA_1 = createSignedWithoutKeyId(MC_COY, TestJwk.RSA_1); - static final String MC_COY_SIGNED_RSA_2 = createSignedWithoutKeyId(MC_COY, TestJwk.RSA_2); - static final String MC_COY_SIGNED_RSA_X = createSignedWithoutKeyId(MC_COY, TestJwk.RSA_X); - } + static final String MC_COY_SIGNED_OCT_2 = createSigned(MC_COY_2, TestJwk.OCT_2); - static class PeculiarEscaping { - static final String MC_COY_SIGNED_RSA_1 = createSignedWithPeculiarEscaping(MC_COY, TestJwk.RSA_1); - } + static final String MC_COY_SIGNED_NO_AUDIENCE_OCT_1 = createSigned(MC_COY_NO_AUDIENCE, TestJwk.OCT_1); + static final String MC_COY_SIGNED_NO_ISSUER_OCT_1 = createSigned(MC_COY_NO_ISSUER, TestJwk.OCT_1); - static JwtToken create(String subject, String audience, Object... moreClaims) { - JwtClaims claims = new JwtClaims(); + static final String MC_COY_SIGNED_OCT_1_INVALID_KID = createSigned(MC_COY, TestJwk.FORWARD_SLASH_KID_OCT_1); - claims.setSubject(subject); - claims.setAudience(audience); + static final String MC_COY_SIGNED_RSA_1 = createSigned(MC_COY, TestJwk.RSA_1); - if (moreClaims != null) { - for (int i = 0; i < moreClaims.length; i += 2) { - claims.setClaim(String.valueOf(moreClaims[i]), moreClaims[i + 1]); - } - } + static final String MC_COY_SIGNED_RSA_X = createSigned(MC_COY, TestJwk.RSA_X); - JwtToken result = new JwtToken(claims); + static final String MC_COY_EXPIRED_SIGNED_OCT_1 = createSigned(MC_COY_EXPIRED, TestJwk.OCT_1); - return result; - } + static class NoKid { + static final String MC_COY_SIGNED_RSA_1 = createSignedWithoutKeyId(MC_COY, TestJwk.RSA_1); + static final String MC_COY_SIGNED_RSA_2 = createSignedWithoutKeyId(MC_COY, TestJwk.RSA_2); + static final String MC_COY_SIGNED_RSA_X = createSignedWithoutKeyId(MC_COY, TestJwk.RSA_X); + } + + static class PeculiarEscaping { + static final String MC_COY_SIGNED_RSA_1 = createSignedWithPeculiarEscaping(MC_COY, TestJwk.RSA_1); + } + + static JwtToken create(String subject, String audience, String issuer, Object... moreClaims) { + JwtClaims claims = new JwtClaims(); - static String createSigned(JwtToken baseJwt, JsonWebKey jwk) { + claims.setSubject(subject); + if (audience != null) { + claims.setAudience(audience); + } + if (issuer != null) { + claims.setIssuer(issuer); + } + + if (moreClaims != null) { + for (int i = 0; i < moreClaims.length; i += 2) { + claims.setClaim(String.valueOf(moreClaims[i]), moreClaims[i + 1]); + } + } + + JwtToken result = new JwtToken(claims); + + return result; + } + + static String createSigned(JwtToken baseJwt, JsonWebKey jwk) { return createSigned(baseJwt, jwk, JwsUtils.getSignatureProvider(jwk)); } static String createSigned(JwtToken baseJwt, JsonWebKey jwk, JwsSignatureProvider signatureProvider) { - JwsHeaders jwsHeaders = new JwsHeaders(); - JwtToken signedToken = new JwtToken(jwsHeaders, baseJwt.getClaims()); + JwsHeaders jwsHeaders = new JwsHeaders(); + JwtToken signedToken = new JwtToken(jwsHeaders, baseJwt.getClaims()); - jwsHeaders.setKeyId(jwk.getKeyId()); + jwsHeaders.setKeyId(jwk.getKeyId()); return new JoseJwtProducer().processJwt(signedToken, null, signatureProvider); - } - - static String createSignedWithoutKeyId(JwtToken baseJwt, JsonWebKey jwk) { - JwsHeaders jwsHeaders = new JwsHeaders(); - JwtToken signedToken = new JwtToken(jwsHeaders, baseJwt.getClaims()); + } - return new JoseJwtProducer().processJwt(signedToken, null, JwsUtils.getSignatureProvider(jwk)); - } + static String createSignedWithoutKeyId(JwtToken baseJwt, JsonWebKey jwk) { + JwsHeaders jwsHeaders = new JwsHeaders(); + JwtToken signedToken = new JwtToken(jwsHeaders, baseJwt.getClaims()); - static String createSignedWithPeculiarEscaping(JwtToken baseJwt, JsonWebKey jwk) { - JwsSignatureProvider signatureProvider = JwsUtils.getSignatureProvider(jwk); - JwsHeaders jwsHeaders = new JwsHeaders(); - JwtToken signedToken = new JwtToken(jwsHeaders, baseJwt.getClaims()); + return new JoseJwtProducer().processJwt(signedToken, null, JwsUtils.getSignatureProvider(jwk)); + } - // Depends on CXF not escaping the input string. This may fail for other frameworks or versions. - jwsHeaders.setKeyId(jwk.getKeyId().replace("/", "\\/")); + static String createSignedWithPeculiarEscaping(JwtToken baseJwt, JsonWebKey jwk) { + JwsSignatureProvider signatureProvider = JwsUtils.getSignatureProvider(jwk); + JwsHeaders jwsHeaders = new JwsHeaders(); + JwtToken signedToken = new JwtToken(jwsHeaders, baseJwt.getClaims()); - return new JoseJwtProducer().processJwt(signedToken, null, signatureProvider); - } + // Depends on CXF not escaping the input string. This may fail for other frameworks or versions. + jwsHeaders.setKeyId(jwk.getKeyId().replace("/", "\\/")); - static String createMcCoySignedOct1(long nbf, long exp) - { - JwtToken jwt_token = create( - MCCOY_SUBJECT, TEST_AUDIENCE, - ROLES_CLAIM, TEST_ROLES_STRING, - JwtConstants.CLAIM_NOT_BEFORE, nbf, - JwtConstants.CLAIM_EXPIRY, exp); + return new JoseJwtProducer().processJwt(signedToken, null, signatureProvider); + } - return createSigned(jwt_token, TestJwk.OCT_1); - } + static String createMcCoySignedOct1(long nbf, long exp) { + JwtToken jwt_token = create( + MCCOY_SUBJECT, + TEST_AUDIENCE, + TEST_ISSUER, + ROLES_CLAIM, + TEST_ROLES_STRING, + JwtConstants.CLAIM_NOT_BEFORE, + nbf, + JwtConstants.CLAIM_EXPIRY, + exp + ); + + return createSigned(jwt_token, TestJwk.OCT_1); + } } diff --git a/src/test/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticatorTest.java b/src/test/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticatorTest.java index bfaf33049d..5a70a963c6 100644 --- a/src/test/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticatorTest.java +++ b/src/test/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticatorTest.java @@ -62,37 +62,39 @@ public class HTTPSamlAuthenticatorTest { protected MockSamlIdpServer mockSamlIdpServer; - private static final Pattern WWW_AUTHENTICATE_PATTERN = Pattern - .compile("([^\\s]+)\\s*([^\\s=]+)=\"([^\"]+)\"\\s*([^\\s=]+)=\"([^\"]+)\"\\s*([^\\s=]+)=\"([^\"]+)\"\\s*"); + private static final Pattern WWW_AUTHENTICATE_PATTERN = Pattern.compile( + "([^\\s]+)\\s*([^\\s=]+)=\"([^\"]+)\"\\s*([^\\s=]+)=\"([^\"]+)\"\\s*([^\\s=]+)=\"([^\"]+)\"\\s*" + ); private static final String SPOCK_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" - + "MIIE6TAbBgkqhkiG9w0BBQMwDgQI0JMa7PyPedwCAggABIIEyLdPL2RXj8jjKqFT\n" - + "p+7vywwyxyUQOQvvIIU6H+lKZPd/y6pxzYtGd1suT2aermrrlh4b/ZXXfj/EcKcw\n" - + "GgcXB60Kr7UHIv7Xr498S4EKa9R7UG0NtWtsA3FVR5ndwXI+CiRSShhkskmpseVH\n" - + "dNWAoUsKQFbZRLnoINMKIw1/lpQBUwAUcYVB7LxLeKSTVHn/h9kvq0tad1kbE5OY\n" - + "GnOLEVW311++XQ3Ep/13tGEZCrxef+QsnmXuYxXBq4RvbyGZOvyM2FC7va8KzJxl\n" - + "P38SPEL1TzqokQB/eLDBMBOCqkhTbP/8lNuoEVm44T6//ijBp6VdBB+YRIFh3NrS\n" - + "1fPuDVgHr1jrRGICe8lzWy/bSa+4FlxYjn5qpEzZQtbC6C+iRzlwtlCiDdKl8zJ1\n" - + "YF80OW9Gr3Kvph2LJukBiODcyWUAsAf5vJH3vfPV4T9kWTNMu2NCy3Ch8u9d906k\n" - + "zojB/tRRdZ/XCftkU05gYU/5ruU1YA49U60s0KWXvSLmecFo2SjkcEoPDI+Y80Uw\n" - + "OB/5kdh1M1uu/qjoJTPWBbZ28L6e0fiMsr7eWSG7PQFwnN6VzY6Oesm8AS8LMe3V\n" - + "Dr4Syec8vVfGg/EDsjNC1yeZTzlO66NQYGkpnHwK1kgX/XXe7fjDfztPyM9crBXj\n" - + "YcYpNULAkMj9QUVDQqQ7L8TjoAFQiSdvNa+kkDhaxnAXoxfqeacTtkpKcHADsAQL\n" - + "azfoyflnpuZ1dIn0noRFsVuguKDp4k990bhXu9RkQ1H5IzIoYqJwypacVdt3m74o\n" - + "jpZvBY6z0EtBNkze6WA0Vj0BSWpy/IzndDwroG4Xf+54hn0R/Tp5K5UNttOaJN8c\n" - + "9U/NTiGJTJg1O4x6xbPD7C5bBdoJ/MH5yJuk/dUc7pVkisLpuH9sAPETjYCdFIjX\n" - + "MSRJCtq2ouT0ZRW1yBIrKIadgHLExhjZjTSQCBXJMbO7r2DjPHMZU23GTiPtC8ua\n" - + "L2BmC+AW7RQ2Fyo3hJDT2TM4XlMMlTtGuFxkWwmjV+FiwfjbiR3cp0+99/X6OFu5\n" - + "ysgZLuTMQsmWNJ8ZARZqBnkGnN92Aw4D5GLCFv3QXO+fqJnOP1PbkPwpjq59Yytf\n" - + "U4XqyTwRYSXRzwPFFb7RcgL9HbmjpRBEnvqEjKYeXxkBnhs+WOWN/PuJzGgP5uAk\n" - + "jAjQbtgLEPd4WpGcwEhkX6S1DBi8NrGapuehCjXsN1axify8Kx4eRuTiPdINlgsq\n" - + "d2MsPIuDgU2+0QXrXjRLwABcMGuKcmmfZjC+zZomj+yr4+Togs3vhSj9yGK3HHMh\n" - + "NgOlPBTibruXXa4AI07c28j3sEry+CMZrUGyYg6o1HLBpBfOmp7V5HJcvkMFWCVy\n" - + "DPFm5LZu0jZMDj9a+oGkv4hfp1xSXSUjhjiGz47xFJb6PH9pOUIkhTEdFCgEXbaR\n" - + "fXcR+kakLOotL4X1cT9cpxdimN3CCTBpr03gCv2NCVYMYhHKHK+CQVngJrY+PzMH\n" - + "q6fw81bUNcixZyeXFfLFN6GK75k51UV7YS/X2H8YkqGeIVNaFjrcqUoVAN8jQOeb\n" - + "XXIa8gT/MdNT0+W3NHKcbE31pDhOI92COZWlhOyp1cLhyo1ytayjxPTl/2RM/Vtj\n" + "T9IKkp7810LOKhrCDQ==\n" - + "-----END ENCRYPTED PRIVATE KEY-----"; + + "MIIE6TAbBgkqhkiG9w0BBQMwDgQI0JMa7PyPedwCAggABIIEyLdPL2RXj8jjKqFT\n" + + "p+7vywwyxyUQOQvvIIU6H+lKZPd/y6pxzYtGd1suT2aermrrlh4b/ZXXfj/EcKcw\n" + + "GgcXB60Kr7UHIv7Xr498S4EKa9R7UG0NtWtsA3FVR5ndwXI+CiRSShhkskmpseVH\n" + + "dNWAoUsKQFbZRLnoINMKIw1/lpQBUwAUcYVB7LxLeKSTVHn/h9kvq0tad1kbE5OY\n" + + "GnOLEVW311++XQ3Ep/13tGEZCrxef+QsnmXuYxXBq4RvbyGZOvyM2FC7va8KzJxl\n" + + "P38SPEL1TzqokQB/eLDBMBOCqkhTbP/8lNuoEVm44T6//ijBp6VdBB+YRIFh3NrS\n" + + "1fPuDVgHr1jrRGICe8lzWy/bSa+4FlxYjn5qpEzZQtbC6C+iRzlwtlCiDdKl8zJ1\n" + + "YF80OW9Gr3Kvph2LJukBiODcyWUAsAf5vJH3vfPV4T9kWTNMu2NCy3Ch8u9d906k\n" + + "zojB/tRRdZ/XCftkU05gYU/5ruU1YA49U60s0KWXvSLmecFo2SjkcEoPDI+Y80Uw\n" + + "OB/5kdh1M1uu/qjoJTPWBbZ28L6e0fiMsr7eWSG7PQFwnN6VzY6Oesm8AS8LMe3V\n" + + "Dr4Syec8vVfGg/EDsjNC1yeZTzlO66NQYGkpnHwK1kgX/XXe7fjDfztPyM9crBXj\n" + + "YcYpNULAkMj9QUVDQqQ7L8TjoAFQiSdvNa+kkDhaxnAXoxfqeacTtkpKcHADsAQL\n" + + "azfoyflnpuZ1dIn0noRFsVuguKDp4k990bhXu9RkQ1H5IzIoYqJwypacVdt3m74o\n" + + "jpZvBY6z0EtBNkze6WA0Vj0BSWpy/IzndDwroG4Xf+54hn0R/Tp5K5UNttOaJN8c\n" + + "9U/NTiGJTJg1O4x6xbPD7C5bBdoJ/MH5yJuk/dUc7pVkisLpuH9sAPETjYCdFIjX\n" + + "MSRJCtq2ouT0ZRW1yBIrKIadgHLExhjZjTSQCBXJMbO7r2DjPHMZU23GTiPtC8ua\n" + + "L2BmC+AW7RQ2Fyo3hJDT2TM4XlMMlTtGuFxkWwmjV+FiwfjbiR3cp0+99/X6OFu5\n" + + "ysgZLuTMQsmWNJ8ZARZqBnkGnN92Aw4D5GLCFv3QXO+fqJnOP1PbkPwpjq59Yytf\n" + + "U4XqyTwRYSXRzwPFFb7RcgL9HbmjpRBEnvqEjKYeXxkBnhs+WOWN/PuJzGgP5uAk\n" + + "jAjQbtgLEPd4WpGcwEhkX6S1DBi8NrGapuehCjXsN1axify8Kx4eRuTiPdINlgsq\n" + + "d2MsPIuDgU2+0QXrXjRLwABcMGuKcmmfZjC+zZomj+yr4+Togs3vhSj9yGK3HHMh\n" + + "NgOlPBTibruXXa4AI07c28j3sEry+CMZrUGyYg6o1HLBpBfOmp7V5HJcvkMFWCVy\n" + + "DPFm5LZu0jZMDj9a+oGkv4hfp1xSXSUjhjiGz47xFJb6PH9pOUIkhTEdFCgEXbaR\n" + + "fXcR+kakLOotL4X1cT9cpxdimN3CCTBpr03gCv2NCVYMYhHKHK+CQVngJrY+PzMH\n" + + "q6fw81bUNcixZyeXFfLFN6GK75k51UV7YS/X2H8YkqGeIVNaFjrcqUoVAN8jQOeb\n" + + "XXIa8gT/MdNT0+W3NHKcbE31pDhOI92COZWlhOyp1cLhyo1ytayjxPTl/2RM/Vtj\n" + + "T9IKkp7810LOKhrCDQ==\n" + + "-----END ENCRYPTED PRIVATE KEY-----"; private static X509Certificate spSigningCertificate; private static PrivateKey spSigningPrivateKey; @@ -121,9 +123,14 @@ public void basicTest() throws Exception { mockSamlIdpServer.setAuthenticateUser("horst"); mockSamlIdpServer.setEndpointQueryString(null); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -137,9 +144,11 @@ public void basicTest() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -157,11 +166,18 @@ public void decryptAssertionsTest() throws Exception { mockSamlIdpServer.setSpSignatureCertificate(spSigningCertificate); mockSamlIdpServer.setEncryptAssertion(true); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("sp.signature_private_key", "-BEGIN PRIVATE KEY-\n" - + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-") - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put( + "sp.signature_private_key", + "-BEGIN PRIVATE KEY-\n" + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-" + ) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -175,9 +191,11 @@ public void decryptAssertionsTest() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -196,11 +214,18 @@ public void shouldUnescapeSamlEntitiesTest() throws Exception { mockSamlIdpServer.setEncryptAssertion(true); mockSamlIdpServer.setAuthenticateUserRoles(Arrays.asList("ABC\\Admin")); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("sp.signature_private_key", "-BEGIN PRIVATE KEY-\n" - + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-") - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put( + "sp.signature_private_key", + "-BEGIN PRIVATE KEY-\n" + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-" + ) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -214,9 +239,11 @@ public void shouldUnescapeSamlEntitiesTest() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -225,7 +252,7 @@ public void shouldUnescapeSamlEntitiesTest() throws Exception { JwtToken jwt = jwtConsumer.getJwtToken(); Assert.assertEquals("ABC\\User1", jwt.getClaim("sub")); - Assert.assertEquals("ABC\\User1", samlAuthenticator.httpJwtAuthenticator.extractSubject(jwt.getClaims())); + Assert.assertEquals("ABC\\User1", samlAuthenticator.httpJwtAuthenticator.extractSubject(jwt.getClaims())); Assert.assertEquals("[ABC\\Admin]", String.valueOf(jwt.getClaim("roles"))); Assert.assertEquals("ABC\\Admin", samlAuthenticator.httpJwtAuthenticator.extractRoles(jwt.getClaims())[0]); } @@ -238,11 +265,18 @@ public void shouldUnescapeSamlEntitiesTest2() throws Exception { mockSamlIdpServer.setEncryptAssertion(true); mockSamlIdpServer.setAuthenticateUserRoles(Arrays.asList("ABC\"Admin")); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("sp.signature_private_key", "-BEGIN PRIVATE KEY-\n" - + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-") - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put( + "sp.signature_private_key", + "-BEGIN PRIVATE KEY-\n" + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-" + ) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -256,9 +290,11 @@ public void shouldUnescapeSamlEntitiesTest2() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -267,7 +303,7 @@ public void shouldUnescapeSamlEntitiesTest2() throws Exception { JwtToken jwt = jwtConsumer.getJwtToken(); Assert.assertEquals("ABC\"User1", jwt.getClaim("sub")); - Assert.assertEquals("ABC\"User1", samlAuthenticator.httpJwtAuthenticator.extractSubject(jwt.getClaims())); + Assert.assertEquals("ABC\"User1", samlAuthenticator.httpJwtAuthenticator.extractSubject(jwt.getClaims())); Assert.assertEquals("[ABC\"Admin]", String.valueOf(jwt.getClaim("roles"))); Assert.assertEquals("ABC\"Admin", samlAuthenticator.httpJwtAuthenticator.extractRoles(jwt.getClaims())[0]); } @@ -280,11 +316,18 @@ public void shouldNotEscapeSamlEntities() throws Exception { mockSamlIdpServer.setEncryptAssertion(true); mockSamlIdpServer.setAuthenticateUserRoles(Arrays.asList("ABC/Admin")); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("sp.signature_private_key", "-BEGIN PRIVATE KEY-\n" - + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-") - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put( + "sp.signature_private_key", + "-BEGIN PRIVATE KEY-\n" + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-" + ) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -298,9 +341,11 @@ public void shouldNotEscapeSamlEntities() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -309,7 +354,7 @@ public void shouldNotEscapeSamlEntities() throws Exception { JwtToken jwt = jwtConsumer.getJwtToken(); Assert.assertEquals("ABC/User1", jwt.getClaim("sub")); - Assert.assertEquals("ABC/User1", samlAuthenticator.httpJwtAuthenticator.extractSubject(jwt.getClaims())); + Assert.assertEquals("ABC/User1", samlAuthenticator.httpJwtAuthenticator.extractSubject(jwt.getClaims())); Assert.assertEquals("[ABC/Admin]", String.valueOf(jwt.getClaim("roles"))); Assert.assertEquals("ABC/Admin", samlAuthenticator.httpJwtAuthenticator.extractRoles(jwt.getClaims())[0]); } @@ -322,11 +367,18 @@ public void shouldNotTrimWhitespaceInJwtRoles() throws Exception { mockSamlIdpServer.setEncryptAssertion(true); mockSamlIdpServer.setAuthenticateUserRoles(Arrays.asList(" ABC/Admin ")); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("sp.signature_private_key", "-BEGIN PRIVATE KEY-\n" - + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-") - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put( + "sp.signature_private_key", + "-BEGIN PRIVATE KEY-\n" + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-" + ) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -340,9 +392,11 @@ public void shouldNotTrimWhitespaceInJwtRoles() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -362,12 +416,16 @@ public void testMetadataBody() throws Exception { // Note: We need to replace endpoint with mockSamlIdpServer endpoint final String metadataBody = FileHelper.loadFile("saml/metadata.xml") - .replaceAll("http://localhost:33667/", mockSamlIdpServer.getMetadataUri()); + .replaceAll("http://localhost:33667/", mockSamlIdpServer.getMetadataUri()); - Settings settings = Settings.builder().put(IDP_METADATA_CONTENT, metadataBody) + Settings settings = Settings.builder() + .put(IDP_METADATA_CONTENT, metadataBody) .put("kibana_url", "http://wherever") .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -381,9 +439,11 @@ public void testMetadataBody() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, new TypeReference>() { - }); + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -394,18 +454,21 @@ public void testMetadataBody() throws Exception { Assert.assertEquals("horst", jwt.getClaim("sub")); } - - @Test(expected= RuntimeException.class) + @Test(expected = RuntimeException.class) public void testEmptyMetadataBody() throws Exception { mockSamlIdpServer.setSignResponses(true); mockSamlIdpServer.loadSigningKeys("saml/kirk-keystore.jks", "kirk"); mockSamlIdpServer.setAuthenticateUser("horst"); mockSamlIdpServer.setEndpointQueryString(null); - Settings settings = Settings.builder().put(IDP_METADATA_CONTENT, "") + Settings settings = Settings.builder() + .put(IDP_METADATA_CONTENT, "") .put("kibana_url", "http://wherever") .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); new HTTPSamlAuthenticator(settings, null); } @@ -418,24 +481,34 @@ public void unsolicitedSsoTest() throws Exception { mockSamlIdpServer.setEndpointQueryString(null); mockSamlIdpServer.setDefaultAssertionConsumerService("http://wherever/opendistrosecurity/saml/acs/idpinitiated"); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); String encodedSamlResponse = mockSamlIdpServer.createUnsolicitedSamlResponse(); - RestRequest tokenRestRequest = buildTokenExchangeRestRequest(encodedSamlResponse, null, - "/opendistrosecurity/saml/acs/idpinitiated"); + RestRequest tokenRestRequest = buildTokenExchangeRestRequest( + encodedSamlResponse, + null, + "/opendistrosecurity/saml/acs/idpinitiated" + ); TestRestChannel tokenRestChannel = new TestRestChannel(tokenRestRequest); samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -454,19 +527,29 @@ public void badUnsolicitedSsoTest() throws Exception { mockSamlIdpServer.setEndpointQueryString(null); mockSamlIdpServer.setDefaultAssertionConsumerService("http://wherever/opendistrosecurity/saml/acs/idpinitiated"); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); String encodedSamlResponse = mockSamlIdpServer.createUnsolicitedSamlResponse(); - AuthenticateHeaders authenticateHeaders = new AuthenticateHeaders("http://wherever/opendistrosecurity/saml/acs/", - "wrong_request_id"); + AuthenticateHeaders authenticateHeaders = new AuthenticateHeaders( + "http://wherever/opendistrosecurity/saml/acs/", + "wrong_request_id" + ); - RestRequest tokenRestRequest = buildTokenExchangeRestRequest(encodedSamlResponse, authenticateHeaders, - "/opendistrosecurity/saml/acs/idpinitiated"); + RestRequest tokenRestRequest = buildTokenExchangeRestRequest( + encodedSamlResponse, + authenticateHeaders, + "/opendistrosecurity/saml/acs/idpinitiated" + ); TestRestChannel tokenRestChannel = new TestRestChannel(tokenRestRequest); samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); @@ -481,9 +564,14 @@ public void wrongCertTest() throws Exception { mockSamlIdpServer.setAuthenticateUser("horst"); mockSamlIdpServer.setEndpointQueryString(null); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -507,9 +595,14 @@ public void noSignatureTest() throws Exception { mockSamlIdpServer.setAuthenticateUser("horst"); mockSamlIdpServer.setEndpointQueryString(null); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -534,9 +627,15 @@ public void rolesTest() throws Exception { mockSamlIdpServer.setAuthenticateUserRoles(Arrays.asList("a ,c", "b ,d, e", "f", "g,,h, ,i")); mockSamlIdpServer.setEndpointQueryString(null); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").put("roles_seperator", ",").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .put("roles_seperator", ",") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -550,9 +649,11 @@ public void rolesTest() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -561,8 +662,10 @@ public void rolesTest() throws Exception { JwtToken jwt = jwtConsumer.getJwtToken(); Assert.assertEquals("horst", jwt.getClaim("sub")); - Assert.assertArrayEquals(new String[] { "a ", "c", "b ", "d", " e", "f", "g", "h", " ", "i" }, - ((List) jwt.getClaim("roles")).toArray(new String[0])); + Assert.assertArrayEquals( + new String[] { "a ", "c", "b ", "d", " e", "f", "g", "h", " ", "i" }, + ((List) jwt.getClaim("roles")).toArray(new String[0]) + ); } @Test @@ -572,9 +675,14 @@ public void idpEndpointWithQueryStringTest() throws Exception { mockSamlIdpServer.setAuthenticateUser("horst"); mockSamlIdpServer.setEndpointQueryString("extra=query"); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -588,9 +696,11 @@ public void idpEndpointWithQueryStringTest() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -622,9 +732,12 @@ private void commaSeparatedRoles(final String rolesAsString, final Settings.Buil mockSamlIdpServer.setEndpointQueryString(null); Settings settings = settingsBuilder.put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".") - .build(); + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); AuthenticateHeaders authenticateHeaders = getAutenticateHeaders(samlAuthenticator); @@ -637,9 +750,11 @@ private void commaSeparatedRoles(final String rolesAsString, final Settings.Buil samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -648,8 +763,7 @@ private void commaSeparatedRoles(final String rolesAsString, final Settings.Buil JwtToken jwt = jwtConsumer.getJwtToken(); Assert.assertEquals("horst", jwt.getClaim("sub")); - Assert.assertArrayEquals(new String[] { "a", "b" }, - ((List) jwt.getClaim("roles")).toArray(new String[0])); + Assert.assertArrayEquals(new String[] { "a", "b" }, ((List) jwt.getClaim("roles")).toArray(new String[0])); } @Test @@ -660,12 +774,18 @@ public void basicLogoutTest() throws Exception { mockSamlIdpServer.setSpSignatureCertificate(spSigningCertificate); mockSamlIdpServer.setEndpointQueryString(null); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles") - .put("sp.signature_private_key", "-BEGIN PRIVATE KEY-\n" - + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-") - .put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put( + "sp.signature_private_key", + "-BEGIN PRIVATE KEY-\n" + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-" + ) + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -688,10 +808,16 @@ public void basicLogoutTestEncryptedKey() throws Exception { mockSamlIdpServer.setSpSignatureCertificate(spSigningCertificate); mockSamlIdpServer.setEndpointQueryString(null); - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("sp.signature_private_key", SPOCK_KEY) - .put("sp.signature_private_key_password", "changeit").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("sp.signature_private_key", SPOCK_KEY) + .put("sp.signature_private_key_password", "changeit") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -710,10 +836,15 @@ public void basicLogoutTestEncryptedKey() throws Exception { public void initialConnectionFailureTest() throws Exception { try (MockSamlIdpServer mockSamlIdpServer = new MockSamlIdpServer()) { - Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) - .put("idp.min_refresh_delay", 100) - .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) - .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + Settings settings = Settings.builder() + .put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("idp.min_refresh_delay", 100) + .put("kibana_url", "http://wherever") + .put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("exchange_key", "abc") + .put("roles_key", "roles") + .put("path.home", ".") + .build(); HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); @@ -742,9 +873,11 @@ public void initialConnectionFailureTest() throws Exception { samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); - HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, - new TypeReference>() { - }); + HashMap response = DefaultObjectMapper.objectMapper.readValue( + responseJson, + new TypeReference>() { + } + ); String authorization = (String) response.get("authorization"); Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); @@ -765,8 +898,7 @@ private AuthenticateHeaders getAutenticateHeaders(HTTPSamlAuthenticator samlAuth List wwwAuthenticateHeaders = restChannel.response.getHeaders().get("WWW-Authenticate"); Assert.assertNotNull(wwwAuthenticateHeaders); - Assert.assertEquals("More than one WWW-Authenticate header: " + wwwAuthenticateHeaders, 1, - wwwAuthenticateHeaders.size()); + Assert.assertEquals("More than one WWW-Authenticate header: " + wwwAuthenticateHeaders, 1, wwwAuthenticateHeaders.size()); String wwwAuthenticateHeader = wwwAuthenticateHeaders.get(0); @@ -786,26 +918,36 @@ private AuthenticateHeaders getAutenticateHeaders(HTTPSamlAuthenticator samlAuth return new AuthenticateHeaders(location, requestId); } - private RestRequest buildTokenExchangeRestRequest(String encodedSamlResponse, - AuthenticateHeaders authenticateHeaders) { + private RestRequest buildTokenExchangeRestRequest(String encodedSamlResponse, AuthenticateHeaders authenticateHeaders) { return buildTokenExchangeRestRequest(encodedSamlResponse, authenticateHeaders, "/opendistrosecurity/saml/acs"); } - private RestRequest buildTokenExchangeRestRequest(String encodedSamlResponse, - AuthenticateHeaders authenticateHeaders, String acsEndpoint) { + private RestRequest buildTokenExchangeRestRequest( + String encodedSamlResponse, + AuthenticateHeaders authenticateHeaders, + String acsEndpoint + ) { String authtokenPostJson; if (authenticateHeaders != null) { - authtokenPostJson = "{\"SAMLResponse\": \"" + encodedSamlResponse + "\", \"RequestId\": \"" - + authenticateHeaders.requestId + "\"}"; + authtokenPostJson = "{\"SAMLResponse\": \"" + + encodedSamlResponse + + "\", \"RequestId\": \"" + + authenticateHeaders.requestId + + "\"}"; } else { - authtokenPostJson = "{\"SAMLResponse\": \"" + encodedSamlResponse - + "\", \"RequestId\": null, \"acsEndpoint\": \"" + acsEndpoint + "\" }"; + authtokenPostJson = "{\"SAMLResponse\": \"" + + encodedSamlResponse + + "\", \"RequestId\": null, \"acsEndpoint\": \"" + + acsEndpoint + + "\" }"; } - return new FakeRestRequest.Builder().withPath("/_opendistro/_security/api/authtoken").withMethod(Method.POST) - .withContent(new BytesArray(authtokenPostJson)) - .withHeaders(ImmutableMap.of("Content-Type", "application/json")).build(); + return new FakeRestRequest.Builder().withPath("/_opendistro/_security/api/authtoken") + .withMethod(Method.POST) + .withContent(new BytesArray(authtokenPostJson)) + .withHeaders(ImmutableMap.of("Content-Type", "application/json")) + .build(); } @BeforeClass @@ -814,8 +956,7 @@ public static void initSpSigningKeys() { KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); KeyStore keyStore = KeyStore.getInstance("JKS"); - InputStream keyStream = new FileInputStream( - FileHelper.getAbsoluteFilePathFromClassPath("saml/spock-keystore.jks").toFile()); + InputStream keyStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("saml/spock-keystore.jks").toFile()); keyStore.load(keyStream, "changeit".toCharArray()); kmf.init(keyStore, "changeit".toCharArray()); @@ -824,8 +965,7 @@ public static void initSpSigningKeys() { spSigningPrivateKey = (PrivateKey) keyStore.getKey("spock", "changeit".toCharArray()); - } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException - | UnrecoverableKeyException e) { + } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException | UnrecoverableKeyException e) { throw new RuntimeException(e); } } @@ -876,7 +1016,8 @@ public void sendResponse(RestResponse response) { } @Override - public XContentBuilder newBuilder(XContentType xContentType, XContentType responseContentType, boolean useFiltering) throws IOException { + public XContentBuilder newBuilder(XContentType xContentType, XContentType responseContentType, boolean useFiltering) + throws IOException { return null; } diff --git a/src/test/java/com/amazon/dlic/auth/http/saml/MockSamlIdpServer.java b/src/test/java/com/amazon/dlic/auth/http/saml/MockSamlIdpServer.java index 4f4a8c9640..ef54e3e833 100644 --- a/src/test/java/com/amazon/dlic/auth/http/saml/MockSamlIdpServer.java +++ b/src/test/java/com/amazon/dlic/auth/http/saml/MockSamlIdpServer.java @@ -193,46 +193,50 @@ class MockSamlIdpServer implements Closeable { this.loadSigningKeys("saml/kirk-keystore.jks", "kirk"); - ServerBootstrap serverBootstrap = ServerBootstrap.bootstrap().setListenerPort(port) - .register(CTX_METADATA, new HttpRequestHandler() { + ServerBootstrap serverBootstrap = ServerBootstrap.bootstrap() + .setListenerPort(port) + .register(CTX_METADATA, new HttpRequestHandler() { - @Override - public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, IOException { + @Override + public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, + IOException { - handleMetadataRequest(request, response, context); + handleMetadataRequest(request, response, context); - } - }).register(CTX_SAML_SSO, new HttpRequestHandler() { + } + }) + .register(CTX_SAML_SSO, new HttpRequestHandler() { - @Override - public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, IOException { - handleSsoRequest(request, response, context); - } - }).register(CTX_SAML_SLO, new HttpRequestHandler() { + @Override + public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, + IOException { + handleSsoRequest(request, response, context); + } + }) + .register(CTX_SAML_SLO, new HttpRequestHandler() { - @Override - public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, IOException { - handleSloRequest(request, response, context); - } - }); + @Override + public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, + IOException { + handleSloRequest(request, response, context); + } + }); if (ssl) { - serverBootstrap = serverBootstrap.setSslContext(createSSLContext()) - .setSslSetupHandler(new Callback() { - @Override - public void execute(SSLParameters object) { - object.setNeedClientAuth(true); - } - }) - .setConnectionFactory(new HttpConnectionFactory() { - @Override - public DefaultBHttpServerConnection createConnection(final Socket socket) throws IOException { - final DefaultBHttpServerConnection conn = new DefaultBHttpServerConnection(ssl ? "https" : "http", Http1Config.DEFAULT); - conn.bind(socket); - return conn; - } - }); + serverBootstrap = serverBootstrap.setSslContext(createSSLContext()).setSslSetupHandler(new Callback() { + @Override + public void execute(SSLParameters object) { + object.setNeedClientAuth(true); + } + }).setConnectionFactory(new HttpConnectionFactory() { + @Override + public DefaultBHttpServerConnection createConnection(final Socket socket) throws IOException { + final DefaultBHttpServerConnection conn = new DefaultBHttpServerConnection(ssl ? "https" : "http", Http1Config.DEFAULT); + conn.bind(socket); + return conn; + } + }); } this.httpServer = serverBootstrap.create(); @@ -289,16 +293,15 @@ public int getPort() { return port; } - protected void handleMetadataRequest(HttpRequest request, ClassicHttpResponse response, HttpContext context) - throws HttpException, IOException { + protected void handleMetadataRequest(HttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, + IOException { response.setCode(200); response.setHeader("Cache-Control", "public, max-age=31536000"); response.setHeader("Content-Type", "application/xml"); response.setEntity(new StringEntity(createMetadata())); } - protected void handleSsoRequest(HttpRequest request, HttpResponse response, HttpContext context) - throws HttpException, IOException { + protected void handleSsoRequest(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { if ("GET".equalsIgnoreCase(request.getMethod())) { handleSsoGetRequestBase(request); @@ -308,8 +311,7 @@ protected void handleSsoRequest(HttpRequest request, HttpResponse response, Http } - protected void handleSloRequest(HttpRequest request, HttpResponse response, HttpContext context) - throws HttpException, IOException { + protected void handleSloRequest(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { if ("GET".equalsIgnoreCase(request.getMethod())) { handleSloGetRequestBase(request); @@ -375,10 +377,10 @@ public void handleSloGetRequestBase(HttpRequest request) { LogoutRequest logoutRequest = (LogoutRequest) messageContext.getMessage(); - SAML2HTTPRedirectDeflateSignatureSecurityHandler signatureSecurityHandler = new SAML2HTTPRedirectDeflateSignatureSecurityHandler(); + SAML2HTTPRedirectDeflateSignatureSecurityHandler signatureSecurityHandler = + new SAML2HTTPRedirectDeflateSignatureSecurityHandler(); SignatureValidationParameters validationParams = new SignatureValidationParameters(); - SecurityParametersContext securityParametersContext = messageContext - .getSubcontext(SecurityParametersContext.class, true); + SecurityParametersContext securityParametersContext = messageContext.getSubcontext(SecurityParametersContext.class, true); SAMLPeerEntityContext peerEntityContext = messageContext.getSubcontext(SAMLPeerEntityContext.class, true); peerEntityContext.setEntityId(idpEntityId); @@ -397,8 +399,7 @@ public void handleSloGetRequestBase(HttpRequest request) { throw new RuntimeException("Unexpected NameID in LogoutRequest: " + logoutRequest); } - } catch (URISyntaxException | ComponentInitializationException | MessageDecodingException - | MessageHandlerException e) { + } catch (URISyntaxException | ComponentInitializationException | MessageDecodingException | MessageHandlerException e) { throw new RuntimeException(e); } } @@ -436,12 +437,24 @@ private String createSamlAuthResponse(AuthnRequest authnRequest) { if (authnRequest != null) { subject.getSubjectConfirmations() - .add(createSubjectConfirmation("urn:oasis:names:tc:SAML:2.0:cm:bearer", - new DateTime().plusMinutes(1), authnRequest.getID(), - authnRequest.getAssertionConsumerServiceURL())); + .add( + createSubjectConfirmation( + "urn:oasis:names:tc:SAML:2.0:cm:bearer", + new DateTime().plusMinutes(1), + authnRequest.getID(), + authnRequest.getAssertionConsumerServiceURL() + ) + ); } else { - subject.getSubjectConfirmations().add(createSubjectConfirmation("urn:oasis:names:tc:SAML:2.0:cm:bearer", - new DateTime().plusMinutes(1), null, defaultAssertionConsumerService)); + subject.getSubjectConfirmations() + .add( + createSubjectConfirmation( + "urn:oasis:names:tc:SAML:2.0:cm:bearer", + new DateTime().plusMinutes(1), + null, + defaultAssertionConsumerService + ) + ); } Conditions conditions = createSamlElement(Conditions.class); @@ -464,7 +477,7 @@ private String createSamlAuthResponse(AuthnRequest authnRequest) { attribute.getAttributeValues().add(createXSAny(AttributeValue.DEFAULT_ELEMENT_NAME, role)); } } - + if (signResponses) { Signature signature = createSamlElement(Signature.class); assertion.setSignature(signature); @@ -478,7 +491,7 @@ private String createSamlAuthResponse(AuthnRequest authnRequest) { Signer.signObject(signature); } - if (this.encryptAssertion){ + if (this.encryptAssertion) { Encrypter encrypter = getEncrypter(); EncryptedAssertion encryptedAssertion = encrypter.encrypt(assertion); response.getEncryptedAssertions().add(encryptedAssertion); @@ -486,7 +499,6 @@ private String createSamlAuthResponse(AuthnRequest authnRequest) { response.getAssertions().add(assertion); } - String marshalledXml = marshallSamlXml(response); return Base64Support.encode(marshalledXml.getBytes("UTF-8"), Base64Support.UNCHUNKED); @@ -498,10 +510,11 @@ private String createSamlAuthResponse(AuthnRequest authnRequest) { private Encrypter getEncrypter() { KeyEncryptionParameters kek = new KeyEncryptionParameters(); - // Algorithm from https://santuario.apache.org/Java/api/constant-values.html#org.apache.xml.security.utils.EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15 + // Algorithm from + // https://santuario.apache.org/Java/api/constant-values.html#org.apache.xml.security.utils.EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15 kek.setAlgorithm("http://www.w3.org/2001/04/xmlenc#rsa-1_5"); kek.setEncryptionCredential(new BasicX509Credential(spSignatureCertificate)); - Encrypter encrypter = new Encrypter( new DataEncryptionParameters(),kek); + Encrypter encrypter = new Encrypter(new DataEncryptionParameters(), kek); encrypter.setKeyPlacement(Encrypter.KeyPlacement.INLINE); return encrypter; } @@ -554,8 +567,7 @@ private NameID createNameID(String format, String value) { return nameID; } - private SubjectConfirmation createSubjectConfirmation(String method, DateTime notOnOrAfter, String inResponseTo, - String recipient) { + private SubjectConfirmation createSubjectConfirmation(String method, DateTime notOnOrAfter, String inResponseTo, String recipient) { SubjectConfirmation result = createSamlElement(SubjectConfirmation.class); result.setMethod(method); @@ -601,8 +613,7 @@ private String createMetadata() { redirectSingleLogoutService.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"); redirectSingleLogoutService.setLocation(getSamlSloUri()); - idpSsoDescriptor.getNameIDFormats() - .add(createNameIDFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified")); + idpSsoDescriptor.getNameIDFormats().add(createNameIDFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified")); SingleSignOnService redirectSingleSignOnService = createSamlElement(SingleSignOnService.class); idpSsoDescriptor.getSingleSignOnServices().add(redirectSingleSignOnService); @@ -619,8 +630,7 @@ private String createMetadata() { signingKeyDescriptor.setUse(UsageType.SIGNING); - signingKeyDescriptor - .setKeyInfo(keyInfoGenerator.generate(new BasicX509Credential(this.signingCertificate))); + signingKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(new BasicX509Credential(this.signingCertificate))); return marshallSamlXml(idpEntityDescriptor); } catch (org.opensaml.security.SecurityException e) { @@ -640,16 +650,14 @@ private String marshallSamlXml(XMLObject xmlObject) { transformer.transform(source, new StreamResult(stringWriter)); return stringWriter.toString(); - } catch (ParserConfigurationException | MarshallingException | TransformerFactoryConfigurationError - | TransformerException e) { + } catch (ParserConfigurationException | MarshallingException | TransformerFactoryConfigurationError | TransformerException e) { throw new RuntimeException(e); } } private SignatureTrustEngine buildSignatureTrustEngine(X509Certificate certificate) { CredentialResolver credentialResolver = new StaticCredentialResolver(new BasicX509Credential(certificate)); - KeyInfoCredentialResolver keyInfoCredentialResolver = new StaticKeyInfoCredentialResolver( - new BasicX509Credential(certificate)); + KeyInfoCredentialResolver keyInfoCredentialResolver = new StaticKeyInfoCredentialResolver(new BasicX509Credential(certificate)); return new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoCredentialResolver); } @@ -666,11 +674,12 @@ void loadSigningKeys(String path, String alias) { this.signingCertificate = (X509Certificate) keyStore.getCertificate(alias); - this.signingCredential = new BasicX509Credential(this.signingCertificate, - (PrivateKey) keyStore.getKey(alias, "changeit".toCharArray())); + this.signingCredential = new BasicX509Credential( + this.signingCertificate, + (PrivateKey) keyStore.getKey(alias, "changeit".toCharArray()) + ); - } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException - | UnrecoverableKeyException e) { + } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException | UnrecoverableKeyException e) { throw new RuntimeException(e); } } @@ -683,15 +692,13 @@ private SSLContext createSSLContext() { try { final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); final KeyStore trustStore = KeyStore.getInstance("JKS"); - InputStream trustStream = new FileInputStream( - FileHelper.getAbsoluteFilePathFromClassPath("jwt/truststore.jks").toFile()); + InputStream trustStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("jwt/truststore.jks").toFile()); trustStore.load(trustStream, "changeit".toCharArray()); tmf.init(trustStore); final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); final KeyStore keyStore = KeyStore.getInstance("JKS"); - InputStream keyStream = new FileInputStream( - FileHelper.getAbsoluteFilePathFromClassPath("jwt/node-0-keystore.jks").toFile()); + InputStream keyStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("jwt/node-0-keystore.jks").toFile()); keyStore.load(keyStream, "changeit".toCharArray()); kmf.init(keyStore, "changeit".toCharArray()); @@ -709,14 +716,26 @@ private String nextId() { } static class SSLTestHttpServerConnection extends DefaultBHttpServerConnection { - public SSLTestHttpServerConnection(final String scheme, Http1Config http1Config, - final CharsetDecoder charDecoder, final CharsetEncoder charEncoder, - final ContentLengthStrategy incomingContentStrategy, - final ContentLengthStrategy outgoingContentStrategy, - final HttpMessageParserFactory requestParserFactory, - final HttpMessageWriterFactory responseWriterFactory) { - super(scheme, http1Config, charDecoder, charEncoder, incomingContentStrategy, - outgoingContentStrategy, requestParserFactory, responseWriterFactory); + public SSLTestHttpServerConnection( + final String scheme, + Http1Config http1Config, + final CharsetDecoder charDecoder, + final CharsetEncoder charEncoder, + final ContentLengthStrategy incomingContentStrategy, + final ContentLengthStrategy outgoingContentStrategy, + final HttpMessageParserFactory requestParserFactory, + final HttpMessageWriterFactory responseWriterFactory + ) { + super( + scheme, + http1Config, + charDecoder, + charEncoder, + incomingContentStrategy, + outgoingContentStrategy, + requestParserFactory, + responseWriterFactory + ); } } @@ -729,8 +748,9 @@ static class FakeHttpServletRequest implements HttpServletRequest { this.delegate = delegate; String uri = delegate.getRequestUri(); this.uriBuilder = new URIBuilder(uri); - this.queryParams = uriBuilder.getQueryParams().stream() - .collect(Collectors.toMap(NameValuePair::getName, NameValuePair::getValue)); + this.queryParams = uriBuilder.getQueryParams() + .stream() + .collect(Collectors.toMap(NameValuePair::getName, NameValuePair::getValue)); } @Override @@ -959,8 +979,7 @@ public String getHeader(String name) { @SuppressWarnings("rawtypes") @Override public Enumeration getHeaderNames() { - return Collections.enumeration( - Arrays.asList(delegate.getHeaders()).stream().map(Header::getName).collect(Collectors.toSet())); + return Collections.enumeration(Arrays.asList(delegate.getHeaders()).stream().map(Header::getName).collect(Collectors.toSet())); } @SuppressWarnings("rawtypes") @@ -969,8 +988,7 @@ public Enumeration getHeaders(String name) { Header[] headers = delegate.getHeaders(name); if (headers != null) { - return Collections - .enumeration(Arrays.asList(headers).stream().map(Header::getName).collect(Collectors.toSet())); + return Collections.enumeration(Arrays.asList(headers).stream().map(Header::getName).collect(Collectors.toSet())); } else { return null; } diff --git a/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendIntegTest.java b/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendIntegTest.java index 81654d4c19..b2ba079dff 100644 --- a/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendIntegTest.java +++ b/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendIntegTest.java @@ -74,13 +74,19 @@ public void testAttributesWithImpersonation() throws Exception { String securityConfigAsYamlString = FileHelper.loadFile("ldap/config.yml"); securityConfigAsYamlString = securityConfigAsYamlString.replace("${ldapsPort}", String.valueOf(ldapsPort)); final Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".cn=Captain Spock,ou=people,o=TEST", "*") - .build(); + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".cn=Captain Spock,ou=people,o=TEST", "*") + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setConfigAsYamlString(securityConfigAsYamlString), settings); final RestHelper rh = nonSslRestHelper(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as", "jacksonm") - ,encodeBasicHeader("spock", "spocksecret"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "jacksonm"), + encodeBasicHeader("spock", "spocksecret") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("ldap.dn")); Assert.assertTrue(res.getBody().contains("attr.ldap.entryDN")); @@ -88,7 +94,6 @@ public void testAttributesWithImpersonation() throws Exception { } - @AfterClass public static void tearDownLdap() throws Exception { diff --git a/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTest.java b/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTest.java index db961eb9a4..3cc5006198 100755 --- a/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTest.java +++ b/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTest.java @@ -61,128 +61,138 @@ public static void startLdapServer() throws Exception { @Test public void testLdapAuthentication() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } - @Test(expected=OpenSearchSecurityException.class) + @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationFakeLogin() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, true) - .build(); - - new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("unknown", "unknown" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, true) + .build(); + + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("unknown", "unknown".getBytes(StandardCharsets.UTF_8)) + ); } - @Test(expected=OpenSearchSecurityException.class) + @Test(expected = OpenSearchSecurityException.class) public void testLdapInjection() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); String injectString = "*jack*"; - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials(injectString, "secret" - .getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials(injectString, "secret".getBytes(StandardCharsets.UTF_8)) + ); } @Test public void testLdapAuthenticationBindDn() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") - .put(ConfigConstants.LDAP_PASSWORD, "spocksecret") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") + .put(ConfigConstants.LDAP_PASSWORD, "spocksecret") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } - @Test(expected=OpenSearchSecurityException.class) + @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationWrongBindDn() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") - .put(ConfigConstants.LDAP_PASSWORD, "wrong") - .build(); - - new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") + .put(ConfigConstants.LDAP_PASSWORD, "wrong") + .build(); + + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); } - @Test(expected=OpenSearchSecurityException.class) + @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationBindFail() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "wrong".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "wrong".getBytes(StandardCharsets.UTF_8)) + ); } - @Test(expected=OpenSearchSecurityException.class) + @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationNoUser() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("UNKNOWN", "UNKNOWN".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("UNKNOWN", "UNKNOWN".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationFail() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8)) + ); } @Test public void testLdapAuthenticationSSL() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false) - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -190,36 +200,34 @@ public void testLdapAuthenticationSSL() throws Exception { @Test public void testLdapAuthenticationSSLPEMFile() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").toFile().getName()) - .put("verify_hostnames", false) - .put("path.home",".") - .put("path.conf",FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").getParent()) - .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, Paths.get("src/test/resources/ldap")).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").toFile().getName() + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .put("path.conf", FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").getParent()) + .build(); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, Paths.get("src/test/resources/ldap")).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @Test public void testLdapAuthenticationSSLPEMText() throws Exception { - final Settings settingsFromFile = Settings - .builder() - .loadFromPath( - Paths - .get(FileHelper - .getAbsoluteFilePathFromClassPath("ldap/test1.yml") - .toFile() - .getAbsolutePath())) - .build(); - Settings settings = Settings.builder().put(settingsFromFile).putList("hosts", "localhost:"+ldapsPort).build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + final Settings settingsFromFile = Settings.builder() + .loadFromPath(Paths.get(FileHelper.getAbsoluteFilePathFromClassPath("ldap/test1.yml").toFile().getAbsolutePath())) + .build(); + Settings settings = Settings.builder().put(settingsFromFile).putList("hosts", "localhost:" + ldapsPort).build(); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -227,20 +235,23 @@ public void testLdapAuthenticationSSLPEMText() throws Exception { @Test public void testLdapAuthenticationSSLSSLv3() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false) - .putList("enabled_ssl_protocols", "SSLv3") - .put("path.home",".") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_protocols", "SSLv3") + .put("path.home", ".") + .build(); try { - new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); } catch (Exception e) { Assert.assertEquals(e.getCause().getClass(), org.ldaptive.LdapException.class); Assert.assertTrue(e.getCause().getMessage().contains("Unable to connec")); @@ -251,20 +262,23 @@ public void testLdapAuthenticationSSLSSLv3() throws Exception { @Test public void testLdapAuthenticationSSLUnknowCipher() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false) - .putList("enabled_ssl_ciphers", "AAA") - .put("path.home",".") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_ciphers", "AAA") + .put("path.home", ".") + .build(); try { - new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); } catch (Exception e) { Assert.assertEquals(e.getCause().getClass(), org.ldaptive.LdapException.class); Assert.assertTrue(e.getCause().getMessage().contains("Unable to connec")); @@ -275,20 +289,23 @@ public void testLdapAuthenticationSSLUnknowCipher() throws Exception { @Test public void testLdapAuthenticationSpecialCipherProtocol() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false) - .putList("enabled_ssl_protocols", "TLSv1.2") - .putList("enabled_ssl_ciphers", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA") - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_protocols", "TLSv1.2") + .putList("enabled_ssl_ciphers", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); @@ -297,18 +314,21 @@ public void testLdapAuthenticationSpecialCipherProtocol() throws Exception { @Test public void testLdapAuthenticationSSLNoKeystore() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false) - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -316,15 +336,16 @@ public void testLdapAuthenticationSSLNoKeystore() throws Exception { @Test public void testLdapAuthenticationSSLFailPlain() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true).build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .build(); try { - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); } catch (final Exception e) { Assert.assertEquals(org.ldaptive.LdapException.class, e.getCause().getClass()); } @@ -333,10 +354,10 @@ public void testLdapAuthenticationSSLFailPlain() throws Exception { @Test public void testLdapExists() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); final LDAPAuthenticationBackend lbe = new LDAPAuthenticationBackend(settings, null); Assert.assertTrue(lbe.exists(new User("jacksonm"))); @@ -346,20 +367,20 @@ public void testLdapExists() throws Exception { @Test public void testLdapAuthorization() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - // .put("plugins.security.authentication.authorization.ldap.userrolename", - // "(uniqueMember={0})") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + // .put("plugins.security.authentication.authorization.ldap.userrolename", + // "(uniqueMember={0})") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -373,19 +394,19 @@ public void testLdapAuthorization() throws Exception { @Test public void testLdapAuthenticationReturnAttributes() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, "mail", "cn", "uid") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, "mail", "cn", "uid") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -401,10 +422,10 @@ public void testLdapAuthenticationReturnAttributes() throws Exception { @Test public void testLdapAuthenticationReferral() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); final Connection con = LDAPAuthorizationBackend.getConnection(settings, null); try { @@ -418,17 +439,21 @@ public void testLdapAuthenticationReferral() throws Exception { @Test public void testLdapDontFollowReferrals() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.FOLLOW_REFERRALS, false).build(); - + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.FOLLOW_REFERRALS, false) + .build(); final Connection con = LDAPAuthorizationBackend.getConnection(settings, null); try { - //If following is off then should fail to return the result provided by following - final LdapEntry ref1 = LdapHelper.lookup(con, "cn=Ref1,ou=people,o=TEST", ReturnAttributes.ALL.value(), settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT)); + // If following is off then should fail to return the result provided by following + final LdapEntry ref1 = LdapHelper.lookup( + con, + "cn=Ref1,ou=people,o=TEST", + ReturnAttributes.ALL.value(), + settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT) + ); Assert.assertNull(ref1); } finally { con.close(); @@ -438,20 +463,20 @@ public void testLdapDontFollowReferrals() throws Exception { @Test public void testLdapEscape() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ssign", "ssignsecret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ssign", "ssignsecret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Special\\, Sign,ou=people,o=TEST", user.getName()); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -463,18 +488,18 @@ public void testLdapEscape() throws Exception { @Test public void testLdapAuthorizationRoleSearchUsername() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(cn={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember=cn={1},ou=people,o=TEST)") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("Michael Jackson", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(cn={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember=cn={1},ou=people,o=TEST)") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("Michael Jackson", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -489,15 +514,14 @@ public void testLdapAuthorizationRoleSearchUsername() throws Exception { @Test public void testLdapAuthorizationOnly() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("jacksonm"); @@ -509,19 +533,17 @@ public void testLdapAuthorizationOnly() throws Exception { Assert.assertEquals("ceo", new ArrayList(new TreeSet(user.getRoles())).get(0)); } - - @Test public void testLdapAuthorizationNonDNEntry() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("jacksonm"); @@ -533,20 +555,18 @@ public void testLdapAuthorizationNonDNEntry() throws Exception { Assert.assertEquals("ceo-ceo", new ArrayList(new TreeSet(user.getRoles())).get(0)); } - @Test public void testLdapAuthorizationNested() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("spock"); @@ -561,17 +581,16 @@ public void testLdapAuthorizationNested() throws Exception { @Test public void testLdapAuthorizationNestedFilter() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=nested2,ou=groups,o=TEST") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=nested2,ou=groups,o=TEST") + .build(); final User user = new User("spock"); @@ -587,16 +606,15 @@ public void testLdapAuthorizationNestedFilter() throws Exception { @Test public void testLdapAuthorizationDnNested() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("spock"); @@ -611,17 +629,16 @@ public void testLdapAuthorizationDnNested() throws Exception { @Test public void testLdapAuthorizationDn() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "UID") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "UID") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret".getBytes())); @@ -636,13 +653,16 @@ public void testLdapAuthorizationDn() throws Exception { @Test public void testLdapAuthenticationUserNameAttribute() throws Exception { - - final Settings settings = Settings.builder().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST").put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + final Settings settings = Settings.builder() + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("jacksonm", user.getName()); } @@ -650,17 +670,21 @@ public void testLdapAuthenticationUserNameAttribute() throws Exception { @Test public void testLdapAuthenticationStartTLS() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_START_TLS, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_START_TLS, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -668,19 +692,19 @@ public void testLdapAuthenticationStartTLS() throws Exception { @Test public void testLdapAuthorizationSkipUsers() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "cn=Michael Jackson,ou*people,o=TEST") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "cn=Michael Jackson,ou*people,o=TEST") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -694,17 +718,18 @@ public void testLdapAuthorizationSkipUsers() throws Exception { public void testLdapAuthorizationSkipUsersNoDn() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "jacksonm") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "jacksonm") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -717,18 +742,17 @@ public void testLdapAuthorizationSkipUsersNoDn() throws Exception { @Test public void testLdapAuthorizationNestedAttr() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("spock"); @@ -744,19 +768,18 @@ public void testLdapAuthorizationNestedAttr() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilter() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=rolemo4*") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=rolemo4*") + .build(); final User user = new User("spock"); @@ -773,19 +796,18 @@ public void testLdapAuthorizationNestedAttrFilter() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilterAll() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*") + .build(); final User user = new User("spock"); @@ -800,18 +822,18 @@ public void testLdapAuthorizationNestedAttrFilterAll() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilterAllEqualsNestedFalse() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) //-> same like putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) // -> same like + // putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("spock"); @@ -826,18 +848,17 @@ public void testLdapAuthorizationNestedAttrFilterAllEqualsNestedFalse() throws E @Test public void testLdapAuthorizationNestedAttrNoRoleSearch() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "unused") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(((unused") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, false) - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "unused") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(((unused") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, false) + .build(); final User user = new User("spock"); @@ -854,35 +875,42 @@ public void testLdapAuthorizationNestedAttrNoRoleSearch() throws Exception { public void testCustomAttributes() throws Exception { Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); Assert.assertEquals(user.getCustomAttributesMap().toString(), 16, user.getCustomAttributesMap().size()); - Assert.assertFalse(user.getCustomAttributesMap().toString(), user.getCustomAttributesMap().keySet().contains("attr.ldap.userpassword")); + Assert.assertFalse( + user.getCustomAttributesMap().toString(), + user.getCustomAttributesMap().keySet().contains("attr.ldap.userpassword") + ); settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 0) - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 0) + .build(); - user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertEquals(user.getCustomAttributesMap().toString(), 2, user.getCustomAttributesMap().size()); settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .putList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, "*objectclass*","entryParentId") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .putList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, "*objectclass*", "entryParentId") + .build(); - user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertEquals(user.getCustomAttributesMap().toString(), 2, user.getCustomAttributesMap().size()); @@ -892,16 +920,16 @@ public void testCustomAttributes() throws Exception { public void testLdapAuthorizationNonDNRoles() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description, ou") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description, ou") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("nondnroles"); @@ -914,25 +942,28 @@ public void testLdapAuthorizationNonDNRoles() throws Exception { Assert.assertTrue("Roles do not contain non-LDAP role 'humanresources'", user.getRoles().contains("humanresources")); Assert.assertTrue("Roles do not contain LDAP role 'dummyempty'", user.getRoles().contains("dummyempty")); Assert.assertTrue("Roles do not contain non-LDAP role 'role2'", user.getRoles().contains("role2")); - Assert.assertTrue("Roles do not contain non-LDAP role 'anotherrole' from second role name", user.getRoles().contains("anotherrole")); + Assert.assertTrue( + "Roles do not contain non-LDAP role 'anotherrole' from second role name", + user.getRoles().contains("anotherrole") + ); } - @Test public void testLdapSpecial186() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("spec186", "spec186" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("spec186", "spec186".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST", user.getName()); Assert.assertEquals("AA BB/CC (DD) my, company end=with=whitespace ", user.getUserEntry().getAttribute("cn").getStringValue()); @@ -948,12 +979,18 @@ public void testLdapSpecial186() throws Exception { Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); @@ -963,17 +1000,18 @@ public void testLdapSpecial186() throws Exception { public void testLdapSpecial186_2() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("spec186", "spec186" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("spec186", "spec186".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST", user.getName()); Assert.assertEquals("AA BB/CC (DD) my, company end=with=whitespace ", user.getUserEntry().getAttribute("cn").getStringValue()); @@ -989,13 +1027,18 @@ public void testLdapSpecial186_2() throws Exception { Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); - - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); @@ -1004,13 +1047,14 @@ public void testLdapSpecial186_2() throws Exception { @Test public void testOperationalAttributes() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); LdapAttribute operationAttribute = user.getUserEntry().getAttribute("entryUUID"); Assert.assertNotNull(operationAttribute); @@ -1023,23 +1067,23 @@ public void testOperationalAttributes() throws Exception { public void testMultiCn() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("multi", "multi" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("multi", "multi".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=cabc,ou=people,o=TEST", user.getName()); System.out.println(user.getUserEntry().getAttribute("cn")); } - @AfterClass public static void tearDown() throws Exception { diff --git a/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTestClientCert.java b/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTestClientCert.java index 6f62cd48dd..1765b5fd26 100644 --- a/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTestClientCert.java +++ b/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTestClientCert.java @@ -39,106 +39,124 @@ public class LdapBackendTestClientCert { @Test public void testNoAuth() throws Exception { - //no auth + // no auth final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); LdapUser user; try { - user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail(); } catch (Exception e) { - Assert.assertTrue(ExceptionUtils.getRootCause(e).getMessage(), ExceptionUtils.getRootCause(e).getMessage().contains("authentication required")); + Assert.assertTrue( + ExceptionUtils.getRootCause(e).getMessage(), + ExceptionUtils.getRootCause(e).getMessage().contains("authentication required") + ); } } @Test public void testNoAuthX() throws Exception { - //no auth + // no auth final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, false) - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, false) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); LdapUser user; try { - user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail(); } catch (Exception e) { - Assert.assertTrue(ExceptionUtils.getRootCause(e).getMessage(), ExceptionUtils.getRootCause(e).getMessage().contains("authentication required")); + Assert.assertTrue( + ExceptionUtils.getRootCause(e).getMessage(), + ExceptionUtils.getRootCause(e).getMessage().contains("authentication required") + ); } } @Test public void testNoAuthY() throws Exception { - //no auth + // no auth final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/wrong/truststore.jks") - .put(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, false) - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/wrong/truststore.jks" + ) + .put(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, false) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); LdapUser user; try { - user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail(); } catch (Exception e) { - Assert.assertTrue(ExceptionUtils.getRootCause(e).getMessage(), ExceptionUtils.getRootCause(e).getMessage().contains("Unable to connect to any")); + Assert.assertTrue( + ExceptionUtils.getRootCause(e).getMessage(), + ExceptionUtils.getRootCause(e).getMessage().contains("Unable to connect to any") + ); } } - - - @Test public void testBindDnAuthLocalhost() throws Exception { - //bin dn auth + // bin dn auth final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } @@ -147,21 +165,27 @@ public void testBindDnAuthLocalhost() throws Exception { public void testLdapSslAuth() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put("plugins.security.ssl.transport.keystore_filepath", "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock-keystore.jks") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) - .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "spock") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + "plugins.security.ssl.transport.keystore_filepath", + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock-keystore.jks" + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) + .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "spock") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } @@ -170,24 +194,30 @@ public void testLdapSslAuth() throws Exception { public void testLdapSslAuthPem() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/ca/root-ca.pem") - .put(ConfigConstants.LDAPS_PEMCERT_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock.crtfull.pem") - .put(ConfigConstants.LDAPS_PEMKEY_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock.key.pem") - //.put(ConfigConstants.LDAPS_PEMKEY_PASSWORD, "changeit") - .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - //.put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") - // .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/ca/root-ca.pem" + ) + .put( + ConfigConstants.LDAPS_PEMCERT_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock.crtfull.pem" + ) + .put(ConfigConstants.LDAPS_PEMKEY_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock.key.pem") + // .put(ConfigConstants.LDAPS_PEMKEY_PASSWORD, "changeit") + .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + // .put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") + // .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } @@ -196,59 +226,66 @@ public void testLdapSslAuthPem() throws Exception { public void testLdapSslAuthNo() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put("plugins.security.ssl.transport.keystore_filepath", "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/kirk-keystore.jks") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) - .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "kirk") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + "plugins.security.ssl.transport.keystore_filepath", + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/kirk-keystore.jks" + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) + .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "kirk") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } - public void testLdapAuthenticationSSL() throws Exception { - //startLDAPServer(); + // startLDAPServer(); final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - //.put("plugins.security.ssl.transport.keystore_filepath", "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/cn=ldapbinder,ou=people,dc=example,dc=com-keystore.jks") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - //.put("verify_hostnames", false) - //.put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) - //.put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "cn=ldapbinder,ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - //.put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") - //.put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") - - //.putList(ConfigConstants.LDAPS_ENABLED_SSL_CIPHERS, "TLS_RSA_WITH_AES_128_CBC_SHA") - //.putList(ConfigConstants.LDAPS_ENABLED_SSL_PROTOCOLS, "TLSv1") - //TLS_RSA_AES_128_CBC_SHA1 - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + // .put("plugins.security.ssl.transport.keystore_filepath", + // "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/cn=ldapbinder,ou=people,dc=example,dc=com-keystore.jks") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + // .put("verify_hostnames", false) + // .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) + // .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "cn=ldapbinder,ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + // .put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") + // .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") + + // .putList(ConfigConstants.LDAPS_ENABLED_SSL_CIPHERS, "TLS_RSA_WITH_AES_128_CBC_SHA") + // .putList(ConfigConstants.LDAPS_ENABLED_SSL_PROTOCOLS, "TLSv1") + // TLS_RSA_AES_128_CBC_SHA1 + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } - - public static File getAbsoluteFilePathFromClassPath(final String fileNameFromClasspath) { File file = null; final URL fileUrl = LdapBackendTestClientCert.class.getClassLoader().getResource(fileNameFromClasspath); diff --git a/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTestNewStyleConfig.java b/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTestNewStyleConfig.java index 3e21a223e2..8bc13eec48 100644 --- a/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTestNewStyleConfig.java +++ b/src/test/java/com/amazon/dlic/auth/ldap/LdapBackendTestNewStyleConfig.java @@ -52,7 +52,7 @@ public class LdapBackendTestNewStyleConfig { public static void startLdapServer() throws Exception { ldapServer = new EmbeddedLDAPServer(); ldapServer.start(); - ldapServer.applyLdif("base.ldif","base2.ldif"); + ldapServer.applyLdif("base.ldif", "base2.ldif"); ldapPort = ldapServer.getLdapPort(); ldapsPort = ldapServer.getLdapsPort(); } @@ -61,11 +61,13 @@ public static void startLdapServer() throws Exception { public void testLdapAuthentication() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -74,38 +76,46 @@ public void testLdapAuthentication() throws Exception { public void testLdapAuthenticationFakeLogin() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, true).build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, true) + .build(); - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("unknown", "unknown".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("unknown", "unknown".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapInjection() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); String injectString = "*jack*"; @SuppressWarnings("unused") - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials(injectString, "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials(injectString, "secret".getBytes(StandardCharsets.UTF_8)) + ); } @Test public void testLdapAuthenticationBindDn() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") - .put(ConfigConstants.LDAP_PASSWORD, "spocksecret").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") + .put(ConfigConstants.LDAP_PASSWORD, "spocksecret") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -114,60 +124,75 @@ public void testLdapAuthenticationBindDn() throws Exception { public void testLdapAuthenticationWrongBindDn() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") - .put(ConfigConstants.LDAP_PASSWORD, "wrong").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") + .put(ConfigConstants.LDAP_PASSWORD, "wrong") + .build(); - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationBindFail() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "wrong".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "wrong".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationNoUser() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("UNKNOWN", "UNKNOWN".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("UNKNOWN", "UNKNOWN".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationFail() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8)) + ); } @Test public void testLdapAuthenticationSSL() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -176,14 +201,20 @@ public void testLdapAuthenticationSSL() throws Exception { public void testLdapAuthenticationSSLPEMFile() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").toFile().getName()) - .put("verify_hostnames", false).put("path.home", ".") - .put("path.conf", FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").getParent()).build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, Paths.get("src/test/resources/ldap")) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").toFile().getName() + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .put("path.conf", FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").getParent()) + .build(); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, Paths.get("src/test/resources/ldap")).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -191,18 +222,13 @@ public void testLdapAuthenticationSSLPEMFile() throws Exception { @Test public void testLdapAuthenticationSSLPEMText() throws Exception { - final Settings settingsFromFile = Settings - .builder() - .loadFromPath( - Paths - .get(FileHelper - .getAbsoluteFilePathFromClassPath("ldap/test1.yml") - .toFile() - .getAbsolutePath())) - .build(); - Settings settings = Settings.builder().put(settingsFromFile).putList("hosts", "localhost:"+ldapsPort).build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settingsFromFile = Settings.builder() + .loadFromPath(Paths.get(FileHelper.getAbsoluteFilePathFromClassPath("ldap/test1.yml").toFile().getAbsolutePath())) + .build(); + Settings settings = Settings.builder().put(settingsFromFile).putList("hosts", "localhost:" + ldapsPort).build(); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -211,15 +237,22 @@ public void testLdapAuthenticationSSLPEMText() throws Exception { public void testLdapAuthenticationSSLSSLv3() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_protocols", "SSLv3").put("path.home", ".").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_protocols", "SSLv3") + .put("path.home", ".") + .build(); try { - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); } catch (Exception e) { Assert.assertEquals(e.getCause().getClass(), org.ldaptive.LdapException.class); Assert.assertTrue(e.getCause().getMessage().contains("Unable to connec")); @@ -231,15 +264,22 @@ public void testLdapAuthenticationSSLSSLv3() throws Exception { public void testLdapAuthenticationSSLUnknownCipher() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_ciphers", "AAA").put("path.home", ".").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_ciphers", "AAA") + .put("path.home", ".") + .build(); try { - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); } catch (Exception e) { Assert.assertEquals(e.getCause().getClass(), org.ldaptive.LdapException.class); Assert.assertTrue(e.getCause().getMessage().contains("Unable to connec")); @@ -251,15 +291,22 @@ public void testLdapAuthenticationSSLUnknownCipher() throws Exception { public void testLdapAuthenticationSpecialCipherProtocol() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_protocols", "TLSv1.2") - .putList("enabled_ssl_ciphers", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA").put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_protocols", "TLSv1.2") + .putList("enabled_ssl_ciphers", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); @@ -269,14 +316,20 @@ public void testLdapAuthenticationSpecialCipherProtocol() throws Exception { public void testLdapAuthenticationSSLNoKeystore() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -285,12 +338,15 @@ public void testLdapAuthenticationSSLNoKeystore() throws Exception { public void testLdapAuthenticationSSLFailPlain() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true).build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .build(); try { - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); } catch (final Exception e) { Assert.assertEquals(org.ldaptive.LdapException.class, e.getCause().getClass()); } @@ -300,8 +356,9 @@ public void testLdapAuthenticationSSLFailPlain() throws Exception { public void testLdapExists() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); final LDAPAuthenticationBackend lbe = new LDAPAuthenticationBackend(settings, null); Assert.assertTrue(lbe.exists(new User("jacksonm"))); @@ -312,16 +369,19 @@ public void testLdapExists() throws Exception { public void testLdapAuthorization() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})") - // .put("plugins.security.authentication.authorization.ldap.userrolename", - // "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + // .put("plugins.security.authentication.authorization.ldap.userrolename", + // "(uniqueMember={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -336,8 +396,9 @@ public void testLdapAuthorization() throws Exception { public void testLdapAuthenticationReferral() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); final Connection con = LDAPAuthorizationBackend.getConnection(settings, null); try { @@ -352,17 +413,21 @@ public void testLdapAuthenticationReferral() throws Exception { @Test public void testLdapDontFollowReferrals() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.FOLLOW_REFERRALS, false).build(); - + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.FOLLOW_REFERRALS, false) + .build(); final Connection con = LDAPAuthorizationBackend.getConnection(settings, null); try { - //If following is off then should fail to return the result provided by following - final LdapEntry ref1 = LdapHelper.lookup(con, "cn=Ref1,ou=people,o=TEST", ReturnAttributes.ALL.value(), settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT)); + // If following is off then should fail to return the result provided by following + final LdapEntry ref1 = LdapHelper.lookup( + con, + "cn=Ref1,ou=people,o=TEST", + ReturnAttributes.ALL.value(), + settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT) + ); Assert.assertNull(ref1); } finally { con.close(); @@ -373,15 +438,19 @@ public void testLdapDontFollowReferrals() throws Exception { public void testLdapEscape() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("ssign", "ssignsecret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("ssign", "ssignsecret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Special\\, Sign,ou=people,o=TEST", user.getName()); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -394,13 +463,17 @@ public void testLdapEscape() throws Exception { public void testLdapAuthorizationRoleSearchUsername() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(cn={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember=cn={1},ou=people,o=TEST)").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(cn={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember=cn={1},ou=people,o=TEST)") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("Michael Jackson", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("Michael Jackson", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -416,10 +489,13 @@ public void testLdapAuthorizationRoleSearchUsername() throws Exception { public void testLdapAuthorizationOnly() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + .build(); final User user = new User("jacksonm"); @@ -435,11 +511,14 @@ public void testLdapAuthorizationOnly() throws Exception { public void testLdapAuthorizationNested() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put("roles.g1.search", "(uniqueMember={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .build(); final User user = new User("spock"); @@ -455,12 +534,15 @@ public void testLdapAuthorizationNested() throws Exception { public void testLdapAuthorizationNestedFilter() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put("roles.g1.search", "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=nested2,ou=groups,o=TEST").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=nested2,ou=groups,o=TEST") + .build(); final User user = new User("spock"); @@ -477,11 +559,14 @@ public void testLdapAuthorizationNestedFilter() throws Exception { public void testLdapAuthorizationDnNested() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put("roles.g1.search", "(uniqueMember={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .build(); final User user = new User("spock"); @@ -497,15 +582,17 @@ public void testLdapAuthorizationDnNested() throws Exception { public void testLdapAuthorizationDn() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "UID") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) - .put("roles.g1.search", "(uniqueMember={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "UID") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) + .put("roles.g1.search", "(uniqueMember={0})") + .build(); - final User user = new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes())); + final User user = new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("jacksonm", "secret".getBytes())); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -519,12 +606,15 @@ public void testLdapAuthorizationDn() throws Exception { public void testLdapAuthenticationUserNameAttribute() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.base", "ou=people,o=TEST").put("users.u1.search", "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.base", "ou=people,o=TEST") + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("jacksonm", user.getName()); } @@ -533,14 +623,20 @@ public void testLdapAuthenticationUserNameAttribute() throws Exception { public void testLdapAuthenticationStartTLS() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_START_TLS, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_START_TLS, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -549,14 +645,18 @@ public void testLdapAuthenticationStartTLS() throws Exception { public void testLdapAuthorizationSkipUsers() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "cn=Michael Jackson,ou*people,o=TEST").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "cn=Michael Jackson,ou*people,o=TEST") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -570,13 +670,16 @@ public void testLdapAuthorizationSkipUsers() throws Exception { public void testLdapAuthorizationNestedAttr() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("spock"); @@ -593,14 +696,17 @@ public void testLdapAuthorizationNestedAttr() throws Exception { public void testLdapAuthorizationNestedAttrFilter() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=rolemo4*").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=rolemo4*") + .build(); final User user = new User("spock"); @@ -618,14 +724,17 @@ public void testLdapAuthorizationNestedAttrFilter() throws Exception { public void testLdapAuthorizationNestedAttrFilterAll() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*") + .build(); final User user = new User("spock"); @@ -641,15 +750,18 @@ public void testLdapAuthorizationNestedAttrFilterAll() throws Exception { public void testLdapAuthorizationNestedAttrFilterAllEqualsNestedFalse() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) // -> same like - // putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, - // "*") - .put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) // -> same like + // putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, + // "*") + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("spock"); @@ -665,12 +777,16 @@ public void testLdapAuthorizationNestedAttrFilterAllEqualsNestedFalse() throws E public void testLdapAuthorizationNestedAttrNoRoleSearch() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "unused").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(((unused") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, false).build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "unused") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(((unused") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, false) + .build(); final User user = new User("spock"); @@ -687,33 +803,39 @@ public void testLdapAuthorizationNestedAttrNoRoleSearch() throws Exception { public void testCustomAttributes() throws Exception { Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); Assert.assertEquals(user.getCustomAttributesMap().toString(), 16, user.getCustomAttributesMap().size()); - Assert.assertFalse(user.getCustomAttributesMap().toString(), - user.getCustomAttributesMap().containsKey("attr.ldap.userpassword")); + Assert.assertFalse(user.getCustomAttributesMap().toString(), user.getCustomAttributesMap().containsKey("attr.ldap.userpassword")); settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 0).build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 0) + .build(); - user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertEquals(user.getCustomAttributesMap().toString(), 2, user.getCustomAttributesMap().size()); settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})") - .putList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, "*objectclass*", "entryParentId").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .putList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, "*objectclass*", "entryParentId") + .build(); - user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertEquals(user.getCustomAttributesMap().toString(), 2, user.getCustomAttributesMap().size()); @@ -723,13 +845,16 @@ public void testCustomAttributes() throws Exception { public void testLdapAuthorizationNonDNRoles() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description, ou") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description, ou") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("nondnroles"); @@ -739,24 +864,29 @@ public void testLdapAuthorizationNonDNRoles() throws Exception { Assert.assertEquals("nondnroles", user.getName()); Assert.assertEquals(5, user.getRoles().size()); Assert.assertTrue("Roles do not contain non-LDAP role 'kibanauser'", user.getRoles().contains("kibanauser")); - Assert.assertTrue("Roles do not contain non-LDAP role 'humanresources'", - user.getRoles().contains("humanresources")); + Assert.assertTrue("Roles do not contain non-LDAP role 'humanresources'", user.getRoles().contains("humanresources")); Assert.assertTrue("Roles do not contain LDAP role 'dummyempty'", user.getRoles().contains("dummyempty")); Assert.assertTrue("Roles do not contain non-LDAP role 'role2'", user.getRoles().contains("role2")); - Assert.assertTrue("Roles do not contain non-LDAP role 'anotherrole' from second role name", - user.getRoles().contains("anotherrole")); + Assert.assertTrue( + "Roles do not contain non-LDAP role 'anotherrole' from second role name", + user.getRoles().contains("anotherrole") + ); } @Test public void testChainedLdapAuthentication1() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("users.u2.search", "(uid={0})").put("users.u2.base", "ou=people2,o=TEST").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("users.u2.search", "(uid={0})") + .put("users.u2.base", "ou=people2,o=TEST") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -765,12 +895,16 @@ public void testChainedLdapAuthentication1() throws Exception { public void testChainedLdapAuthentication2() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("users.u2.search", "(uid={0})").put("users.u2.base", "ou=people2,o=TEST").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("users.u2.search", "(uid={0})") + .put("users.u2.base", "ou=people2,o=TEST") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("presleye", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("presleye", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Elvis Presley,ou=people2,o=TEST", user.getName()); } @@ -779,13 +913,17 @@ public void testChainedLdapAuthentication2() throws Exception { public void testChainedLdapAuthenticationDuplicate() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_SEARCH_ALL_BASES, true).put("users.u1.search", "(uid={0})") - .put("users.u1.base", "ou=people,o=TEST").put("users.u2.search", "(uid={0})") - .put("users.u2.base", "ou=people2,o=TEST").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_SEARCH_ALL_BASES, true) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("users.u2.search", "(uid={0})") + .put("users.u2.base", "ou=people2,o=TEST") + .build(); - new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); // Fails with OpenSearchSecurityException because two possible instances are // found @@ -795,9 +933,11 @@ public void testChainedLdapAuthenticationDuplicate() throws Exception { public void testChainedLdapExists() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u2.search", "(uid={0})") - .put("users.u2.base", "ou=people2,o=TEST").build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u2.search", "(uid={0})") + .put("users.u2.base", "ou=people2,o=TEST") + .build(); final LDAPAuthenticationBackend lbe = new LDAPAuthenticationBackend(settings, null); Assert.assertTrue(lbe.exists(new User("jacksonm"))); @@ -809,17 +949,19 @@ public void testChainedLdapExists() throws Exception { public void testChainedLdapAuthorization() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.base", "ou=groups,o=TEST") - .put("roles.g1.search", "(uniqueMember={0})") - .put("roles.g2.base", "ou=groups2,o=TEST") - .put("roles.g2.search", "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.base", "ou=groups,o=TEST") + .put("roles.g1.search", "(uniqueMember={0})") + .put("roles.g2.base", "ou=groups2,o=TEST") + .put("roles.g2.search", "(uniqueMember={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -838,17 +980,19 @@ public void testChainedLdapAuthorization() throws Exception { public void testCrossChainedLdapAuthorization() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people2,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.base", "ou=groups,o=TEST") - .put("roles.g1.search", "(uniqueMember={0})") - .put("roles.g2.base", "ou=groups2,o=TEST") - .put("roles.g2.search", "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people2,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.base", "ou=groups,o=TEST") + .put("roles.g1.search", "(uniqueMember={0})") + .put("roles.g2.base", "ou=groups2,o=TEST") + .put("roles.g2.search", "(uniqueMember={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null) - .authenticate(new AuthCredentials("mercuryf", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("mercuryf", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); diff --git a/src/test/java/com/amazon/dlic/auth/ldap/UtilsTest.java b/src/test/java/com/amazon/dlic/auth/ldap/UtilsTest.java index cbfa40f850..ce22bf6036 100644 --- a/src/test/java/com/amazon/dlic/auth/ldap/UtilsTest.java +++ b/src/test/java/com/amazon/dlic/auth/ldap/UtilsTest.java @@ -19,39 +19,38 @@ public class UtilsTest { - @Test public void testLDAPName() throws Exception { - //same ldapname - Assert.assertEquals(new LdapName("CN=1,OU=2,O=3,C=4"),new LdapName("CN=1,OU=2,O=3,C=4")); + // same ldapname + Assert.assertEquals(new LdapName("CN=1,OU=2,O=3,C=4"), new LdapName("CN=1,OU=2,O=3,C=4")); - //case differ - Assert.assertEquals(new LdapName("CN=1,OU=2,O=3,C=4".toLowerCase()),new LdapName("CN=1,OU=2,O=3,C=4".toUpperCase())); + // case differ + Assert.assertEquals(new LdapName("CN=1,OU=2,O=3,C=4".toLowerCase()), new LdapName("CN=1,OU=2,O=3,C=4".toUpperCase())); - //case differ - Assert.assertEquals(new LdapName("CN=abc,OU=xyz,O=3,C=4".toLowerCase()),new LdapName("CN=abc,OU=xyz,O=3,C=4".toUpperCase())); + // case differ + Assert.assertEquals(new LdapName("CN=abc,OU=xyz,O=3,C=4".toLowerCase()), new LdapName("CN=abc,OU=xyz,O=3,C=4".toUpperCase())); - //same ldapname - Assert.assertEquals(new LdapName("CN=a,OU=2,O=3,C=xxx"),new LdapName("CN=A,OU=2,O=3,C=XxX")); + // same ldapname + Assert.assertEquals(new LdapName("CN=a,OU=2,O=3,C=xxx"), new LdapName("CN=A,OU=2,O=3,C=XxX")); - //case differ and spaces - Assert.assertEquals(new LdapName("Cn =1 ,OU=2, O = 3,C=4"),new LdapName("CN= 1,Ou=2,O=3,c=4")); + // case differ and spaces + Assert.assertEquals(new LdapName("Cn =1 ,OU=2, O = 3,C=4"), new LdapName("CN= 1,Ou=2,O=3,c=4")); - //same components, different order - Assert.assertNotEquals(new LdapName("CN=1,OU=2,C=4,O=3"),new LdapName("CN=1,OU=2,O=3,C=4")); + // same components, different order + Assert.assertNotEquals(new LdapName("CN=1,OU=2,C=4,O=3"), new LdapName("CN=1,OU=2,O=3,C=4")); - //last component missing - Assert.assertNotEquals(new LdapName("CN=1,OU=2,O=3"),new LdapName("CN=1,OU=2,O=3,C=4")); + // last component missing + Assert.assertNotEquals(new LdapName("CN=1,OU=2,O=3"), new LdapName("CN=1,OU=2,O=3,C=4")); - //first component missing - Assert.assertNotEquals(new LdapName("OU=2,O=3,C=4"),new LdapName("CN=1,OU=2,O=3,C=4")); + // first component missing + Assert.assertNotEquals(new LdapName("OU=2,O=3,C=4"), new LdapName("CN=1,OU=2,O=3,C=4")); - //parse exception + // parse exception try { new LdapName("OU2,O=3,C=4"); Assert.fail(); } catch (InvalidNameException e) { - //expected + // expected } } } diff --git a/src/test/java/com/amazon/dlic/auth/ldap/srv/EmbeddedLDAPServer.java b/src/test/java/com/amazon/dlic/auth/ldap/srv/EmbeddedLDAPServer.java index 2dd3fc8284..b56f432e6e 100755 --- a/src/test/java/com/amazon/dlic/auth/ldap/srv/EmbeddedLDAPServer.java +++ b/src/test/java/com/amazon/dlic/auth/ldap/srv/EmbeddedLDAPServer.java @@ -11,7 +11,6 @@ package com.amazon.dlic.auth.ldap.srv; - public class EmbeddedLDAPServer { LdapServer s = new LdapServer(); diff --git a/src/test/java/com/amazon/dlic/auth/ldap/srv/LdapServer.java b/src/test/java/com/amazon/dlic/auth/ldap/srv/LdapServer.java index 3ce93e8761..bb7738d3fd 100644 --- a/src/test/java/com/amazon/dlic/auth/ldap/srv/LdapServer.java +++ b/src/test/java/com/amazon/dlic/auth/ldap/srv/LdapServer.java @@ -49,11 +49,13 @@ final class LdapServer { private static final int LOCK_TIMEOUT = 60; private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; - private static final String LOCK_TIMEOUT_MSG = "Unable to obtain lock due to timeout after " + LOCK_TIMEOUT + " " + TIME_UNIT.toString(); + private static final String LOCK_TIMEOUT_MSG = "Unable to obtain lock due to timeout after " + + LOCK_TIMEOUT + + " " + + TIME_UNIT.toString(); private static final String SERVER_NOT_STARTED = "The LDAP server is not started."; private static final String SERVER_ALREADY_STARTED = "The LDAP server is already started."; - private InMemoryDirectoryServer server; private final AtomicBoolean isStarted = new AtomicBoolean(Boolean.FALSE); private final ReentrantLock serverStateLock = new ReentrantLock(); @@ -61,9 +63,7 @@ final class LdapServer { private int ldapPort = -1; private int ldapsPort = -1; - - public LdapServer() { - } + public LdapServer() {} public boolean isStarted() { return this.isStarted.get(); @@ -77,7 +77,7 @@ public int getLdapsPort() { return ldapsPort; } - public int start(String... ldifFiles) throws Exception { + public int start(String... ldifFiles) throws Exception { boolean hasLock = false; try { hasLock = serverStateLock.tryLock(LdapServer.LOCK_TIMEOUT, LdapServer.TIME_UNIT); @@ -89,7 +89,7 @@ public int start(String... ldifFiles) throws Exception { throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); } } catch (InterruptedException ioe) { - //lock interrupted + // lock interrupted LOG.error(ioe.getMessage(), ioe); } finally { if (hasLock) { @@ -112,8 +112,10 @@ private Collection getInMemoryListenerConfigs() throws E String serverKeyStorePath = FileHelper.getAbsoluteFilePathFromClassPath("ldap/node-0-keystore.jks").toFile().getAbsolutePath(); final SSLUtil serverSSLUtil = new SSLUtil( - new KeyStoreKeyManager(serverKeyStorePath, "changeit".toCharArray()), new TrustStoreTrustManager(serverKeyStorePath)); - //final SSLUtil clientSSLUtil = new SSLUtil(new TrustStoreTrustManager(serverKeyStorePath)); + new KeyStoreKeyManager(serverKeyStorePath, "changeit".toCharArray()), + new TrustStoreTrustManager(serverKeyStorePath) + ); + // final SSLUtil clientSSLUtil = new SSLUtil(new TrustStoreTrustManager(serverKeyStorePath)); ldapPort = SocketUtils.findAvailableTcpPort(); ldapsPort = SocketUtils.findAvailableTcpPort(); @@ -127,11 +129,10 @@ private Collection getInMemoryListenerConfigs() throws E private final String loadFile(final String file) throws IOException { String ldif; - try (final Reader reader = new InputStreamReader(this.getClass().getResourceAsStream("/ldap/" + file),StandardCharsets.UTF_8)) { + try (final Reader reader = new InputStreamReader(this.getClass().getResourceAsStream("/ldap/" + file), StandardCharsets.UTF_8)) { ldif = CharStreams.toString(reader); } - ldif = ldif.replace("${hostname}", "localhost"); ldif = ldif.replace("${port}", String.valueOf(ldapPort)); return ldif; @@ -146,14 +147,14 @@ private synchronized int configureAndStartServer(String... ldifFiles) throws Exc final String rootObjectDN = "o=TEST"; InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(new DN(rootObjectDN)); - config.setSchema(schema); //schema can be set on the rootDN too, per javadoc. + config.setSchema(schema); // schema can be set on the rootDN too, per javadoc. config.setListenerConfigs(listenerConfigs); config.setEnforceAttributeSyntaxCompliance(false); config.setEnforceSingleStructuralObjectClass(false); - //config.setLDAPDebugLogHandler(DEBUG_HANDLER); - //config.setAccessLogHandler(DEBUG_HANDLER); - //config.addAdditionalBindCredentials(configuration.getBindDn(), configuration.getPassword()); + // config.setLDAPDebugLogHandler(DEBUG_HANDLER); + // config.setAccessLogHandler(DEBUG_HANDLER); + // config.addAdditionalBindCredentials(configuration.getBindDn(), configuration.getPassword()); server = new InMemoryDirectoryServer(config); @@ -185,7 +186,7 @@ public void stop() { throw new IllegalStateException(LdapServer.LOCK_TIMEOUT_MSG); } } catch (InterruptedException ioe) { - //lock interrupted + // lock interrupted LOG.debug(ExceptionUtils.getStackTrace(ioe)); } finally { if (hasLock) { @@ -198,13 +199,13 @@ private int loadLdifFiles(String... ldifFiles) throws Exception { int ldifLoadCount = 0; for (String ldif : ldifFiles) { ldifLoadCount++; - try (LDIFReader r = new LDIFReader(new BufferedReader(new StringReader(loadFile(ldif))))){ + try (LDIFReader r = new LDIFReader(new BufferedReader(new StringReader(loadFile(ldif))))) { Entry entry = null; while ((entry = r.readEntry()) != null) { server.add(entry); ldifLoadCount++; } - } catch(Exception e) { + } catch (Exception e) { LOG.error(e.toString(), e); throw e; } diff --git a/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendIntegTest2.java b/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendIntegTest2.java index 0ce9d0c857..e88491e994 100644 --- a/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendIntegTest2.java +++ b/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendIntegTest2.java @@ -74,13 +74,19 @@ public void testAttributesWithImpersonation() throws Exception { String securityConfigAsYamlString = FileHelper.loadFile("ldap/config_ldap2.yml"); securityConfigAsYamlString = securityConfigAsYamlString.replace("${ldapsPort}", String.valueOf(ldapsPort)); final Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".cn=Captain Spock,ou=people,o=TEST", "*") - .build(); + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".cn=Captain Spock,ou=people,o=TEST", "*") + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setConfigAsYamlString(securityConfigAsYamlString), settings); final RestHelper rh = nonSslRestHelper(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as", "jacksonm") - ,encodeBasicHeader("spock", "spocksecret"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "jacksonm"), + encodeBasicHeader("spock", "spocksecret") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("ldap.dn")); Assert.assertTrue(res.getBody().contains("attr.ldap.entryDN")); @@ -88,7 +94,6 @@ public void testAttributesWithImpersonation() throws Exception { } - @AfterClass public static void tearDownLdap() throws Exception { diff --git a/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestClientCert2.java b/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestClientCert2.java index ac8aca7d15..6ba7a84b4a 100644 --- a/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestClientCert2.java +++ b/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestClientCert2.java @@ -39,109 +39,127 @@ public class LdapBackendTestClientCert2 { @Test public void testNoAuth() throws Exception { - //no auth + // no auth final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); @SuppressWarnings("unused") LdapUser user; try { - user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail(); } catch (Exception e) { - Assert.assertTrue(ExceptionUtils.getRootCause(e).getMessage(), ExceptionUtils.getRootCause(e).getMessage().contains("authentication required")); + Assert.assertTrue( + ExceptionUtils.getRootCause(e).getMessage(), + ExceptionUtils.getRootCause(e).getMessage().contains("authentication required") + ); } } @Test public void testNoAuthX() throws Exception { - //no auth + // no auth final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, false) - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, false) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); @SuppressWarnings("unused") LdapUser user; try { - user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail(); } catch (Exception e) { - Assert.assertTrue(ExceptionUtils.getRootCause(e).getMessage(), ExceptionUtils.getRootCause(e).getMessage().contains("authentication required")); + Assert.assertTrue( + ExceptionUtils.getRootCause(e).getMessage(), + ExceptionUtils.getRootCause(e).getMessage().contains("authentication required") + ); } } @Test public void testNoAuthY() throws Exception { - //no auth + // no auth final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/wrong/truststore.jks") - .put(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, false) - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/wrong/truststore.jks" + ) + .put(ConfigConstants.LDAPS_VERIFY_HOSTNAMES, false) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); @SuppressWarnings("unused") LdapUser user; try { - user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail(); } catch (Exception e) { - Assert.assertTrue(ExceptionUtils.getRootCause(e).getMessage(), ExceptionUtils.getRootCause(e).getMessage().contains("Unable to connect to any")); + Assert.assertTrue( + ExceptionUtils.getRootCause(e).getMessage(), + ExceptionUtils.getRootCause(e).getMessage().contains("Unable to connect to any") + ); } } - - - @Test public void testBindDnAuthLocalhost() throws Exception { - //bin dn auth + // bin dn auth final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } @@ -150,21 +168,27 @@ public void testBindDnAuthLocalhost() throws Exception { public void testLdapSslAuth() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put("plugins.security.ssl.transport.keystore_filepath", "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock-keystore.jks") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) - .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "spock") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + "plugins.security.ssl.transport.keystore_filepath", + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock-keystore.jks" + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) + .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "spock") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } @@ -173,24 +197,30 @@ public void testLdapSslAuth() throws Exception { public void testLdapSslAuthPem() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/ca/root-ca.pem") - .put(ConfigConstants.LDAPS_PEMCERT_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock.crtfull.pem") - .put(ConfigConstants.LDAPS_PEMKEY_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock.key.pem") - //.put(ConfigConstants.LDAPS_PEMKEY_PASSWORD, "changeit") - .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - //.put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") - // .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/ca/root-ca.pem" + ) + .put( + ConfigConstants.LDAPS_PEMCERT_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock.crtfull.pem" + ) + .put(ConfigConstants.LDAPS_PEMKEY_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/spock.key.pem") + // .put(ConfigConstants.LDAPS_PEMKEY_PASSWORD, "changeit") + .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + // .put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") + // .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } @@ -199,59 +229,66 @@ public void testLdapSslAuthPem() throws Exception { public void testLdapSslAuthNo() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put("plugins.security.ssl.transport.keystore_filepath", "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/kirk-keystore.jks") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) - .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "kirk") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + "plugins.security.ssl.transport.keystore_filepath", + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/kirk-keystore.jks" + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) + .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "kirk") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } - public void testLdapAuthenticationSSL() throws Exception { - //startLDAPServer(); + // startLDAPServer(); final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_SSL, true) - //.put("plugins.security.ssl.transport.keystore_filepath", "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/cn=ldapbinder,ou=people,dc=example,dc=com-keystore.jks") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks") - //.put("verify_hostnames", false) - //.put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) - //.put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "cn=ldapbinder,ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") - //.put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") - //.put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") - - //.putList(ConfigConstants.LDAPS_ENABLED_SSL_CIPHERS, "TLS_RSA_WITH_AES_128_CBC_SHA") - //.putList(ConfigConstants.LDAPS_ENABLED_SSL_PROTOCOLS, "TLSv1") - //TLS_RSA_AES_128_CBC_SHA1 - .put("path.home",".") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("ldap_hr_employee" - , "ldap_hr_employee" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "kdc.dummy.com:636") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + // .put("plugins.security.ssl.transport.keystore_filepath", + // "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/cn=ldapbinder,ou=people,dc=example,dc=com-keystore.jks") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + "/Users/temp/opendistro_security_integration_tests/ldap/ssl-root-ca/truststore.jks" + ) + // .put("verify_hostnames", false) + // .put(ConfigConstants.LDAPS_ENABLE_SSL_CLIENT_AUTH, true) + // .put(ConfigConstants.LDAPS_JKS_CERT_ALIAS, "cn=ldapbinder,ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,dc=example,dc=com") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + // .put(ConfigConstants.LDAP_BIND_DN, "cn=ldapbinder,ou=people,dc=example,dc=com") + // .put(ConfigConstants.LDAP_PASSWORD, "ldapbinder") + + // .putList(ConfigConstants.LDAPS_ENABLED_SSL_CIPHERS, "TLS_RSA_WITH_AES_128_CBC_SHA") + // .putList(ConfigConstants.LDAPS_ENABLED_SSL_PROTOCOLS, "TLSv1") + // TLS_RSA_AES_128_CBC_SHA1 + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ldap_hr_employee", "ldap_hr_employee".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("ldap_hr_employee", user.getName()); } - - public static File getAbsoluteFilePathFromClassPath(final String fileNameFromClasspath) { File file = null; final URL fileUrl = LdapBackendTestClientCert2.class.getClassLoader().getResource(fileNameFromClasspath); diff --git a/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestNewStyleConfig2.java b/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestNewStyleConfig2.java index dfa3296a25..a53e73772d 100644 --- a/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestNewStyleConfig2.java +++ b/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestNewStyleConfig2.java @@ -62,7 +62,7 @@ public class LdapBackendTestNewStyleConfig2 { public static void startLdapServer() throws Exception { ldapServer = new EmbeddedLDAPServer(); ldapServer.start(); - ldapServer.applyLdif("base.ldif","base2.ldif"); + ldapServer.applyLdif("base.ldif", "base2.ldif"); ldapPort = ldapServer.getLdapPort(); ldapsPort = ldapServer.getLdapsPort(); } @@ -86,12 +86,13 @@ protected Settings.Builder createBaseSettings() { @Test public void testLdapAuthentication() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -99,39 +100,44 @@ public void testLdapAuthentication() throws Exception { @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationFakeLogin() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, true) + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("unknown", "unknown".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("unknown", "unknown".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapInjection() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); String injectString = "*jack*"; @SuppressWarnings("unused") - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials(injectString, "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials(injectString, "secret".getBytes(StandardCharsets.UTF_8)) + ); } @Test public void testLdapAuthenticationBindDn() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") - .put(ConfigConstants.LDAP_PASSWORD, "spocksecret").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") + .put(ConfigConstants.LDAP_PASSWORD, "spocksecret") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -140,14 +146,16 @@ public void testLdapAuthenticationBindDn() throws Exception { public void testLdapAuthenticationWrongBindDn() throws Exception { try { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") - .put(ConfigConstants.LDAP_PASSWORD, "wrong").build(); - - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") + .put(ConfigConstants.LDAP_PASSWORD, "wrong") + .build(); + + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail("Expected exception"); } catch (Exception e) { Assert.assertTrue(ExceptionUtils.getStackTrace(e), ExceptionUtils.getStackTrace(e).contains("password was incorrect")); @@ -157,48 +165,56 @@ public void testLdapAuthenticationWrongBindDn() throws Exception { @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationBindFail() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "wrong".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "wrong".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationNoUser() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("UNKNOWN", "UNKNOWN".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("UNKNOWN", "UNKNOWN".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationFail() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8)) + ); } @Test public void testLdapAuthenticationSSL() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -206,15 +222,20 @@ public void testLdapAuthenticationSSL() throws Exception { @Test public void testLdapAuthenticationSSLPEMFile() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").toFile().getName()) - .put("verify_hostnames", false).put("path.home", ".") - .put("path.conf", FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").getParent()).build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, Paths.get("src/test/resources/ldap")) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").toFile().getName() + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .put("path.conf", FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").getParent()) + .build(); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, Paths.get("src/test/resources/ldap")).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -222,18 +243,13 @@ public void testLdapAuthenticationSSLPEMFile() throws Exception { @Test public void testLdapAuthenticationSSLPEMText() throws Exception { - final Settings settingsFromFile = Settings - .builder() - .loadFromPath( - Paths - .get(FileHelper - .getAbsoluteFilePathFromClassPath("ldap/test1.yml") - .toFile() - .getAbsolutePath())) - .build(); - Settings settings = Settings.builder().put(settingsFromFile).putList("hosts", "localhost:"+ldapsPort).build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settingsFromFile = Settings.builder() + .loadFromPath(Paths.get(FileHelper.getAbsoluteFilePathFromClassPath("ldap/test1.yml").toFile().getAbsolutePath())) + .build(); + Settings settings = Settings.builder().put(settingsFromFile).putList("hosts", "localhost:" + ldapsPort).build(); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -241,16 +257,22 @@ public void testLdapAuthenticationSSLPEMText() throws Exception { @Test public void testLdapAuthenticationSSLSSLv3() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_protocols", "SSLv3").put("path.home", ".").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_protocols", "SSLv3") + .put("path.home", ".") + .build(); try { - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail("Expected Exception"); } catch (Exception e) { Assert.assertEquals(org.ldaptive.provider.ConnectionException.class, e.getCause().getClass()); @@ -262,20 +284,29 @@ public void testLdapAuthenticationSSLSSLv3() throws Exception { @Test public void testLdapAuthenticationSSLUnknownCipher() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_ciphers", "AAA").put("path.home", ".").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_ciphers", "AAA") + .put("path.home", ".") + .build(); try { - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail("Expected Exception"); } catch (Exception e) { Assert.assertEquals(org.ldaptive.provider.ConnectionException.class, e.getCause().getClass()); - Assert.assertTrue(ExceptionUtils.getStackTrace(e), WildcardMatcher.from("*unsupported*ciphersuite*aaa*").test(ExceptionUtils.getStackTrace(e).toLowerCase())); + Assert.assertTrue( + ExceptionUtils.getStackTrace(e), + WildcardMatcher.from("*unsupported*ciphersuite*aaa*").test(ExceptionUtils.getStackTrace(e).toLowerCase()) + ); } } @@ -283,16 +314,22 @@ public void testLdapAuthenticationSSLUnknownCipher() throws Exception { @Test public void testLdapAuthenticationSpecialCipherProtocol() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_protocols", "TLSv1.2") - .putList("enabled_ssl_ciphers", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA").put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_protocols", "TLSv1.2") + .putList("enabled_ssl_ciphers", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); @@ -301,15 +338,20 @@ public void testLdapAuthenticationSpecialCipherProtocol() throws Exception { @Test public void testLdapAuthenticationSSLNoKeystore() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -317,13 +359,15 @@ public void testLdapAuthenticationSSLNoKeystore() throws Exception { @Test public void testLdapAuthenticationSSLFailPlain() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .build(); try { - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail("Expected exception"); } catch (final Exception e) { Assert.assertEquals(IllegalStateException.class, e.getCause().getClass()); @@ -333,9 +377,9 @@ public void testLdapAuthenticationSSLFailPlain() throws Exception { @Test public void testLdapExists() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); final LDAPAuthenticationBackend2 lbe = new LDAPAuthenticationBackend2(settings, null); Assert.assertTrue(lbe.exists(new User("jacksonm"))); @@ -345,17 +389,19 @@ public void testLdapExists() throws Exception { @Test public void testLdapAuthorization() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})") - // .put("plugins.security.authentication.authorization.ldap.userrolename", - // "(uniqueMember={0})") - .build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + // .put("plugins.security.authentication.authorization.ldap.userrolename", + // "(uniqueMember={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -369,16 +415,18 @@ public void testLdapAuthorization() throws Exception { @Test public void testLdapAuthorizationReturnAttributes() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, "mail", "cn", "uid") - .build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_RETURN_ATTRIBUTES, "mail", "cn", "uid") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend2(settings, null).fillRoles(user, null); @@ -394,12 +442,11 @@ public void testLdapAuthorizationReturnAttributes() throws Exception { @Test public void testLdapAuthenticationReferral() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - final Connection con = new LDAPConnectionFactoryFactory(settings, null).createBasicConnectionFactory() - .getConnection(); + final Connection con = new LDAPConnectionFactoryFactory(settings, null).createBasicConnectionFactory().getConnection(); try { con.open(); final LdapEntry ref1 = LdapHelper.lookup(con, "cn=Ref1,ou=people,o=TEST", ReturnAttributes.ALL.value(), true); @@ -413,17 +460,21 @@ public void testLdapAuthenticationReferral() throws Exception { @Test public void testLdapDontFollowReferrals() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.FOLLOW_REFERRALS, false).build(); - + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.FOLLOW_REFERRALS, false) + .build(); final Connection con = LDAPAuthorizationBackend.getConnection(settings, null); try { - //If following is off then should fail to return the result provided by following - final LdapEntry ref1 = LdapHelper.lookup(con, "cn=Ref1,ou=people,o=TEST", ReturnAttributes.ALL.value(), settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT)); + // If following is off then should fail to return the result provided by following + final LdapEntry ref1 = LdapHelper.lookup( + con, + "cn=Ref1,ou=people,o=TEST", + ReturnAttributes.ALL.value(), + settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT) + ); Assert.assertNull(ref1); } finally { con.close(); @@ -433,16 +484,19 @@ public void testLdapDontFollowReferrals() throws Exception { @Test public void testLdapEscape() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("ssign", "ssignsecret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ssign", "ssignsecret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Special\\, Sign,ou=people,o=TEST", user.getName()); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -454,14 +508,17 @@ public void testLdapEscape() throws Exception { @Test public void testLdapAuthorizationRoleSearchUsername() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(cn={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember=cn={1},ou=people,o=TEST)").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(cn={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember=cn={1},ou=people,o=TEST)") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("Michael Jackson", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("Michael Jackson", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -476,11 +533,13 @@ public void testLdapAuthorizationRoleSearchUsername() throws Exception { @Test public void testLdapAuthorizationOnly() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + .build(); final User user = new User("jacksonm"); @@ -495,12 +554,14 @@ public void testLdapAuthorizationOnly() throws Exception { @Test public void testLdapAuthorizationNested() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(uniqueMember={0})") - .build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .build(); final User user = new User("spock"); @@ -515,12 +576,15 @@ public void testLdapAuthorizationNested() throws Exception { @Test public void testLdapAuthorizationNestedFilter() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=nested2,ou=groups,o=TEST").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=nested2,ou=groups,o=TEST") + .build(); final User user = new User("spock"); @@ -536,12 +600,14 @@ public void testLdapAuthorizationNestedFilter() throws Exception { @Test public void testLdapAuthorizationDnNested() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(uniqueMember={0})") - .build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .build(); final User user = new User("spock"); @@ -556,16 +622,17 @@ public void testLdapAuthorizationDnNested() throws Exception { @Test public void testLdapAuthorizationDn() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "UID") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) - .put("roles.g1.search", "(uniqueMember={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "UID") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) + .put("roles.g1.search", "(uniqueMember={0})") + .build(); - final User user = new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes())); + final User user = new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("jacksonm", "secret".getBytes())); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -578,13 +645,15 @@ public void testLdapAuthorizationDn() throws Exception { @Test public void testLdapAuthenticationUserNameAttribute() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.base", "ou=people,o=TEST").put("users.u1.search", "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.base", "ou=people,o=TEST") + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("jacksonm", user.getName()); } @@ -592,15 +661,20 @@ public void testLdapAuthenticationUserNameAttribute() throws Exception { @Test public void testLdapAuthenticationStartTLS() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_START_TLS, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_START_TLS, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -608,15 +682,18 @@ public void testLdapAuthenticationStartTLS() throws Exception { @Test public void testLdapAuthorizationSkipUsers() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put("roles.g1.search", "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "cn=Michael Jackson,ou*people,o=TEST").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.search", "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "cn=Michael Jackson,ou*people,o=TEST") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -629,13 +706,16 @@ public void testLdapAuthorizationSkipUsers() throws Exception { @Test public void testLdapAuthorizationNestedAttr() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("spock"); @@ -651,14 +731,17 @@ public void testLdapAuthorizationNestedAttr() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilter() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=rolemo4*").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=rolemo4*") + .build(); final User user = new User("spock"); @@ -675,14 +758,17 @@ public void testLdapAuthorizationNestedAttrFilter() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilterAll() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*") + .build(); final User user = new User("spock"); @@ -697,16 +783,18 @@ public void testLdapAuthorizationNestedAttrFilterAll() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilterAllEqualsNestedFalse() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) // -> same like - // putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, - // "*") - .put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) // -> same like + // putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, + // "*") + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("spock"); @@ -721,13 +809,16 @@ public void testLdapAuthorizationNestedAttrFilterAllEqualsNestedFalse() throws E @Test public void testLdapAuthorizationNestedAttrNoRoleSearch() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "unused").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(((unused") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, false).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "unused") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(((unused") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, false) + .build(); final User user = new User("spock"); @@ -743,34 +834,40 @@ public void testLdapAuthorizationNestedAttrNoRoleSearch() throws Exception { @Test public void testCustomAttributes() throws Exception { - Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").build(); + Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .build(); - LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); Assert.assertEquals(user.getCustomAttributesMap().toString(), 16, user.getCustomAttributesMap().size()); - Assert.assertFalse(user.getCustomAttributesMap().toString(), - user.getCustomAttributesMap().keySet().contains("attr.ldap.userpassword")); + Assert.assertFalse( + user.getCustomAttributesMap().toString(), + user.getCustomAttributesMap().keySet().contains("attr.ldap.userpassword") + ); - settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 0).build(); + settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 0) + .build(); - user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertEquals(user.getCustomAttributesMap().toString(), 2, user.getCustomAttributesMap().size()); - settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})") - .putList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, "*objectclass*", "entryParentId").build(); + settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .putList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, "*objectclass*", "entryParentId") + .build(); - user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertEquals(user.getCustomAttributesMap().toString(), 2, user.getCustomAttributesMap().size()); @@ -779,13 +876,16 @@ public void testCustomAttributes() throws Exception { @Test public void testLdapAuthorizationNonDNRoles() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("roles.g1.base", "ou=groups,o=TEST").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).put("roles.g1.search", "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description, ou") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("roles.g1.base", "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put("roles.g1.search", "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description, ou") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("nondnroles"); @@ -795,24 +895,28 @@ public void testLdapAuthorizationNonDNRoles() throws Exception { Assert.assertEquals("nondnroles", user.getName()); Assert.assertEquals(5, user.getRoles().size()); Assert.assertTrue("Roles do not contain non-LDAP role 'kibanauser'", user.getRoles().contains("kibanauser")); - Assert.assertTrue("Roles do not contain non-LDAP role 'humanresources'", - user.getRoles().contains("humanresources")); + Assert.assertTrue("Roles do not contain non-LDAP role 'humanresources'", user.getRoles().contains("humanresources")); Assert.assertTrue("Roles do not contain LDAP role 'dummyempty'", user.getRoles().contains("dummyempty")); Assert.assertTrue("Roles do not contain non-LDAP role 'role2'", user.getRoles().contains("role2")); - Assert.assertTrue("Roles do not contain non-LDAP role 'anotherrole' from second role name", - user.getRoles().contains("anotherrole")); + Assert.assertTrue( + "Roles do not contain non-LDAP role 'anotherrole' from second role name", + user.getRoles().contains("anotherrole") + ); } @Test public void testChainedLdapAuthentication1() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("users.u2.search", "(uid={0})").put("users.u2.base", "ou=people2,o=TEST").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("users.u2.search", "(uid={0})") + .put("users.u2.base", "ou=people2,o=TEST") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -820,13 +924,16 @@ public void testChainedLdapAuthentication1() throws Exception { @Test public void testChainedLdapAuthentication2() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put("users.u2.search", "(uid={0})").put("users.u2.base", "ou=people2,o=TEST").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("users.u2.search", "(uid={0})") + .put("users.u2.base", "ou=people2,o=TEST") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("presleye", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("presleye", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Elvis Presley,ou=people2,o=TEST", user.getName()); } @@ -834,14 +941,17 @@ public void testChainedLdapAuthentication2() throws Exception { @Test(expected = OpenSearchSecurityException.class) public void testChainedLdapAuthenticationDuplicate() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_SEARCH_ALL_BASES, true).put("users.u1.search", "(uid={0})") - .put("users.u1.base", "ou=people,o=TEST").put("users.u2.search", "(uid={0})") - .put("users.u2.base", "ou=people2,o=TEST").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_SEARCH_ALL_BASES, true) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put("users.u2.search", "(uid={0})") + .put("users.u2.base", "ou=people2,o=TEST") + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); // Fails with OpenSearchSecurityException because two possible instances are // found @@ -850,10 +960,11 @@ public void testChainedLdapAuthenticationDuplicate() throws Exception { @Test public void testChainedLdapExists() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u2.search", "(uid={0})") - .put("users.u2.base", "ou=people2,o=TEST").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u2.search", "(uid={0})") + .put("users.u2.base", "ou=people2,o=TEST") + .build(); final LDAPAuthenticationBackend2 lbe = new LDAPAuthenticationBackend2(settings, null); Assert.assertTrue(lbe.exists(new User("jacksonm"))); @@ -864,15 +975,19 @@ public void testChainedLdapExists() throws Exception { @Test public void testChainedLdapAuthorization() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn").put("roles.g1.base", "ou=groups,o=TEST") - .put("roles.g1.search", "(uniqueMember={0})").put("roles.g2.base", "ou=groups2,o=TEST") - .put("roles.g2.search", "(uniqueMember={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.base", "ou=groups,o=TEST") + .put("roles.g1.search", "(uniqueMember={0})") + .put("roles.g2.base", "ou=groups2,o=TEST") + .put("roles.g2.search", "(uniqueMember={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -890,15 +1005,19 @@ public void testChainedLdapAuthorization() throws Exception { @Test public void testCrossChainedLdapAuthorization() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put("users.u1.search", "(uid={0})").put("users.u1.base", "ou=people2,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn").put("roles.g1.base", "ou=groups,o=TEST") - .put("roles.g1.search", "(uniqueMember={0})").put("roles.g2.base", "ou=groups2,o=TEST") - .put("roles.g2.search", "(uniqueMember={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put("users.u1.search", "(uid={0})") + .put("users.u1.base", "ou=people2,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put("roles.g1.base", "ou=groups,o=TEST") + .put("roles.g1.search", "(uniqueMember={0})") + .put("roles.g2.base", "ou=groups2,o=TEST") + .put("roles.g2.search", "(uniqueMember={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("mercuryf", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("mercuryf", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -914,13 +1033,13 @@ public void testCrossChainedLdapAuthorization() throws Exception { public void testLdapAuthorizationNonDNEntry() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("jacksonm"); @@ -936,17 +1055,18 @@ public void testLdapAuthorizationNonDNEntry() throws Exception { public void testLdapSpecial186() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("spec186", "spec186" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("spec186", "spec186".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST", user.getName()); Assert.assertEquals("AA BB/CC (DD) my, company end=with=whitespace ", user.getUserEntry().getAttribute("cn").getStringValue()); @@ -962,12 +1082,18 @@ public void testLdapSpecial186() throws Exception { Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); @@ -977,17 +1103,18 @@ public void testLdapSpecial186() throws Exception { public void testLdapSpecial186_2() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("spec186", "spec186" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("spec186", "spec186".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST", user.getName()); Assert.assertEquals("AA BB/CC (DD) my, company end=with=whitespace ", user.getUserEntry().getAttribute("cn").getStringValue()); @@ -1003,13 +1130,18 @@ public void testLdapSpecial186_2() throws Exception { Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); - - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); @@ -1018,13 +1150,14 @@ public void testLdapSpecial186_2() throws Exception { @Test public void testOperationalAttributes() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); LdapAttribute operationAttribute = user.getUserEntry().getAttribute("entryUUID"); Assert.assertNotNull(operationAttribute); diff --git a/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestOldStyleConfig2.java b/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestOldStyleConfig2.java index 8a4afee5da..8c6f4dc85d 100755 --- a/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestOldStyleConfig2.java +++ b/src/test/java/com/amazon/dlic/auth/ldap2/LdapBackendTestOldStyleConfig2.java @@ -88,12 +88,13 @@ protected Settings.Builder createBaseSettings() { @Test public void testLdapAuthentication() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -101,13 +102,14 @@ public void testLdapAuthentication() throws Exception { @Test public void testLdapAuthenticationPooled() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAP_POOL_ENABLED, true) - .build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_POOL_ENABLED, true) + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -115,41 +117,44 @@ public void testLdapAuthenticationPooled() throws Exception { @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationFakeLogin() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_FAKE_LOGIN_ENABLED, true) + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("unknown", "unknown".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("unknown", "unknown".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapInjection() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); String injectString = "*jack*"; @SuppressWarnings("unused") - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials(injectString, "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials(injectString, "secret".getBytes(StandardCharsets.UTF_8)) + ); } @Test public void testLdapAuthenticationBindDn() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") - .put(ConfigConstants.LDAP_PASSWORD, "spocksecret").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") + .put(ConfigConstants.LDAP_PASSWORD, "spocksecret") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -157,15 +162,16 @@ public void testLdapAuthenticationBindDn() throws Exception { @Test public void testLdapAuthenticationWrongBindDn() throws Exception { try { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") - .put(ConfigConstants.LDAP_PASSWORD, "wrong").build(); - - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_BIND_DN, "cn=Captain Spock,ou=people,o=TEST") + .put(ConfigConstants.LDAP_PASSWORD, "wrong") + .build(); + + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail("Expected exception"); } catch (Exception e) { Assert.assertTrue(ExceptionUtils.getStackTrace(e), ExceptionUtils.getStackTrace(e).contains("password was incorrect")); @@ -175,60 +181,69 @@ public void testLdapAuthenticationWrongBindDn() throws Exception { @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationBindFail() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "wrong".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "wrong".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationNoUser() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("UNKNOWN", "UNKNOWN".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("UNKNOWN", "UNKNOWN".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationFail() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8)) + ); } @Test(expected = OpenSearchSecurityException.class) public void testLdapAuthenticationFailPooled() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAP_POOL_ENABLED, true) - .build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_POOL_ENABLED, true) + .build(); - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "xxxxx".getBytes(StandardCharsets.UTF_8)) + ); } @Test public void testLdapAuthenticationSSL() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -236,16 +251,21 @@ public void testLdapAuthenticationSSL() throws Exception { @Test public void testLdapAuthenticationSSLPooled() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(ConfigConstants.LDAP_POOL_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put(ConfigConstants.LDAP_POOL_ENABLED, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -253,15 +273,20 @@ public void testLdapAuthenticationSSLPooled() throws Exception { @Test public void testLdapAuthenticationSSLPEMFile() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").toFile().getName()) - .put("verify_hostnames", false).put("path.home", ".") - .put("path.conf", FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").getParent()).build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, Paths.get("src/test/resources/ldap")) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + ConfigConstants.LDAPS_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").toFile().getName() + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .put("path.conf", FileHelper.getAbsoluteFilePathFromClassPath("ldap/root-ca.pem").getParent()) + .build(); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, Paths.get("src/test/resources/ldap")).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -269,18 +294,13 @@ public void testLdapAuthenticationSSLPEMFile() throws Exception { @Test public void testLdapAuthenticationSSLPEMText() throws Exception { - final Settings settingsFromFile = Settings - .builder() - .loadFromPath( - Paths - .get(FileHelper - .getAbsoluteFilePathFromClassPath("ldap/test1.yml") - .toFile() - .getAbsolutePath())) - .build(); - Settings settings = Settings.builder().put(settingsFromFile).putList("hosts", "localhost:"+ldapsPort).build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settingsFromFile = Settings.builder() + .loadFromPath(Paths.get(FileHelper.getAbsoluteFilePathFromClassPath("ldap/test1.yml").toFile().getAbsolutePath())) + .build(); + Settings settings = Settings.builder().put(settingsFromFile).putList("hosts", "localhost:" + ldapsPort).build(); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -288,16 +308,22 @@ public void testLdapAuthenticationSSLPEMText() throws Exception { @Test public void testLdapAuthenticationSSLSSLv3() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_protocols", "SSLv3").put("path.home", ".").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_protocols", "SSLv3") + .put("path.home", ".") + .build(); try { - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail("Expected Exception"); } catch (Exception e) { Assert.assertEquals(org.ldaptive.provider.ConnectionException.class, e.getCause().getClass()); @@ -309,20 +335,30 @@ public void testLdapAuthenticationSSLSSLv3() throws Exception { @Test public void testLdapAuthenticationSSLUnknowCipher() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_ciphers", "AAA").put("path.home", ".").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_ciphers", "AAA") + .put("path.home", ".") + .build(); try { - new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail("Expected Exception"); } catch (Exception e) { - Assert.assertEquals(e.getCause().getClass().toString(), org.ldaptive.provider.ConnectionException.class, e.getCause().getClass()); - Assert.assertTrue(ExceptionUtils.getStackTrace(e), EXCEPTION_MATCHER.test( ExceptionUtils.getStackTrace(e).toLowerCase())); + Assert.assertEquals( + e.getCause().getClass().toString(), + org.ldaptive.provider.ConnectionException.class, + e.getCause().getClass() + ); + Assert.assertTrue(ExceptionUtils.getStackTrace(e), EXCEPTION_MATCHER.test(ExceptionUtils.getStackTrace(e).toLowerCase())); } } @@ -330,16 +366,22 @@ public void testLdapAuthenticationSSLUnknowCipher() throws Exception { @Test public void testLdapAuthenticationSpecialCipherProtocol() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).putList("enabled_ssl_protocols", "TLSv1.2") - .putList("enabled_ssl_ciphers", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA").put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .putList("enabled_ssl_protocols", "TLSv1.2") + .putList("enabled_ssl_ciphers", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA") + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); @@ -348,15 +390,20 @@ public void testLdapAuthenticationSpecialCipherProtocol() throws Exception { @Test public void testLdapAuthenticationSSLNoKeystore() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapsPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -364,14 +411,15 @@ public void testLdapAuthenticationSSLNoKeystore() throws Exception { @Test public void testLdapAuthenticationSSLFailPlain() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").put(ConfigConstants.LDAPS_ENABLE_SSL, true) - .build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_SSL, true) + .build(); try { - new LDAPAuthenticationBackend2(settings, new File("").toPath()) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + new LDAPAuthenticationBackend2(settings, new File("").toPath()).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.fail("Expected exception"); } catch (final Exception e) { Assert.assertEquals(IllegalStateException.class, e.getCause().getClass()); @@ -381,9 +429,9 @@ public void testLdapAuthenticationSSLFailPlain() throws Exception { @Test public void testLdapExists() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); final LDAPAuthenticationBackend2 lbe = new LDAPAuthenticationBackend2(settings, null); Assert.assertTrue(lbe.exists(new User("jacksonm"))); @@ -393,19 +441,19 @@ public void testLdapExists() throws Exception { @Test public void testLdapAuthorization() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - // .put("plugins.security.authentication.authorization.ldap.userrolename", - // "(uniqueMember={0})") - .build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + // .put("plugins.security.authentication.authorization.ldap.userrolename", + // "(uniqueMember={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -419,20 +467,20 @@ public void testLdapAuthorization() throws Exception { @Test public void testLdapAuthorizationPooled() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_POOL_ENABLED, true) - // .put("plugins.security.authentication.authorization.ldap.userrolename", - // "(uniqueMember={0})") - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_POOL_ENABLED, true) + // .put("plugins.security.authentication.authorization.ldap.userrolename", + // "(uniqueMember={0})") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -446,12 +494,11 @@ public void testLdapAuthorizationPooled() throws Exception { @Test public void testLdapAuthenticationReferral() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - final Connection con = new LDAPConnectionFactoryFactory(settings, null).createBasicConnectionFactory() - .getConnection(); + final Connection con = new LDAPConnectionFactoryFactory(settings, null).createBasicConnectionFactory().getConnection(); try { con.open(); final LdapEntry ref1 = LdapHelper.lookup(con, "cn=Ref1,ou=people,o=TEST", ReturnAttributes.ALL.value(), true); @@ -465,17 +512,21 @@ public void testLdapAuthenticationReferral() throws Exception { @Test public void testLdapDontFollowReferrals() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.FOLLOW_REFERRALS, false).build(); - + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.FOLLOW_REFERRALS, false) + .build(); final Connection con = LDAPAuthorizationBackend.getConnection(settings, null); try { - //If following is off then should fail to return the result provided by following - final LdapEntry ref1 = LdapHelper.lookup(con, "cn=Ref1,ou=people,o=TEST", ReturnAttributes.ALL.value(), settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT)); + // If following is off then should fail to return the result provided by following + final LdapEntry ref1 = LdapHelper.lookup( + con, + "cn=Ref1,ou=people,o=TEST", + ReturnAttributes.ALL.value(), + settings.getAsBoolean(ConfigConstants.FOLLOW_REFERRALS, ConfigConstants.FOLLOW_REFERRALS_DEFAULT) + ); Assert.assertNull(ref1); } finally { con.close(); @@ -485,18 +536,19 @@ public void testLdapDontFollowReferrals() throws Exception { @Test public void testLdapEscape() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true).build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("ssign", "ssignsecret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("ssign", "ssignsecret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Special\\, Sign,ou=people,o=TEST", user.getName()); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -508,16 +560,17 @@ public void testLdapEscape() throws Exception { @Test public void testLdapAuthorizationRoleSearchUsername() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(cn={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember=cn={1},ou=people,o=TEST)").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(cn={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember=cn={1},ou=people,o=TEST)") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("Michael Jackson", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("Michael Jackson", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -532,13 +585,13 @@ public void testLdapAuthorizationRoleSearchUsername() throws Exception { @Test public void testLdapAuthorizationOnly() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("jacksonm"); @@ -553,14 +606,14 @@ public void testLdapAuthorizationOnly() throws Exception { @Test public void testLdapAuthorizationNested() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("spock"); @@ -575,15 +628,15 @@ public void testLdapAuthorizationNested() throws Exception { @Test public void testLdapAuthorizationNestedFilter() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=nested2,ou=groups,o=TEST").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=nested2,ou=groups,o=TEST") + .build(); final User user = new User("spock"); @@ -599,14 +652,14 @@ public void testLdapAuthorizationNestedFilter() throws Exception { @Test public void testLdapAuthorizationDnNested() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("spock"); @@ -621,18 +674,17 @@ public void testLdapAuthorizationDnNested() throws Exception { @Test public void testLdapAuthorizationDn() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "UID") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "UID") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); - final User user = new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes())); + final User user = new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("jacksonm", "secret".getBytes())); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -645,14 +697,15 @@ public void testLdapAuthorizationDn() throws Exception { @Test public void testLdapAuthenticationUserNameAttribute() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERNAME_ATTRIBUTE, "uid") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("jacksonm", user.getName()); } @@ -660,16 +713,20 @@ public void testLdapAuthenticationUserNameAttribute() throws Exception { @Test public void testLdapAuthenticationStartTLS() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAPS_ENABLE_START_TLS, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks")) - .put("verify_hostnames", false).put("path.home", ".").build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAPS_ENABLE_START_TLS, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ldap/truststore.jks") + ) + .put("verify_hostnames", false) + .put("path.home", ".") + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); } @@ -677,17 +734,18 @@ public void testLdapAuthenticationStartTLS() throws Exception { @Test public void testLdapAuthorizationSkipUsers() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "cn=Michael Jackson,ou*people,o=TEST").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .putList(ConfigConstants.LDAP_AUTHZ_SKIP_USERS, "cn=Michael Jackson,ou*people,o=TEST") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); new LDAPAuthorizationBackend(settings, null).fillRoles(user, null); @@ -700,16 +758,16 @@ public void testLdapAuthorizationSkipUsers() throws Exception { @Test public void testLdapAuthorizationNestedAttr() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("spock"); @@ -725,17 +783,17 @@ public void testLdapAuthorizationNestedAttr() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilter() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=rolemo4*").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "cn=rolemo4*") + .build(); final User user = new User("spock"); @@ -752,17 +810,17 @@ public void testLdapAuthorizationNestedAttrFilter() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilterAll() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) - .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*").build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, "*") + .build(); final User user = new User("spock"); @@ -777,18 +835,18 @@ public void testLdapAuthorizationNestedAttrFilterAll() throws Exception { @Test public void testLdapAuthorizationNestedAttrFilterAllEqualsNestedFalse() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) // -> same like - // putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, - // "*") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, false) // -> same like + // putList(ConfigConstants.LDAP_AUTHZ_NESTEDROLEFILTER, + // "*") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("spock"); @@ -803,15 +861,16 @@ public void testLdapAuthorizationNestedAttrFilterAllEqualsNestedFalse() throws E @Test public void testLdapAuthorizationNestedAttrNoRoleSearch() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "unused").put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(((unused") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, false).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "unused") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(((unused") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, false) + .build(); final User user = new User("spock"); @@ -827,35 +886,37 @@ public void testLdapAuthorizationNestedAttrNoRoleSearch() throws Exception { @Test public void testCustomAttributes() throws Exception { - Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("cn=Michael Jackson,ou=people,o=TEST", user.getName()); Assert.assertEquals(user.getCustomAttributesMap().toString(), 16, user.getCustomAttributesMap().size()); - Assert.assertFalse(user.getCustomAttributesMap().toString(), - user.getCustomAttributesMap().containsKey("attr.ldap.userpassword")); + Assert.assertFalse(user.getCustomAttributesMap().toString(), user.getCustomAttributesMap().containsKey("attr.ldap.userpassword")); - settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 0).build(); + settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_CUSTOM_ATTR_MAXVAL_LEN, 0) + .build(); - user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertEquals(user.getCustomAttributesMap().toString(), 2, user.getCustomAttributesMap().size()); - settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .putList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, "*objectclass*", "entryParentId").build(); + settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "127.0.0.1:4", "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .putList(ConfigConstants.LDAP_CUSTOM_ATTR_WHITELIST, "*objectclass*", "entryParentId") + .build(); - user = (LdapUser) new LDAPAuthenticationBackend2(settings, null) - .authenticate(new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8))); + user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertEquals(user.getCustomAttributesMap().toString(), 2, user.getCustomAttributesMap().size()); @@ -864,16 +925,16 @@ public void testCustomAttributes() throws Exception { @Test public void testLdapAuthorizationNonDNRoles() throws Exception { - final Settings settings = createBaseSettings() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description, ou") // no memberOf OID - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true).build(); + final Settings settings = createBaseSettings().putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "cn") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_USERROLENAME, "description, ou") // no memberOf OID + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH_ENABLED, true) + .build(); final User user = new User("nondnroles"); @@ -883,26 +944,26 @@ public void testLdapAuthorizationNonDNRoles() throws Exception { Assert.assertEquals("nondnroles", user.getName()); Assert.assertEquals(5, user.getRoles().size()); Assert.assertTrue("Roles do not contain non-LDAP role 'kibanauser'", user.getRoles().contains("kibanauser")); - Assert.assertTrue("Roles do not contain non-LDAP role 'humanresources'", - user.getRoles().contains("humanresources")); + Assert.assertTrue("Roles do not contain non-LDAP role 'humanresources'", user.getRoles().contains("humanresources")); Assert.assertTrue("Roles do not contain LDAP role 'dummyempty'", user.getRoles().contains("dummyempty")); Assert.assertTrue("Roles do not contain non-LDAP role 'role2'", user.getRoles().contains("role2")); - Assert.assertTrue("Roles do not contain non-LDAP role 'anotherrole' from second role name", - user.getRoles().contains("anotherrole")); + Assert.assertTrue( + "Roles do not contain non-LDAP role 'anotherrole' from second role name", + user.getRoles().contains("anotherrole") + ); } - @Test public void testLdapAuthorizationNonDNEntry() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .build(); final User user = new User("jacksonm"); @@ -918,17 +979,18 @@ public void testLdapAuthorizationNonDNEntry() throws Exception { public void testLdapSpecial186() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("spec186", "spec186" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "description") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("spec186", "spec186".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST", user.getName()); Assert.assertEquals("AA BB/CC (DD) my, company end=with=whitespace ", user.getUserEntry().getAttribute("cn").getStringValue()); @@ -944,12 +1006,18 @@ public void testLdapSpecial186() throws Exception { Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLEx(186n) consists of\\, special=")); Assert.assertTrue(user.getRoles().toString().contains("ROLE/(186nn) consists of\\, special=")); @@ -959,17 +1027,18 @@ public void testLdapSpecial186() throws Exception { public void testLdapSpecial186_2() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") - .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") - .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") - .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") - .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) - .build(); - - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate(new AuthCredentials("spec186", "spec186" - .getBytes(StandardCharsets.UTF_8))); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .put(ConfigConstants.LDAP_AUTHC_USERBASE, "ou=people,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLEBASE, "ou=groups,o=TEST") + .put(ConfigConstants.LDAP_AUTHZ_ROLENAME, "dn") + .put(ConfigConstants.LDAP_AUTHZ_ROLESEARCH, "(uniqueMember={0})") + .put(ConfigConstants.LDAP_AUTHZ_RESOLVE_NESTED_ROLES, true) + .build(); + + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend(settings, null).authenticate( + new AuthCredentials("spec186", "spec186".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); Assert.assertEquals("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST", user.getName()); Assert.assertEquals("AA BB/CC (DD) my, company end=with=whitespace ", user.getUserEntry().getAttribute("cn").getStringValue()); @@ -985,13 +1054,18 @@ public void testLdapSpecial186_2() throws Exception { Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); - - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); - new LDAPAuthorizationBackend(settings, null).fillRoles(new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), null); + new LDAPAuthorizationBackend(settings, null).fillRoles( + new User("CN=AA BB\\/CC (DD) my\\, company end\\=with\\=whitespace\\ ,ou=people,o=TEST"), + null + ); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186n) consists of\\, special\\=chars\\ ")); Assert.assertTrue(user.getRoles().toString().contains("cn=ROLE/(186nn) consists of\\, special\\=chars\\ ")); @@ -1000,13 +1074,14 @@ public void testLdapSpecial186_2() throws Exception { @Test public void testOperationalAttributes() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) - .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})").build(); + .putList(ConfigConstants.LDAP_HOSTS, "localhost:" + ldapPort) + .put(ConfigConstants.LDAP_AUTHC_USERSEARCH, "(uid={0})") + .build(); - final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate(new AuthCredentials("jacksonm", "secret" - .getBytes(StandardCharsets.UTF_8))); + final LdapUser user = (LdapUser) new LDAPAuthenticationBackend2(settings, null).authenticate( + new AuthCredentials("jacksonm", "secret".getBytes(StandardCharsets.UTF_8)) + ); Assert.assertNotNull(user); LdapAttribute operationAttribute = user.getUserEntry().getAttribute("entryUUID"); Assert.assertNotNull(operationAttribute); @@ -1015,7 +1090,6 @@ public void testOperationalAttributes() throws Exception { Assert.assertTrue(operationAttribute.getStringValue().split("-").length == 5); } - @AfterClass public static void tearDown() throws Exception { diff --git a/src/test/java/org/opensearch/bootstrap/JarHell.java b/src/test/java/org/opensearch/bootstrap/JarHell.java index 11978a780c..3024a169bc 100644 --- a/src/test/java/org/opensearch/bootstrap/JarHell.java +++ b/src/test/java/org/opensearch/bootstrap/JarHell.java @@ -24,9 +24,16 @@ */ public class JarHell { private JarHell() {} + public static void checkJarHell(Consumer output) throws IOException, Exception {} + public static void checkJarHell(Set urls, Consumer output) throws URISyntaxException, IOException {} + public static void checkVersionFormat(String targetVersion) {} + public static void checkJavaVersion(String resource, String targetVersion) {} - public static Set parseClassPath() {return new HashSet();} + + public static Set parseClassPath() { + return new HashSet(); + } } diff --git a/src/test/java/org/opensearch/node/PluginAwareNode.java b/src/test/java/org/opensearch/node/PluginAwareNode.java index 39c93e6b8e..4cd7ff9247 100644 --- a/src/test/java/org/opensearch/node/PluginAwareNode.java +++ b/src/test/java/org/opensearch/node/PluginAwareNode.java @@ -33,15 +33,18 @@ import org.opensearch.plugins.Plugin; public class PluginAwareNode extends Node { - + private final boolean clusterManagerEligible; @SafeVarargs public PluginAwareNode(boolean clusterManagerEligible, final Settings preparedSettings, final Class... plugins) { - super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, Collections.emptyMap(), null, () -> System.getenv("HOSTNAME")), Arrays.asList(plugins), true); + super( + InternalSettingsPreparer.prepareEnvironment(preparedSettings, Collections.emptyMap(), null, () -> System.getenv("HOSTNAME")), + Arrays.asList(plugins), + true + ); this.clusterManagerEligible = clusterManagerEligible; } - public boolean isClusterManagerEligible() { return clusterManagerEligible; diff --git a/src/test/java/org/opensearch/security/AdvancedSecurityMigrationTests.java b/src/test/java/org/opensearch/security/AdvancedSecurityMigrationTests.java index 3b069a2339..e8ac049385 100644 --- a/src/test/java/org/opensearch/security/AdvancedSecurityMigrationTests.java +++ b/src/test/java/org/opensearch/security/AdvancedSecurityMigrationTests.java @@ -50,8 +50,11 @@ public void testPluginEnabledDataNodeWithSSlOnlyClusterManagerNode_ReqOnSSLNode( final Settings advSecSettings = getAdvSecSettings().build(); final Settings sslOnlySettings = getSSLOnlyModeSettings().build(); - setupGenericNodes(Arrays.asList(sslOnlySettings, advSecSettings, advSecSettings, sslOnlySettings), - Arrays.asList(true, false, false, true), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(sslOnlySettings, advSecSettings, advSecSettings, sslOnlySettings), + Arrays.asList(true, false, false, true), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); commonTestsForAdvancedSecurityMigration(nonSslRestHelper(), null); @@ -67,8 +70,11 @@ public void testPluginEnabledDataNodeWithSSlOnlyClusterManagerNode_ReqOnAdvSecNo final Settings advSecSettings = getAdvSecSettings().build(); final Settings sslOnlySettings = getSSLOnlyModeSettings().build(); - setupGenericNodes(Arrays.asList(advSecSettings, sslOnlySettings, advSecSettings, sslOnlySettings), - Arrays.asList(false, true, false, true), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(advSecSettings, sslOnlySettings, advSecSettings, sslOnlySettings), + Arrays.asList(false, true, false, true), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); commonTestsForAdvancedSecurityMigration(nonSslRestHelper(), encodeBasicHeader("admin", "admin")); @@ -84,11 +90,14 @@ public void testPluginEnabledClusterManagerNodeWithSSlOnlyDataNode_ReqOnSSLNode( final Settings advSecSettings = getAdvSecSettings().build(); final Settings sslOnlySettings = getSSLOnlyModeSettings().build(); - setupGenericNodes(Arrays.asList(sslOnlySettings, sslOnlySettings, advSecSettings, advSecSettings), - Arrays.asList(true, true, false, false), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(sslOnlySettings, sslOnlySettings, advSecSettings, advSecSettings), + Arrays.asList(true, true, false, false), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); - commonTestsForAdvancedSecurityMigration(nonSslRestHelper(),null); + commonTestsForAdvancedSecurityMigration(nonSslRestHelper(), null); } /** @@ -101,8 +110,11 @@ public void testPluginEnabledClusterManagerNodeWithSSlOnlyDataNode_ReqOnAdvSecNo final Settings advSecSettings = getAdvSecSettings().build(); final Settings sslOnlySettings = getSSLOnlyModeSettings().build(); - setupGenericNodes(Arrays.asList(advSecSettings, sslOnlySettings, sslOnlySettings, advSecSettings), - Arrays.asList(false, true, true, false), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(advSecSettings, sslOnlySettings, sslOnlySettings, advSecSettings), + Arrays.asList(false, true, true, false), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); commonTestsForAdvancedSecurityMigration(nonSslRestHelper(), encodeBasicHeader("admin", "admin")); @@ -118,11 +130,14 @@ public void testPluginEnabledDataNodeWithDisabledClusterManagerNode_ReqOnDisable final Settings advSecSettings = getAdvSecSettingsDualMode().build(); final Settings disabledSettings = getDisabledSettings().build(); - setupGenericNodes(Arrays.asList(disabledSettings, advSecSettings, advSecSettings, disabledSettings), - Arrays.asList(false, false, false, false), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(disabledSettings, advSecSettings, advSecSettings, disabledSettings), + Arrays.asList(false, false, false, false), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); - commonTestsForAdvancedSecurityMigration(nonSslRestHelper(),null); + commonTestsForAdvancedSecurityMigration(nonSslRestHelper(), null); } /** @@ -135,8 +150,11 @@ public void testPluginEnabledDataNodeWithDisabledClusterManagerNode_ReqOnAdvSecN final Settings advSecSettings = getAdvSecSettingsDualMode().build(); final Settings disabledSettings = getDisabledSettings().build(); - setupGenericNodes(Arrays.asList(advSecSettings, disabledSettings, advSecSettings, disabledSettings), - Arrays.asList(false, false, false, false), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(advSecSettings, disabledSettings, advSecSettings, disabledSettings), + Arrays.asList(false, false, false, false), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); commonTestsForAdvancedSecurityMigration(nonSslRestHelper(), encodeBasicHeader("admin", "admin")); @@ -152,8 +170,11 @@ public void testPluginEnabledClusterManagerNodeWithDisabledDataNode_ReqOnDisable final Settings advSecSettings = getAdvSecSettingsDualMode().build(); final Settings disabledSettings = getDisabledSettings().build(); - setupGenericNodes(Arrays.asList(disabledSettings, disabledSettings, advSecSettings, advSecSettings), - Arrays.asList(false, false, false, false), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(disabledSettings, disabledSettings, advSecSettings, advSecSettings), + Arrays.asList(false, false, false, false), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); commonTestsForAdvancedSecurityMigration(nonSslRestHelper(), null); @@ -169,8 +190,11 @@ public void testPluginEnabledClusterManagerNodeWithDisabledDataNode_ReqOnAdvSecN final Settings advSecSettings = getAdvSecSettingsDualMode().build(); final Settings disabledSettings = getDisabledSettings().build(); - setupGenericNodes(Arrays.asList(advSecSettings, disabledSettings, advSecSettings, advSecSettings), - Arrays.asList(false, false, false, false), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(advSecSettings, disabledSettings, advSecSettings, advSecSettings), + Arrays.asList(false, false, false, false), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); commonTestsForAdvancedSecurityMigration(nonSslRestHelper(), encodeBasicHeader("admin", "admin")); @@ -178,13 +202,17 @@ public void testPluginEnabledClusterManagerNodeWithDisabledDataNode_ReqOnAdvSecN @Test public void testWithPassiveAuthDisabled() throws Exception { - final Settings advSecSettings = getAdvSecSettings() - .put(ConfigConstants.SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY, false) - .build(); + final Settings advSecSettings = getAdvSecSettings().put( + ConfigConstants.SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY, + false + ).build(); final Settings sslOnlySettings = getSSLOnlyModeSettings().build(); - setupGenericNodes(Arrays.asList(sslOnlySettings, sslOnlySettings, advSecSettings, advSecSettings), - Arrays.asList(true, true, false, false), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(sslOnlySettings, sslOnlySettings, advSecSettings, advSecSettings), + Arrays.asList(true, true, false, false), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); Thread.sleep(10000); RestHelper.HttpResponse res; @@ -196,15 +224,19 @@ public void testWithPassiveAuthDisabled() throws Exception { @Test public void testWithPassiveAuthDisabledDynamic() throws Exception { - final Settings advSecSettings = getAdvSecSettingsDualMode() - .put(ConfigConstants.SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY, false) - .build(); + final Settings advSecSettings = getAdvSecSettingsDualMode().put( + ConfigConstants.SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY, + false + ).build(); final Settings disabledSettings = getDisabledSettings().build(); - setupGenericNodes(Arrays.asList(disabledSettings, disabledSettings, advSecSettings, advSecSettings), - Arrays.asList(false, false, false, false), ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA); + setupGenericNodes( + Arrays.asList(disabledSettings, disabledSettings, advSecSettings, advSecSettings), + Arrays.asList(false, false, false, false), + ClusterConfiguration.ONE_CLUSTER_MANAGER_THREE_DATA + ); - Thread.sleep(5*1000); + Thread.sleep(5 * 1000); RestHelper.HttpResponse res; RestHelper rh = nonSslRestHelper(); @@ -214,7 +246,7 @@ public void testWithPassiveAuthDisabledDynamic() throws Exception { } private void commonTestsForAdvancedSecurityMigration(final RestHelper rh, final Header basicHeaders) throws Exception { - Thread.sleep(5*1000); + Thread.sleep(5 * 1000); RestHelper.HttpResponse res; res = rh.executePutRequest("testindex", getIndexSettingsForAdvSec(), basicHeaders); @@ -250,50 +282,47 @@ private void commonTestsForAnIndex(final RestHelper rh, final String index, fina private Settings.Builder getAdvSecSettings() { return Settings.builder() - .put(ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX, true) - .put(ConfigConstants.SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY, true) - .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) - .put("node.attr.custom_node", true); + .put(ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX, true) + .put(ConfigConstants.SECURITY_UNSUPPORTED_PASSIVE_INTERTRANSPORT_AUTH_INITIALLY, true) + .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) + .put("node.attr.custom_node", true); } private Settings.Builder getAdvSecSettingsDualMode() { - return getAdvSecSettings() - .put(ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, true); + return getAdvSecSettings().put(ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, true); } private Settings.Builder getSSLOnlyModeSettings() { - return Settings.builder() - .put(ConfigConstants.SECURITY_SSL_ONLY, true); + return Settings.builder().put(ConfigConstants.SECURITY_SSL_ONLY, true); } private Settings.Builder getDisabledSettings() { - return Settings.builder() - .put(ConfigConstants.SECURITY_DISABLED, true); + return Settings.builder().put(ConfigConstants.SECURITY_DISABLED, true); } // Create index with shards only in adv sec nodes private String getIndexSettingsForAdvSec() { - return "{\n" + - " \"settings\" : {\n" + - " \"index\" : {\n" + - " \"number_of_shards\" : 2, \n" + - " \"number_of_replicas\" : 1, \n" + - " \"routing.allocation.include.custom_node\" : true \n" + - " }\n" + - " }\n" + - "}"; + return "{\n" + + " \"settings\" : {\n" + + " \"index\" : {\n" + + " \"number_of_shards\" : 2, \n" + + " \"number_of_replicas\" : 1, \n" + + " \"routing.allocation.include.custom_node\" : true \n" + + " }\n" + + " }\n" + + "}"; } // Create index with shards only in non adv sec nodes private String getIndexSettingForSSLOnlyNode() { - return "{\n" + - " \"settings\" : {\n" + - " \"index\" : {\n" + - " \"number_of_shards\" : 2, \n" + - " \"number_of_replicas\" : 1, \n" + - " \"routing.allocation.exclude.custom_node\" : true \n" + - " }\n" + - " }\n" + - "}"; + return "{\n" + + " \"settings\" : {\n" + + " \"index\" : {\n" + + " \"number_of_shards\" : 2, \n" + + " \"number_of_replicas\" : 1, \n" + + " \"routing.allocation.exclude.custom_node\" : true \n" + + " }\n" + + " }\n" + + "}"; } } diff --git a/src/test/java/org/opensearch/security/AggregationTests.java b/src/test/java/org/opensearch/security/AggregationTests.java index c2feddd6b6..728965f82d 100644 --- a/src/test/java/org/opensearch/security/AggregationTests.java +++ b/src/test/java/org/opensearch/security/AggregationTests.java @@ -46,37 +46,74 @@ public class AggregationTests extends SingleClusterTest { @Test public void testBasicAggregations() throws Exception { - final Settings settings = Settings.builder() - .build(); - + final Settings settings = Settings.builder().build(); + setup(settings); final RestHelper rh = nonSslRestHelper(); - + try (Client tc = getClient()) { - tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("xyz").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("xyz").alias("alias1"))).actionGet(); + tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.index(new IndexRequest("xyz").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf")) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("xyz").alias("alias1"))) + .actionGet(); } - + HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_search?pretty", "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":40}}}}",encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "_search?pretty", + "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":40}}}}", + encodeBasicHeader("nagilum", "nagilum") + )).getStatusCode() + ); System.out.println(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -88,8 +125,15 @@ public void testBasicAggregations() throws Exception { assertContains(res, "*xyz*"); assertContains(res, "*role01_role02*"); assertContains(res, "*\"failed\" : 0*"); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("*/_search?pretty", "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":40}}}}",encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "*/_search?pretty", + "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":40}}}}", + encodeBasicHeader("nagilum", "nagilum") + )).getStatusCode() + ); System.out.println(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -101,8 +145,15 @@ public void testBasicAggregations() throws Exception { assertContains(res, "*xyz*"); assertContains(res, "*role01_role02*"); assertContains(res, "*\"failed\" : 0*"); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_search?pretty", "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":40}}}}",encodeBasicHeader("worf", "worf"))).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "_search?pretty", + "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":40}}}}", + encodeBasicHeader("worf", "worf") + )).getStatusCode() + ); System.out.println(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -114,9 +165,16 @@ public void testBasicAggregations() throws Exception { assertContains(res, "*public*"); assertContains(res, "*xyz*"); assertContains(res, "*\"failed\" : 0*"); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executePostRequest("_search?pretty", "{\"size\":0,\"aggs\":{\"myindices\":{\"terms\":{\"field\":\"_index\",\"size\":40}}}}",encodeBasicHeader("worf", "worf"))).getStatusCode()); - + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePostRequest( + "_search?pretty", + "{\"size\":0,\"aggs\":{\"myindices\":{\"terms\":{\"field\":\"_index\",\"size\":40}}}}", + encodeBasicHeader("worf", "worf") + )).getStatusCode() + ); + } - + } diff --git a/src/test/java/org/opensearch/security/AlwaysFalseInterClusterRequestEvaluator.java b/src/test/java/org/opensearch/security/AlwaysFalseInterClusterRequestEvaluator.java index 7fdf2d8bfc..b741dd2c70 100644 --- a/src/test/java/org/opensearch/security/AlwaysFalseInterClusterRequestEvaluator.java +++ b/src/test/java/org/opensearch/security/AlwaysFalseInterClusterRequestEvaluator.java @@ -32,7 +32,6 @@ import org.opensearch.security.transport.InterClusterRequestEvaluator; import org.opensearch.transport.TransportRequest; - public class AlwaysFalseInterClusterRequestEvaluator implements InterClusterRequestEvaluator { public AlwaysFalseInterClusterRequestEvaluator(Settings settings) { @@ -40,14 +39,22 @@ public AlwaysFalseInterClusterRequestEvaluator(Settings settings) { } @Override - public boolean isInterClusterRequest(TransportRequest request, X509Certificate[] localCerts, X509Certificate[] peerCerts, - String principal) { - - if(localCerts == null || peerCerts == null || principal == null - || localCerts.length == 0 || peerCerts.length == 0 || principal.length() == 0) { + public boolean isInterClusterRequest( + TransportRequest request, + X509Certificate[] localCerts, + X509Certificate[] peerCerts, + String principal + ) { + + if (localCerts == null + || peerCerts == null + || principal == null + || localCerts.length == 0 + || peerCerts.length == 0 + || principal.length() == 0) { return true; } - + return false; } diff --git a/src/test/java/org/opensearch/security/ConfigTests.java b/src/test/java/org/opensearch/security/ConfigTests.java index c5b8c089e4..519faa612d 100644 --- a/src/test/java/org/opensearch/security/ConfigTests.java +++ b/src/test/java/org/opensearch/security/ConfigTests.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security; @@ -46,89 +46,97 @@ import org.opensearch.security.test.SingleClusterTest; public class ConfigTests { - + private static final ObjectMapper YAML = new ObjectMapper(new YAMLFactory()); - + @Test public void testEmptyConfig() throws Exception { Assert.assertTrue(SecurityDynamicConfiguration.empty().deepClone() != SecurityDynamicConfiguration.empty()); } - + @Test public void testMigrate() throws Exception { - Tuple, SecurityDynamicConfiguration> rolesResult = Migration.migrateRoles((SecurityDynamicConfiguration)load("./legacy/securityconfig_v6/roles.yml", CType.ROLES), - (SecurityDynamicConfiguration)load("./legacy/securityconfig_v6/roles_mapping.yml", CType.ROLESMAPPING)); - + Tuple, SecurityDynamicConfiguration> rolesResult = Migration.migrateRoles( + (SecurityDynamicConfiguration) load("./legacy/securityconfig_v6/roles.yml", CType.ROLES), + (SecurityDynamicConfiguration) load("./legacy/securityconfig_v6/roles_mapping.yml", CType.ROLESMAPPING) + ); + System.out.println(Strings.toString(XContentType.JSON, rolesResult.v2(), true, false)); System.out.println(Strings.toString(XContentType.JSON, rolesResult.v1(), true, false)); - - - SecurityDynamicConfiguration actionGroupsResult = Migration.migrateActionGroups((SecurityDynamicConfiguration)load("./legacy/securityconfig_v6/action_groups.yml", CType.ACTIONGROUPS)); + + SecurityDynamicConfiguration actionGroupsResult = Migration.migrateActionGroups( + (SecurityDynamicConfiguration) load("./legacy/securityconfig_v6/action_groups.yml", CType.ACTIONGROUPS) + ); System.out.println(Strings.toString(XContentType.JSON, actionGroupsResult, true, false)); - SecurityDynamicConfiguration configResult =Migration.migrateConfig((SecurityDynamicConfiguration)load("./legacy/securityconfig_v6/config.yml", CType.CONFIG)); + SecurityDynamicConfiguration configResult = Migration.migrateConfig( + (SecurityDynamicConfiguration) load("./legacy/securityconfig_v6/config.yml", CType.CONFIG) + ); System.out.println(Strings.toString(XContentType.JSON, configResult, true, false)); - SecurityDynamicConfiguration internalUsersResult = Migration.migrateInternalUsers((SecurityDynamicConfiguration)load("./legacy/securityconfig_v6/internal_users.yml", CType.INTERNALUSERS)); + SecurityDynamicConfiguration internalUsersResult = Migration.migrateInternalUsers( + (SecurityDynamicConfiguration) load("./legacy/securityconfig_v6/internal_users.yml", CType.INTERNALUSERS) + ); System.out.println(Strings.toString(XContentType.JSON, internalUsersResult, true, false)); - SecurityDynamicConfiguration rolemappingsResult = Migration.migrateRoleMappings((SecurityDynamicConfiguration)load("./legacy/securityconfig_v6/roles_mapping.yml", CType.ROLESMAPPING)); + SecurityDynamicConfiguration rolemappingsResult = Migration.migrateRoleMappings( + (SecurityDynamicConfiguration) load("./legacy/securityconfig_v6/roles_mapping.yml", CType.ROLESMAPPING) + ); System.out.println(Strings.toString(XContentType.JSON, rolemappingsResult, true, false)); } - + @Test public void testParseSg67Config() throws Exception { check("./legacy/securityconfig_v6/action_groups.yml", CType.ACTIONGROUPS); check("./action_groups.yml", CType.ACTIONGROUPS); - + check("./legacy/securityconfig_v6/config.yml", CType.CONFIG); check("./config.yml", CType.CONFIG); - + check("./legacy/securityconfig_v6/roles.yml", CType.ROLES); check("./roles.yml", CType.ROLES); - + check("./legacy/securityconfig_v6/internal_users.yml", CType.INTERNALUSERS); check("./internal_users.yml", CType.INTERNALUSERS); - + check("./legacy/securityconfig_v6/roles_mapping.yml", CType.ROLESMAPPING); check("./roles_mapping.yml", CType.ROLESMAPPING); - + check("./tenants.yml", CType.TENANTS); - + } - + private void check(String file, CType cType) throws Exception { final String adjustedFilePath = SingleClusterTest.TEST_RESOURCE_RELATIVE_PATH + file; JsonNode jsonNode = YAML.readTree(FileUtils.readFileToString(new File(adjustedFilePath), "UTF-8")); int configVersion = 1; System.out.println("%%%%%%%% THIS IS A LINE OF INTEREST %%%%%%%"); - if(jsonNode.get("_meta") != null) { + if (jsonNode.get("_meta") != null) { Assert.assertEquals(jsonNode.get("_meta").get("type").asText(), cType.toLCString()); configVersion = jsonNode.get("_meta").get("config_version").asInt(); } + System.out.println("%%%%%%%% THIS IS A LINE OF INTEREST: CONFIG VERSION: " + configVersion + "%%%%%%%"); - System.out.println("%%%%%%%% THIS IS A LINE OF INTEREST: CONFIG VERSION: "+ configVersion + "%%%%%%%"); - SecurityDynamicConfiguration dc = load(file, cType); Assert.assertNotNull(dc); - //Assert.assertTrue(dc.getCEntries().size() > 0); + // Assert.assertTrue(dc.getCEntries().size() > 0); String jsonSerialize = DefaultObjectMapper.objectMapper.writeValueAsString(dc); SecurityDynamicConfiguration conf = SecurityDynamicConfiguration.fromJson(jsonSerialize, cType, configVersion, 0, 0); SecurityDynamicConfiguration.fromJson(Strings.toString(XContentType.JSON, conf), cType, configVersion, 0, 0); - + } - + private SecurityDynamicConfiguration load(String file, CType cType) throws Exception { final String adjustedFilePath = SingleClusterTest.TEST_RESOURCE_RELATIVE_PATH + file; JsonNode jsonNode = YAML.readTree(FileUtils.readFileToString(new File(adjustedFilePath), "UTF-8")); int configVersion = 1; System.out.println("%%%%%%%% THIS IS A LINE OF INTEREST LOAD: CONFIG VERSION: %%%%%%%"); - if(jsonNode.get("_meta") != null) { + if (jsonNode.get("_meta") != null) { Assert.assertEquals(jsonNode.get("_meta").get("type").asText(), cType.toLCString()); configVersion = jsonNode.get("_meta").get("config_version").asInt(); } - System.out.println("%%%%%%%% THIS IS A LINE OF INTEREST: CONFIG VERSION: "+ configVersion + "%%%%%%%"); + System.out.println("%%%%%%%% THIS IS A LINE OF INTEREST: CONFIG VERSION: " + configVersion + "%%%%%%%"); return SecurityDynamicConfiguration.fromNode(jsonNode, cType, configVersion, 0, 0); } } diff --git a/src/test/java/org/opensearch/security/DataStreamIntegrationTests.java b/src/test/java/org/opensearch/security/DataStreamIntegrationTests.java index 78c9ab7818..773244c7ea 100644 --- a/src/test/java/org/opensearch/security/DataStreamIntegrationTests.java +++ b/src/test/java/org/opensearch/security/DataStreamIntegrationTests.java @@ -19,25 +19,29 @@ import org.opensearch.security.test.helper.rest.RestHelper; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; - public class DataStreamIntegrationTests extends SingleClusterTest { - final String bulkDocsBody = - "{ \"create\" : {} }" + System.lineSeparator() + - "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"vlb44hny\", \"name\": \"Sam\"}, \"message\" : \"Login attempt failed\" }" + System.lineSeparator() + - "{ \"create\" : {} }" + System.lineSeparator() + - "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"8a4f500d\", \"name\": \"Dam\"}, \"message\" : \"Login successful\" }" + System.lineSeparator() + - "{ \"create\" : {} }" + System.lineSeparator() + - "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"l7gk7f82\", \"name\": \"Pam\"}, \"message\" : \"Login attempt failed\" }" + System.lineSeparator(); + final String bulkDocsBody = "{ \"create\" : {} }" + + System.lineSeparator() + + "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"vlb44hny\", \"name\": \"Sam\"}, \"message\" : \"Login attempt failed\" }" + + System.lineSeparator() + + "{ \"create\" : {} }" + + System.lineSeparator() + + "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"8a4f500d\", \"name\": \"Dam\"}, \"message\" : \"Login successful\" }" + + System.lineSeparator() + + "{ \"create\" : {} }" + + System.lineSeparator() + + "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"l7gk7f82\", \"name\": \"Pam\"}, \"message\" : \"Login attempt failed\" }" + + System.lineSeparator(); final String searchQuery1 = "{ \"seq_no_primary_term\" : true, \"query\": { \"match\": { \"user.id\": \"8a4f500d\"}}}"; final String searchQuery2 = "{ \"seq_no_primary_term\" : true, \"query\": { \"match\": { \"user.id\": \"l7gk7f82\"}}}"; public String getIndexTemplateBody() { - return "{\"index_patterns\": [ \"my-data-stream*\" ], \"data_stream\": { }, \"priority\": 200, \"template\": {\"settings\": { } } }"; + return "{\"index_patterns\": [ \"my-data-stream*\" ], \"data_stream\": { }, \"priority\": 200, \"template\": {\"settings\": { } } }"; } - public void createSampleDataStreams(RestHelper rh) throws Exception{ + public void createSampleDataStreams(RestHelper rh) throws Exception { // Valid index-template is required to create data-streams rh.executePutRequest("/_index_template/my-data-stream-template", getIndexTemplateBody(), encodeBasicHeader("ds1", "nagilum")); @@ -55,10 +59,18 @@ public void testCreateDataStream() throws Exception { RestHelper rh = nonSslRestHelper(); HttpResponse response; - response = rh.executePutRequest("/_index_template/my-data-stream-template", getIndexTemplateBody(), encodeBasicHeader("ds0", "nagilum")); + response = rh.executePutRequest( + "/_index_template/my-data-stream-template", + getIndexTemplateBody(), + encodeBasicHeader("ds0", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - response = rh.executePutRequest("/_index_template/my-data-stream-template", getIndexTemplateBody(), encodeBasicHeader("ds1", "nagilum")); + response = rh.executePutRequest( + "/_index_template/my-data-stream-template", + getIndexTemplateBody(), + encodeBasicHeader("ds1", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executePutRequest("/_data_stream/my-data-stream11", getIndexTemplateBody(), encodeBasicHeader("ds0", "nagilum")); diff --git a/src/test/java/org/opensearch/security/EncryptionInTransitMigrationTests.java b/src/test/java/org/opensearch/security/EncryptionInTransitMigrationTests.java index 5535d8a924..462cd591e6 100644 --- a/src/test/java/org/opensearch/security/EncryptionInTransitMigrationTests.java +++ b/src/test/java/org/opensearch/security/EncryptionInTransitMigrationTests.java @@ -44,7 +44,7 @@ private void testSslOnlyMode(boolean dualModeEnabled) throws Exception { HttpResponse res = rh.executeGetRequest("_opendistro/_security/sslinfo"); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - res = rh.executePutRequest("/xyz/_doc/1","{\"a\":5}"); + res = rh.executePutRequest("/xyz/_doc/1", "{\"a\":5}"); Assert.assertEquals(HttpStatus.SC_CREATED, res.getStatusCode()); res = rh.executeGetRequest("/_mappings"); @@ -58,21 +58,29 @@ private void testSslOnlyMode(boolean dualModeEnabled) throws Exception { Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); Assert.assertTrue(res.getBody().contains("\"plugins.security_config.ssl_dual_mode_enabled\":\"true\"")); - String disableDualModeClusterSetting = "{ \"persistent\": { \"" + ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED + "\": false } }"; + String disableDualModeClusterSetting = "{ \"persistent\": { \"" + + ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED + + "\": false } }"; res = rh.executePutRequest("_cluster/settings", disableDualModeClusterSetting); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertEquals("{\"acknowledged\":true,\"persistent\":{\"plugins\":{\"security_config\":{\"ssl_dual_mode_enabled\":\"false\"}}},\"transient\":{}}", res.getBody()); - + Assert.assertEquals( + "{\"acknowledged\":true,\"persistent\":{\"plugins\":{\"security_config\":{\"ssl_dual_mode_enabled\":\"false\"}}},\"transient\":{}}", + res.getBody() + ); res = rh.executeGetRequest("_cluster/settings?flat_settings&include_defaults"); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); Assert.assertTrue(res.getBody().contains("\"plugins.security_config.ssl_dual_mode_enabled\":\"false\"")); - String enableDualModeClusterSetting = "{ \"persistent\": { \"" + ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED + "\": true } }"; + String enableDualModeClusterSetting = "{ \"persistent\": { \"" + + ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED + + "\": true } }"; res = rh.executePutRequest("_cluster/settings", enableDualModeClusterSetting); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertEquals("{\"acknowledged\":true,\"persistent\":{\"plugins\":{\"security_config\":{\"ssl_dual_mode_enabled\":\"true\"}}},\"transient\":{}}", res.getBody()); - + Assert.assertEquals( + "{\"acknowledged\":true,\"persistent\":{\"plugins\":{\"security_config\":{\"ssl_dual_mode_enabled\":\"true\"}}},\"transient\":{}}", + res.getBody() + ); res = rh.executeGetRequest("_cluster/settings?flat_settings&include_defaults"); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); @@ -80,8 +88,10 @@ private void testSslOnlyMode(boolean dualModeEnabled) throws Exception { res = rh.executePutRequest("_cluster/settings", disableDualModeClusterSetting); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertEquals("{\"acknowledged\":true,\"persistent\":{\"plugins\":{\"security_config\":{\"ssl_dual_mode_enabled\":\"false\"}}},\"transient\":{}}", res.getBody()); - + Assert.assertEquals( + "{\"acknowledged\":true,\"persistent\":{\"plugins\":{\"security_config\":{\"ssl_dual_mode_enabled\":\"false\"}}},\"transient\":{}}", + res.getBody() + ); res = rh.executeGetRequest("_cluster/settings?flat_settings&include_defaults"); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); @@ -118,23 +128,19 @@ public void testSslOnlyModeDualModeWithNonSSLDataNode() throws Exception { @Test public void testDualModeSettingFallback() throws Exception { final Settings legacySettings = Settings.builder() - .put(ConfigConstants.LEGACY_OPENDISTRO_SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, true) - .build(); + .put(ConfigConstants.LEGACY_OPENDISTRO_SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, true) + .build(); Assert.assertEquals(SecuritySettings.SSL_DUAL_MODE_SETTING.get(legacySettings), true); final Settings legacySettings2 = Settings.builder() - .put(ConfigConstants.LEGACY_OPENDISTRO_SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, false) - .build(); + .put(ConfigConstants.LEGACY_OPENDISTRO_SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, false) + .build(); Assert.assertEquals(SecuritySettings.SSL_DUAL_MODE_SETTING.get(legacySettings2), false); - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, true) - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, true).build(); Assert.assertEquals(SecuritySettings.SSL_DUAL_MODE_SETTING.get(settings), true); - final Settings settings2 = Settings.builder() - .put(ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, false) - .build(); + final Settings settings2 = Settings.builder().put(ConfigConstants.SECURITY_CONFIG_SSL_DUAL_MODE_ENABLED, false).build(); Assert.assertEquals(SecuritySettings.SSL_DUAL_MODE_SETTING.get(settings2), false); } } diff --git a/src/test/java/org/opensearch/security/HealthTests.java b/src/test/java/org/opensearch/security/HealthTests.java index 4cba4030e6..a31e22dff4 100644 --- a/src/test/java/org/opensearch/security/HealthTests.java +++ b/src/test/java/org/opensearch/security/HealthTests.java @@ -37,39 +37,48 @@ import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; public class HealthTests extends SingleClusterTest { - + @Test public void testHealth() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig(), Settings.EMPTY); - + RestHelper rh = nonSslRestHelper(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_opendistro/_security/health?pretty&mode=lenient")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_opendistro/_security/health?pretty&mode=lenient")).getStatusCode() + ); System.out.println(res.getBody()); assertContains(res, "*UP*"); assertNotContains(res, "*DOWN*"); assertNotContains(res, "*strict*"); - + Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); System.out.println(res.getBody()); assertContains(res, "*UP*"); assertContains(res, "*strict*"); assertNotContains(res, "*DOWN*"); } - + @Test public void testHealthUnitialized() throws Exception { setup(Settings.EMPTY, null, Settings.EMPTY, false); - + RestHelper rh = nonSslRestHelper(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_opendistro/_security/health?pretty&mode=lenient")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_opendistro/_security/health?pretty&mode=lenient")).getStatusCode() + ); System.out.println(res.getBody()); assertContains(res, "*UP*"); assertNotContains(res, "*DOWN*"); assertNotContains(res, "*strict*"); - - Assert.assertEquals(HttpStatus.SC_SERVICE_UNAVAILABLE, (res = rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_SERVICE_UNAVAILABLE, + (res = rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode() + ); System.out.println(res.getBody()); assertContains(res, "*DOWN*"); assertContains(res, "*strict*"); diff --git a/src/test/java/org/opensearch/security/HttpIntegrationTests.java b/src/test/java/org/opensearch/security/HttpIntegrationTests.java index d9ed9c34df..a4011b05f6 100644 --- a/src/test/java/org/opensearch/security/HttpIntegrationTests.java +++ b/src/test/java/org/opensearch/security/HttpIntegrationTests.java @@ -64,205 +64,373 @@ public class HttpIntegrationTests extends SingleClusterTest { @Test public void testHTTPBasic() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".worf", "knuddel","nonexists") - .build(); + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".worf", "knuddel", "nonexists") + .build(); setup(settings); final RestHelper rh = nonSslRestHelper(); - - try (Client tc = getClient()) { - tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("v2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("v3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); - - } - - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("_search").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeDeleteRequest("nonexistentindex*", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest(".nonexistentindex*", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest(".opendistro_security/_doc/2", "{}",encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, rh.executeGetRequest(".opendistro_security/_doc/0", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, rh.executeGetRequest("xxxxyyyy/_doc/0", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("abc", "abc:abc")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("userwithnopassword", "")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("userwithblankpassword", "")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrongpasswd")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "Basic "+"wrongheader")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "Basic ")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "Basic")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("picard", "picard")).getStatusCode()); - - for(int i=0; i< 10; i++) { - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrongpasswd")).getStatusCode()); - } - - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("/theindex","{}",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_CREATED, rh.executePutRequest("/theindex/_doc/1?refresh=true","{\"a\":0}",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - //Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("/theindex/_analyze?text=this+is+a+test",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - //Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_analyze?text=this+is+a+test",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeDeleteRequest("/theindex",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeDeleteRequest("/klingonempire",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("starfleet/_search", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_search", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeDeleteRequest(".opendistro_security/", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("/.opendistro_security/_close", null,encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("/.opendistro_security/_upgrade", null,encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest("/.opendistro_security/_mapping","{}",encodeBasicHeader("worf", "worf")).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest(".opendistro_security/", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest(".opendistro_security/_doc/2", "{}",encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest(".opendistro_security/_doc/0",encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeDeleteRequest(".opendistro_security/_doc/0",encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest(".opendistro_security/_doc/0","{}",encodeBasicHeader("worf", "worf")).getStatusCode()); - - HttpResponse resc = rh.executeGetRequest("_cat/indices/public?v",encodeBasicHeader("bug108", "nagilum")); - Assert.assertTrue(resc.getBody().contains("green")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("role01_role02/_search?pretty",encodeBasicHeader("user_role01_role02_role03", "user_role01_role02_role03")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("role01_role02/_search?pretty",encodeBasicHeader("user_role01", "user_role01")).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("spock/_search?pretty",encodeBasicHeader("spock", "spock")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("spock/_search?pretty",encodeBasicHeader("kirk", "kirk")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("kirk/_search?pretty",encodeBasicHeader("kirk", "kirk")).getStatusCode()); - - //all - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest(".opendistro_security/_mget","{\"ids\" : [\"0\"]}",encodeBasicHeader("worf", "worf")).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode()); - - try (Client tc = getClient()) { - tc.index(new IndexRequest(".opendistro_security").id("roles").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("roles", FileHelper.readYamlContent("roles_deny.yml"))).actionGet(); - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"roles"})).actionGet(); - Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); - } - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode()); - - try (Client tc = getClient()) { - tc.index(new IndexRequest(".opendistro_security").id("roles").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("roles", FileHelper.readYamlContent("roles.yml"))).actionGet(); - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"roles"})).actionGet(); - Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); - } - - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode()); - HttpResponse res = rh.executeGetRequest("_search?pretty", encodeBasicHeader("nagilum", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("\"value\" : 11")); - Assert.assertTrue(!res.getBody().contains(".opendistro_security")); - - res = rh.executeGetRequest("_nodes/stats?pretty", encodeBasicHeader("nagilum", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("total_in_bytes")); - Assert.assertTrue(res.getBody().contains("max_file_descriptors")); - Assert.assertTrue(res.getBody().contains("buffer_pools")); - Assert.assertFalse(res.getBody().contains("\"nodes\" : { }")); - - res = rh.executePostRequest("*/_upgrade", "", encodeBasicHeader("nagilum", "nagilum")); - System.out.println(res.getBody()); - System.out.println(res.getStatusReason()); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator(); - - res = rh.executePostRequest("_bulk", bulkBody, encodeBasicHeader("writer", "writer")); - System.out.println(res.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("\"errors\":false")); - Assert.assertTrue(res.getBody().contains("\"status\":201")); - - res = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("security_tenant", "unittesttenant"), encodeBasicHeader("worf", "worf")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("tenant")); - Assert.assertTrue(res.getBody().contains("unittesttenant")); - Assert.assertTrue(res.getBody().contains("\"kltentrw\":true")); - Assert.assertTrue(res.getBody().contains("\"user_name\":\"worf\"")); - - res = rh.executeGetRequest("_opendistro/_security/authinfo", encodeBasicHeader("worf", "worf")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("tenant")); - Assert.assertTrue(res.getBody().contains("\"user_requested_tenant\":null")); - Assert.assertTrue(res.getBody().contains("\"kltentrw\":true")); - Assert.assertTrue(res.getBody().contains("\"user_name\":\"worf\"")); - Assert.assertTrue(res.getBody().contains("\"custom_attribute_names\":[]")); - Assert.assertFalse(res.getBody().contains("attributes=")); - - res = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("custattr", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("tenants")); - Assert.assertTrue(res.getBody().contains("\"user_requested_tenant\" : null")); - Assert.assertTrue(res.getBody().contains("\"user_name\" : \"custattr\"")); - Assert.assertTrue(res.getBody().contains("\"custom_attribute_names\" : [")); - Assert.assertTrue(res.getBody().contains("attr.internal.c3")); - Assert.assertTrue(res.getBody().contains("attr.internal.c1")); - - res = rh.executeGetRequest("v2/_search", encodeBasicHeader("custattr", "nagilum")); - Assert.assertEquals(res.getBody(), HttpStatus.SC_OK, res.getStatusCode()); - - res = rh.executeGetRequest("v3/_search", encodeBasicHeader("custattr", "nagilum")); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - - final String reindex = "{"+ - "\"source\": {"+ - "\"index\": \"starfleet\""+ - "},"+ - "\"dest\": {"+ - "\"index\": \"copysf\""+ - "}"+ - "}"; - - res = rh.executePostRequest("_reindex?pretty", reindex, encodeBasicHeader("nagilum", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("\"total\" : 1")); - Assert.assertTrue(res.getBody().contains("\"batches\" : 1")); - Assert.assertTrue(res.getBody().contains("\"failures\" : [ ]")); - - //rest impersonation - res = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as","knuddel"), encodeBasicHeader("worf", "worf")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("name=knuddel")); - Assert.assertTrue(res.getBody().contains("attr.internal.test1")); - Assert.assertFalse(res.getBody().contains("worf")); - - res = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as","nonexists"), encodeBasicHeader("worf", "worf")); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - - res = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as","notallowed"), encodeBasicHeader("worf", "worf")); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); + + try (Client tc = getClient()) { + tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("v2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("v3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf")) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))) + .actionGet(); + + } + + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("_search").getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeDeleteRequest("nonexistentindex*", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest(".nonexistentindex*", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest(".opendistro_security/_doc/2", "{}", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + rh.executeGetRequest(".opendistro_security/_doc/0", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + rh.executeGetRequest("xxxxyyyy/_doc/0", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("abc", "abc:abc")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", encodeBasicHeader("userwithnopassword", "")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", encodeBasicHeader("userwithblankpassword", "")).getStatusCode() + ); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrongpasswd")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", new BasicHeader("Authorization", "Basic " + "wrongheader")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", new BasicHeader("Authorization", "Basic ")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", new BasicHeader("Authorization", "Basic")).getStatusCode() + ); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("picard", "picard")).getStatusCode()); + + for (int i = 0; i < 10; i++) { + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", encodeBasicHeader("worf", "wrongpasswd")).getStatusCode() + ); + } + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest("/theindex", "{}", encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_CREATED, + rh.executePutRequest("/theindex/_doc/1?refresh=true", "{\"a\":0}", encodeBasicHeader("theindexadmin", "theindexadmin")) + .getStatusCode() + ); + // Assert.assertEquals(HttpStatus.SC_OK, + // rh.executeGetRequest("/theindex/_analyze?text=this+is+a+test",encodeBasicHeader("theindexadmin", + // "theindexadmin")).getStatusCode()); + // Assert.assertEquals(HttpStatus.SC_FORBIDDEN, + // rh.executeGetRequest("_analyze?text=this+is+a+test",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeDeleteRequest("/theindex", encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeDeleteRequest("/klingonempire", encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode() + ); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("starfleet/_search", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_search", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeDeleteRequest(".opendistro_security/", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest("/.opendistro_security/_close", null, encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest("/.opendistro_security/_upgrade", null, encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("/.opendistro_security/_mapping", "{}", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest(".opendistro_security/", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest(".opendistro_security/_doc/2", "{}", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest(".opendistro_security/_doc/0", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeDeleteRequest(".opendistro_security/_doc/0", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest(".opendistro_security/_doc/0", "{}", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + + HttpResponse resc = rh.executeGetRequest("_cat/indices/public?v", encodeBasicHeader("bug108", "nagilum")); + Assert.assertTrue(resc.getBody().contains("green")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest( + "role01_role02/_search?pretty", + encodeBasicHeader("user_role01_role02_role03", "user_role01_role02_role03") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest("role01_role02/_search?pretty", encodeBasicHeader("user_role01", "user_role01")).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("spock/_search?pretty", encodeBasicHeader("spock", "spock")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest("spock/_search?pretty", encodeBasicHeader("kirk", "kirk")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("kirk/_search?pretty", encodeBasicHeader("kirk", "kirk")).getStatusCode() + ); + + // all + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest(".opendistro_security/_mget", "{\"ids\" : [\"0\"]}", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + + try (Client tc = getClient()) { + tc.index( + new IndexRequest(".opendistro_security").id("roles") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("roles", FileHelper.readYamlContent("roles_deny.yml")) + ).actionGet(); + ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[] { "roles" })) + .actionGet(); + Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); } + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + + try (Client tc = getClient()) { + tc.index( + new IndexRequest(".opendistro_security").id("roles") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("roles", FileHelper.readYamlContent("roles.yml")) + ).actionGet(); + ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[] { "roles" })) + .actionGet(); + Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); + } + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + HttpResponse res = rh.executeGetRequest("_search?pretty", encodeBasicHeader("nagilum", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("\"value\" : 11")); + Assert.assertTrue(!res.getBody().contains(".opendistro_security")); + + res = rh.executeGetRequest("_nodes/stats?pretty", encodeBasicHeader("nagilum", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("total_in_bytes")); + Assert.assertTrue(res.getBody().contains("max_file_descriptors")); + Assert.assertTrue(res.getBody().contains("buffer_pools")); + Assert.assertFalse(res.getBody().contains("\"nodes\" : { }")); + + res = rh.executePostRequest("*/_upgrade", "", encodeBasicHeader("nagilum", "nagilum")); + System.out.println(res.getBody()); + System.out.println(res.getStatusReason()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator(); + + res = rh.executePostRequest("_bulk", bulkBody, encodeBasicHeader("writer", "writer")); + System.out.println(res.getBody()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("\"errors\":false")); + Assert.assertTrue(res.getBody().contains("\"status\":201")); + + res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("security_tenant", "unittesttenant"), + encodeBasicHeader("worf", "worf") + ); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("tenant")); + Assert.assertTrue(res.getBody().contains("unittesttenant")); + Assert.assertTrue(res.getBody().contains("\"kltentrw\":true")); + Assert.assertTrue(res.getBody().contains("\"user_name\":\"worf\"")); + + res = rh.executeGetRequest("_opendistro/_security/authinfo", encodeBasicHeader("worf", "worf")); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("tenant")); + Assert.assertTrue(res.getBody().contains("\"user_requested_tenant\":null")); + Assert.assertTrue(res.getBody().contains("\"kltentrw\":true")); + Assert.assertTrue(res.getBody().contains("\"user_name\":\"worf\"")); + Assert.assertTrue(res.getBody().contains("\"custom_attribute_names\":[]")); + Assert.assertFalse(res.getBody().contains("attributes=")); + + res = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("custattr", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("tenants")); + Assert.assertTrue(res.getBody().contains("\"user_requested_tenant\" : null")); + Assert.assertTrue(res.getBody().contains("\"user_name\" : \"custattr\"")); + Assert.assertTrue(res.getBody().contains("\"custom_attribute_names\" : [")); + Assert.assertTrue(res.getBody().contains("attr.internal.c3")); + Assert.assertTrue(res.getBody().contains("attr.internal.c1")); + + res = rh.executeGetRequest("v2/_search", encodeBasicHeader("custattr", "nagilum")); + Assert.assertEquals(res.getBody(), HttpStatus.SC_OK, res.getStatusCode()); + + res = rh.executeGetRequest("v3/_search", encodeBasicHeader("custattr", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); + + final String reindex = "{" + + "\"source\": {" + + "\"index\": \"starfleet\"" + + "}," + + "\"dest\": {" + + "\"index\": \"copysf\"" + + "}" + + "}"; + + res = rh.executePostRequest("_reindex?pretty", reindex, encodeBasicHeader("nagilum", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("\"total\" : 1")); + Assert.assertTrue(res.getBody().contains("\"batches\" : 1")); + Assert.assertTrue(res.getBody().contains("\"failures\" : [ ]")); + + // rest impersonation + res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "knuddel"), + encodeBasicHeader("worf", "worf") + ); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("name=knuddel")); + Assert.assertTrue(res.getBody().contains("attr.internal.test1")); + Assert.assertFalse(res.getBody().contains("worf")); + + res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "nonexists"), + encodeBasicHeader("worf", "worf") + ); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); + + res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "notallowed"), + encodeBasicHeader("worf", "worf") + ); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); + } + @Test public void testHTTPSCompressionEnabled() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .put("http.compression",true) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .put("http.compression", true) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings, true); - final RestHelper rh = restHelper(); //ssl resthelper + final RestHelper rh = restHelper(); // ssl resthelper HttpResponse res = rh.executeGetRequest("_opendistro/_security/sslinfo", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); @@ -274,16 +442,16 @@ public void testHTTPSCompressionEnabled() throws Exception { assertNotContains(res, "*\"compression\":\"false\"*"); assertContains(res, "*\"compression\":\"true\"*"); } - + @Test public void testHTTPSCompression() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings, true); - final RestHelper rh = restHelper(); //ssl resthelper + final RestHelper rh = restHelper(); // ssl resthelper HttpResponse res = rh.executeGetRequest("_opendistro/_security/sslinfo", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); @@ -298,78 +466,92 @@ public void testHTTPSCompression() throws Exception { @Test public void testHTTPAnon() throws Exception { - - setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_anon.yml"), Settings.EMPTY, true); - - RestHelper rh = nonSslRestHelper(); - - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrong")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - - HttpResponse resc = rh.executeGetRequest("_opendistro/_security/authinfo"); - Assert.assertTrue(resc.getBody().contains("opendistro_security_anonymous")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - - resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty=true"); - System.out.println(resc.getBody()); - Assert.assertTrue(resc.getBody().contains("\"remote_address\" : \"")); //check pretty print - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - - resc = rh.executeGetRequest("_opendistro/_security/authinfo", encodeBasicHeader("nagilum", "nagilum")); - System.out.println(resc.getBody()); - Assert.assertTrue(resc.getBody().contains("nagilum")); - Assert.assertFalse(resc.getBody().contains("opendistro_security_anonymous")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - - try (Client tc = getClient()) { - tc.index(new IndexRequest(".opendistro_security").id("config").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("config", FileHelper.readYamlContent("config.yml"))).actionGet(); - tc.index(new IndexRequest(".opendistro_security").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("internalusers").source("internalusers", FileHelper.readYamlContent("internal_users.yml"))).actionGet(); - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"config","roles","rolesmapping","internalusers","actiongroups"})).actionGet(); - Assert.assertFalse(cur.hasFailures()); - Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); - } - - - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("_opendistro/_security/authinfo").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrong")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + + setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_anon.yml"), Settings.EMPTY, true); + + RestHelper rh = nonSslRestHelper(); + + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("").getStatusCode()); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrong")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + + HttpResponse resc = rh.executeGetRequest("_opendistro/_security/authinfo"); + Assert.assertTrue(resc.getBody().contains("opendistro_security_anonymous")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty=true"); + System.out.println(resc.getBody()); + Assert.assertTrue(resc.getBody().contains("\"remote_address\" : \"")); // check pretty print + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + resc = rh.executeGetRequest("_opendistro/_security/authinfo", encodeBasicHeader("nagilum", "nagilum")); + System.out.println(resc.getBody()); + Assert.assertTrue(resc.getBody().contains("nagilum")); + Assert.assertFalse(resc.getBody().contains("opendistro_security_anonymous")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + try (Client tc = getClient()) { + tc.index( + new IndexRequest(".opendistro_security").id("config") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("config", FileHelper.readYamlContent("config.yml")) + ).actionGet(); + tc.index( + new IndexRequest(".opendistro_security").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("internalusers") + .source("internalusers", FileHelper.readYamlContent("internal_users.yml")) + ).actionGet(); + ConfigUpdateResponse cur = tc.execute( + ConfigUpdateAction.INSTANCE, + new ConfigUpdateRequest(new String[] { "config", "roles", "rolesmapping", "internalusers", "actiongroups" }) + ).actionGet(); + Assert.assertFalse(cur.hasFailures()); + Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); + } + + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("_opendistro/_security/authinfo").getStatusCode()); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrong")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); } @Test public void testHTTPClientCert() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.clientauth_mode","REQUIRE") - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .putList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, "TLSv1.1","TLSv1.2") - .putList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_CIPHERS, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256") - .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "TLSv1.1","TLSv1.2") - .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256") - .build(); - + .put("plugins.security.ssl.http.clientauth_mode", "REQUIRE") + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .putList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, "TLSv1.1", "TLSv1.2") + .putList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_CIPHERS, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256") + .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "TLSv1.1", "TLSv1.2") + .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256") + .build(); + setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_clientcert.yml"), settings, true); - + try (Client tc = getClient()) { - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"config","roles","rolesmapping","internalusers","actiongroups"})).actionGet(); + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + ConfigUpdateResponse cur = tc.execute( + ConfigUpdateAction.INSTANCE, + new ConfigUpdateRequest(new String[] { "config", "roles", "rolesmapping", "internalusers", "actiongroups" }) + ).actionGet(); Assert.assertFalse(cur.hasFailures()); Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); } - + RestHelper rh = restHelper(); - + rh.enableHTTPClientSSL = true; rh.trustHTTPServerCertificate = true; rh.sendAdminCertificate = true; rh.keystore = "spock-keystore.jks"; Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_search").getStatusCode()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest(".opendistro_security/_doc/x", "{}").getStatusCode()); - + rh.keystore = "kirk-keystore.jks"; Assert.assertEquals(HttpStatus.SC_CREATED, rh.executePutRequest(".opendistro_security/_doc/y", "{}").getStatusCode()); HttpResponse res; @@ -380,13 +562,13 @@ public void testHTTPClientCert() throws Exception { @Test @Ignore public void testHTTPPlaintextErrMsg() throws Exception { - + try { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .put("plugins.security.ssl.http.enabled", true) - .build(); + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .put("plugins.security.ssl.http.enabled", true) + .build(); setup(settings); RestHelper rh = nonSslRestHelper(); rh.executeGetRequest("", encodeBasicHeader("worf", "worf")); @@ -395,27 +577,75 @@ public void testHTTPPlaintextErrMsg() throws Exception { String log = FileUtils.readFileToString(new File("unittest.log"), StandardCharsets.UTF_8); Assert.assertTrue(log, log.contains("speaks http plaintext instead of ssl, will close the channel")); } catch (Exception e) { - Assert.fail("NoHttpResponseException expected but was "+e.getClass()+"#"+e.getMessage()); + Assert.fail("NoHttpResponseException expected but was " + e.getClass() + "#" + e.getMessage()); } } - @Test public void testHTTPProxyDefault() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_proxy.yml"), Settings.EMPTY, true); RestHelper rh = nonSslRestHelper(); - + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"),new BasicHeader("x-proxy-user", "scotty"), encodeBasicHeader("nagilum-wrong", "nagilum-wrong")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"),new BasicHeader("x-proxy-user-wrong", "scotty"), encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, rh.executeGetRequest("", new BasicHeader("x-forwarded-for", "a"),new BasicHeader("x-proxy-user", "scotty"), encodeBasicHeader("nagilum-wrong", "nagilum-wrong")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, rh.executeGetRequest("", new BasicHeader("x-forwarded-for", "a,b,c"),new BasicHeader("x-proxy-user", "scotty")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"),new BasicHeader("x-proxy-user", "scotty")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"),new BasicHeader("X-Proxy-User", "scotty")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"),new BasicHeader("x-proxy-user", "scotty"),new BasicHeader("x-proxy-roles", "starfleet,engineer")).getStatusCode()); - + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest( + "", + new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"), + new BasicHeader("x-proxy-user", "scotty"), + encodeBasicHeader("nagilum-wrong", "nagilum-wrong") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest( + "", + new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"), + new BasicHeader("x-proxy-user-wrong", "scotty"), + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + rh.executeGetRequest( + "", + new BasicHeader("x-forwarded-for", "a"), + new BasicHeader("x-proxy-user", "scotty"), + encodeBasicHeader("nagilum-wrong", "nagilum-wrong") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + rh.executeGetRequest("", new BasicHeader("x-forwarded-for", "a,b,c"), new BasicHeader("x-proxy-user", "scotty")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest( + "", + new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"), + new BasicHeader("x-proxy-user", "scotty") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest( + "", + new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"), + new BasicHeader("X-Proxy-User", "scotty") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest( + "", + new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"), + new BasicHeader("x-proxy-user", "scotty"), + new BasicHeader("x-proxy-roles", "starfleet,engineer") + ).getStatusCode() + ); + } @Test @@ -423,140 +653,282 @@ public void testHTTPProxyRolesSeparator() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_proxy_custom.yml"), Settings.EMPTY, true); RestHelper rh = nonSslRestHelper(); // separator is configured as ";" so separating roles with "," leads to one (wrong) backend role - HttpResponse res = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"),new BasicHeader("user", "scotty"),new BasicHeader("roles", "starfleet,engineer")); - Assert.assertTrue("Expected one backend role since separator is incorrect", res.getBody().contains("\"backend_roles\":[\"starfleet,engineer\"]")); + HttpResponse res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"), + new BasicHeader("user", "scotty"), + new BasicHeader("roles", "starfleet,engineer") + ); + Assert.assertTrue( + "Expected one backend role since separator is incorrect", + res.getBody().contains("\"backend_roles\":[\"starfleet,engineer\"]") + ); // correct separator, now we should see two backend roles - res = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"),new BasicHeader("user", "scotty"),new BasicHeader("roles", "starfleet;engineer")); - Assert.assertTrue("Expected two backend roles string since separator is correct: " + res.getBody(), res.getBody().contains("\"backend_roles\":[\"starfleet\",\"engineer\"]")); - + res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("x-forwarded-for", "localhost,192.168.0.1,10.0.0.2"), + new BasicHeader("user", "scotty"), + new BasicHeader("roles", "starfleet;engineer") + ); + Assert.assertTrue( + "Expected two backend roles string since separator is correct: " + res.getBody(), + res.getBody().contains("\"backend_roles\":[\"starfleet\",\"engineer\"]") + ); + } @Test - public void testHTTPBasic2() throws Exception { - - setup(Settings.EMPTY, new DynamicSecurityConfig(), Settings.EMPTY); - - try (Client tc = getClient()) { - - tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); - } - - RestHelper rh = nonSslRestHelper(); - - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeDeleteRequest("nonexistentindex*", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest(".nonexistentindex*", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest(".opendistro_security/_doc/2", "{}",encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, rh.executeGetRequest(".opendistro_security/_doc/0", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, rh.executeGetRequest("xxxxyyyy/_doc/0", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("abc", "abc:abc")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("userwithnopassword", "")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("userwithblankpassword", "")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrongpasswd")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "Basic "+"wrongheader")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "Basic ")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "Basic")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("picard", "picard")).getStatusCode()); - - for(int i=0; i< 10; i++) { - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrongpasswd")).getStatusCode()); - } - - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("/theindex","{}",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_CREATED, rh.executePutRequest("/theindex/_doc/1?refresh=true","{\"a\":0}",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - //Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("/theindex/_analyze?text=this+is+a+test",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - //Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_analyze?text=this+is+a+test",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeDeleteRequest("/theindex",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeDeleteRequest("/klingonempire",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("starfleet/_search", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_search", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeDeleteRequest(".opendistro_security/", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("/.opendistro_security/_close", null,encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("/.opendistro_security/_upgrade", null,encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest("/.opendistro_security/_mapping","{}",encodeBasicHeader("worf", "worf")).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest(".opendistro_security/", encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest(".opendistro_security/_doc/2", "{}",encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest(".opendistro_security/_doc/0",encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeDeleteRequest(".opendistro_security/_doc/0",encodeBasicHeader("worf", "worf")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest(".opendistro_security/_doc/0","{}",encodeBasicHeader("worf", "worf")).getStatusCode()); - - HttpResponse resc = rh.executeGetRequest("_cat/indices/public",encodeBasicHeader("bug108", "nagilum")); - System.out.println(resc.getBody()); - //Assert.assertTrue(resc.getBody().contains("green")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("role01_role02/_search?pretty",encodeBasicHeader("user_role01_role02_role03", "user_role01_role02_role03")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("role01_role02/_search?pretty",encodeBasicHeader("user_role01", "user_role01")).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("spock/_search?pretty",encodeBasicHeader("spock", "spock")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("spock/_search?pretty",encodeBasicHeader("kirk", "kirk")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("kirk/_search?pretty",encodeBasicHeader("kirk", "kirk")).getStatusCode()); - - System.out.println("ok"); - //all - - + public void testHTTPBasic2() throws Exception { + + setup(Settings.EMPTY, new DynamicSecurityConfig(), Settings.EMPTY); + + try (Client tc = getClient()) { + + tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); + + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf")) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))) + .actionGet(); + } + + RestHelper rh = nonSslRestHelper(); + + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeDeleteRequest("nonexistentindex*", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest(".nonexistentindex*", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest(".opendistro_security/_doc/2", "{}", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + rh.executeGetRequest(".opendistro_security/_doc/0", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + rh.executeGetRequest("xxxxyyyy/_doc/0", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("abc", "abc:abc")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", encodeBasicHeader("userwithnopassword", "")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", encodeBasicHeader("userwithblankpassword", "")).getStatusCode() + ); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("worf", "wrongpasswd")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", new BasicHeader("Authorization", "Basic " + "wrongheader")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", new BasicHeader("Authorization", "Basic ")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", new BasicHeader("Authorization", "Basic")).getStatusCode() + ); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", new BasicHeader("Authorization", "")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("picard", "picard")).getStatusCode()); + + for (int i = 0; i < 10; i++) { + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executeGetRequest("", encodeBasicHeader("worf", "wrongpasswd")).getStatusCode() + ); } - + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest("/theindex", "{}", encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_CREATED, + rh.executePutRequest("/theindex/_doc/1?refresh=true", "{\"a\":0}", encodeBasicHeader("theindexadmin", "theindexadmin")) + .getStatusCode() + ); + // Assert.assertEquals(HttpStatus.SC_OK, + // rh.executeGetRequest("/theindex/_analyze?text=this+is+a+test",encodeBasicHeader("theindexadmin", + // "theindexadmin")).getStatusCode()); + // Assert.assertEquals(HttpStatus.SC_FORBIDDEN, + // rh.executeGetRequest("_analyze?text=this+is+a+test",encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeDeleteRequest("/theindex", encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeDeleteRequest("/klingonempire", encodeBasicHeader("theindexadmin", "theindexadmin")).getStatusCode() + ); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("starfleet/_search", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_search", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeDeleteRequest(".opendistro_security/", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest("/.opendistro_security/_close", null, encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest("/.opendistro_security/_upgrade", null, encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("/.opendistro_security/_mapping", "{}", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest(".opendistro_security/", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest(".opendistro_security/_doc/2", "{}", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest(".opendistro_security/_doc/0", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeDeleteRequest(".opendistro_security/_doc/0", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest(".opendistro_security/_doc/0", "{}", encodeBasicHeader("worf", "worf")).getStatusCode() + ); + + HttpResponse resc = rh.executeGetRequest("_cat/indices/public", encodeBasicHeader("bug108", "nagilum")); + System.out.println(resc.getBody()); + // Assert.assertTrue(resc.getBody().contains("green")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest( + "role01_role02/_search?pretty", + encodeBasicHeader("user_role01_role02_role03", "user_role01_role02_role03") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest("role01_role02/_search?pretty", encodeBasicHeader("user_role01", "user_role01")).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("spock/_search?pretty", encodeBasicHeader("spock", "spock")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest("spock/_search?pretty", encodeBasicHeader("kirk", "kirk")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("kirk/_search?pretty", encodeBasicHeader("kirk", "kirk")).getStatusCode() + ); + + System.out.println("ok"); + // all + + } + @Test public void testBulk() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityRoles("roles_bulk.yml"), settings); final RestHelper rh = nonSslRestHelper(); - - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator(); - + + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator(); + HttpResponse res = rh.executePostRequest("_bulk", bulkBody, encodeBasicHeader("bulk", "nagilum")); System.out.println(res.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); Assert.assertTrue(res.getBody().contains("\"errors\":false")); Assert.assertTrue(res.getBody().contains("\"status\":201")); } @Test public void testBulkWithOneIndexFailure() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityRoles("roles_bulk.yml"), settings); final RestHelper rh = nonSslRestHelper(); - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"a\" : \"b\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"myindex\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"a\" : \"b\" }"+System.lineSeparator(); + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"a\" : \"b\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"myindex\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"a\" : \"b\" }" + + System.lineSeparator(); HttpResponse res = rh.executePostRequest("_bulk?refresh=true", bulkBody, encodeBasicHeader("bulk_test_user", "nagilum")); System.out.println(res.getBody()); @@ -569,64 +941,101 @@ public void testBulkWithOneIndexFailure() throws Exception { @Test public void test557() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings); - + try (Client tc = getClient()) { - + tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - + + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + } - + final RestHelper rh = nonSslRestHelper(); - HttpResponse res = rh.executePostRequest("/*/_search", "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":10}}}}", encodeBasicHeader("nagilum", "nagilum")); + HttpResponse res = rh.executePostRequest( + "/*/_search", + "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":10}}}}", + encodeBasicHeader("nagilum", "nagilum") + ); System.out.println(res.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); Assert.assertTrue(res.getBody().contains("starfleet_academy")); - res = rh.executePostRequest("/*/_search", "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":10}}}}", encodeBasicHeader("557", "nagilum")); + res = rh.executePostRequest( + "/*/_search", + "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":10}}}}", + encodeBasicHeader("557", "nagilum") + ); System.out.println(res.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody().contains("starfleet_academy")); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody().contains("starfleet_academy")); } - + @Test public void testITT1635() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_dnfof.yml").setSecurityRoles("roles_itt1635.yml"), settings); - + try (Client tc = getClient()) { - - tc.index(new IndexRequest("esb-prod-1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("esb-prod-2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("esb-prod-3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("esb-prod-4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":4}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("esb-prod-5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":5}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-1","esb-prod-2","esb-prod-3","esb-prod-4","esb-prod-5").alias("esb-prod-all"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-1").alias("esb-alias-1"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-2").alias("esb-alias-2"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-3").alias("esb-alias-3"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-4").alias("esb-alias-4"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-5").alias("esb-alias-5"))).actionGet(); + + tc.index(new IndexRequest("esb-prod-1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("esb-prod-2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("esb-prod-3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("esb-prod-4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":4}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("esb-prod-5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":5}", XContentType.JSON)) + .actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add() + .indices("esb-prod-1", "esb-prod-2", "esb-prod-3", "esb-prod-4", "esb-prod-5") + .alias("esb-prod-all") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-1").alias("esb-alias-1"))) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-2").alias("esb-alias-2"))) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-3").alias("esb-alias-3"))) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-4").alias("esb-alias-4"))) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-5").alias("esb-alias-5"))) + .actionGet(); } - + final RestHelper rh = nonSslRestHelper(); System.out.println("###1"); HttpResponse res = rh.executeGetRequest("/esb-prod-*/_search?pretty", encodeBasicHeader("itt1635", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); System.out.println("###2"); res = rh.executeGetRequest("/esb-alias-*/_search?pretty", encodeBasicHeader("itt1635", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); @@ -634,49 +1043,82 @@ public void testITT1635() throws Exception { res = rh.executeGetRequest("/esb-prod-all/_search?pretty", encodeBasicHeader("itt1635", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); } - + @Test public void testTenantInfo() throws Exception { - final Settings settings = Settings.builder() - .build(); + final Settings settings = Settings.builder().build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings); - + /* - + [admin_1, praxisrw, abcdef_2_2, kltentro, praxisro, kltentrw] - admin_1==.kibana_-1139640511_admin1 - praxisrw==.kibana_-1386441176_praxisrw - abcdef_2_2==.kibana_-634608247_abcdef22 - kltentro==.kibana_-2014056171_kltentro - praxisro==.kibana_-1386441184_praxisro - kltentrw==.kibana_-2014056163_kltentrw - + admin_1==.kibana_-1139640511_admin1 + praxisrw==.kibana_-1386441176_praxisrw + abcdef_2_2==.kibana_-634608247_abcdef22 + kltentro==.kibana_-2014056171_kltentro + praxisro==.kibana_-1386441184_praxisro + kltentrw==.kibana_-2014056163_kltentrw + */ - + try (Client tc = getClient()) { - - tc.index(new IndexRequest(".kibana-6").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest(".kibana_-1139640511_admin1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest(".kibana_-1386441176_praxisrw").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest(".kibana_-634608247_abcdef22").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest(".kibana_-12345_123456").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest(".kibana2_-12345_123456").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest(".kibana_9876_xxx_ccc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest(".kibana_fff_eee").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - - - tc.index(new IndexRequest("esb-prod-5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":5}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices(".kibana-6").alias(".kibana"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-5").alias(".kibana_-2014056163_kltentrw"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-5").alias("esb-alias-5"))).actionGet(); + + tc.index(new IndexRequest(".kibana-6").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest(".kibana_-1139640511_admin1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":3}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest(".kibana_-1386441176_praxisrw").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":3}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest(".kibana_-634608247_abcdef22").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":3}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest(".kibana_-12345_123456").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":3}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest(".kibana2_-12345_123456").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":3}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest(".kibana_9876_xxx_ccc").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":3}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest(".kibana_fff_eee").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON) + ).actionGet(); + + tc.index(new IndexRequest("esb-prod-5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":5}", XContentType.JSON)) + .actionGet(); + + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices(".kibana-6").alias(".kibana"))) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("esb-prod-5").alias(".kibana_-2014056163_kltentrw") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("esb-prod-5").alias("esb-alias-5"))) + .actionGet(); } - + final RestHelper rh = nonSslRestHelper(); HttpResponse res = rh.executeGetRequest("_opendistro/_security/tenantinfo?pretty", encodeBasicHeader("itt1635", "nagilum")); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); res = rh.executeGetRequest("_opendistro/_security/tenantinfo?pretty", encodeBasicHeader("kibanaserver", "kibanaserver")); System.out.println(res.getBody()); @@ -691,17 +1133,21 @@ public void testTenantInfo() throws Exception { Assert.assertFalse(res.getBody().contains("xxx")); Assert.assertFalse(res.getBody().contains(".kibana2")); } - + @Test public void testRestImpersonation() throws Exception { final Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".worf", "someotherusernotininternalusersfile") - .build(); + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".worf", "someotherusernotininternalusersfile") + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_rest_impersonation.yml"), settings); final RestHelper rh = nonSslRestHelper(); - - //rest impersonation - HttpResponse res = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as","someotherusernotininternalusersfile"), encodeBasicHeader("worf", "worf")); + + // rest impersonation + HttpResponse res = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "someotherusernotininternalusersfile"), + encodeBasicHeader("worf", "worf") + ); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); Assert.assertTrue(res.getBody().contains("name=someotherusernotininternalusersfile")); Assert.assertFalse(res.getBody().contains("worf")); @@ -709,16 +1155,14 @@ public void testRestImpersonation() throws Exception { @Test public void testSslOnlyMode() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_SSL_ONLY, true).build(); setupSslOnlyMode(settings); final RestHelper rh = nonSslRestHelper(); HttpResponse res = rh.executeGetRequest("_opendistro/_security/sslinfo"); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - res = rh.executePutRequest("/xyz/_doc/1","{\"a\":5}"); + res = rh.executePutRequest("/xyz/_doc/1", "{\"a\":5}"); Assert.assertEquals(HttpStatus.SC_CREATED, res.getStatusCode()); res = rh.executeGetRequest("/_mappings"); @@ -736,10 +1180,13 @@ public void testAll() throws Exception { try (Client tc = getClient()) { tc.index(new IndexRequest("abcdef").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) - .actionGet(); + .actionGet(); } - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_all/_search", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest("_all/_search", encodeBasicHeader("worf", "worf")).getStatusCode() + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("*/_search", encodeBasicHeader("worf", "worf")).getStatusCode()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_search", encodeBasicHeader("worf", "worf")).getStatusCode()); } diff --git a/src/test/java/org/opensearch/security/IndexIntegrationTests.java b/src/test/java/org/opensearch/security/IndexIntegrationTests.java index 8f2ee960bd..6a8703842e 100644 --- a/src/test/java/org/opensearch/security/IndexIntegrationTests.java +++ b/src/test/java/org/opensearch/security/IndexIntegrationTests.java @@ -59,68 +59,103 @@ public class IndexIntegrationTests extends SingleClusterTest { @Test public void testComposite() throws Exception { - - setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("composite_config.yml").setSecurityRoles("roles_composite.yml"), Settings.EMPTY, true); + + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setConfig("composite_config.yml").setSecurityRoles("roles_composite.yml"), + Settings.EMPTY, + true + ); final RestHelper rh = nonSslRestHelper(); - + try (Client tc = getClient()) { - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); } - - String msearchBody = - "{\"index\":\"starfleet\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"klingonempire\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"public\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - - + + String msearchBody = "{\"index\":\"starfleet\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"klingonempire\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"public\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); + HttpResponse resc = rh.executePostRequest("_msearch", msearchBody, encodeBasicHeader("worf", "worf")); Assert.assertEquals(200, resc.getStatusCode()); Assert.assertTrue(resc.getBody(), resc.getBody().contains("\"_index\":\"klingonempire\"")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("hits")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("no permissions for [indices:data/read/search]")); - + } - + @Test public void testBulkShards() throws Exception { - + setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityRoles("roles_bs.yml"), Settings.EMPTY, true); final RestHelper rh = nonSslRestHelper(); - + try (Client tc = getClient()) { - //create indices and mapping upfront - tc.index(new IndexRequest("test").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("lorem").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)).actionGet(); + // create indices and mapping upfront + tc.index(new IndexRequest("test").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("lorem").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)) + .actionGet(); } - - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"3\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"4\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"5\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"3\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"4\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"5\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"delete\" : { \"_index\" : \"lorem\", \"_id\" : \"5\" } }"+System.lineSeparator(); - + + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"3\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"4\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"5\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"3\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"4\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"lorem\", \"_id\" : \"5\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"delete\" : { \"_index\" : \"lorem\", \"_id\" : \"5\" } }" + + System.lineSeparator(); + System.out.println("############ _bulk"); HttpResponse res = rh.executePostRequest("_bulk?refresh=true&pretty=true", bulkBody, encodeBasicHeader("worf", "worf")); System.out.println(res.getBody()); @@ -128,129 +163,177 @@ public void testBulkShards() throws Exception { Assert.assertTrue(res.getBody().contains("\"errors\" : true")); Assert.assertTrue(res.getBody().contains("\"status\" : 201")); Assert.assertTrue(res.getBody().contains("no permissions for")); - + System.out.println("############ check shards"); System.out.println(rh.executeGetRequest("_cat/shards?v", encodeBasicHeader("nagilum", "nagilum"))); - } @Test public void testCreateIndex() throws Exception { - + setup(); RestHelper rh = nonSslRestHelper(); - + HttpResponse res; - Assert.assertEquals("Unable to create index 'nag'", HttpStatus.SC_OK, rh.executePutRequest("nag1", null, encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals("Unable to create index 'starfleet_library'", HttpStatus.SC_OK, rh.executePutRequest("starfleet_library", null, encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - + Assert.assertEquals( + "Unable to create index 'nag'", + HttpStatus.SC_OK, + rh.executePutRequest("nag1", null, encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + "Unable to create index 'starfleet_library'", + HttpStatus.SC_OK, + rh.executePutRequest("starfleet_library", null, encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + clusterHelper.waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10), clusterInfo.numNodes); - - Assert.assertEquals("Unable to close index 'starfleet_library'", HttpStatus.SC_OK, rh.executePostRequest("starfleet_library/_close", null, encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - - Assert.assertEquals("Unable to open index 'starfleet_library'", HttpStatus.SC_OK, (res = rh.executePostRequest("starfleet_library/_open", null, encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + + Assert.assertEquals( + "Unable to close index 'starfleet_library'", + HttpStatus.SC_OK, + rh.executePostRequest("starfleet_library/_close", null, encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + + Assert.assertEquals( + "Unable to open index 'starfleet_library'", + HttpStatus.SC_OK, + (res = rh.executePostRequest("starfleet_library/_open", null, encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); Assert.assertTrue("open index 'starfleet_library' not acknowledged", res.getBody().contains("acknowledged")); Assert.assertFalse("open index 'starfleet_library' not acknowledged", res.getBody().contains("false")); - + clusterHelper.waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10), clusterInfo.numNodes); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePutRequest("public", null, encodeBasicHeader("spock", "spock")).getStatusCode()); - - + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("public", null, encodeBasicHeader("spock", "spock")).getStatusCode() + ); + } @Test public void testFilteredAlias() throws Exception { - + setup(); - + try (Client tc = getClient()) { - tc.index(new IndexRequest("theindex").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("otherindex").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().alias("alias1").filter(QueryBuilders.termQuery("_type", "type1")).index("theindex"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().alias("alias2").filter(QueryBuilders.termQuery("_type", "type2")).index("theindex"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().alias("alias3").filter(QueryBuilders.termQuery("_type", "type2")).index("otherindex"))).actionGet(); + tc.index(new IndexRequest("theindex").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("otherindex").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().alias("alias1").filter(QueryBuilders.termQuery("_type", "type1")).index("theindex") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().alias("alias2").filter(QueryBuilders.termQuery("_type", "type2")).index("theindex") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().alias("alias3").filter(QueryBuilders.termQuery("_type", "type2")).index("otherindex") + ) + ) + .actionGet(); } - - + RestHelper rh = nonSslRestHelper(); - - //opendistro_security_user1 -> worf - //opendistro_security_user2 -> picard - + + // opendistro_security_user1 -> worf + // opendistro_security_user2 -> picard + HttpResponse resc = rh.executeGetRequest("alias*/_search", encodeBasicHeader("worf", "worf")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - - resc = rh.executeGetRequest("theindex/_search", encodeBasicHeader("nagilum", "nagilum")); + + resc = rh.executeGetRequest("theindex/_search", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - - resc = rh.executeGetRequest("alias3/_search", encodeBasicHeader("nagilum", "nagilum")); + + resc = rh.executeGetRequest("alias3/_search", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - resc = rh.executeGetRequest("_cat/indices", encodeBasicHeader("nagilum", "nagilum")); + resc = rh.executeGetRequest("_cat/indices", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - + } - + @Test public void testIndexTypeEvaluation() throws Exception { - + setup(); try (Client tc = getClient()) { - tc.index(new IndexRequest("foo1").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("foo2").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("foo").id("3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("fooba").id("4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":4}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("foo1").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("foo2").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("foo").id("3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("fooba").id("4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":4}", XContentType.JSON) + ).actionGet(); try { - tc.index(new IndexRequest("x#a").id("4a").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":4}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("x#a").id("4a").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":4}", XContentType.JSON) + ).actionGet(); Assert.fail("Indexname can contain #"); } catch (InvalidIndexNameException e) { - //expected + // expected } } - + RestHelper rh = nonSslRestHelper(); - + HttpResponse resc = rh.executeGetRequest("/foo1/_search?pretty", encodeBasicHeader("baz", "worf")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("\"content\" : 1")); - + resc = rh.executeGetRequest("/foo2/_search?pretty", encodeBasicHeader("baz", "worf")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("\"content\" : 2")); - + resc = rh.executeGetRequest("/foo/_search?pretty", encodeBasicHeader("baz", "worf")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("\"content\" : 3")); - - //resc = rh.executeGetRequest("/fooba/z/_search?pretty", encodeBasicHeader("baz", "worf")); - //Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - + + // resc = rh.executeGetRequest("/fooba/z/_search?pretty", encodeBasicHeader("baz", "worf")); + // Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + resc = rh.executeGetRequest("/foo1/_doc/1?pretty", encodeBasicHeader("baz", "worf")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("\"found\" : true")); Assert.assertTrue(resc.getBody().contains("\"content\" : 1")); - + resc = rh.executeGetRequest("/foo2/_doc/2?pretty", encodeBasicHeader("baz", "worf")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("\"content\" : 2")); Assert.assertTrue(resc.getBody().contains("\"found\" : true")); - + resc = rh.executeGetRequest("/foo/_doc/3?pretty", encodeBasicHeader("baz", "worf")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("\"content\" : 3")); Assert.assertTrue(resc.getBody().contains("\"found\" : true")); - - //resc = rh.executeGetRequest("/fooba/z/4?pretty", encodeBasicHeader("baz", "worf")); - //Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - - //resc = rh.executeGetRequest("/foo*/_search?pretty", encodeBasicHeader("baz", "worf")); - //Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - + + // resc = rh.executeGetRequest("/fooba/z/4?pretty", encodeBasicHeader("baz", "worf")); + // Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // resc = rh.executeGetRequest("/foo*/_search?pretty", encodeBasicHeader("baz", "worf")); + // Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + resc = rh.executeGetRequest("/foo*,-fooba/_search?pretty", encodeBasicHeader("baz", "worf")); Assert.assertEquals(200, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("\"content\" : 1")); @@ -259,77 +342,178 @@ public void testIndexTypeEvaluation() throws Exception { @Test public void testIndices() throws Exception { - + setup(); - + try (Client tc = getClient()) { - tc.index(new IndexRequest("nopermindex").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("logstash-1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - + tc.index(new IndexRequest("nopermindex").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("logstash-1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("logstash-2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("logstash-3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("logstash-4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd", SecurityUtils.EN_Locale); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); - + String date = sdf.format(new Date()); - tc.index(new IndexRequest("logstash-"+date).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("logstash-" + date).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); } - + RestHelper rh = nonSslRestHelper(); - + HttpResponse res = null; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-1/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - //nonexistent index with permissions - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, (res = rh.executeGetRequest("/logstash-nonex/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - //existent index without permissions - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/nopermindex/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - //nonexistent index without permissions - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/does-not-exist-and-no-perm/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - //nonexistent and existent index with permissions - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, (res = rh.executeGetRequest("/logstash-nonex,logstash-1/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - //existent index with permissions - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-1/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - //nonexistent index with failed login - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, (res = rh.executeGetRequest("/logstash-nonex/_search", encodeBasicHeader("nouser", "nosuer"))).getStatusCode()); - - //nonexistent index with no login - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, (res = rh.executeGetRequest("/logstash-nonex/_search")).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/_all/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/*/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/nopermindex,logstash-1,nonexist/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/logstash-1,nonexist/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/nonexist/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/%3Clogstash-%7Bnow%2Fd%7D%3E/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/%3Cnonex-%7Bnow%2Fd%7D%3E/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/%3Clogstash-%7Bnow%2Fd%7D%3E,logstash-*/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/%3Clogstash-%7Bnow%2Fd%7D%3E,logstash-1/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_CREATED, (res = rh.executePutRequest("/logstash-b/_doc/1", "{}",encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePutRequest("/%3Clogstash-cnew-%7Bnow%2Fd%7D%3E", "{}",encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_CREATED, (res = rh.executePutRequest("/%3Clogstash-new-%7Bnow%2Fd%7D%3E/_doc/1", "{}",encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/_cat/indices?v" ,encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-1/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))) + .getStatusCode() + ); + + // nonexistent index with permissions + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + (res = rh.executeGetRequest("/logstash-nonex/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))) + .getStatusCode() + ); + + // existent index without permissions + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/nopermindex/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))) + .getStatusCode() + ); + + // nonexistent index without permissions + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest( + "/does-not-exist-and-no-perm/_search", + encodeBasicHeader("opendistro_security_logstash", "nagilum") + )).getStatusCode() + ); + + // nonexistent and existent index with permissions + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + (res = rh.executeGetRequest("/logstash-nonex,logstash-1/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))) + .getStatusCode() + ); + + // existent index with permissions + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-1/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))) + .getStatusCode() + ); + + // nonexistent index with failed login + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + (res = rh.executeGetRequest("/logstash-nonex/_search", encodeBasicHeader("nouser", "nosuer"))).getStatusCode() + ); + + // nonexistent index with no login + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, (res = rh.executeGetRequest("/logstash-nonex/_search")).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/_all/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/*/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest( + "/nopermindex,logstash-1,nonexist/_search", + encodeBasicHeader("opendistro_security_logstash", "nagilum") + )).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/logstash-1,nonexist/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))) + .getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/nonexist/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "/%3Clogstash-%7Bnow%2Fd%7D%3E/_search", + encodeBasicHeader("opendistro_security_logstash", "nagilum") + )).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/%3Cnonex-%7Bnow%2Fd%7D%3E/_search", encodeBasicHeader("opendistro_security_logstash", "nagilum"))) + .getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "/%3Clogstash-%7Bnow%2Fd%7D%3E,logstash-*/_search", + encodeBasicHeader("opendistro_security_logstash", "nagilum") + )).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "/%3Clogstash-%7Bnow%2Fd%7D%3E,logstash-1/_search", + encodeBasicHeader("opendistro_security_logstash", "nagilum") + )).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_CREATED, + (res = rh.executePutRequest("/logstash-b/_doc/1", "{}", encodeBasicHeader("opendistro_security_logstash", "nagilum"))) + .getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePutRequest( + "/%3Clogstash-cnew-%7Bnow%2Fd%7D%3E", + "{}", + encodeBasicHeader("opendistro_security_logstash", "nagilum") + )).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_CREATED, + (res = rh.executePutRequest( + "/%3Clogstash-new-%7Bnow%2Fd%7D%3E/_doc/1", + "{}", + encodeBasicHeader("opendistro_security_logstash", "nagilum") + )).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/_cat/indices?v", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("logstash-b")); @@ -337,86 +521,126 @@ public void testIndices() throws Exception { Assert.assertTrue(res.getBody().contains("logstash-cnew-20")); Assert.assertFalse(res.getBody().contains("<")); } - + @Test public void testAliases() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(settings); - + try (Client tc = getClient()) { - tc.index(new IndexRequest("nopermindex").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("logstash-1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-del").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-del-ok").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("nopermindex").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("logstash-1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("logstash-2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("logstash-3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("logstash-4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("logstash-5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("logstash-del").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("logstash-del-ok").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); String date = new SimpleDateFormat("YYYY.MM.dd").format(new Date()); - tc.index(new IndexRequest("logstash-"+date).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("nopermindex").alias("nopermalias"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices(".opendistro_security").alias("mysgi"))).actionGet(); + tc.index( + new IndexRequest("logstash-" + date).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("nopermindex").alias("nopermalias"))) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices(".opendistro_security").alias("mysgi"))) + .actionGet(); } - + RestHelper rh = nonSslRestHelper(); - + HttpResponse res = null; - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executePostRequest("/mysgi/_doc", "{}",encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/mysgi/_search?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePostRequest("/mysgi/_doc", "{}", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/mysgi/_search?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); assertContains(res, "*\"hits\" : {*\"value\" : 0,*\"hits\" : [ ]*"); - + System.out.println("#### add alias to allowed index"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePutRequest("/logstash-1/_alias/alog1", "",encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePutRequest("/logstash-1/_alias/alog1", "", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); System.out.println("#### add alias to not existing (no perm)"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executePutRequest("/nonexitent/_alias/alnp", "",encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); - + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePutRequest("/nonexitent/_alias/alnp", "", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); + System.out.println("#### add alias to not existing (with perm)"); - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, (res = rh.executePutRequest("/logstash-nonex/_alias/alnp", "",encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); - + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + (res = rh.executePutRequest("/logstash-nonex/_alias/alnp", "", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); + System.out.println("#### add alias to not allowed index"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executePutRequest("/nopermindex/_alias/alnp", "",encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); - - String aliasRemoveIndex = "{"+ - "\"actions\" : ["+ - "{ \"add\": { \"index\": \"logstash-del-ok\", \"alias\": \"logstash-del\" } },"+ - "{ \"remove_index\": { \"index\": \"logstash-del\" } } "+ - "]"+ - "}"; - + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePutRequest("/nopermindex/_alias/alnp", "", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); + + String aliasRemoveIndex = "{" + + "\"actions\" : [" + + "{ \"add\": { \"index\": \"logstash-del-ok\", \"alias\": \"logstash-del\" } }," + + "{ \"remove_index\": { \"index\": \"logstash-del\" } } " + + "]" + + "}"; + System.out.println("#### remove_index"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executePostRequest("/_aliases", aliasRemoveIndex,encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePostRequest("/_aliases", aliasRemoveIndex, encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); - System.out.println("#### get alias for permitted index"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-1/_alias/alog1", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-1/_alias/alog1", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); - System.out.println("#### get alias for all indices"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/_alias/alog1", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/_alias/alog1", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); - System.out.println("#### get alias no perm"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("/_alias/nopermalias", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); - - String alias = - "{"+ - "\"aliases\": {"+ - "\"alias1\": {}"+ - "}"+ - "}"; - - + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("/_alias/nopermalias", encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); + + String alias = "{" + "\"aliases\": {" + "\"alias1\": {}" + "}" + "}"; + System.out.println("#### create alias along with index"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executePutRequest("/beats-withalias", alias,encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePutRequest("/beats-withalias", alias, encodeBasicHeader("aliasmngt", "nagilum"))).getStatusCode() + ); } @Test @@ -425,83 +649,90 @@ public void testIndexResolveInvalidIndexName() throws Exception { final RestHelper rh = nonSslRestHelper(); // invalid_index_name_exception should be thrown and responded when invalid index name is mentioned in requests. - HttpResponse res = rh.executeGetRequest(URLEncoder.encode("_##pdt_data/_search", "UTF-8"), encodeBasicHeader("ccsresolv", "nagilum")); + HttpResponse res = rh.executeGetRequest( + URLEncoder.encode("_##pdt_data/_search", "UTF-8"), + encodeBasicHeader("ccsresolv", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, res.getStatusCode()); Assert.assertTrue(res.getBody().contains("invalid_index_name_exception")); } - + @Test public void testCCSIndexResolve() throws Exception { - + setup(); final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - tc.index(new IndexRequest(".abc-6").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest(".abc-6").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); } - //ccsresolv has perm for ?abc* + // ccsresolv has perm for ?abc* HttpResponse res = rh.executeGetRequest("ggg:.abc-6,.abc-6/_search", encodeBasicHeader("ccsresolv", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); res = rh.executeGetRequest("/*:.abc-6,.abc-6/_search", encodeBasicHeader("ccsresolv", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - //TODO: Change for 25.0 to be forbidden (possible bug in ES regarding ccs wildcard) + // TODO: Change for 25.0 to be forbidden (possible bug in ES regarding ccs wildcard) } @Test @Ignore public void testCCSIndexResolve2() throws Exception { - + setup(); final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - tc.index(new IndexRequest(".abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("xyz").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("noperm").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest(".abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("xyz").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("noperm").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":3}", XContentType.JSON)) + .actionGet(); } - + HttpResponse res = rh.executeGetRequest("/*:.abc,.abc/_search", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody(),res.getBody().contains("\"content\":1")); - + Assert.assertTrue(res.getBody(), res.getBody().contains("\"content\":1")); + res = rh.executeGetRequest("/ba*bcuzh/_search", encodeBasicHeader("nagilum", "nagilum")); - Assert.assertTrue(res.getBody(),res.getBody().contains("\"content\":12")); + Assert.assertTrue(res.getBody(), res.getBody().contains("\"content\":12")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - + res = rh.executeGetRequest("/*:.abc/_search", encodeBasicHeader("nagilum", "nagilum")); - Assert.assertTrue(res.getBody(),res.getBody().contains("\"content\":1")); + Assert.assertTrue(res.getBody(), res.getBody().contains("\"content\":1")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - + res = rh.executeGetRequest("/*:xyz,xyz/_search", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody(),res.getBody().contains("\"content\":2")); - - //res = rh.executeGetRequest("/*noexist/_search", encodeBasicHeader("nagilum", "nagilum")); - //Assert.assertEquals(HttpStatus.SC_NOT_FOUND, res.getStatusCode()); - + Assert.assertTrue(res.getBody(), res.getBody().contains("\"content\":2")); + + // res = rh.executeGetRequest("/*noexist/_search", encodeBasicHeader("nagilum", "nagilum")); + // Assert.assertEquals(HttpStatus.SC_NOT_FOUND, res.getStatusCode()); + res = rh.executeGetRequest("/*:.abc/_search", encodeBasicHeader("nagilum", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody(),res.getBody().contains("\"content\":1")); - + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody(), res.getBody().contains("\"content\":1")); + res = rh.executeGetRequest("/*:xyz/_search", encodeBasicHeader("nagilum", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - Assert.assertTrue(res.getBody(),res.getBody().contains("\"content\":2")); - + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertTrue(res.getBody(), res.getBody().contains("\"content\":2")); + res = rh.executeGetRequest("/.abc/_search", encodeBasicHeader("ccsresolv", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); res = rh.executeGetRequest("/xyz/_search", encodeBasicHeader("ccsresolv", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); res = rh.executeGetRequest("/*:.abc,.abc/_search", encodeBasicHeader("ccsresolv", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); res = rh.executeGetRequest("/*:xyz,xyz/_search", encodeBasicHeader("ccsresolv", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); res = rh.executeGetRequest("/*:.abc/_search", encodeBasicHeader("ccsresolv", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); res = rh.executeGetRequest("/*:xyz/_search", encodeBasicHeader("ccsresolv", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); res = rh.executeGetRequest("/*:noperm/_search", encodeBasicHeader("ccsresolv", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); res = rh.executeGetRequest("/*:noperm/_search", encodeBasicHeader("ccsresolv", "nagilum")); @@ -515,24 +746,32 @@ public void testCCSIndexResolve2() throws Exception { @Test public void testIndexResolveIgnoreUnavailable() throws Exception { - setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_respect_indices_options.yml").setSecurityRoles("roles_bs.yml"), Settings.EMPTY, true); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setConfig("config_respect_indices_options.yml").setSecurityRoles("roles_bs.yml"), + Settings.EMPTY, + true + ); final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - //create indices and mapping upfront - tc.index(new IndexRequest("test").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("lorem").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)).actionGet(); + // create indices and mapping upfront + tc.index(new IndexRequest("test").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("lorem").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)) + .actionGet(); } - String msearchBody = - "{\"index\": [\"tes*\",\"-security\",\"-missing\"], \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"match_all\":{}}}"+System.lineSeparator(); + String msearchBody = "{\"index\": [\"tes*\",\"-security\",\"-missing\"], \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"match_all\":{}}}" + + System.lineSeparator(); HttpResponse resc = rh.executePostRequest("_msearch", msearchBody, encodeBasicHeader("worf", "worf")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody(), resc.getBody().contains("\"total\":{\"value\":1")); } - + @Test public void testIndexResolveIndicesAlias() throws Exception { @@ -540,24 +779,29 @@ public void testIndexResolveIndicesAlias() throws Exception { final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - //create indices and mapping upfront - tc.index(new IndexRequest("foo-index").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("foo-index").alias("foo-alias"))).actionGet(); + // create indices and mapping upfront + tc.index( + new IndexRequest("foo-index").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON) + ).actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("foo-index").alias("foo-alias"))) + .actionGet(); tc.admin().indices().delete(new DeleteIndexRequest("foo-index")).actionGet(); } - + HttpResponse resc = rh.executeGetRequest("/_cat/aliases", encodeBasicHeader("nagilum", "nagilum")); Assert.assertFalse(resc.getBody().contains("foo")); resc = rh.executeGetRequest("/foo-alias/_search", encodeBasicHeader("foo_index", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - + resc = rh.executeGetRequest("/foo-index/_search", encodeBasicHeader("foo_index", "nagilum")); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, resc.getStatusCode()); - + resc = rh.executeGetRequest("/foo-alias/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, resc.getStatusCode()); - + } @Test @@ -567,8 +811,10 @@ public void testIndexResolveMinus() throws Exception { final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - //create indices and mapping upfront - tc.index(new IndexRequest("foo-abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON)).actionGet(); + // create indices and mapping upfront + tc.index( + new IndexRequest("foo-abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"field2\":\"init\"}", XContentType.JSON) + ).actionGet(); } HttpResponse resc = rh.executeGetRequest("/**/_search", encodeBasicHeader("foo_all", "nagilum")); @@ -576,30 +822,30 @@ public void testIndexResolveMinus() throws Exception { resc = rh.executeGetRequest("/*/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - + resc = rh.executeGetRequest("/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - + resc = rh.executeGetRequest("/**,-foo*/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - + resc = rh.executeGetRequest("/*,-foo*/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - + resc = rh.executeGetRequest("/*,-*security/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); resc = rh.executeGetRequest("/*,-*security/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - + resc = rh.executeGetRequest("/*,-*security,-foo*/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - + resc = rh.executeGetRequest("/_all,-*security/_search", encodeBasicHeader("foo_all", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - + resc = rh.executeGetRequest("/_all,-*security/_search", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, resc.getStatusCode()); - + } } diff --git a/src/test/java/org/opensearch/security/IndexTemplateClusterPermissionsCheckTest.java b/src/test/java/org/opensearch/security/IndexTemplateClusterPermissionsCheckTest.java index b2c483abd7..03d26e2062 100644 --- a/src/test/java/org/opensearch/security/IndexTemplateClusterPermissionsCheckTest.java +++ b/src/test/java/org/opensearch/security/IndexTemplateClusterPermissionsCheckTest.java @@ -20,45 +20,55 @@ import org.opensearch.security.test.helper.rest.RestHelper; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class IndexTemplateClusterPermissionsCheckTest extends SingleClusterTest{ - private RestHelper rh; +public class IndexTemplateClusterPermissionsCheckTest extends SingleClusterTest { + private RestHelper rh; - final static String indexTemplateBody = "{ \"index_patterns\": [\"sem1234*\"], \"template\": { \"settings\": { \"number_of_shards\": 2, \"number_of_replicas\": 1 }, \"mappings\": { \"properties\": { \"timestamp\": { \"type\": \"date\", \"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis\" }, \"value\": { \"type\": \"double\" } } } } }"; + final static String indexTemplateBody = + "{ \"index_patterns\": [\"sem1234*\"], \"template\": { \"settings\": { \"number_of_shards\": 2, \"number_of_replicas\": 1 }, \"mappings\": { \"properties\": { \"timestamp\": { \"type\": \"date\", \"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis\" }, \"value\": { \"type\": \"double\" } } } } }"; - private String getFailureResponseReason(String user) { - return "no permissions for [indices:admin/index_template/put] and User [name=" + user + ", backend_roles=[], requestedTenant=null]"; - } + private String getFailureResponseReason(String user) { + return "no permissions for [indices:admin/index_template/put] and User [name=" + user + ", backend_roles=[], requestedTenant=null]"; + } - @Before - public void setupRestHelper() throws Exception{ - setup(); - rh = nonSslRestHelper(); - } - @Test - public void testPutIndexTemplateByNonPrivilegedUser() throws Exception { - String expectedFailureResponse = getFailureResponseReason("ds4"); + @Before + public void setupRestHelper() throws Exception { + setup(); + rh = nonSslRestHelper(); + } - // should fail, as user `ds3` doesn't have correct permissions - HttpResponse response = rh.executePutRequest("/_index_template/sem1234", indexTemplateBody, encodeBasicHeader("ds4", "nagilum")); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - Assert.assertEquals(expectedFailureResponse, response.findValueInJson("error.root_cause[0].reason")); - } + @Test + public void testPutIndexTemplateByNonPrivilegedUser() throws Exception { + String expectedFailureResponse = getFailureResponseReason("ds4"); - @Test - public void testPutIndexTemplateByPrivilegedUser() throws Exception { - // should pass, as user `sem-user` has correct permissions - HttpResponse response = rh.executePutRequest("/_index_template/sem1234", indexTemplateBody, encodeBasicHeader("sem-user", "nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - } + // should fail, as user `ds3` doesn't have correct permissions + HttpResponse response = rh.executePutRequest("/_index_template/sem1234", indexTemplateBody, encodeBasicHeader("ds4", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); + Assert.assertEquals(expectedFailureResponse, response.findValueInJson("error.root_cause[0].reason")); + } - @Test - public void testPutIndexTemplateAsIndexLevelPermission() throws Exception { - String expectedFailureResponse = getFailureResponseReason("sem-user2"); + @Test + public void testPutIndexTemplateByPrivilegedUser() throws Exception { + // should pass, as user `sem-user` has correct permissions + HttpResponse response = rh.executePutRequest( + "/_index_template/sem1234", + indexTemplateBody, + encodeBasicHeader("sem-user", "nagilum") + ); + Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); + } - // should fail, as user `sem-user2` is assigned `put-template` permission as index-level, not cluster-level - HttpResponse response = rh.executePutRequest("/_index_template/sem1234", indexTemplateBody, encodeBasicHeader("sem-user2", "nagilum")); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - Assert.assertEquals(expectedFailureResponse, response.findValueInJson("error.root_cause[0].reason")); - } + @Test + public void testPutIndexTemplateAsIndexLevelPermission() throws Exception { + String expectedFailureResponse = getFailureResponseReason("sem-user2"); + // should fail, as user `sem-user2` is assigned `put-template` permission as index-level, not cluster-level + HttpResponse response = rh.executePutRequest( + "/_index_template/sem1234", + indexTemplateBody, + encodeBasicHeader("sem-user2", "nagilum") + ); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); + Assert.assertEquals(expectedFailureResponse, response.findValueInJson("error.root_cause[0].reason")); } + +} diff --git a/src/test/java/org/opensearch/security/InitializationIntegrationTests.java b/src/test/java/org/opensearch/security/InitializationIntegrationTests.java index 17ced9e325..0fec953472 100644 --- a/src/test/java/org/opensearch/security/InitializationIntegrationTests.java +++ b/src/test/java/org/opensearch/security/InitializationIntegrationTests.java @@ -65,26 +65,34 @@ public class InitializationIntegrationTests extends SingleClusterTest { @Test public void testEnsureInitViaRestDoesWork() throws Exception { - + final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, null, settings, false); - final RestHelper rh = restHelper(); //ssl resthelper + final RestHelper rh = restHelper(); // ssl resthelper rh.enableHTTPClientSSL = true; rh.trustHTTPServerCertificate = true; rh.sendAdminCertificate = true; - Assert.assertEquals(HttpStatus.SC_SERVICE_UNAVAILABLE, rh.executePutRequest(".opendistro_security/_doc/0", "{}", encodeBasicHeader("___", "")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_SERVICE_UNAVAILABLE, rh.executePutRequest(".opendistro_security/_doc/config", "{}", encodeBasicHeader("___", "")).getStatusCode()); - - + Assert.assertEquals( + HttpStatus.SC_SERVICE_UNAVAILABLE, + rh.executePutRequest(".opendistro_security/_doc/0", "{}", encodeBasicHeader("___", "")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_SERVICE_UNAVAILABLE, + rh.executePutRequest(".opendistro_security/_doc/config", "{}", encodeBasicHeader("___", "")).getStatusCode() + ); + rh.keystore = "kirk-keystore.jks"; - Assert.assertEquals(HttpStatus.SC_CREATED, rh.executePutRequest(".opendistro_security/_doc/config", "{}", encodeBasicHeader("___", "")).getStatusCode()); - + Assert.assertEquals( + HttpStatus.SC_CREATED, + rh.executePutRequest(".opendistro_security/_doc/config", "{}", encodeBasicHeader("___", "")).getStatusCode() + ); + Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"tx_size_in_bytes\" : 0")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"rx_count\" : 0")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"rx_size_in_bytes\" : 0")); @@ -96,28 +104,38 @@ public void testEnsureInitViaRestDoesWork() throws Exception { public void testInitWithInjectedUser() throws Exception { final Settings settings = Settings.builder() - .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .put("plugins.security.unsupported.inject_user.enabled", true) - .build(); + .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) + .put("plugins.security.unsupported.inject_user.enabled", true) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_disable_all.yml"), settings, true); RestHelper rh = nonSslRestHelper(); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executePutRequest(".opendistro_security/_doc/0", "{}", encodeBasicHeader("___", "")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executePutRequest(".opendistro_security/_doc/config", "{}", encodeBasicHeader("___", "")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executePutRequest(".opendistro_security/_doc/0", "{}", encodeBasicHeader("___", "")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_UNAUTHORIZED, + rh.executePutRequest(".opendistro_security/_doc/config", "{}", encodeBasicHeader("___", "")).getStatusCode() + ); } @Test public void testWhoAmI() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); - setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityInternalUsers("internal_empty.yml") - .setSecurityRoles("roles_deny.yml"), settings, true); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setSecurityInternalUsers("internal_empty.yml").setSecurityRoles("roles_deny.yml"), + settings, + true + ); try (RestHighLevelClient restHighLevelClient = getRestClient(clusterInfo, "spock-keystore.jks", "truststore.jks")) { Response whoAmIRes = restHighLevelClient.getLowLevelClient().performRequest(new Request("GET", "/_plugins/_security/whoami")); @@ -135,14 +153,25 @@ public void testWhoAmI() throws Exception { @Test public void testWhoAmIForceHttp1() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); - setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityInternalUsers("internal_empty.yml") - .setSecurityRoles("roles_deny.yml"), settings, true); - - try (RestHighLevelClient restHighLevelClient = getRestClient(clusterInfo, "spock-keystore.jks", "truststore.jks", HttpVersionPolicy.FORCE_HTTP_1)) { + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setSecurityInternalUsers("internal_empty.yml").setSecurityRoles("roles_deny.yml"), + settings, + true + ); + + try ( + RestHighLevelClient restHighLevelClient = getRestClient( + clusterInfo, + "spock-keystore.jks", + "truststore.jks", + HttpVersionPolicy.FORCE_HTTP_1 + ) + ) { Response whoAmIRes = restHighLevelClient.getLowLevelClient().performRequest(new Request("GET", "/_plugins/_security/whoami")); Assert.assertEquals(whoAmIRes.getStatusLine().getStatusCode(), 200); // The HTTP/1.1 is forced and should be used instead @@ -157,46 +186,87 @@ public void testWhoAmIForceHttp1() throws Exception { @Test public void testConfigHotReload() throws Exception { - + setup(); RestHelper rh = nonSslRestHelper(); Header spock = encodeBasicHeader("spock", "spock"); - + for (Iterator iterator = clusterInfo.httpAdresses.iterator(); iterator.hasNext();) { TransportAddress TransportAddress = (TransportAddress) iterator.next(); - HttpResponse res = rh.executeRequest(new HttpGet("http://"+TransportAddress.getAddress()+":"+TransportAddress.getPort() + "/" + "_opendistro/_security/authinfo?pretty=true"), spock); + HttpResponse res = rh.executeRequest( + new HttpGet( + "http://" + + TransportAddress.getAddress() + + ":" + + TransportAddress.getPort() + + "/" + + "_opendistro/_security/authinfo?pretty=true" + ), + spock + ); Assert.assertTrue(res.getBody().contains("spock")); Assert.assertFalse(res.getBody().contains("additionalrole")); Assert.assertTrue(res.getBody().contains("vulcan")); } - + try (Client tc = getClient()) { Assert.assertEquals(clusterInfo.numNodes, tc.admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); - tc.index(new IndexRequest(".opendistro_security").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("internalusers").source("internalusers", FileHelper.readYamlContent("internal_users_spock_add_roles.yml"))).actionGet(); - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"config","roles","rolesmapping","internalusers","actiongroups"})).actionGet(); - Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); - } - + tc.index( + new IndexRequest(".opendistro_security").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("internalusers") + .source("internalusers", FileHelper.readYamlContent("internal_users_spock_add_roles.yml")) + ).actionGet(); + ConfigUpdateResponse cur = tc.execute( + ConfigUpdateAction.INSTANCE, + new ConfigUpdateRequest(new String[] { "config", "roles", "rolesmapping", "internalusers", "actiongroups" }) + ).actionGet(); + Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); + } + for (Iterator iterator = clusterInfo.httpAdresses.iterator(); iterator.hasNext();) { TransportAddress TransportAddress = (TransportAddress) iterator.next(); - log.debug("http://"+TransportAddress.getAddress()+":"+TransportAddress.getPort()); - HttpResponse res = rh.executeRequest(new HttpGet("http://"+TransportAddress.getAddress()+":"+TransportAddress.getPort() + "/" + "_opendistro/_security/authinfo?pretty=true"), spock); + log.debug("http://" + TransportAddress.getAddress() + ":" + TransportAddress.getPort()); + HttpResponse res = rh.executeRequest( + new HttpGet( + "http://" + + TransportAddress.getAddress() + + ":" + + TransportAddress.getPort() + + "/" + + "_opendistro/_security/authinfo?pretty=true" + ), + spock + ); Assert.assertTrue(res.getBody().contains("spock")); Assert.assertTrue(res.getBody().contains("additionalrole1")); Assert.assertTrue(res.getBody().contains("additionalrole2")); Assert.assertFalse(res.getBody().contains("starfleet")); } - + try (Client tc = getClient()) { Assert.assertEquals(clusterInfo.numNodes, tc.admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); - tc.index(new IndexRequest(".opendistro_security").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("config").source("config", FileHelper.readYamlContent("config_anon.yml"))).actionGet(); - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"config"})).actionGet(); - Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); + tc.index( + new IndexRequest(".opendistro_security").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("config") + .source("config", FileHelper.readYamlContent("config_anon.yml")) + ).actionGet(); + ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[] { "config" })) + .actionGet(); + Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); } - + for (Iterator iterator = clusterInfo.httpAdresses.iterator(); iterator.hasNext();) { TransportAddress TransportAddress = (TransportAddress) iterator.next(); - HttpResponse res = rh.executeRequest(new HttpGet("http://"+TransportAddress.getAddress()+":"+TransportAddress.getPort() + "/" + "_opendistro/_security/authinfo?pretty=true")); + HttpResponse res = rh.executeRequest( + new HttpGet( + "http://" + + TransportAddress.getAddress() + + ":" + + TransportAddress.getPort() + + "/" + + "_opendistro/_security/authinfo?pretty=true" + ) + ); log.debug(res.getBody()); Assert.assertTrue(res.getBody().contains("role_host1")); Assert.assertTrue(res.getBody().contains("opendistro_security_anonymous")); @@ -208,13 +278,11 @@ public void testConfigHotReload() throws Exception { @Test public void testDefaultConfig() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX, true) - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX, true).build(); setup(Settings.EMPTY, null, settings, false); RestHelper rh = nonSslRestHelper(); Thread.sleep(10000); - + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("admin", "admin")).getStatusCode()); HttpResponse res = rh.executeGetRequest("/_cluster/health", encodeBasicHeader("admin", "admin")); Assert.assertEquals(res.getBody(), HttpStatus.SC_OK, res.getStatusCode()); @@ -223,14 +291,17 @@ public void testDefaultConfig() throws Exception { @Test public void testInvalidDefaultConfig() throws Exception { try { - final String defaultInitDirectory = ClusterHelper.updateDefaultDirectory(new File(TEST_RESOURCE_RELATIVE_PATH + "invalid_config").getAbsolutePath()); - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX, true) - .build(); + final String defaultInitDirectory = ClusterHelper.updateDefaultDirectory( + new File(TEST_RESOURCE_RELATIVE_PATH + "invalid_config").getAbsolutePath() + ); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX, true).build(); setup(Settings.EMPTY, null, settings, false); RestHelper rh = nonSslRestHelper(); Thread.sleep(10000); - Assert.assertEquals(HttpStatus.SC_SERVICE_UNAVAILABLE, rh.executeGetRequest("", encodeBasicHeader("admin", "admin")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_SERVICE_UNAVAILABLE, + rh.executeGetRequest("", encodeBasicHeader("admin", "admin")).getStatusCode() + ); ClusterHelper.updateDefaultDirectory(defaultInitDirectory); restart(Settings.EMPTY, null, settings, false); @@ -244,21 +315,32 @@ public void testInvalidDefaultConfig() throws Exception { @Test public void testDisabled() throws Exception { - + final Settings settings = Settings.builder().put("plugins.security.disabled", true).build(); - + setup(Settings.EMPTY, null, settings, false); RestHelper rh = nonSslRestHelper(); - + HttpResponse resc = rh.executeGetRequest("_search"); Assert.assertEquals(200, resc.getStatusCode()); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("hits")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("hits")); } @Test - public void testDiscoveryWithoutInitialization() throws Exception { + public void testDiscoveryWithoutInitialization() throws Exception { setup(Settings.EMPTY, null, Settings.EMPTY, false); - Assert.assertEquals(clusterInfo.numNodes, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); + Assert.assertEquals( + clusterInfo.numNodes, + clusterHelper.nodeClient() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForGreenStatus()) + .actionGet() + .getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); } } diff --git a/src/test/java/org/opensearch/security/IntegrationTests.java b/src/test/java/org/opensearch/security/IntegrationTests.java index 226551a5ae..399d226bd9 100644 --- a/src/test/java/org/opensearch/security/IntegrationTests.java +++ b/src/test/java/org/opensearch/security/IntegrationTests.java @@ -62,60 +62,76 @@ public class IntegrationTests extends SingleClusterTest { @Test - public void testSearchScroll() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".worf", "knuddel","nonexists") + public void testSearchScroll() throws Exception { + final Settings settings = Settings.builder() + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".worf", "knuddel", "nonexists") .build(); - setup(settings); - final RestHelper rh = nonSslRestHelper(); + setup(settings); + final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - for(int i=0; i<3; i++) - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + for (int i = 0; i < 3; i++) + tc.index( + new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); } - - + System.out.println("########search"); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executeGetRequest("vulcangov/_search?scroll=1m&pretty=true", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); - + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("vulcangov/_search?scroll=1m&pretty=true", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); + System.out.println(res.getBody()); int start = res.getBody().indexOf("_scroll_id") + 15; - String scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start+1)); + String scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start + 1)); System.out.println(scrollid); System.out.println("########search scroll"); - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executePostRequest("/_search/scroll?pretty=true", "{\"scroll_id\" : \""+scrollid+"\"}", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); - + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "/_search/scroll?pretty=true", + "{\"scroll_id\" : \"" + scrollid + "\"}", + encodeBasicHeader("nagilum", "nagilum") + )).getStatusCode() + ); System.out.println("########search done"); - - + } @Test public void testDnParsingCertAuth() throws Exception { - Settings settings = Settings.builder() - .put("username_attribute", "cn") - .put("roles_attribute", "l") - .build(); + Settings settings = Settings.builder().put("username_attribute", "cn").put("roles_attribute", "l").build(); HTTPClientCertAuthenticator auth = new HTTPClientCertAuthenticator(settings, null); Assert.assertEquals("abc", auth.extractCredentials(null, newThreadContext("cn=abc,cn=xxx,l=ert,st=zui,c=qwe")).getUsername()); Assert.assertEquals("abc", auth.extractCredentials(null, newThreadContext("cn=abc,l=ert,st=zui,c=qwe")).getUsername()); - Assert.assertEquals("abc", auth.extractCredentials(null, newThreadContext("CN=abc,L=ert,st=zui,c=qwe")).getUsername()); + Assert.assertEquals("abc", auth.extractCredentials(null, newThreadContext("CN=abc,L=ert,st=zui,c=qwe")).getUsername()); Assert.assertEquals("abc", auth.extractCredentials(null, newThreadContext("l=ert,cn=abc,st=zui,c=qwe")).getUsername()); Assert.assertNull(auth.extractCredentials(null, newThreadContext("L=ert,CN=abc,c,st=zui,c=qwe"))); Assert.assertEquals("abc", auth.extractCredentials(null, newThreadContext("l=ert,st=zui,c=qwe,cn=abc")).getUsername()); - Assert.assertEquals("abc", auth.extractCredentials(null, newThreadContext("L=ert,st=zui,c=qwe,CN=abc")).getUsername()); - Assert.assertEquals("L=ert,st=zui,c=qwe", auth.extractCredentials(null, newThreadContext("L=ert,st=zui,c=qwe")).getUsername()); - Assert.assertArrayEquals(new String[] {"ert"}, auth.extractCredentials(null, newThreadContext("cn=abc,l=ert,st=zui,c=qwe")).getBackendRoles().toArray(new String[0])); - Assert.assertArrayEquals(new String[] {"bleh", "ert"}, new TreeSet<>(auth.extractCredentials(null, newThreadContext("cn=abc,l=ert,L=bleh,st=zui,c=qwe")).getBackendRoles()).toArray(new String[0])); - - settings = Settings.builder() - .build(); + Assert.assertEquals("abc", auth.extractCredentials(null, newThreadContext("L=ert,st=zui,c=qwe,CN=abc")).getUsername()); + Assert.assertEquals("L=ert,st=zui,c=qwe", auth.extractCredentials(null, newThreadContext("L=ert,st=zui,c=qwe")).getUsername()); + Assert.assertArrayEquals( + new String[] { "ert" }, + auth.extractCredentials(null, newThreadContext("cn=abc,l=ert,st=zui,c=qwe")).getBackendRoles().toArray(new String[0]) + ); + Assert.assertArrayEquals( + new String[] { "bleh", "ert" }, + new TreeSet<>(auth.extractCredentials(null, newThreadContext("cn=abc,l=ert,L=bleh,st=zui,c=qwe")).getBackendRoles()).toArray( + new String[0] + ) + ); + + settings = Settings.builder().build(); auth = new HTTPClientCertAuthenticator(settings, null); - Assert.assertEquals("cn=abc,l=ert,st=zui,c=qwe", auth.extractCredentials(null, newThreadContext("cn=abc,l=ert,st=zui,c=qwe")).getUsername()); + Assert.assertEquals( + "cn=abc,l=ert,st=zui,c=qwe", + auth.extractCredentials(null, newThreadContext("cn=abc,l=ert,st=zui,c=qwe")).getUsername() + ); } - + private ThreadContext newThreadContext(String sslPrincipal) { ThreadContext threadContext = new ThreadContext(Settings.EMPTY); threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_PRINCIPAL, sslPrincipal); @@ -124,51 +140,70 @@ private ThreadContext newThreadContext(String sslPrincipal) { @Test public void testDNSpecials() throws Exception { - + final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("node-untspec5-keystore.p12")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "1") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") - .putList(ConfigConstants.SECURITY_NODES_DN, "EMAILADDRESS=unt@tst.com,CN=node-untspec5.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE") - .putList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, "EMAILADDRESS=unt@xxx.com,CN=node-untspec6.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE") - .put(ConfigConstants.SECURITY_CERT_OID,"1.2.3.4.5.6") - .build(); - - + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("node-untspec5-keystore.p12") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "1") + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") + .putList( + ConfigConstants.SECURITY_NODES_DN, + "EMAILADDRESS=unt@tst.com,CN=node-untspec5.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE" + ) + .putList( + ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, + "EMAILADDRESS=unt@xxx.com,CN=node-untspec6.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE" + ) + .put(ConfigConstants.SECURITY_CERT_OID, "1.2.3.4.5.6") + .build(); + Settings tcSettings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("node-untspec6-keystore.p12")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") - .build(); - + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("node-untspec6-keystore.p12") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") + .build(); + setup(tcSettings, new DynamicSecurityConfig(), settings, true); RestHelper rh = nonSslRestHelper(); - + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("worf", "worf")).getStatusCode()); - + } - + @Test public void testDNSpecials1() throws Exception { - + final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("node-untspec5-keystore.p12")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "1") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") - .putList("plugins.security.nodes_dn", "EMAILADDRESS=unt@tst.com,CN=node-untspec5.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE") - .putList("plugins.security.authcz.admin_dn", "EMAILADDREss=unt@xxx.com, cn=node-untspec6.example.com, OU=SSL,O=Te\\, st,L=Test, c=DE") - .put("plugins.security.cert.oid","1.2.3.4.5.6") - .build(); - - + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("node-untspec5-keystore.p12") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "1") + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") + .putList("plugins.security.nodes_dn", "EMAILADDRESS=unt@tst.com,CN=node-untspec5.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE") + .putList( + "plugins.security.authcz.admin_dn", + "EMAILADDREss=unt@xxx.com, cn=node-untspec6.example.com, OU=SSL,O=Te\\, st,L=Test, c=DE" + ) + .put("plugins.security.cert.oid", "1.2.3.4.5.6") + .build(); + Settings tcSettings = Settings.builder() - .put("plugins.security.ssl.transport.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-untspec6-keystore.p12")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") - .build(); - + .put( + "plugins.security.ssl.transport.keystore_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("node-untspec6-keystore.p12") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") + .build(); + setup(tcSettings, new DynamicSecurityConfig(), settings, true); RestHelper rh = nonSslRestHelper(); - + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("").getStatusCode()); Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("worf", "worf")).getStatusCode()); } @@ -181,203 +216,274 @@ public void testEnsureOpenSSLAvailability() { @Test public void testMultiget() throws Exception { - + setup(); - + try (Client tc = getClient()) { - tc.index(new IndexRequest("mindex1").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("mindex2").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("mindex1").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("mindex2").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON) + ).actionGet(); } - - //opendistro_security_multiget -> picard - - - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"mindex1\","+ - "\"_id\" : \"1\""+ - " },"+ - " {"+ - "\"_index\" : \"mindex2\","+ - " \"_id\" : \"2\""+ - "}"+ - "]"+ - "}"; - - RestHelper rh = nonSslRestHelper(); - HttpResponse resc = rh.executePostRequest("_mget?refresh=true", mgetBody, encodeBasicHeader("picard", "picard")); - System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - Assert.assertFalse(resc.getBody().contains("type2")); - + + // opendistro_security_multiget -> picard + + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"mindex1\"," + + "\"_id\" : \"1\"" + + " }," + + " {" + + "\"_index\" : \"mindex2\"," + + " \"_id\" : \"2\"" + + "}" + + "]" + + "}"; + + RestHelper rh = nonSslRestHelper(); + HttpResponse resc = rh.executePostRequest("_mget?refresh=true", mgetBody, encodeBasicHeader("picard", "picard")); + System.out.println(resc.getBody()); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + Assert.assertFalse(resc.getBody().contains("type2")); + } @Test public void testRestImpersonation() throws Exception { - + final Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".spock", "knuddel","userwhonotexists").build(); - + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".spock", "knuddel", "userwhonotexists") + .build(); + setup(settings); - + RestHelper rh = nonSslRestHelper(); - - //knuddel: - // hash: _rest_impersonation_only_ - + + // knuddel: + // hash: _rest_impersonation_only_ + HttpResponse resp; - resp = rh.executeGetRequest("/_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as", "knuddel"), encodeBasicHeader("worf", "worf")); + resp = rh.executeGetRequest( + "/_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "knuddel"), + encodeBasicHeader("worf", "worf") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resp.getStatusCode()); - - resp = rh.executeGetRequest("/_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as", "knuddel"), encodeBasicHeader("spock", "spock")); + + resp = rh.executeGetRequest( + "/_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "knuddel"), + encodeBasicHeader("spock", "spock") + ); Assert.assertEquals(HttpStatus.SC_OK, resp.getStatusCode()); Assert.assertTrue(resp.getBody().contains("name=knuddel")); Assert.assertFalse(resp.getBody().contains("spock")); - - resp = rh.executeGetRequest("/_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as", "userwhonotexists"), encodeBasicHeader("spock", "spock")); + + resp = rh.executeGetRequest( + "/_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "userwhonotexists"), + encodeBasicHeader("spock", "spock") + ); System.out.println(resp.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resp.getStatusCode()); - - resp = rh.executeGetRequest("/_opendistro/_security/authinfo", new BasicHeader("opendistro_security_impersonate_as", "invalid"), encodeBasicHeader("spock", "spock")); + + resp = rh.executeGetRequest( + "/_opendistro/_security/authinfo", + new BasicHeader("opendistro_security_impersonate_as", "invalid"), + encodeBasicHeader("spock", "spock") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resp.getStatusCode()); } @Test public void testSingle() throws Exception { - + setup(); - + try (Client tc = getClient()) { - tc.index(new IndexRequest("shakespeare").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"config","roles","rolesmapping","internalusers","actiongroups"})).actionGet(); + tc.index( + new IndexRequest("shakespeare").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + ConfigUpdateResponse cur = tc.execute( + ConfigUpdateAction.INSTANCE, + new ConfigUpdateRequest(new String[] { "config", "roles", "rolesmapping", "internalusers", "actiongroups" }) + ).actionGet(); Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); } - + RestHelper rh = nonSslRestHelper(); - //opendistro_security_shakespeare -> picard - + // opendistro_security_shakespeare -> picard + HttpResponse resc = rh.executeGetRequest("shakespeare/_search", encodeBasicHeader("picard", "picard")); System.out.println(resc.getBody()); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("\"content\":1")); - + resc = rh.executeHeadRequest("shakespeare", encodeBasicHeader("picard", "picard")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - + } @Test public void testSpecialUsernames() throws Exception { - - setup(); + + setup(); RestHelper rh = nonSslRestHelper(); - + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("bug.99", "nagilum")).getStatusCode()); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest("", encodeBasicHeader("a", "b")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("\"'+-,;_?*@<>!$%&/()=#", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("", encodeBasicHeader("\"'+-,;_?*@<>!$%&/()=#", "nagilum")).getStatusCode() + ); Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("", encodeBasicHeader("§ÄÖÜäöüß", "nagilum")).getStatusCode()); - + } @Test public void testXff() throws Exception { - + setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_xff.yml"), Settings.EMPTY, true); RestHelper rh = nonSslRestHelper(); - HttpResponse resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader("x-forwarded-for", "10.0.0.7"), encodeBasicHeader("worf", "worf")); + HttpResponse resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader("x-forwarded-for", "10.0.0.7"), + encodeBasicHeader("worf", "worf") + ); Assert.assertEquals(200, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("10.0.0.7")); } @Test public void testRegexExcludes() throws Exception { - + setup(Settings.EMPTY, new DynamicSecurityConfig(), Settings.EMPTY); try (Client tc = getClient()) { - tc.index(new IndexRequest("indexa").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"indexa\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("indexb").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"indexb\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("isallowed").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"isallowed\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("special").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"special\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("alsonotallowed").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"alsonotallowed\":1}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("indexa").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"indexa\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("indexb").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"indexb\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("isallowed").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"isallowed\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("special").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"special\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("alsonotallowed").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"alsonotallowed\":1}", XContentType.JSON) + ).actionGet(); } - + RestHelper rh = nonSslRestHelper(); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("index*/_search",encodeBasicHeader("rexclude", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("indexa/_search",encodeBasicHeader("rexclude", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("isallowed/_search",encodeBasicHeader("rexclude", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("special/_search",encodeBasicHeader("rexclude", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("alsonotallowed/_search",encodeBasicHeader("rexclude", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("index*/_search", encodeBasicHeader("rexclude", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("indexa/_search", encodeBasicHeader("rexclude", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("isallowed/_search", encodeBasicHeader("rexclude", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest("special/_search", encodeBasicHeader("rexclude", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executeGetRequest("alsonotallowed/_search", encodeBasicHeader("rexclude", "nagilum")).getStatusCode() + ); } - + @Test public void testMultiRoleSpan() throws Exception { - + setup(); final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - tc.index(new IndexRequest("mindex_1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("mindex_2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("mindex_1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("mindex_2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)) + .actionGet(); } - + HttpResponse res = rh.executeGetRequest("/mindex_1,mindex_2/_search", encodeBasicHeader("mindex12", "nagilum")); System.out.println(res.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); Assert.assertFalse(res.getBody().contains("\"content\":1")); Assert.assertFalse(res.getBody().contains("\"content\":2")); - + try (Client tc = getClient()) { - tc.index(new IndexRequest(".opendistro_security").id("config").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("config", FileHelper.readYamlContent("config_multirolespan.yml"))).actionGet(); - - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"config"})).actionGet(); + tc.index( + new IndexRequest(".opendistro_security").id("config") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("config", FileHelper.readYamlContent("config_multirolespan.yml")) + ).actionGet(); + + ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[] { "config" })) + .actionGet(); Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); } - + res = rh.executeGetRequest("/mindex_1,mindex_2/_search", encodeBasicHeader("mindex12", "nagilum")); System.out.println(res.getBody()); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); Assert.assertTrue(res.getBody().contains("\"content\":1")); Assert.assertTrue(res.getBody().contains("\"content\":2")); - + } - + @Test public void testMultiRoleSpan2() throws Exception { - + setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_multirolespan.yml"), Settings.EMPTY); final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - tc.index(new IndexRequest("mindex_1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("mindex_2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("mindex_3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("mindex_4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("mindex_1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("mindex_2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("mindex_3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("mindex_4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":2}", XContentType.JSON)) + .actionGet(); } - + HttpResponse res = rh.executeGetRequest("/mindex_1,mindex_2/_search", encodeBasicHeader("mindex12", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - + res = rh.executeGetRequest("/mindex_1,mindex_3/_search", encodeBasicHeader("mindex12", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); res = rh.executeGetRequest("/mindex_1,mindex_4/_search", encodeBasicHeader("mindex12", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - + } - + @Test public void testSecurityUnderscore() throws Exception { - + setup(); final RestHelper rh = nonSslRestHelper(); - - HttpResponse res = rh.executePostRequest("abc_xyz_2018_05_24/_doc/1", "{\"content\":1}", encodeBasicHeader("underscore", "nagilum")); - + + HttpResponse res = rh.executePostRequest( + "abc_xyz_2018_05_24/_doc/1", + "{\"content\":1}", + encodeBasicHeader("underscore", "nagilum") + ); + res = rh.executeGetRequest("abc_xyz_2018_05_24/_doc/1", encodeBasicHeader("underscore", "nagilum")); - Assert.assertTrue(res.getBody(),res.getBody().contains("\"content\":1")); + Assert.assertTrue(res.getBody(), res.getBody().contains("\"content\":1")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); res = rh.executeGetRequest("abc_xyz_2018_05_24/_refresh", encodeBasicHeader("underscore", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); @@ -391,45 +497,52 @@ public void testDeleteByQueryDnfof() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_dnfof.yml"), Settings.EMPTY); try (Client tc = getClient()) { - for(int i=0; i<3; i++) { - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + for (int i = 0; i < 3; i++) { + tc.index( + new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); } } RestHelper rh = nonSslRestHelper(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executePostRequest("/vulcango*/_delete_by_query?refresh=true&wait_for_completion=true&pretty=true", "{\"query\" : {\"match_all\" : {}}}", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "/vulcango*/_delete_by_query?refresh=true&wait_for_completion=true&pretty=true", + "{\"query\" : {\"match_all\" : {}}}", + encodeBasicHeader("nagilum", "nagilum") + )).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"deleted\" : 3")); } @Test public void testUpdate() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(settings); final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - tc.index(new IndexRequest("indexc").id("0") - .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"content\":1}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("indexc").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); } - HttpResponse res = rh.executePostRequest("indexc/_update/0?pretty=true&refresh=true", "{\"doc\" : {\"content\":2}}", - encodeBasicHeader("user_c", "user_c")); + HttpResponse res = rh.executePostRequest( + "indexc/_update/0?pretty=true&refresh=true", + "{\"doc\" : {\"content\":2}}", + encodeBasicHeader("user_c", "user_c") + ); System.out.println(res.getBody()); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); } - @Test public void testDnfof() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_dnfof.yml"), settings); final RestHelper rh = nonSslRestHelper(); @@ -437,49 +550,95 @@ public void testDnfof() throws Exception { try (Client tc = getClient()) { tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - tc.index(new IndexRequest("indexa").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":\"indexa\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("indexb").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":\"indexb\"}", XContentType.JSON)).actionGet(); - - - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); + tc.index( + new IndexRequest("indexa").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":\"indexa\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("indexb").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":\"indexb\"}", XContentType.JSON) + ).actionGet(); + + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf")) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))) + .actionGet(); } HttpResponse resc; - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexa")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexb")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("exception")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("permission")); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_b", "user_b"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_b", "user_b"))).getStatusCode() + ); System.out.println(resc.getBody()); Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexa")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexb")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("exception")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("permission")); - String msearchBody = - "{\"index\":\"indexa\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"indexb\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"index*\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + String msearchBody = "{\"index\":\"indexa\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"indexb\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"index*\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); System.out.println("#### msearch"); resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_a", "user_a")); Assert.assertEquals(200, resc.getStatusCode()); @@ -501,106 +660,145 @@ public void testDnfof() throws Exception { Assert.assertEquals(3, resc.getBody().split("\"status\" : 200").length); Assert.assertEquals(2, resc.getBody().split("\"status\" : 403").length); - msearchBody = - "{\"index\":\"indexc\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"indexd\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + msearchBody = "{\"index\":\"indexc\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"indexd\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_b", "user_b")); Assert.assertEquals(403, resc.getStatusCode()); - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"indexa\","+ - "\"_id\" : \"0\""+ - " },"+ - " {"+ - "\"_index\" : \"indexb\","+ - " \"_id\" : \"0\""+ - "}"+ - "]"+ - "}"; + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"indexa\"," + + "\"_id\" : \"0\"" + + " }," + + " {" + + "\"_index\" : \"indexb\"," + + " \"_id\" : \"0\"" + + "}" + + "]" + + "}"; System.out.println("#### mget"); - resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); + resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); Assert.assertEquals(200, resc.getStatusCode()); Assert.assertFalse(resc.getBody(), resc.getBody().contains("\"content\" : \"indexa\"")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("\"content\" : \"indexb\"")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); - mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"indexx\","+ - "\"_id\" : \"0\""+ - " },"+ - " {"+ - "\"_index\" : \"indexy\","+ - " \"_id\" : \"0\""+ - "}"+ - "]"+ - "}"; - - resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); + mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"indexx\"," + + "\"_id\" : \"0\"" + + " }," + + " {" + + "\"_index\" : \"indexy\"," + + " \"_id\" : \"0\"" + + "}" + + "]" + + "}"; + + resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); Assert.assertEquals(403, resc.getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexa")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexb")); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("index*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("index*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexa")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexb")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("exception")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("permission")); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("indexa/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("indexa/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("_all/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("_all/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("notexists/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("notexists/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, (resc=rh.executeGetRequest("permitnotexistentindex/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + (resc = rh.executeGetRequest("permitnotexistentindex/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("permitnotexistentindex*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("permitnotexistentindex*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, (resc=rh.executeGetRequest("indexanbh,indexabb*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + (resc = rh.executeGetRequest("indexanbh,indexabb*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode() + ); System.out.println(resc.getBody()); System.out.println("#### _all/_mapping/field/*"); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("_all/_mapping/field/*", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("_all/_mapping/field/*", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); System.out.println(resc.getBody()); } - @Test public void testNoDnfof() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings); final RestHelper rh = nonSslRestHelper(); @@ -608,39 +806,83 @@ public void testNoDnfof() throws Exception { try (Client tc = getClient()) { tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - tc.index(new IndexRequest("indexa").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":\"indexa\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("indexb").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":\"indexb\"}", XContentType.JSON)).actionGet(); - - - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); + tc.index( + new IndexRequest("indexa").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":\"indexa\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("indexb").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":\"indexb\"}", XContentType.JSON) + ).actionGet(); + + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf")) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))) + .actionGet(); } HttpResponse resc; - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_b", "user_b"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_b", "user_b"))).getStatusCode() + ); System.out.println(resc.getBody()); - String msearchBody = - "{\"index\":\"indexa\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"indexb\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + String msearchBody = "{\"index\":\"indexa\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"indexb\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); System.out.println("#### msearch a"); resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_a", "user_a")); Assert.assertEquals(200, resc.getStatusCode()); @@ -659,11 +901,14 @@ public void testNoDnfof() throws Exception { Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); - msearchBody = - "{\"index\":\"indexc\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"indexd\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + msearchBody = "{\"index\":\"indexc\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"indexd\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); System.out.println("#### msearch b2"); resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_b", "user_b")); @@ -676,82 +921,120 @@ public void testNoDnfof() throws Exception { int count = resc.getBody().split("\"status\" : 403").length; Assert.assertEquals(3, count); - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"indexa\","+ - "\"_id\" : \"0\""+ - " },"+ - " {"+ - "\"_index\" : \"indexb\","+ - " \"_id\" : \"0\""+ - "}"+ - "]"+ - "}"; - - resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"indexa\"," + + "\"_id\" : \"0\"" + + " }," + + " {" + + "\"_index\" : \"indexb\"," + + " \"_id\" : \"0\"" + + "}" + + "]" + + "}"; + + resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); Assert.assertEquals(200, resc.getStatusCode()); Assert.assertFalse(resc.getBody(), resc.getBody().contains("\"content\" : \"indexa\"")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexb")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); - mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"indexx\","+ - "\"_id\" : \"0\""+ - " },"+ - " {"+ - "\"_index\" : \"indexy\","+ - " \"_id\" : \"0\""+ - "}"+ - "]"+ - "}"; - - resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); + mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"indexx\"," + + "\"_id\" : \"0\"" + + " }," + + " {" + + "\"_index\" : \"indexy\"," + + " \"_id\" : \"0\"" + + "}" + + "]" + + "}"; + + resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); Assert.assertEquals(200, resc.getStatusCode()); Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); count = resc.getBody().split("root_cause").length; Assert.assertEquals(3, count); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("index*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("index*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("indexa/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("indexa/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("_all/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("_all/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("notexists/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("notexists/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, (resc=rh.executeGetRequest("indexanbh,indexabb*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + (resc = rh.executeGetRequest("indexanbh,indexabb*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); System.out.println(resc.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode() + ); System.out.println(resc.getBody()); System.out.println("#### _all/_mapping/field/*"); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("_all/_mapping/field/*", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("_all/_mapping/field/*", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); System.out.println(resc.getBody()); System.out.println("#### _mapping/field/*"); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("_mapping/field/*", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("_mapping/field/*", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); System.out.println(resc.getBody()); System.out.println("#### */_mapping/field/*"); - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("*/_mapping/field/*", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("*/_mapping/field/*", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); System.out.println(resc.getBody()); } @@ -760,43 +1043,58 @@ public void testSecurityIndexSecurity() throws Exception { setup(); final RestHelper rh = nonSslRestHelper(); - HttpResponse res = rh.executePutRequest(".opendistro_security/_mapping?pretty", "{\"properties\": {\"name\":{\"type\":\"text\"}}}", - encodeBasicHeader("nagilum", "nagilum")); + HttpResponse res = rh.executePutRequest( + ".opendistro_security/_mapping?pretty", + "{\"properties\": {\"name\":{\"type\":\"text\"}}}", + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - res = rh.executePutRequest("*dis*rit*/_mapping?pretty", "{\"properties\": {\"name\":{\"type\":\"text\"}}}", - encodeBasicHeader("nagilum", "nagilum")); + res = rh.executePutRequest( + "*dis*rit*/_mapping?pretty", + "{\"properties\": {\"name\":{\"type\":\"text\"}}}", + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - res = rh.executePutRequest("*/_mapping?pretty", "{\"properties\": {\"name\":{\"type\":\"text\"}}}", - encodeBasicHeader("nagilum", "nagilum")); + res = rh.executePutRequest( + "*/_mapping?pretty", + "{\"properties\": {\"name\":{\"type\":\"text\"}}}", + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - res = rh.executePutRequest("_all/_mapping?pretty", "{\"properties\": {\"name\":{\"type\":\"text\"}}}", - encodeBasicHeader("nagilum", "nagilum")); + res = rh.executePutRequest( + "_all/_mapping?pretty", + "{\"properties\": {\"name\":{\"type\":\"text\"}}}", + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - res = rh.executePostRequest(".opendistro_security/_close", "", - encodeBasicHeader("nagilum", "nagilum")); + res = rh.executePostRequest(".opendistro_security/_close", "", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - res = rh.executeDeleteRequest(".opendistro_security", - encodeBasicHeader("nagilum", "nagilum")); - res = rh.executeDeleteRequest("_all", - encodeBasicHeader("nagilum", "nagilum")); + res = rh.executeDeleteRequest(".opendistro_security", encodeBasicHeader("nagilum", "nagilum")); + res = rh.executeDeleteRequest("_all", encodeBasicHeader("nagilum", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - res = rh.executePutRequest(".opendistro_security/_settings", "{\"index\" : {\"number_of_replicas\" : 2}}", - encodeBasicHeader("nagilum", "nagilum")); + res = rh.executePutRequest( + ".opendistro_security/_settings", + "{\"index\" : {\"number_of_replicas\" : 2}}", + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); - res = rh.executePutRequest(".opendistro_secur*/_settings", "{\"index\" : {\"number_of_replicas\" : 2}}", - encodeBasicHeader("nagilum", "nagilum")); + res = rh.executePutRequest( + ".opendistro_secur*/_settings", + "{\"index\" : {\"number_of_replicas\" : 2}}", + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, res.getStatusCode()); -// res = rh.executePostRequest(".opendistro_security/_freeze", "", -// encodeBasicHeader("nagilum", "nagilum")); -// Assert.assertTrue(res.getStatusCode() >= 400); + // res = rh.executePostRequest(".opendistro_security/_freeze", "", + // encodeBasicHeader("nagilum", "nagilum")); + // Assert.assertTrue(res.getStatusCode() >= 400); String bulkBody = "{ \"index\" : { \"_index\" : \".opendistro_security\", \"_id\" : \"1\" } }\n" - + "{ \"field1\" : \"value1\" }\n" - + "{ \"index\" : { \"_index\" : \".opendistro_security\", \"_id\" : \"2\" } }\n" - + "{ \"field2\" : \"value2\" }\n" - + "{ \"index\" : { \"_index\" : \"myindex\", \"_id\" : \"2\" } }\n" - + "{ \"field2\" : \"value2\" }\n" - + "{ \"delete\" : { \"_index\" : \".opendistro_security\", \"_id\" : \"config\" } }\n"; + + "{ \"field1\" : \"value1\" }\n" + + "{ \"index\" : { \"_index\" : \".opendistro_security\", \"_id\" : \"2\" } }\n" + + "{ \"field2\" : \"value2\" }\n" + + "{ \"index\" : { \"_index\" : \"myindex\", \"_id\" : \"2\" } }\n" + + "{ \"field2\" : \"value2\" }\n" + + "{ \"delete\" : { \"_index\" : \".opendistro_security\", \"_id\" : \"config\" } }\n"; res = rh.executePostRequest("_bulk?refresh=true&pretty", bulkBody, encodeBasicHeader("nagilum", "nagilum")); JsonNode jsonNode = readTree(res.getBody()); System.out.println(res.getBody()); @@ -813,6 +1111,6 @@ public void testMonitorHealth() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig(), Settings.EMPTY); RestHelper rh = nonSslRestHelper(); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_cat/health",encodeBasicHeader("picard", "picard")).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_cat/health", encodeBasicHeader("picard", "picard")).getStatusCode()); } } diff --git a/src/test/java/org/opensearch/security/PitIntegrationTests.java b/src/test/java/org/opensearch/security/PitIntegrationTests.java index 11c624eba6..035cc2ce3e 100644 --- a/src/test/java/org/opensearch/security/PitIntegrationTests.java +++ b/src/test/java/org/opensearch/security/PitIntegrationTests.java @@ -37,86 +37,75 @@ public void testPitExplicitAPIAccess() throws Exception { RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { // create alias - tc.admin().indices().create(new CreateIndexRequest("pit_1") - .alias(new Alias("alias"))) - .actionGet(); + tc.admin().indices().create(new CreateIndexRequest("pit_1").alias(new Alias("alias"))).actionGet(); // create index - tc.index(new IndexRequest("pit_2").id("2").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE). - source("{\"content\":2}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("pit_2").id("2") + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":2}", XContentType.JSON) + ).actionGet(); } RestHelper.HttpResponse resc; // Create point in time in index should be successful since the user has permission for index - resc = rh.executePostRequest("/alias/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executePostRequest("/alias/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - String pitId1 = resc.findValueInJson("pit_id"); + String pitId1 = resc.findValueInJson("pit_id"); // Create point in time in index for which the user does not have permission - resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // Create point in time in index for which the user has permission for - resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("pit-2", "nagilum")); + resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("pit-2", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - String pitId2 = resc.findValueInJson("pit_id"); - resc = rh.executePostRequest("/pit*/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("all-pit", "nagilum")); + String pitId2 = resc.findValueInJson("pit_id"); + resc = rh.executePostRequest("/pit*/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("all-pit", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); // PIT segments should work since there is atleast one PIT for which user has access for - resc = rh.executeGetRequest("/_cat/pit_segments", - "{\"pit_id\":\"" + pitId1 +"\"}", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeGetRequest("/_cat/pit_segments", "{\"pit_id\":\"" + pitId1 + "\"}", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); // PIT segments should work since there is atleast one PIT for which user has access for - resc = rh.executeGetRequest("/_cat/pit_segments", - "{\"pit_id\":\"" + pitId1 +"\"}", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeGetRequest("/_cat/pit_segments", "{\"pit_id\":\"" + pitId1 + "\"}", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); // Should throw error since user does not have access for pitId2 - resc = rh.executeGetRequest("/_cat/pit_segments", - "{\"pit_id\":\"" + pitId2 +"\"}", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeGetRequest("/_cat/pit_segments", "{\"pit_id\":\"" + pitId2 + "\"}", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // Should throw error since user does not have access for pitId2 - resc = rh.executeGetRequest("/_cat/pit_segments", - "{\"pit_id\":[\"" + pitId1 +"\",\"" + pitId2 + "\"]}", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeGetRequest( + "/_cat/pit_segments", + "{\"pit_id\":[\"" + pitId1 + "\",\"" + pitId2 + "\"]}", + encodeBasicHeader("pit-1", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // Delete explicit PITs should work for PIT for which user has access for - resc = rh.executeDeleteRequest("/_search/point_in_time", - "{\"pit_id\":\"" + pitId1 +"\"}", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeDeleteRequest("/_search/point_in_time", "{\"pit_id\":\"" + pitId1 + "\"}", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertEquals(pitId1, resc.findValueInJson("pits[0].pit_id")); Assert.assertEquals("true", resc.findValueInJson("pits[0].successful")); // Should throw error since user does not have access for pitId2 - resc = rh.executeDeleteRequest("/_search/point_in_time", - "{\"pit_id\":\"" + pitId2 +"\"}", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeDeleteRequest("/_search/point_in_time", "{\"pit_id\":\"" + pitId2 + "\"}", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // Should throw error since user does not have access for pitId2 - resc = rh.executeDeleteRequest("/_search/point_in_time", - "{\"pit_id\":[\"" + pitId1 +"\",\"" + pitId2 + "\"]}", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeDeleteRequest( + "/_search/point_in_time", + "{\"pit_id\":[\"" + pitId1 + "\",\"" + pitId2 + "\"]}", + encodeBasicHeader("pit-1", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // Delete explicit PITs should work for PIT for which user has access for - resc = rh.executeDeleteRequest("/_search/point_in_time", - "{\"pit_id\":\"" + pitId2 +"\"}", - encodeBasicHeader("pit-2", "nagilum")); + resc = rh.executeDeleteRequest("/_search/point_in_time", "{\"pit_id\":\"" + pitId2 + "\"}", encodeBasicHeader("pit-2", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertEquals(pitId2, resc.findValueInJson("pits[0].pit_id")); Assert.assertEquals("true", resc.findValueInJson("pits[0].successful")); @@ -130,40 +119,41 @@ public void testPitAllAPIAccess() throws Exception { // Create two indices try (Client tc = getClient()) { - tc.index(new IndexRequest("pit_1").id("1").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE). - source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("pit_2").id("2").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE). - source("{\"content\":2}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("pit_1").id("1") + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("pit_2").id("2") + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":2}", XContentType.JSON) + ).actionGet(); } RestHelper.HttpResponse resc; // Create point in time in index should be successful since the user has permission for index - resc = rh.executePostRequest("/pit_1/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executePostRequest("/pit_1/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); String pitId1 = resc.findValueInJson("pit_id"); // Create point in time in index for which the user does not have permission - resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // Create point in time in index for which the user has permission for - resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("pit-2", "nagilum")); + resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("pit-2", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); String pitId2 = resc.findValueInJson("pit_id"); // Throw security error if user does not have all index permission - resc = rh.executeGetRequest("/_search/point_in_time/_all", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeGetRequest("/_search/point_in_time/_all", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // List all PITs should work for user with all index access - resc = rh.executeGetRequest("/_search/point_in_time/_all", - encodeBasicHeader("all-pit", "nagilum")); + resc = rh.executeGetRequest("/_search/point_in_time/_all", encodeBasicHeader("all-pit", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); List pitList = new ArrayList<>(); pitList.add(pitId1); @@ -172,24 +162,19 @@ public void testPitAllAPIAccess() throws Exception { pitList.contains(resc.findValueInJson("pits[1].pit_id")); // Throw security error if user does not have all index permission - resc = rh.executeGetRequest("/_cat/pit_segments/_all", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeGetRequest("/_cat/pit_segments/_all", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // PIT segments should work for user with all index access - resc = rh.executeGetRequest("/_cat/pit_segments/_all", - encodeBasicHeader("all-pit", "nagilum")); + resc = rh.executeGetRequest("/_cat/pit_segments/_all", encodeBasicHeader("all-pit", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - // Throw security error if user does not have all index permission - resc = rh.executeDeleteRequest("/_search/point_in_time/_all", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeDeleteRequest("/_search/point_in_time/_all", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // Delete all PITs should work for user with all index access - resc = rh.executeDeleteRequest("/_search/point_in_time/_all", - encodeBasicHeader("all-pit", "nagilum")); + resc = rh.executeDeleteRequest("/_search/point_in_time/_all", encodeBasicHeader("all-pit", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); pitList.contains(resc.findValueInJson("pits[0].pit_id")); pitList.contains(resc.findValueInJson("pits[1].pit_id")); @@ -202,8 +187,8 @@ public void testPitAllAPIAccess() throws Exception { public void testDataStreamWithPits() throws Exception { setup(); RestHelper rh = nonSslRestHelper(); - String indexTemplate = "{\"index_patterns\": [ \"my-data-stream*\" ], \"data_stream\": { }, \"priority\": 200, " + - "\"template\": {\"settings\": { } } }"; + String indexTemplate = "{\"index_patterns\": [ \"my-data-stream*\" ], \"data_stream\": { }, \"priority\": 200, " + + "\"template\": {\"settings\": { } } }"; rh.executePutRequest("/_index_template/my-data-stream-template", indexTemplate, encodeBasicHeader("ds1", "nagilum")); @@ -212,32 +197,25 @@ public void testDataStreamWithPits() throws Exception { RestHelper.HttpResponse resc; // create pit should work since user has permission on data stream - resc = rh.executePostRequest("/my-data-stream11/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executePostRequest("/my-data-stream11/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - String pitId1 = resc.findValueInJson("pit_id"); + String pitId1 = resc.findValueInJson("pit_id"); // PIT segments works since the user has access for backing indices - resc = rh.executeGetRequest("/_cat/pit_segments", - "{\"pit_id\":\"" + pitId1 +"\"}", - encodeBasicHeader("pit-1", "nagilum")); + resc = rh.executeGetRequest("/_cat/pit_segments", "{\"pit_id\":\"" + pitId1 + "\"}", encodeBasicHeader("pit-1", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); // create pit should work since user has permission on data stream - resc = rh.executePostRequest("/my-data-stream21/_search/point_in_time?keep_alive=100m", "", - encodeBasicHeader("pit-2", "nagilum")); + resc = rh.executePostRequest("/my-data-stream21/_search/point_in_time?keep_alive=100m", "", encodeBasicHeader("pit-2", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - String pitId2 = resc.findValueInJson("pit_id"); + String pitId2 = resc.findValueInJson("pit_id"); // since pit-3 doesn't have permission to backing data stream indices, throw security error - resc = rh.executeGetRequest("/_cat/pit_segments", - "{\"pit_id\":\"" + pitId2 +"\"}", - encodeBasicHeader("pit-3", "nagilum")); + resc = rh.executeGetRequest("/_cat/pit_segments", "{\"pit_id\":\"" + pitId2 + "\"}", encodeBasicHeader("pit-3", "nagilum")); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); // Delete all PITs should work for user with all index access - resc = rh.executeDeleteRequest("/_search/point_in_time/_all", - encodeBasicHeader("all-pit", "nagilum")); + resc = rh.executeDeleteRequest("/_search/point_in_time/_all", encodeBasicHeader("all-pit", "nagilum")); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); } } diff --git a/src/test/java/org/opensearch/security/PrivilegesEvaluationTest.java b/src/test/java/org/opensearch/security/PrivilegesEvaluationTest.java index 1f9668c641..b7af395daa 100644 --- a/src/test/java/org/opensearch/security/PrivilegesEvaluationTest.java +++ b/src/test/java/org/opensearch/security/PrivilegesEvaluationTest.java @@ -31,21 +31,27 @@ public void resolveTestHidden() throws Exception { try (Client client = getClient()) { - client.index(new IndexRequest("hidden_test_not_hidden").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(XContentType.JSON, "index", - "hidden_test_not_hidden", "b", "y", "date", "1985/01/01")).actionGet(); - - client.admin().indices().create(new CreateIndexRequest(".hidden_test_actually_hidden").settings(ImmutableMap.of("index.hidden", true))) - .actionGet(); - client.index(new IndexRequest(".hidden_test_actually_hidden").id("test").source("a", "b").setRefreshPolicy(RefreshPolicy.IMMEDIATE)) - .actionGet(); + client.index( + new IndexRequest("hidden_test_not_hidden").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source(XContentType.JSON, "index", "hidden_test_not_hidden", "b", "y", "date", "1985/01/01") + ).actionGet(); + + client.admin() + .indices() + .create(new CreateIndexRequest(".hidden_test_actually_hidden").settings(ImmutableMap.of("index.hidden", true))) + .actionGet(); + client.index( + new IndexRequest(".hidden_test_actually_hidden").id("test").source("a", "b").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + ).actionGet(); } RestHelper rh = nonSslRestHelper(); - RestHelper.HttpResponse httpResponse = rh.executeGetRequest("/*hidden_test*/_search?expand_wildcards=all&pretty=true", - encodeBasicHeader("hidden_test", "nagilum")); + RestHelper.HttpResponse httpResponse = rh.executeGetRequest( + "/*hidden_test*/_search?expand_wildcards=all&pretty=true", + encodeBasicHeader("hidden_test", "nagilum") + ); Assert.assertEquals(httpResponse.getBody(), 403, httpResponse.getStatusCode()); - httpResponse = rh.executeGetRequest("/hidden_test_not_hidden?pretty=true", - encodeBasicHeader("hidden_test", "nagilum")); + httpResponse = rh.executeGetRequest("/hidden_test_not_hidden?pretty=true", encodeBasicHeader("hidden_test", "nagilum")); Assert.assertEquals(httpResponse.getBody(), 200, httpResponse.getStatusCode()); } } diff --git a/src/test/java/org/opensearch/security/ResolveAPITests.java b/src/test/java/org/opensearch/security/ResolveAPITests.java index 2c297e3bbe..088702acd9 100644 --- a/src/test/java/org/opensearch/security/ResolveAPITests.java +++ b/src/test/java/org/opensearch/security/ResolveAPITests.java @@ -32,9 +32,8 @@ import org.opensearch.security.test.SingleClusterTest; import org.opensearch.security.test.helper.rest.RestHelper; - public class ResolveAPITests extends SingleClusterTest { - + protected final Logger log = LogManager.getLogger(this.getClass()); @Test @@ -48,7 +47,10 @@ public void testResolveDnfofFalse() throws Exception { final RestHelper rh = nonSslRestHelper(); RestHelper.HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_resolve/index/*?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_resolve/index/*?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); log.debug(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -59,7 +61,10 @@ public void testResolveDnfofFalse() throws Exception { assertContains(res, "*xyz*"); assertContains(res, "*role01_role02*"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_resolve/index/starfleet*?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_resolve/index/starfleet*?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); log.debug(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -72,10 +77,16 @@ public void testResolveDnfofFalse() throws Exception { assertContains(res, "*starfleet_academy*"); assertContains(res, "*starfleet_library*"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("_resolve/index/*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("_resolve/index/*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode() + ); log.debug(res.getBody()); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_resolve/index/starfleet*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_resolve/index/starfleet*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode() + ); log.debug(res.getBody()); assertContains(res, "*starfleet*"); assertContains(res, "*starfleet_academy*"); @@ -92,7 +103,10 @@ public void testResolveDnfofTrue() throws Exception { final RestHelper rh = nonSslRestHelper(); RestHelper.HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_resolve/index/*?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_resolve/index/*?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); log.debug(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -103,7 +117,10 @@ public void testResolveDnfofTrue() throws Exception { assertContains(res, "*xyz*"); assertContains(res, "*role01_role02*"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_resolve/index/starfleet*?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_resolve/index/starfleet*?pretty", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); log.debug(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -116,7 +133,10 @@ public void testResolveDnfofTrue() throws Exception { assertContains(res, "*starfleet_academy*"); assertContains(res, "*starfleet_library*"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_resolve/index/*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_resolve/index/*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode() + ); log.debug(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -127,7 +147,10 @@ public void testResolveDnfofTrue() throws Exception { assertContains(res, "*public*"); assertContains(res, "*xyz*"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_resolve/index/starfleet*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_resolve/index/starfleet*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode() + ); log.debug(res.getBody()); assertNotContains(res, "*xception*"); assertNotContains(res, "*erial*"); @@ -140,30 +163,87 @@ public void testResolveDnfofTrue() throws Exception { assertContains(res, "*starfleet_academy*"); assertContains(res, "*starfleet_library*"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executeGetRequest("_resolve/index/vulcangov*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executeGetRequest("_resolve/index/vulcangov*?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode() + ); log.debug(res.getBody()); } private void setupIndices() { try (Client tc = getClient()) { tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("xyz").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(IndicesAliasesRequest.AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(IndicesAliasesRequest.AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(IndicesAliasesRequest.AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(IndicesAliasesRequest.AliasActions.add().indices("xyz").alias("alias1"))).actionGet(); + tc.index( + new IndexRequest("vulcangov").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("public").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("spock").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("kirk").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("xyz").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + IndicesAliasesRequest.AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + IndicesAliasesRequest.AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + IndicesAliasesRequest.AliasActions.add().indices("public").alias("unrestricted") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(IndicesAliasesRequest.AliasActions.add().indices("xyz").alias("alias1")) + ) + .actionGet(); } } } diff --git a/src/test/java/org/opensearch/security/RolesInjectorIntegTest.java b/src/test/java/org/opensearch/security/RolesInjectorIntegTest.java index d14f8d6600..0ab9736378 100644 --- a/src/test/java/org/opensearch/security/RolesInjectorIntegTest.java +++ b/src/test/java/org/opensearch/security/RolesInjectorIntegTest.java @@ -63,14 +63,21 @@ public RolesInjectorPlugin(final Settings settings, final Path configPath) { } @Override - public Collection createComponents(Client client, ClusterService clusterService, ThreadPool threadPool, - ResourceWatcherService resourceWatcherService, ScriptService scriptService, - NamedXContentRegistry xContentRegistry, Environment environment, - NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry, - IndexNameExpressionResolver indexNameExpressionResolver, - Supplier repositoriesServiceSupplier) { - if(injectedRoles != null) - threadPool.getThreadContext().putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES, injectedRoles); + public Collection createComponents( + Client client, + ClusterService clusterService, + ThreadPool threadPool, + ResourceWatcherService resourceWatcherService, + ScriptService scriptService, + NamedXContentRegistry xContentRegistry, + Environment environment, + NodeEnvironment nodeEnvironment, + NamedWriteableRegistry namedWriteableRegistry, + IndexNameExpressionResolver indexNameExpressionResolver, + Supplier repositoriesServiceSupplier + ) { + if (injectedRoles != null) threadPool.getThreadContext() + .putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES, injectedRoles); return new ArrayList<>(); } } @@ -79,26 +86,42 @@ public Collection createComponents(Client client, ClusterService cluster public void testRolesInject() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityRoles("roles.yml"), Settings.EMPTY); - Assert.assertEquals(clusterInfo.numNodes, clusterHelper.nodeClient().admin().cluster().health( - new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, clusterHelper.nodeClient().admin().cluster(). - health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); - - final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put(minimumSecuritySettings(Settings.EMPTY).get(0)) - .put("cluster.name", clusterInfo.clustername) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") - .put("path.home", "./target") - .put("node.name", "testclient") - .put("discovery.initial_state_timeout", "8s") - .put("plugins.security.allow_default_init_securityindex", "true") - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) - .build(); - - //1. Without roles injection. - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, RolesInjectorPlugin.class).start()) { + Assert.assertEquals( + clusterInfo.numNodes, + clusterHelper.nodeClient() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForGreenStatus()) + .actionGet() + .getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); + + final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) + .put(minimumSecuritySettings(Settings.EMPTY).get(0)) + .put("cluster.name", clusterInfo.clustername) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") + .put("path.home", "./target") + .put("node.name", "testclient") + .put("discovery.initial_state_timeout", "8s") + .put("plugins.security.allow_default_init_securityindex", "true") + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .build(); + + // 1. Without roles injection. + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + RolesInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-1")).actionGet(); @@ -107,10 +130,18 @@ public void testRolesInject() throws Exception { Assert.assertTrue(ier.isExists()); } - //2. With invalid roles, must throw security exception. + // 2. With invalid roles, must throw security exception. RolesInjectorPlugin.injectedRoles = "invalid_user|invalid_role"; Exception exception = null; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, RolesInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + RolesInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-2")).actionGet(); @@ -122,9 +153,17 @@ public void testRolesInject() throws Exception { Assert.assertNotNull(exception); Assert.assertTrue(exception.getMessage().contains("indices:admin/create")); - //3. With valid roles - which has permission to create index. + // 3. With valid roles - which has permission to create index. RolesInjectorPlugin.injectedRoles = "valid_user|opendistro_security_all_access"; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, RolesInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + RolesInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-3")).actionGet(); diff --git a/src/test/java/org/opensearch/security/RolesValidationIntegTest.java b/src/test/java/org/opensearch/security/RolesValidationIntegTest.java index 1b4aee3e51..89e0cd2e45 100644 --- a/src/test/java/org/opensearch/security/RolesValidationIntegTest.java +++ b/src/test/java/org/opensearch/security/RolesValidationIntegTest.java @@ -57,14 +57,22 @@ public RolesValidationPlugin(final Settings settings, final Path configPath) { } @Override - public Collection createComponents(Client client, ClusterService clusterService, ThreadPool threadPool, - ResourceWatcherService resourceWatcherService, ScriptService scriptService, - NamedXContentRegistry xContentRegistry, Environment environment, - NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry, - IndexNameExpressionResolver indexNameExpressionResolver, - Supplier repositoriesServiceSupplier) { - if(rolesValidation != null) { - threadPool.getThreadContext().putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES, "test|opendistro_security_all_access"); + public Collection createComponents( + Client client, + ClusterService clusterService, + ThreadPool threadPool, + ResourceWatcherService resourceWatcherService, + ScriptService scriptService, + NamedXContentRegistry xContentRegistry, + Environment environment, + NodeEnvironment nodeEnvironment, + NamedWriteableRegistry namedWriteableRegistry, + IndexNameExpressionResolver indexNameExpressionResolver, + Supplier repositoriesServiceSupplier + ) { + if (rolesValidation != null) { + threadPool.getThreadContext() + .putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES, "test|opendistro_security_all_access"); threadPool.getThreadContext().putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES_VALIDATION, rolesValidation); } return new ArrayList<>(); @@ -75,21 +83,28 @@ public Collection createComponents(Client client, ClusterService cluster public void testRolesValidation() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityRoles("roles.yml"), Settings.EMPTY); - final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put(minimumSecuritySettings(Settings.EMPTY).get(0)) - .put("cluster.name", clusterInfo.clustername) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") - .put("path.home", "./target") - .put("node.name", "testclient") - .put("discovery.initial_state_timeout", "8s") - .put("plugins.security.allow_default_init_securityindex", "true") - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) - .build(); + final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) + .put(minimumSecuritySettings(Settings.EMPTY).get(0)) + .put("cluster.name", clusterInfo.clustername) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") + .put("path.home", "./target") + .put("node.name", "testclient") + .put("discovery.initial_state_timeout", "8s") + .put("plugins.security.allow_default_init_securityindex", "true") + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .build(); // 1. Without roles validation - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, RolesValidationPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + RolesValidationPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-1")).actionGet(); Assert.assertTrue(cir.isAcknowledged()); @@ -100,8 +115,15 @@ public void testRolesValidation() throws Exception { OpenSearchSecurityException exception = null; // 2. with roles invalid to the user RolesValidationPlugin.rolesValidation = "invalid_role"; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, RolesValidationPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + RolesValidationPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-2")).actionGet(); } catch (OpenSearchSecurityException ex) { @@ -112,8 +134,15 @@ public void testRolesValidation() throws Exception { // 3. with roles valid to the user RolesValidationPlugin.rolesValidation = "opendistro_security_all_access"; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, RolesValidationPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + RolesValidationPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-3")).actionGet(); Assert.assertTrue(cir.isAcknowledged()); diff --git a/src/test/java/org/opensearch/security/SecurityAdminIEndpointsTests.java b/src/test/java/org/opensearch/security/SecurityAdminIEndpointsTests.java index bc5d174739..b8da89e2dc 100644 --- a/src/test/java/org/opensearch/security/SecurityAdminIEndpointsTests.java +++ b/src/test/java/org/opensearch/security/SecurityAdminIEndpointsTests.java @@ -28,35 +28,45 @@ public void testNoSSL() throws Exception { setup(settings); final RestHelper rh = nonSslRestHelper(); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executePutRequest("_plugins/_security/configupdate", "").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executePutRequest("_plugins/_security/configupdate?config_types=xxx", "", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("_plugins/_security/configupdate?config_types=xxx", "", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest("_plugins/_security/whoami").getStatusCode()); } @Test public void testEndpoints() throws Exception { - final Settings settings = Settings.builder().put("plugins.security.ssl.http.enabled", true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .putList("plugins.security.nodes_dn", "CN=node-*.example.com,OU=SSL,O=Test,L=Test,C=DE").build(); + final Settings settings = Settings.builder() + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .putList("plugins.security.nodes_dn", "CN=node-*.example.com,OU=SSL,O=Test,L=Test,C=DE") + .build(); setup(settings); final RestHelper rh = restHelper(); rh.enableHTTPClientSSL = true; rh.trustHTTPServerCertificate = true; rh.sendAdminCertificate = false; - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executePutRequest("_plugins/_security/configupdate", "").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executePutRequest("_plugins/_security/configupdate?config_types=xxx", "", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("_plugins/_security/configupdate?config_types=xxx", "", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); RestHelper.HttpResponse res; Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_plugins/_security/whoami")).getStatusCode()); @@ -71,13 +81,17 @@ public void testEndpoints() throws Exception { assertContains(res, "*\"is_admin\":false*"); assertContains(res, "*\"is_node_certificate_request\":true*"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executePutRequest("_plugins/_security/configupdate", "").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executePutRequest("_plugins/_security/configupdate?config_types=xxx", "", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("_plugins/_security/configupdate?config_types=xxx", "", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); rh.keystore = "spock-keystore.jks"; @@ -87,13 +101,17 @@ public void testEndpoints() throws Exception { assertContains(res, "*\"is_admin\":false*"); assertContains(res, "*\"is_node_certificate_request\":false*"); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executePutRequest("_plugins/_security/configupdate", "").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executePutRequest("_plugins/_security/configupdate?config_types=xxx", "", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePutRequest("_plugins/_security/configupdate?config_types=xxx", "", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); rh.keystore = "kirk-keystore.jks"; @@ -103,14 +121,25 @@ public void testEndpoints() throws Exception { assertContains(res, "*\"is_admin\":true*"); assertContains(res, "*\"is_node_certificate_request\":false*"); - Assert.assertEquals(HttpStatus.SC_OK, - rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) - .getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "{}", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, rh.executePutRequest("_plugins/_security/configupdate", "").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "").getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePutRequest("_plugins/_security/configupdate?config_types=unknown_xxx", "", - encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest("_plugins/_security/configupdate?config_types=roles", "").getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePutRequest( + "_plugins/_security/configupdate?config_types=unknown_xxx", + "", + encodeBasicHeader("nagilum", "nagilum") + )).getStatusCode() + ); assertContains(res, "*\"successful\":0*failed_node_exception*"); } diff --git a/src/test/java/org/opensearch/security/SecurityAdminInvalidConfigsTests.java b/src/test/java/org/opensearch/security/SecurityAdminInvalidConfigsTests.java index 18f5c06529..6cb89dc18f 100644 --- a/src/test/java/org/opensearch/security/SecurityAdminInvalidConfigsTests.java +++ b/src/test/java/org/opensearch/security/SecurityAdminInvalidConfigsTests.java @@ -42,133 +42,153 @@ public class SecurityAdminInvalidConfigsTests extends SingleClusterTest { - @Test - public void testSecurityAdminDuplicateKey() throws Exception { - final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); - setup(settings); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - - List argsAsList = new ArrayList<>(); - argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); - argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); - argsAsList.add("-p"); - argsAsList.add(String.valueOf(clusterInfo.httpPort)); - argsAsList.add("-cn"); - argsAsList.add(clusterInfo.clustername); - argsAsList.add("-cd"); - argsAsList.add(new File("./src/test/resources/invalid_dupkey").getAbsolutePath()); - argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); - Assert.assertNotEquals(0, returnCode); - - RestHelper rh = restHelper(); - - Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - } - - @Test - public void testSecurityAdminDuplicateKeyReload() throws Exception { - testSecurityAdminDuplicateKey(); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - - List argsAsList = new ArrayList<>(); - argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); - argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); - argsAsList.add("-p"); - argsAsList.add(String.valueOf(clusterInfo.httpPort)); - argsAsList.add("-cn"); - argsAsList.add(clusterInfo.clustername); - argsAsList.add("-rl"); - argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); - Assert.assertEquals(0, returnCode); - - RestHelper rh = restHelper(); - - Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - } - - @Test - public void testSecurityAdminDuplicateKeySingleFile() throws Exception { - final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); - setup(settings); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - - List argsAsList = new ArrayList<>(); - argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); - argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); - argsAsList.add("-p"); - argsAsList.add(String.valueOf(clusterInfo.httpPort)); - argsAsList.add("-cn"); - argsAsList.add(clusterInfo.clustername); - argsAsList.add("-f"); - argsAsList.add(new File("./src/test/resources/invalid_dupkey/roles_mapping.yml").getAbsolutePath()); - argsAsList.add("-t"); - argsAsList.add("rolesmapping"); - argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); - Assert.assertNotEquals(0, returnCode); - - RestHelper rh = restHelper(); - - Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - } - - @Test - public void testSecurityAdminDuplicateKeyReloadSingleFile() throws Exception { - testSecurityAdminDuplicateKeySingleFile(); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - - List argsAsList = new ArrayList<>(); - argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); - argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); - argsAsList.add("-p"); - argsAsList.add(String.valueOf(clusterInfo.httpPort)); - argsAsList.add("-cn"); - argsAsList.add(clusterInfo.clustername); - argsAsList.add("-rl"); - argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); - Assert.assertEquals(0, returnCode); - - RestHelper rh = restHelper(); - - Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - } + @Test + public void testSecurityAdminDuplicateKey() throws Exception { + final Settings settings = Settings.builder() + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); + setup(settings); + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + + List argsAsList = new ArrayList<>(); + argsAsList.add("-ts"); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); + argsAsList.add("-ks"); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add("-p"); + argsAsList.add(String.valueOf(clusterInfo.httpPort)); + argsAsList.add("-cn"); + argsAsList.add(clusterInfo.clustername); + argsAsList.add("-cd"); + argsAsList.add(new File("./src/test/resources/invalid_dupkey").getAbsolutePath()); + argsAsList.add("-nhnv"); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + Assert.assertNotEquals(0, returnCode); + + RestHelper rh = restHelper(); + + Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + } + + @Test + public void testSecurityAdminDuplicateKeyReload() throws Exception { + testSecurityAdminDuplicateKey(); + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + + List argsAsList = new ArrayList<>(); + argsAsList.add("-ts"); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); + argsAsList.add("-ks"); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add("-p"); + argsAsList.add(String.valueOf(clusterInfo.httpPort)); + argsAsList.add("-cn"); + argsAsList.add(clusterInfo.clustername); + argsAsList.add("-rl"); + argsAsList.add("-nhnv"); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + Assert.assertEquals(0, returnCode); + + RestHelper rh = restHelper(); + + Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + } + + @Test + public void testSecurityAdminDuplicateKeySingleFile() throws Exception { + final Settings settings = Settings.builder() + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); + setup(settings); + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + + List argsAsList = new ArrayList<>(); + argsAsList.add("-ts"); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); + argsAsList.add("-ks"); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add("-p"); + argsAsList.add(String.valueOf(clusterInfo.httpPort)); + argsAsList.add("-cn"); + argsAsList.add(clusterInfo.clustername); + argsAsList.add("-f"); + argsAsList.add(new File("./src/test/resources/invalid_dupkey/roles_mapping.yml").getAbsolutePath()); + argsAsList.add("-t"); + argsAsList.add("rolesmapping"); + argsAsList.add("-nhnv"); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + Assert.assertNotEquals(0, returnCode); + + RestHelper rh = restHelper(); + + Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + } + + @Test + public void testSecurityAdminDuplicateKeyReloadSingleFile() throws Exception { + testSecurityAdminDuplicateKeySingleFile(); + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + + List argsAsList = new ArrayList<>(); + argsAsList.add("-ts"); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); + argsAsList.add("-ks"); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add("-p"); + argsAsList.add(String.valueOf(clusterInfo.httpPort)); + argsAsList.add("-cn"); + argsAsList.add(clusterInfo.clustername); + argsAsList.add("-rl"); + argsAsList.add("-nhnv"); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + Assert.assertEquals(0, returnCode); + + RestHelper rh = restHelper(); + + Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + } } diff --git a/src/test/java/org/opensearch/security/SecurityAdminTests.java b/src/test/java/org/opensearch/security/SecurityAdminTests.java index bd032fc332..681d04fc3e 100644 --- a/src/test/java/org/opensearch/security/SecurityAdminTests.java +++ b/src/test/java/org/opensearch/security/SecurityAdminTests.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security; @@ -43,34 +43,33 @@ import static org.junit.Assert.assertThrows; public class SecurityAdminTests extends SingleClusterTest { - + @Test public void testSecurityAdmin() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, null, settings, false); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); argsAsList.add(clusterInfo.clustername); addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH); argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + RestHelper rh = restHelper(); Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); @@ -79,79 +78,89 @@ public void testSecurityAdmin() throws Exception { @Test public void testSecurityAdminHostnameVerificationEnforced() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/root-ca.pem")) - .put("plugins.security.ssl.http.pemcert_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/node.crt.pem")) - .put("plugins.security.ssl.http.pemkey_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/node.key.pem")) - .putList("plugins.security.authcz.admin_dn", List.of("CN=kirk,OU=client,O=client,L=test,C=de")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put( + "plugins.security.ssl.http.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/root-ca.pem") + ) + .put("plugins.security.ssl.http.pemcert_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/node.crt.pem")) + .put("plugins.security.ssl.http.pemkey_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/node.key.pem")) + .putList("plugins.security.authcz.admin_dn", List.of("CN=kirk,OU=client,O=client,L=test,C=de")) + .build(); setup(Settings.EMPTY, null, settings, false); - final String prefix = getResourceFolder()==null?"securityadmin/":getResourceFolder()+"/securityadmin/"; + final String prefix = getResourceFolder() == null ? "securityadmin/" : getResourceFolder() + "/securityadmin/"; List argsAsList = new ArrayList<>(); argsAsList.add("-cacert"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"root-ca.pem").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "root-ca.pem").toFile().getAbsolutePath()); argsAsList.add("-cert"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk.crt.pem").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk.crt.pem").toFile().getAbsolutePath()); argsAsList.add("-key"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk.key.pem").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk.key.pem").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-icl"); addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH); - final IOException expectedException = assertThrows(IOException.class, () -> SecurityAdmin.execute(argsAsList.toArray(new String[0]))); - final String expectedMessagePattern = "Certificate for <.+> doesn't match any of the subject alternative names: \\[node-.\\.example\\.com\\]"; + final IOException expectedException = assertThrows( + IOException.class, + () -> SecurityAdmin.execute(argsAsList.toArray(new String[0])) + ); + final String expectedMessagePattern = + "Certificate for <.+> doesn't match any of the subject alternative names: \\[node-.\\.example\\.com\\]"; assertThat(expectedException.getMessage(), matchesPattern(expectedMessagePattern)); } @Test public void testSecurityAdminHostnameVerificationNotEnforced() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/root-ca.pem")) - .put("plugins.security.ssl.http.pemcert_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/node.crt.pem")) - .put("plugins.security.ssl.http.pemkey_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/node.key.pem")) - .putList("plugins.security.authcz.admin_dn", List.of("CN=kirk,OU=client,O=client,L=test,C=de")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put( + "plugins.security.ssl.http.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/root-ca.pem") + ) + .put("plugins.security.ssl.http.pemcert_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/node.crt.pem")) + .put("plugins.security.ssl.http.pemkey_filepath", FileHelper.getAbsoluteFilePathFromClassPath("securityadmin/node.key.pem")) + .putList("plugins.security.authcz.admin_dn", List.of("CN=kirk,OU=client,O=client,L=test,C=de")) + .build(); setup(Settings.EMPTY, null, settings, false); - final String prefix = getResourceFolder()==null?"securityadmin/":getResourceFolder()+"/securityadmin/"; + final String prefix = getResourceFolder() == null ? "securityadmin/" : getResourceFolder() + "/securityadmin/"; List argsAsList = new ArrayList<>(); argsAsList.add("-cacert"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"root-ca.pem").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "root-ca.pem").toFile().getAbsolutePath()); argsAsList.add("-cert"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk.crt.pem").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk.crt.pem").toFile().getAbsolutePath()); argsAsList.add("-key"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk.key.pem").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk.key.pem").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-icl"); addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH); argsAsList.add("-nhnv"); - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); } @Test public void testSecurityAdminInvalidCert() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, null, settings, false); - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); @@ -159,7 +168,7 @@ public void testSecurityAdminInvalidCert() throws Exception { addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH); argsAsList.add("-nhnv"); - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); RestHelper rh = restHelper(); @@ -168,9 +177,9 @@ public void testSecurityAdminInvalidCert() throws Exception { argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"spock-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "spock-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); @@ -179,17 +188,16 @@ public void testSecurityAdminInvalidCert() throws Exception { argsAsList.add("--diagnose"); argsAsList.add("-nhnv"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(-1, returnCode); Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_plugins/_security/health?pretty")).getStatusCode()); argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"node-0-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "node-0-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); @@ -197,7 +205,7 @@ public void testSecurityAdminInvalidCert() throws Exception { addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH); argsAsList.add("-nhnv"); - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(-1, returnCode); Assert.assertEquals(HttpStatus.SC_OK, (rh.executeGetRequest("_plugins/_security/health?pretty")).getStatusCode()); @@ -206,92 +214,90 @@ public void testSecurityAdminInvalidCert() throws Exception { @Test public void testSecurityAdminV6Update() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, null, settings, false); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); argsAsList.add(clusterInfo.clustername); addDirectoryPath(argsAsList, new File("./legacy/securityconfig_v6").getAbsolutePath()); argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertNotEquals(0, returnCode); - + RestHelper rh = restHelper(); Assert.assertEquals(HttpStatus.SC_SERVICE_UNAVAILABLE, rh.executeGetRequest("_opendistro/_security/health?pretty").getStatusCode()); - //System.out.println(res.getBody()); - //assertContains(res, "*UP*"); - //assertContains(res, "*strict*"); - //assertNotContains(res, "*DOWN*"); + // System.out.println(res.getBody()); + // assertContains(res, "*UP*"); + // assertContains(res, "*strict*"); + // assertNotContains(res, "*DOWN*"); } - + @Test public void testSecurityAdminRegularUpdate() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, null, settings, true); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); argsAsList.add(clusterInfo.clustername); addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH); argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + RestHelper rh = restHelper(); HttpResponse res; - + Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); System.out.println(res.getBody()); assertContains(res, "*UP*"); assertContains(res, "*strict*"); assertNotContains(res, "*DOWN*"); } - + @Test public void testSecurityAdminSingularV7Updates() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings, true); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); @@ -301,16 +307,15 @@ public void testSecurityAdminSingularV7Updates() throws Exception { argsAsList.add("-t"); argsAsList.add("config"); argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); @@ -320,16 +325,15 @@ public void testSecurityAdminSingularV7Updates() throws Exception { argsAsList.add("-t"); argsAsList.add("rolesmapping"); argsAsList.add("-nhnv"); - - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); @@ -339,37 +343,36 @@ public void testSecurityAdminSingularV7Updates() throws Exception { argsAsList.add("-t"); argsAsList.add("tenants"); argsAsList.add("-nhnv"); - - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + RestHelper rh = restHelper(); HttpResponse res; - + Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); System.out.println(res.getBody()); assertContains(res, "*UP*"); assertContains(res, "*strict*"); assertNotContains(res, "*DOWN*"); } - + @Test public void testSecurityAdminSingularV6Updates() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings, true); - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); @@ -379,205 +382,209 @@ public void testSecurityAdminSingularV6Updates() throws Exception { argsAsList.add("-t"); argsAsList.add("config"); argsAsList.add("-nhnv"); - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertNotEquals(0, returnCode); - RestHelper rh = restHelper(); HttpResponse res; - + Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); System.out.println(res.getBody()); assertContains(res, "*UP*"); assertContains(res, "*strict*"); assertNotContains(res, "*DOWN*"); } - + @Test public void testSecurityAdminInvalidYml() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings, true); - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); argsAsList.add(clusterInfo.clustername); argsAsList.add("-f"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"roles_invalidxcontent.yml").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "roles_invalidxcontent.yml").toFile().getAbsolutePath()); argsAsList.add("-t"); argsAsList.add("roles"); argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertNotEquals(0, returnCode); - + RestHelper rh = restHelper(); HttpResponse res; - + Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); System.out.println(res.getBody()); assertContains(res, "*UP*"); assertContains(res, "*strict*"); assertNotContains(res, "*DOWN*"); } - + @Test public void testSecurityAdminReloadInvalidConfig() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings, true); - final RestHelper rh = restHelper(); //ssl resthelper + final RestHelper rh = restHelper(); // ssl resthelper rh.enableHTTPClientSSL = true; rh.trustHTTPServerCertificate = true; rh.sendAdminCertificate = true; rh.keystore = "kirk-keystore.jks"; - System.out.println(rh.executePutRequest(".opendistro_security/_doc/roles", FileHelper.loadFile("roles_invalidxcontent.yml")).getBody());; - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest(".opendistro_security/_doc/roles", "{\"roles\":\"dummy\"}").getStatusCode()); - - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - + System.out.println( + rh.executePutRequest(".opendistro_security/_doc/roles", FileHelper.loadFile("roles_invalidxcontent.yml")).getBody() + ); + ; + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest(".opendistro_security/_doc/roles", "{\"roles\":\"dummy\"}").getStatusCode() + ); + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); argsAsList.add(clusterInfo.clustername); argsAsList.add("-rl"); argsAsList.add("-nhnv"); - - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertNotEquals(0, returnCode); - + HttpResponse res; - + Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_opendistro/_security/health?pretty")).getStatusCode()); assertContains(res, "*UP*"); assertContains(res, "*strict*"); assertNotContains(res, "*DOWN*"); } - + @Test public void testSecurityAdminValidateConfig() throws Exception { List argsAsList = new ArrayList<>(); addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH); argsAsList.add("-vc"); - - int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + argsAsList = new ArrayList<>(); argsAsList.add("-f"); argsAsList.add(new File(PROJECT_ROOT_RELATIVE_PATH + "src/test/resources/roles.yml").getAbsolutePath()); argsAsList.add("-vc"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + argsAsList = new ArrayList<>(); argsAsList.add("-f"); argsAsList.add(new File(PROJECT_ROOT_RELATIVE_PATH + "src/main/resources/static_config/static_roles.yml").getAbsolutePath()); argsAsList.add("-vc"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + argsAsList = new ArrayList<>(); argsAsList.add("-f"); - argsAsList.add(new File(PROJECT_ROOT_RELATIVE_PATH + "src/main/resources/static_config/static_action_groups.yml").getAbsolutePath()); + argsAsList.add( + new File(PROJECT_ROOT_RELATIVE_PATH + "src/main/resources/static_config/static_action_groups.yml").getAbsolutePath() + ); argsAsList.add("-vc"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + argsAsList = new ArrayList<>(); argsAsList.add("-f"); argsAsList.add(new File(PROJECT_ROOT_RELATIVE_PATH + "src/main/resources/static_config/static_tenants.yml").getAbsolutePath()); argsAsList.add("-vc"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + argsAsList = new ArrayList<>(); argsAsList.add("-f"); argsAsList.add(TEST_RESOURCE_ABSOLUTE_PATH + "roles.yml"); argsAsList.add("-vc"); argsAsList.add("-t"); argsAsList.add("config"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertNotEquals(0, returnCode); - + argsAsList = new ArrayList<>(); argsAsList.add("-ks"); argsAsList.add(TEST_RESOURCE_ABSOLUTE_PATH); argsAsList.add("-vc"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertNotEquals(0, returnCode); - + argsAsList = new ArrayList<>(); addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH + "legacy/securityconfig_v6"); argsAsList.add("-vc"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertNotEquals(0, returnCode); - + argsAsList = new ArrayList<>(); addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH + "legacy/securityconfig_v6"); argsAsList.add("-vc"); argsAsList.add("6"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + argsAsList = new ArrayList<>(); addDirectoryPath(argsAsList, TEST_RESOURCE_ABSOLUTE_PATH); argsAsList.add("-vc"); argsAsList.add("8"); - - returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); + + returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertNotEquals(0, returnCode); } @Test public void testIsLegacySecurityIndexOnV7Index() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .build(); setup(Settings.EMPTY, null, settings, false); - - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; - + + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; + List argsAsList = new ArrayList<>(); argsAsList.add("-ts"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks").toFile().getAbsolutePath()); argsAsList.add("-ks"); - argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix+"kirk-keystore.jks").toFile().getAbsolutePath()); + argsAsList.add(FileHelper.getAbsoluteFilePathFromClassPath(prefix + "kirk-keystore.jks").toFile().getAbsolutePath()); argsAsList.add("-p"); argsAsList.add(String.valueOf(clusterInfo.httpPort)); argsAsList.add("-cn"); @@ -588,7 +595,7 @@ public void testIsLegacySecurityIndexOnV7Index() throws Exception { // Execute first time to create the index int returnCode = SecurityAdmin.execute(argsAsList.toArray(new String[0])); Assert.assertEquals(0, returnCode); - + ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); PrintStream old = System.out; @@ -600,7 +607,9 @@ public void testIsLegacySecurityIndexOnV7Index() throws Exception { System.out.flush(); System.setOut(old); String standardOut = baos.toString(); - String legacyIndexOutput = "Legacy index '"+ConfigConstants.OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX+"' (ES 6) detected (or forced). You should migrate the configuration!"; + String legacyIndexOutput = "Legacy index '" + + ConfigConstants.OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX + + "' (ES 6) detected (or forced). You should migrate the configuration!"; Assert.assertFalse(standardOut.contains(legacyIndexOutput)); } diff --git a/src/test/java/org/opensearch/security/SecurityRolesTests.java b/src/test/java/org/opensearch/security/SecurityRolesTests.java index ee8e1ea150..24a6bafbb8 100644 --- a/src/test/java/org/opensearch/security/SecurityRolesTests.java +++ b/src/test/java/org/opensearch/security/SecurityRolesTests.java @@ -40,76 +40,89 @@ public class SecurityRolesTests extends SingleClusterTest { - @Test - public void testSecurityRolesAnon() throws Exception { - - setup(Settings.EMPTY, new DynamicSecurityConfig() - .setSecurityInternalUsers("internal_users_sr.yml") - .setConfig("config_anon.yml"), Settings.EMPTY, true); - - RestHelper rh = nonSslRestHelper(); - - HttpResponse resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty"); - Assert.assertTrue(resc.getBody().contains("anonymous")); - Assert.assertFalse(resc.getBody().contains("xyz_sr")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - - resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("sr_user", "nagilum")); - Assert.assertTrue(resc.getBody().contains("sr_user")); - Assert.assertTrue(resc.getBody().contains("xyz_sr")); - Assert.assertFalse(resc.getBody().contains("opendistro_security_kibana_server")); - Assert.assertTrue(resc.getBody().contains("backend_roles=[abc_ber]")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - } - - @Test - public void testSecurityRoles() throws Exception { - - setup(Settings.EMPTY, new DynamicSecurityConfig() - .setSecurityRolesMapping("roles_mapping.yml") - .setSecurityInternalUsers("internal_users_sr.yml"), Settings.EMPTY, true); - - RestHelper rh = nonSslRestHelper(); - rh.sendAdminCertificate = false; - - HttpResponse resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("sr_user", "nagilum")); - Assert.assertTrue(resc.getBody().contains("sr_user")); - Assert.assertTrue(resc.getBody().contains("xyz_sr")); - - // Opendistro_security_roles cannot contain roles that don't exist. - Assert.assertFalse(resc.getBody().contains("xyz_sr_non_existent")); - - // Opendistro_security_roles can contain reserved roles. - Assert.assertTrue(resc.getBody().contains("xyz_sr_reserved")); - - // Opendistro_security_roles cannot contain roles that are hidden in rolesmapping.yml. - Assert.assertFalse(resc.getBody().contains("xyz_sr_hidden")); - - Assert.assertTrue(resc.getBody().contains("backend_roles=[abc_ber]")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - } - - @Test - public void testSecurityRolesImpersonation() throws Exception { - - Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".sr_user", "sr_impuser") - .build(); - - setup(Settings.EMPTY, new DynamicSecurityConfig() - .setSecurityInternalUsers("internal_users_sr.yml"), settings, true); - - RestHelper rh = nonSslRestHelper(); - - HttpResponse resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("sr_user", "nagilum"), new BasicHeader("opendistro_security_impersonate_as", "sr_impuser")); - Assert.assertFalse(resc.getBody().contains("sr_user")); - Assert.assertTrue(resc.getBody().contains("sr_impuser")); - Assert.assertFalse(resc.getBody().contains("xyz_sr")); - Assert.assertTrue(resc.getBody().contains("xyz_impsr")); - Assert.assertTrue(resc.getBody().contains("backend_roles=[ert_ber]")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - - resc = rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("sr_user", "nagilum"), new BasicHeader("opendistro_security_impersonate_as", "sr_impuser")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - } + @Test + public void testSecurityRolesAnon() throws Exception { + + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setSecurityInternalUsers("internal_users_sr.yml").setConfig("config_anon.yml"), + Settings.EMPTY, + true + ); + + RestHelper rh = nonSslRestHelper(); + + HttpResponse resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty"); + Assert.assertTrue(resc.getBody().contains("anonymous")); + Assert.assertFalse(resc.getBody().contains("xyz_sr")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("sr_user", "nagilum")); + Assert.assertTrue(resc.getBody().contains("sr_user")); + Assert.assertTrue(resc.getBody().contains("xyz_sr")); + Assert.assertFalse(resc.getBody().contains("opendistro_security_kibana_server")); + Assert.assertTrue(resc.getBody().contains("backend_roles=[abc_ber]")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + } + + @Test + public void testSecurityRoles() throws Exception { + + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setSecurityRolesMapping("roles_mapping.yml").setSecurityInternalUsers("internal_users_sr.yml"), + Settings.EMPTY, + true + ); + + RestHelper rh = nonSslRestHelper(); + rh.sendAdminCertificate = false; + + HttpResponse resc = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("sr_user", "nagilum")); + Assert.assertTrue(resc.getBody().contains("sr_user")); + Assert.assertTrue(resc.getBody().contains("xyz_sr")); + + // Opendistro_security_roles cannot contain roles that don't exist. + Assert.assertFalse(resc.getBody().contains("xyz_sr_non_existent")); + + // Opendistro_security_roles can contain reserved roles. + Assert.assertTrue(resc.getBody().contains("xyz_sr_reserved")); + + // Opendistro_security_roles cannot contain roles that are hidden in rolesmapping.yml. + Assert.assertFalse(resc.getBody().contains("xyz_sr_hidden")); + + Assert.assertTrue(resc.getBody().contains("backend_roles=[abc_ber]")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + } + + @Test + public void testSecurityRolesImpersonation() throws Exception { + + Settings settings = Settings.builder() + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".sr_user", "sr_impuser") + .build(); + + setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityInternalUsers("internal_users_sr.yml"), settings, true); + + RestHelper rh = nonSslRestHelper(); + + HttpResponse resc = rh.executeGetRequest( + "_opendistro/_security/authinfo?pretty", + encodeBasicHeader("sr_user", "nagilum"), + new BasicHeader("opendistro_security_impersonate_as", "sr_impuser") + ); + Assert.assertFalse(resc.getBody().contains("sr_user")); + Assert.assertTrue(resc.getBody().contains("sr_impuser")); + Assert.assertFalse(resc.getBody().contains("xyz_sr")); + Assert.assertTrue(resc.getBody().contains("xyz_impsr")); + Assert.assertTrue(resc.getBody().contains("backend_roles=[ert_ber]")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + resc = rh.executeGetRequest( + "*/_search?pretty", + encodeBasicHeader("sr_user", "nagilum"), + new BasicHeader("opendistro_security_impersonate_as", "sr_impuser") + ); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + } } diff --git a/src/test/java/org/opensearch/security/SlowIntegrationTests.java b/src/test/java/org/opensearch/security/SlowIntegrationTests.java index 6a90ef8e71..0e7585a08d 100644 --- a/src/test/java/org/opensearch/security/SlowIntegrationTests.java +++ b/src/test/java/org/opensearch/security/SlowIntegrationTests.java @@ -53,100 +53,155 @@ public class SlowIntegrationTests extends SingleClusterTest { @Test public void testCustomInterclusterRequestEvaluator() throws Exception { - + final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_INTERCLUSTER_REQUEST_EVALUATOR_CLASS, "org.opensearch.security.AlwaysFalseInterClusterRequestEvaluator") - .put("discovery.initial_state_timeout","8s") - .build(); - setup(Settings.EMPTY, null, settings, false, ClusterConfiguration.DEFAULT ,5,1); - Assert.assertEquals(1, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); + .put( + ConfigConstants.SECURITY_INTERCLUSTER_REQUEST_EVALUATOR_CLASS, + "org.opensearch.security.AlwaysFalseInterClusterRequestEvaluator" + ) + .put("discovery.initial_state_timeout", "8s") + .build(); + setup(Settings.EMPTY, null, settings, false, ClusterConfiguration.DEFAULT, 5, 1); + Assert.assertEquals( + 1, + clusterHelper.nodeClient() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForGreenStatus()) + .actionGet() + .getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); } @SuppressWarnings("resource") @Test public void testNodeClientAllowedWithServerCertificate() throws Exception { setup(); - Assert.assertEquals(clusterInfo.numNodes, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); - - - final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put(minimumSecuritySettings(Settings.EMPTY).get(0)) - .put("cluster.name", clusterInfo.clustername) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") - .put("path.home", "./target") - .put("node.name", "transportclient") - .put("discovery.initial_state_timeout","8s") - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost+":"+clusterInfo.nodePort) - .build(); - + Assert.assertEquals( + clusterInfo.numNodes, + clusterHelper.nodeClient() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForGreenStatus()) + .actionGet() + .getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); + + final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) + .put(minimumSecuritySettings(Settings.EMPTY).get(0)) + .put("cluster.name", clusterInfo.clustername) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") + .put("path.home", "./target") + .put("node.name", "transportclient") + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .build(); + log.debug("Start node client"); - + try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class).start()) { - Assert.assertFalse(node.client().admin().cluster().health(new ClusterHealthRequest().waitForNodes(String.valueOf(clusterInfo.numNodes+1))).actionGet().isTimedOut()); - Assert.assertEquals(clusterInfo.numNodes+1, node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); + Assert.assertFalse( + node.client() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForNodes(String.valueOf(clusterInfo.numNodes + 1))) + .actionGet() + .isTimedOut() + ); + Assert.assertEquals( + clusterInfo.numNodes + 1, + node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size() + ); } } - + @SuppressWarnings("resource") @Test public void testNodeClientDisallowedWithNonServerCertificate() throws Exception { setup(); - Assert.assertEquals(clusterInfo.numNodes, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); - - - final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put(minimumSecuritySettings(Settings.EMPTY).get(0)) - .put("cluster.name", clusterInfo.clustername) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") - .put("path.home", "./target") - .put("node.name", "transportclient") - .put("discovery.initial_state_timeout","8s") - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost+":"+clusterInfo.nodePort) - .put("plugins.security.ssl.transport.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("kirk-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS,"kirk") - .build(); - + Assert.assertEquals( + clusterInfo.numNodes, + clusterHelper.nodeClient() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForGreenStatus()) + .actionGet() + .getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); + + final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) + .put(minimumSecuritySettings(Settings.EMPTY).get(0)) + .put("cluster.name", clusterInfo.clustername) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") + .put("path.home", "./target") + .put("node.name", "transportclient") + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .put("plugins.security.ssl.transport.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("kirk-keystore.jks")) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "kirk") + .build(); + log.debug("Start node client"); try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class).start()) { Thread.sleep(10000); - Assert.assertEquals(1, node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); + Assert.assertEquals(1, node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); } catch (Exception e) { Assert.fail(e.toString()); } - + } - + @SuppressWarnings("resource") @Test public void testNodeClientDisallowedWithNonServerCertificate2() throws Exception { setup(); - Assert.assertEquals(clusterInfo.numNodes, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); - - final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put(minimumSecuritySettings(Settings.EMPTY).get(0)) - .put("cluster.name", clusterInfo.clustername) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") - .put("path.home", "./target") - .put("node.name", "transportclient") - .put("discovery.initial_state_timeout","8s") - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost+":"+clusterInfo.nodePort) - .put("plugins.security.ssl.transport.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("spock-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS,"spock") - .build(); - + Assert.assertEquals( + clusterInfo.numNodes, + clusterHelper.nodeClient() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForGreenStatus()) + .actionGet() + .getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); + + final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) + .put(minimumSecuritySettings(Settings.EMPTY).get(0)) + .put("cluster.name", clusterInfo.clustername) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") + .put("path.home", "./target") + .put("node.name", "transportclient") + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .put("plugins.security.ssl.transport.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("spock-keystore.jks")) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "spock") + .build(); + log.debug("Start node client"); - + try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class).start()) { Thread.sleep(10000); - Assert.assertEquals(1, node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); + Assert.assertEquals(1, node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); } catch (Exception e) { Assert.fail(e.toString()); } @@ -155,19 +210,26 @@ public void testNodeClientDisallowedWithNonServerCertificate2() throws Exception @Test public void testDelayInSecurityIndexInitialization() throws Exception { final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX, true) - .put("cluster.routing.allocation.exclude._ip", "127.0.0.1") - .build(); + .put(ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX, true) + .put("cluster.routing.allocation.exclude._ip", "127.0.0.1") + .build(); try { setup(Settings.EMPTY, null, settings, false); Assert.fail("Expected IOException here due to red cluster state"); } catch (IOException e) { // Index request has a default timeout of 1 minute, adding buffer between nodes initialization and cluster health check - Thread.sleep(1000*80); - // Ideally, we would want to remove this cluster setting, but default settings cannot be removed. So overriding with a reserved IP address - clusterHelper.nodeClient().admin().cluster().updateSettings( - new ClusterUpdateSettingsRequest().transientSettings(Settings.builder().put("cluster.routing.allocation.exclude._ip", "192.0.2.0").build())); - this.clusterInfo = clusterHelper.waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10),3); + Thread.sleep(1000 * 80); + // Ideally, we would want to remove this cluster setting, but default settings cannot be removed. So overriding with a reserved + // IP address + clusterHelper.nodeClient() + .admin() + .cluster() + .updateSettings( + new ClusterUpdateSettingsRequest().transientSettings( + Settings.builder().put("cluster.routing.allocation.exclude._ip", "192.0.2.0").build() + ) + ); + this.clusterInfo = clusterHelper.waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10), 3); } RestHelper rh = nonSslRestHelper(); Thread.sleep(10000); diff --git a/src/test/java/org/opensearch/security/SnapshotRestoreTests.java b/src/test/java/org/opensearch/security/SnapshotRestoreTests.java index 8e869e250d..1c884a8e5d 100644 --- a/src/test/java/org/opensearch/security/SnapshotRestoreTests.java +++ b/src/test/java/org/opensearch/security/SnapshotRestoreTests.java @@ -54,7 +54,6 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; - public class SnapshotRestoreTests extends SingleClusterTest { private ClusterConfiguration currentClusterConfig = ClusterConfiguration.DEFAULT; @@ -62,233 +61,711 @@ public class SnapshotRestoreTests extends SingleClusterTest { public void testSnapshotEnableSecurityIndexRestore() throws Exception { final Settings settings = Settings.builder() - .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .put("plugins.security.check_snapshot_restore_write_privileges", false) - .put("plugins.security.unsupported.restore.securityindex.enabled", true) - .build(); + .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) + .put("plugins.security.check_snapshot_restore_write_privileges", false) + .put("plugins.security.unsupported.restore.securityindex.enabled", true) + .build(); setup(settings, currentClusterConfig); try (Client tc = getClient()) { - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest("vulcangov").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/vulcangov"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest("vulcangov", "vulcangov_1").indices("vulcangov").includeGlobalState(true).waitForCompletion(true)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest(".opendistro_security").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/.opendistro_security"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest(".opendistro_security", "opendistro_security_1").indices(".opendistro_security").includeGlobalState(false).waitForCompletion(true)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest("all").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/all"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest("all", "all_1").indices("*").includeGlobalState(false).waitForCompletion(true)).actionGet(); + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("vulcangov").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/vulcangov")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest("vulcangov", "vulcangov_1").indices("vulcangov") + .includeGlobalState(true) + .waitForCompletion(true) + ) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest(".opendistro_security").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/.opendistro_security")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest(".opendistro_security", "opendistro_security_1").indices(".opendistro_security") + .includeGlobalState(false) + .waitForCompletion(true) + ) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("all").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/all")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot(new CreateSnapshotRequest("all", "all_1").indices("*").includeGlobalState(false).waitForCompletion(true)) + .actionGet(); } RestHelper rh = nonSslRestHelper(); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/vulcangov", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/vulcangov/vulcangov_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/vulcangov", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/vulcangov/vulcangov_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // worf not allowed to restore vulcangov index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "", + encodeBasicHeader("worf", "worf") + ).getStatusCode() + ); // Try to restore vulcangov index as .opendistro_security index, not possible since Security index is open - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore .opendistro_security index. - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/.opendistro_security", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/.opendistro_security/opendistro_security_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/.opendistro_security", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/.opendistro_security/opendistro_security_1", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); // 500 because Security index is open - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, rh.executePostRequest("_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true","", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + rh.executePostRequest( + "_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true", + "", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore .opendistro_security index as .opendistro_security_copy index - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true","{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true", + "{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore all indices. - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/all", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/all/all_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/all", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/all/all_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); // 500 because Security index is open - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true", "", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); // Try to restore vulcangov index as .opendistro_security index -> 500 because Security index is open - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - // Try to restore .opendistro_security index as .opendistro_security_copy index. Delete opendistro_security_copy first, was created in test above - Assert.assertEquals(HttpStatus.SC_OK, rh.executeDeleteRequest("opendistro_security_copy", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + // Try to restore .opendistro_security index as .opendistro_security_copy index. Delete opendistro_security_copy first, was created + // in test above + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeDeleteRequest("opendistro_security_copy", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore an unknown snapshot - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, rh.executePostRequest("_snapshot/all/unknown-snapshot/_restore?wait_for_completion=true", "", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + rh.executePostRequest( + "_snapshot/all/unknown-snapshot/_restore?wait_for_completion=true", + "", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // close and restore Security index - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest(".opendistro_security/_close", "", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true","", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest(".opendistro_security/_open", "", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest(".opendistro_security/_close", "", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true", + "", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest(".opendistro_security/_open", "", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); } @Test public void testSnapshot() throws Exception { final Settings settings = Settings.builder() - .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .put("plugins.security.check_snapshot_restore_write_privileges", false) - .build(); + .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) + .put("plugins.security.check_snapshot_restore_write_privileges", false) + .build(); setup(settings, currentClusterConfig); try (Client tc = getClient()) { - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest("vulcangov").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/vulcangov"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest("vulcangov", "vulcangov_1").indices("vulcangov").includeGlobalState(true).waitForCompletion(true)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest(".opendistro_security").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/.opendistro_security"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest(".opendistro_security", "opendistro_security_1").indices(".opendistro_security").includeGlobalState(false).waitForCompletion(true)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest("all").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/all"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest("all", "all_1").indices("*").includeGlobalState(false).waitForCompletion(true)).actionGet(); + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("vulcangov").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/vulcangov")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest("vulcangov", "vulcangov_1").indices("vulcangov") + .includeGlobalState(true) + .waitForCompletion(true) + ) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest(".opendistro_security").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/.opendistro_security")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest(".opendistro_security", "opendistro_security_1").indices(".opendistro_security") + .includeGlobalState(false) + .waitForCompletion(true) + ) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("all").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/all")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot(new CreateSnapshotRequest("all", "all_1").indices("*").includeGlobalState(false).waitForCompletion(true)) + .actionGet(); } RestHelper rh = nonSslRestHelper(); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/vulcangov", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/vulcangov/vulcangov_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/vulcangov", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/vulcangov/vulcangov_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "", + encodeBasicHeader("worf", "worf") + ).getStatusCode() + ); // Try to restore vulcangov index as .opendistro_security index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore .opendistro_security index. - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/.opendistro_security", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/.opendistro_security/opendistro_security_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true","", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/.opendistro_security", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/.opendistro_security/opendistro_security_1", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true", + "", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore .opendistro_security index as .opendistro_security_copy index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true","{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true", + "{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore all indices. - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/all", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/all/all_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/all", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/all/all_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true", "", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); // Try to restore .opendistro_security index as .opendistro_security_copy index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore .opendistro_security index as .opendistro_security_copy index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore an unknown snapshot - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/all/unknown-snapshot/_restore?wait_for_completion=true", "", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - // Assert.assertEquals(HttpStatus.SC_FORBIDDEN, executePostRequest("_snapshot/all/unknown-snapshot/_restore?wait_for_completion=true","{ \"indices\": \"the-unknown-index\" }", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/all/unknown-snapshot/_restore?wait_for_completion=true", + "", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + // Assert.assertEquals(HttpStatus.SC_FORBIDDEN, + // executePostRequest("_snapshot/all/unknown-snapshot/_restore?wait_for_completion=true","{ \"indices\": \"the-unknown-index\" }", + // encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); } @Test public void testSnapshotCheckWritePrivileges() throws Exception { - final Settings settings = Settings.builder() - .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .build(); + final Settings settings = Settings.builder().putList("path.repo", repositoryPath.getRoot().getAbsolutePath()).build(); setup(settings, currentClusterConfig); try (Client tc = getClient()) { - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest("vulcangov").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/vulcangov"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest("vulcangov", "vulcangov_1").indices("vulcangov").includeGlobalState(true).waitForCompletion(true)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest(".opendistro_security").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/.opendistro_security"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest(".opendistro_security", "opendistro_security_1").indices(".opendistro_security").includeGlobalState(false).waitForCompletion(true)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest("all").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/all"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest("all", "all_1").indices("*").includeGlobalState(false).waitForCompletion(true)).actionGet(); - - ConfigUpdateResponse cur = tc.execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(new String[]{"config","roles","rolesmapping","internalusers","actiongroups"})).actionGet(); + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("vulcangov").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/vulcangov")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest("vulcangov", "vulcangov_1").indices("vulcangov") + .includeGlobalState(true) + .waitForCompletion(true) + ) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest(".opendistro_security").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/.opendistro_security")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest(".opendistro_security", "opendistro_security_1").indices(".opendistro_security") + .includeGlobalState(false) + .waitForCompletion(true) + ) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("all").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/all")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot(new CreateSnapshotRequest("all", "all_1").indices("*").includeGlobalState(false).waitForCompletion(true)) + .actionGet(); + + ConfigUpdateResponse cur = tc.execute( + ConfigUpdateAction.INSTANCE, + new ConfigUpdateRequest(new String[] { "config", "roles", "rolesmapping", "internalusers", "actiongroups" }) + ).actionGet(); Assert.assertFalse(cur.hasFailures()); Assert.assertEquals(currentClusterConfig.getNodes(), cur.getNodes().size()); } RestHelper rh = nonSslRestHelper(); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/vulcangov", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/vulcangov/vulcangov_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","", encodeBasicHeader("worf", "worf")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/vulcangov", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/vulcangov/vulcangov_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "", + encodeBasicHeader("worf", "worf") + ).getStatusCode() + ); // Try to restore vulcangov index as .opendistro_security index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore .opendistro_security index. - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/.opendistro_security", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/.opendistro_security/opendistro_security_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true","", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/.opendistro_security", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/.opendistro_security/opendistro_security_1", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true", + "", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore .opendistro_security index as .opendistro_security_copy index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true","{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/.opendistro_security/opendistro_security_1/_restore?wait_for_completion=true", + "{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore all indices. - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/all", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/all/all_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/all", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/all/all_1", encodeBasicHeader("nagilum", "nagilum")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true", "", encodeBasicHeader("nagilum", "nagilum")) + .getStatusCode() + ); // Try to restore .opendistro_security index as .opendistro_security_copy index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{ \"indices\": \"vulcangov\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \".opendistro_security\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore .opendistro_security index as .opendistro_security_copy index - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{ \"indices\": \".opendistro_security\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"opendistro_security_copy\" }", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Try to restore an unknown snapshot - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/all/unknown-snapshot/_restore?wait_for_completion=true", "", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/all/unknown-snapshot/_restore?wait_for_completion=true", + "", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); // Tests snapshot with write permissions (OK) - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_restore_1\" }", encodeBasicHeader("restoreuser", "restoreuser")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_restore_2a\" }", encodeBasicHeader("restoreuser", "restoreuser")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_restore_1\" }", + encodeBasicHeader("restoreuser", "restoreuser") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_restore_2a\" }", + encodeBasicHeader("restoreuser", "restoreuser") + ).getStatusCode() + ); // Test snapshot with write permissions (OK) - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_no_restore_1\" }", encodeBasicHeader("restoreuser", "restoreuser")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_no_restore_2\" }", encodeBasicHeader("restoreuser", "restoreuser")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_no_restore_3\" }", encodeBasicHeader("restoreuser", "restoreuser")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_no_restore_4\" }", encodeBasicHeader("restoreuser", "restoreuser")).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_no_restore_1\" }", + encodeBasicHeader("restoreuser", "restoreuser") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_no_restore_2\" }", + encodeBasicHeader("restoreuser", "restoreuser") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_no_restore_3\" }", + encodeBasicHeader("restoreuser", "restoreuser") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/vulcangov/vulcangov_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"$1_no_restore_4\" }", + encodeBasicHeader("restoreuser", "restoreuser") + ).getStatusCode() + ); } @Test public void testSnapshotRestore() throws Exception { - final Settings settings = Settings.builder() - .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .build(); + final Settings settings = Settings.builder().putList("path.repo", repositoryPath.getRoot().getAbsolutePath()).build(); - setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityActionGroups("action_groups_packaged.yml"), settings, true, currentClusterConfig); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setSecurityActionGroups("action_groups_packaged.yml"), + settings, + true, + currentClusterConfig + ); try (Client tc = getClient()) { - tc.index(new IndexRequest("testsnap1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap6").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest("bckrepo").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/bckrepo"))).actionGet(); + tc.index(new IndexRequest("testsnap1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap6").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("bckrepo").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/bckrepo")) + ) + .actionGet(); } RestHelper rh = nonSslRestHelper(); - String putSnapshot = - "{"+ - "\"indices\": \"testsnap1\","+ - "\"ignore_unavailable\": false,"+ - "\"include_global_state\": false"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"?wait_for_completion=true&pretty", putSnapshot, encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"/_restore?wait_for_completion=true&pretty","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - - putSnapshot = - "{"+ - "\"indices\": \".opendistro_security\","+ - "\"ignore_unavailable\": false,"+ - "\"include_global_state\": false"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"?wait_for_completion=true&pretty", putSnapshot, encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"/_restore?wait_for_completion=true&pretty","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - - - putSnapshot = - "{"+ - "\"indices\": \"testsnap2\","+ - "\"ignore_unavailable\": false,"+ - "\"include_global_state\": true"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"?wait_for_completion=true&pretty", putSnapshot, encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"/_restore?wait_for_completion=true&pretty","{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); + String putSnapshot = "{" + + "\"indices\": \"testsnap1\"," + + "\"ignore_unavailable\": false," + + "\"include_global_state\": false" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "?wait_for_completion=true&pretty", + putSnapshot, + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "/_restore?wait_for_completion=true&pretty", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + + putSnapshot = "{" + + "\"indices\": \".opendistro_security\"," + + "\"ignore_unavailable\": false," + + "\"include_global_state\": false" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "?wait_for_completion=true&pretty", + putSnapshot, + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "/_restore?wait_for_completion=true&pretty", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + + putSnapshot = "{" + "\"indices\": \"testsnap2\"," + "\"ignore_unavailable\": false," + "\"include_global_state\": true" + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "?wait_for_completion=true&pretty", + putSnapshot, + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "/_restore?wait_for_completion=true&pretty", + "{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); } @Test @@ -297,33 +774,74 @@ public void testSnapshotRestoreSpecialIndicesPatterns() throws Exception { final List listOfIndexesToTest = Arrays.asList("foo", "bar", "baz"); - final Settings settings = Settings.builder() - .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .build(); + final Settings settings = Settings.builder().putList("path.repo", repositoryPath.getRoot().getAbsolutePath()).build(); - setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityActionGroups("action_groups_packaged.yml"), settings, true, currentClusterConfig); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setSecurityActionGroups("action_groups_packaged.yml"), + settings, + true, + currentClusterConfig + ); try (Client tc = getClient()) { for (String index : listOfIndexesToTest) { tc.admin().indices().create(new CreateIndexRequest(index)).actionGet(); - tc.index(new IndexRequest(index).setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).id("document1").source("{ \"foo\": \"bar\" }", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest(index).setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .id("document1") + .source("{ \"foo\": \"bar\" }", XContentType.JSON) + ).actionGet(); } } - try (Client tc = getClient()) { - tc.admin().cluster().putRepository(new PutRepositoryRequest("all").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/all"))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest("all", "all_1").indices(listOfIndexesToTest).includeGlobalState(false).waitForCompletion(true)).actionGet(); - } + try (Client tc = getClient()) { + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("all").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/all")) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest("all", "all_1").indices(listOfIndexesToTest).includeGlobalState(false).waitForCompletion(true) + ) + .actionGet(); + } RestHelper rh = nonSslRestHelper(); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{\"indices\": \"b*,-bar\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"wild_first_restored_index_$1\"}", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{\"indices\": \"-bar,b*\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"neg_first_restored_index_$1\"}", encodeBasicHeader("nagilum", "nagilum")).getStatusCode()); - String wild_first_body = rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{\"indices\": \"b*,-bar\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"wild_first_restored_index_$1\"}", encodeBasicHeader("nagilum", "nagilum")).getBody(); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{\"indices\": \"b*,-bar\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"wild_first_restored_index_$1\"}", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{\"indices\": \"-bar,b*\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"neg_first_restored_index_$1\"}", + encodeBasicHeader("nagilum", "nagilum") + ).getStatusCode() + ); + String wild_first_body = rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{\"indices\": \"b*,-bar\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"wild_first_restored_index_$1\"}", + encodeBasicHeader("nagilum", "nagilum") + ).getBody(); assertThat(wild_first_body, not(containsString("wild_first_restored_index_foo"))); assertThat(wild_first_body, not(containsString("wild_first_restored_index_bar"))); assertThat(wild_first_body, containsString("wild_first_restored_index_baz")); - String neg_first_body = rh.executePostRequest("_snapshot/all/all_1/_restore?wait_for_completion=true","{\"indices\": \"-bar,b*\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"negate_first_restored_index_$1\"}", encodeBasicHeader("nagilum", "nagilum")).getBody(); + String neg_first_body = rh.executePostRequest( + "_snapshot/all/all_1/_restore?wait_for_completion=true", + "{\"indices\": \"-bar,b*\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"negate_first_restored_index_$1\"}", + encodeBasicHeader("nagilum", "nagilum") + ).getBody(); assertThat(neg_first_body, not(containsString("negate_first_restored_index_foo"))); assertThat(neg_first_body, not(containsString("negate_first_restored_index_bar"))); assertThat(neg_first_body, containsString("negate_first_restored_index_baz")); @@ -333,52 +851,105 @@ public void testSnapshotRestoreSpecialIndicesPatterns() throws Exception { public void testNoSnapshotRestore() throws Exception { final Settings settings = Settings.builder() - .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .put("plugins.security.enable_snapshot_restore_privilege", false) - .build(); - - setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityActionGroups("action_groups_packaged.yml"), settings, true, currentClusterConfig); + .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) + .put("plugins.security.enable_snapshot_restore_privilege", false) + .build(); + + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setSecurityActionGroups("action_groups_packaged.yml"), + settings, + true, + currentClusterConfig + ); try (Client tc = getClient()) { - tc.index(new IndexRequest("testsnap1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("testsnap6").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().cluster().putRepository(new PutRepositoryRequest("bckrepo").type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/bckrepo"))).actionGet(); + tc.index(new IndexRequest("testsnap1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap3").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap5").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("testsnap6").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest("bckrepo").type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/bckrepo")) + ) + .actionGet(); } RestHelper rh = nonSslRestHelper(); - String putSnapshot = - "{"+ - "\"indices\": \"testsnap1\","+ - "\"ignore_unavailable\": false,"+ - "\"include_global_state\": false"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"?wait_for_completion=true&pretty", putSnapshot, encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"/_restore?wait_for_completion=true&pretty","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - - putSnapshot = - "{"+ - "\"indices\": \".opendistro_security\","+ - "\"ignore_unavailable\": false,"+ - "\"include_global_state\": false"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"?wait_for_completion=true&pretty", putSnapshot, encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"/_restore?wait_for_completion=true&pretty","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - - putSnapshot = - "{"+ - "\"indices\": \"testsnap2\","+ - "\"ignore_unavailable\": false,"+ - "\"include_global_state\": true"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, rh.executePutRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"?wait_for_completion=true&pretty", putSnapshot, encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executePostRequest("_snapshot/bckrepo/"+putSnapshot.hashCode()+"/_restore?wait_for_completion=true&pretty","{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", encodeBasicHeader("snapresuser", "nagilum")).getStatusCode()); + String putSnapshot = "{" + + "\"indices\": \"testsnap1\"," + + "\"ignore_unavailable\": false," + + "\"include_global_state\": false" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "?wait_for_completion=true&pretty", + putSnapshot, + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "/_restore?wait_for_completion=true&pretty", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + + putSnapshot = "{" + + "\"indices\": \".opendistro_security\"," + + "\"ignore_unavailable\": false," + + "\"include_global_state\": false" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "?wait_for_completion=true&pretty", + putSnapshot, + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "/_restore?wait_for_completion=true&pretty", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + + putSnapshot = "{" + "\"indices\": \"testsnap2\"," + "\"ignore_unavailable\": false," + "\"include_global_state\": true" + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "?wait_for_completion=true&pretty", + putSnapshot, + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + rh.executePostRequest( + "_snapshot/bckrepo/" + putSnapshot.hashCode() + "/_restore?wait_for_completion=true&pretty", + "{ \"include_global_state\": true, \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_$1\" }", + encodeBasicHeader("snapresuser", "nagilum") + ).getStatusCode() + ); } } diff --git a/src/test/java/org/opensearch/security/SystemIntegratorsTests.java b/src/test/java/org/opensearch/security/SystemIntegratorsTests.java index 4e647a6324..8d287dd8a3 100644 --- a/src/test/java/org/opensearch/security/SystemIntegratorsTests.java +++ b/src/test/java/org/opensearch/security/SystemIntegratorsTests.java @@ -40,81 +40,117 @@ import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; public class SystemIntegratorsTests extends SingleClusterTest { - + @Test public void testInjectedUserMalformed() throws Exception { - - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) - .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") - .build(); - + + final Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) + .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") + .build(); + setup(settings, ClusterConfiguration.USERINJECTOR); - + final RestHelper rh = nonSslRestHelper(); // username|role1,role2|remoteIP|attributes - + HttpResponse resc; - - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, null)); + + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, null) + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "|||")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "|||") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "||127.0.0:80|")); + + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "||127.0.0:80|") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||ip|")); + + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||ip|") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||ip:port|")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||ip:port|") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||ip:80|")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||ip:80|") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||127.0.x:80|")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||127.0.x:80|") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||127.0.0:80|key1,value1,key2")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "username||127.0.0:80|key1,value1,key2") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "||127.0.0:80|key1,value1,key2,value2")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "||127.0.0:80|key1,value1,key2,value2") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); - + } @Test public void testInjectedUser() throws Exception { - - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) - .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") - .build(); - + + final Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) + .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") + .build(); + setup(settings, ClusterConfiguration.USERINJECTOR); - + final RestHelper rh = nonSslRestHelper(); // username|role1,role2|remoteIP|attributes - + HttpResponse resc; - - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin||127.0.0:80|")); + + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin||127.0.0:80|") + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("User [name=admin, backend_roles=[], requestedTenant=null]")); Assert.assertTrue(resc.getBody().contains("\"remote_address\":\"127.0.0.0:80\"")); Assert.assertTrue(resc.getBody().contains("\"backend_roles\":[]")); Assert.assertTrue(resc.getBody().contains("\"custom_attribute_names\":[]")); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin|role1|127.0.0:80|key1,value1")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin|role1|127.0.0:80|key1,value1") + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("User [name=admin, backend_roles=[role1], requestedTenant=null]")); Assert.assertTrue(resc.getBody().contains("\"remote_address\":\"127.0.0.0:80\"")); Assert.assertTrue(resc.getBody().contains("\"backend_roles\":[\"role1\"]")); Assert.assertTrue(resc.getBody().contains("\"custom_attribute_names\":[\"key1\"]")); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin|role1,role2||key1,value1")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin|role1,role2||key1,value1") + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("User [name=admin, backend_roles=[role1, role2], requestedTenant=null]")); // remote IP is assigned by XFFResolver @@ -122,7 +158,10 @@ public void testInjectedUser() throws Exception { Assert.assertTrue(resc.getBody().contains("\"backend_roles\":[\"role1\",\"role2\"]")); Assert.assertTrue(resc.getBody().contains("\"custom_attribute_names\":[\"key1\"]")); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin|role1,role2|8.8.8.8:8|key1,value1,key2,value2")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin|role1,role2|8.8.8.8:8|key1,value1,key2,value2") + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("User [name=admin, backend_roles=[role1, role2], requestedTenant=null]")); // remote IP is assigned by XFFResolver @@ -130,7 +169,10 @@ public void testInjectedUser() throws Exception { Assert.assertTrue(resc.getBody().contains("\"backend_roles\":[\"role1\",\"role2\"]")); Assert.assertTrue(resc.getBody().contains("\"custom_attribute_names\":[\"key1\",\"key2\"]")); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "nagilum|role1,role2|8.8.8.8:8|key1,value1,key2,value2")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "nagilum|role1,role2|8.8.8.8:8|key1,value1,key2,value2") + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("User [name=nagilum, backend_roles=[role1, role2], requestedTenant=null]")); // remote IP is assigned by XFFResolver @@ -139,8 +181,11 @@ public void testInjectedUser() throws Exception { // mapped by username Assert.assertTrue(resc.getBody().contains("\"roles\":[\"opendistro_security_all_access\"")); Assert.assertTrue(resc.getBody().contains("\"custom_attribute_names\":[\"key1\",\"key2\"]")); - - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "myuser|role1,vulcanadmin|8.8.8.8:8|key1,value1,key2,value2")); + + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "myuser|role1,vulcanadmin|8.8.8.8:8|key1,value1,key2,value2") + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("User [name=myuser, backend_roles=[role1, vulcanadmin], requestedTenant=null]")); // remote IP is assigned by XFFResolver @@ -149,9 +194,15 @@ public void testInjectedUser() throws Exception { // mapped by backend role "twitter" Assert.assertTrue(resc.getBody().contains("\"roles\":[\"public\",\"role_vulcans_admin\"]")); Assert.assertTrue(resc.getBody().contains("\"custom_attribute_names\":[\"key1\",\"key2\"]")); - + // add requested tenant - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "myuser|role1,vulcanadmin|8.8.8.8:8|key1,value1,key2,value2|")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader( + ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, + "myuser|role1,vulcanadmin|8.8.8.8:8|key1,value1,key2,value2|" + ) + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("User [name=myuser, backend_roles=[role1, vulcanadmin], requestedTenant=null]")); // remote IP is assigned by XFFResolver @@ -161,7 +212,13 @@ public void testInjectedUser() throws Exception { Assert.assertTrue(resc.getBody(), resc.getBody().contains("\"roles\":[\"public\",\"role_vulcans_admin\"]")); Assert.assertTrue(resc.getBody().contains("\"custom_attribute_names\":[\"key1\",\"key2\"]")); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "myuser|role1,vulcanadmin|8.8.8.8:8|key1,value1,key2,value2|mytenant")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader( + ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, + "myuser|role1,vulcanadmin|8.8.8.8:8|key1,value1,key2,value2|mytenant" + ) + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); Assert.assertTrue(resc.getBody().contains("User [name=myuser, backend_roles=[role1, vulcanadmin], requestedTenant=mytenant]")); // remote IP is assigned by XFFResolver @@ -171,87 +228,110 @@ public void testInjectedUser() throws Exception { Assert.assertTrue(resc.getBody().contains("\"roles\":[\"public\",\"role_vulcans_admin\"]")); Assert.assertTrue(resc.getBody().contains("\"custom_attribute_names\":[\"key1\",\"key2\"]")); - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "myuser|role1,vulcanadmin|8.8.8.8:8||mytenant with whitespace")); + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader( + ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, + "myuser|role1,vulcanadmin|8.8.8.8:8||mytenant with whitespace" + ) + ); Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - Assert.assertTrue(resc.getBody().contains("User [name=myuser, backend_roles=[role1, vulcanadmin], requestedTenant=mytenant with whitespace]")); + Assert.assertTrue( + resc.getBody().contains("User [name=myuser, backend_roles=[role1, vulcanadmin], requestedTenant=mytenant with whitespace]") + ); // remote IP is assigned by XFFResolver Assert.assertTrue(resc.getBody().contains("\"remote_address\":\"8.8.8.8:8\"")); Assert.assertTrue(resc.getBody().contains("\"backend_roles\":[\"role1\",\"vulcanadmin\"]")); // mapped by backend role "twitter" Assert.assertTrue(resc.getBody().contains("\"roles\":[\"public\",\"role_vulcans_admin\"]")); - - } + } @Test public void testInjectedUserDisabled() throws Exception { - - final Settings settings = Settings.builder() - .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") - .build(); - + + final Settings settings = Settings.builder().put("http.type", "org.opensearch.security.http.UserInjectingServerTransport").build(); + setup(settings, ClusterConfiguration.USERINJECTOR); - + final RestHelper rh = nonSslRestHelper(); // username|role1,role2|remoteIP|attributes - + HttpResponse resc; - - resc = rh.executeGetRequest("_opendistro/_security/authinfo", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin|role1|127.0.0:80|key1,value1")); + + resc = rh.executeGetRequest( + "_opendistro/_security/authinfo", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "admin|role1|127.0.0:80|key1,value1") + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, resc.getStatusCode()); } - @Test - public void testInjectedAdminUser() throws Exception { - - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_ADMIN_USER_ENABLED, true) - .putList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, Lists.newArrayList("CN=kirk,OU=client,O=client,L=Test,C=DE","injectedadmin")) - .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") - .build(); - - setup(settings, ClusterConfiguration.USERINJECTOR); - - final RestHelper rh = nonSslRestHelper(); - HttpResponse resc; - - // injected user is admin, access to Security index must be allowed - resc = rh.executeGetRequest(".opendistro_security/_search?pretty", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "injectedadmin|role1|127.0.0:80|key1,value1")); - Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); - Assert.assertTrue(resc.getBody().contains("\"_id\" : \"config\"")); - Assert.assertTrue(resc.getBody().contains("\"_id\" : \"roles\"")); - Assert.assertTrue(resc.getBody().contains("\"_id\" : \"internalusers\"")); - Assert.assertTrue(resc.getBody().contains("\"total\" : 5")); - - resc = rh.executeGetRequest(".opendistro_security/_search?pretty", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "wrongadmin|role1|127.0.0:80|key1,value1")); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); - - } + @Test + public void testInjectedAdminUser() throws Exception { + + final Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) + .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_ADMIN_USER_ENABLED, true) + .putList( + ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, + Lists.newArrayList("CN=kirk,OU=client,O=client,L=Test,C=DE", "injectedadmin") + ) + .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") + .build(); + + setup(settings, ClusterConfiguration.USERINJECTOR); + + final RestHelper rh = nonSslRestHelper(); + HttpResponse resc; + + // injected user is admin, access to Security index must be allowed + resc = rh.executeGetRequest( + ".opendistro_security/_search?pretty", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "injectedadmin|role1|127.0.0:80|key1,value1") + ); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + Assert.assertTrue(resc.getBody().contains("\"_id\" : \"config\"")); + Assert.assertTrue(resc.getBody().contains("\"_id\" : \"roles\"")); + Assert.assertTrue(resc.getBody().contains("\"_id\" : \"internalusers\"")); + Assert.assertTrue(resc.getBody().contains("\"total\" : 5")); + + resc = rh.executeGetRequest( + ".opendistro_security/_search?pretty", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "wrongadmin|role1|127.0.0:80|key1,value1") + ); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + } @Test public void testInjectedAdminUserAdminInjectionDisabled() throws Exception { - - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) - .putList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, Lists.newArrayList("CN=kirk,OU=client,O=client,L=Test,C=DE","injectedadmin")) - .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") - .build(); - + + final Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) + .putList( + ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, + Lists.newArrayList("CN=kirk,OU=client,O=client,L=Test,C=DE", "injectedadmin") + ) + .put("http.type", "org.opensearch.security.http.UserInjectingServerTransport") + .build(); + setup(settings, ClusterConfiguration.USERINJECTOR); - + final RestHelper rh = nonSslRestHelper(); HttpResponse resc; - + // injected user is admin, access to Security index must be allowed - resc = rh.executeGetRequest(".opendistro_security/_search?pretty", new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "injectedadmin|role1|127.0.0:80|key1,value1")); + resc = rh.executeGetRequest( + ".opendistro_security/_search?pretty", + new BasicHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, "injectedadmin|role1|127.0.0:80|key1,value1") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); Assert.assertFalse(resc.getBody().contains("\"_id\" : \"config\"")); Assert.assertFalse(resc.getBody().contains("\"_id\" : \"roles\"")); Assert.assertFalse(resc.getBody().contains("\"_id\" : \"internalusers\"")); Assert.assertFalse(resc.getBody().contains("\"_id\" : \"tattr\"")); Assert.assertFalse(resc.getBody(), resc.getBody().contains("\"total\" : 6")); - - } + + } } diff --git a/src/test/java/org/opensearch/security/TaskTests.java b/src/test/java/org/opensearch/security/TaskTests.java index 0ec671af27..784f5c7418 100644 --- a/src/test/java/org/opensearch/security/TaskTests.java +++ b/src/test/java/org/opensearch/security/TaskTests.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security; @@ -30,16 +30,21 @@ import org.opensearch.tasks.Task; public class TaskTests extends SingleClusterTest { - + @Test public void testXOpaqueIdHeader() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig(), Settings.EMPTY); - + RestHelper rh = nonSslRestHelper(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_tasks?group_by=parents&pretty" - , encodeBasicHeader("nagilum", "nagilum") - , new BasicHeader(Task.X_OPAQUE_ID, "myOpaqueId12"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "_tasks?group_by=parents&pretty", + encodeBasicHeader("nagilum", "nagilum"), + new BasicHeader(Task.X_OPAQUE_ID, "myOpaqueId12") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().split("X-Opaque-Id").length > 2); Assert.assertTrue(!res.getBody().contains("failures")); diff --git a/src/test/java/org/opensearch/security/TracingTests.java b/src/test/java/org/opensearch/security/TracingTests.java index 10372cf73b..2fefd33155 100644 --- a/src/test/java/org/opensearch/security/TracingTests.java +++ b/src/test/java/org/opensearch/security/TracingTests.java @@ -56,10 +56,22 @@ public void testAdvancedMapping() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig(), Settings.EMPTY, true, ClusterConfiguration.DEFAULT); try (Client tc = getClient()) { - tc.admin().indices().create(new CreateIndexRequest("myindex1").mapping(FileHelper.loadFile("mapping1.json"), XContentType.JSON)).actionGet(); - tc.admin().indices().create(new CreateIndexRequest("myindex2").mapping(FileHelper.loadFile("mapping2.json"), XContentType.JSON)).actionGet(); - tc.admin().indices().create(new CreateIndexRequest("myindex3").mapping(FileHelper.loadFile("mapping3.json"), XContentType.JSON)).actionGet(); - tc.admin().indices().create(new CreateIndexRequest("myindex4").mapping(FileHelper.loadFile("mapping4.json"), XContentType.JSON)).actionGet(); + tc.admin() + .indices() + .create(new CreateIndexRequest("myindex1").mapping(FileHelper.loadFile("mapping1.json"), XContentType.JSON)) + .actionGet(); + tc.admin() + .indices() + .create(new CreateIndexRequest("myindex2").mapping(FileHelper.loadFile("mapping2.json"), XContentType.JSON)) + .actionGet(); + tc.admin() + .indices() + .create(new CreateIndexRequest("myindex3").mapping(FileHelper.loadFile("mapping3.json"), XContentType.JSON)) + .actionGet(); + tc.admin() + .indices() + .create(new CreateIndexRequest("myindex4").mapping(FileHelper.loadFile("mapping4.json"), XContentType.JSON)) + .actionGet(); } RestHelper rh = nonSslRestHelper(); @@ -94,69 +106,154 @@ public void testHTTPTraceNoSource() throws Exception { tc.admin().indices().create(new CreateIndexRequest("test")).actionGet(); tc.admin().indices().create(new CreateIndexRequest("u")).actionGet(); - tc.admin().indices().putMapping(new PutMappingRequest("a") - .source("_source","enabled=false","content","store=true,type=text","field1","store=true,type=text", "field2","store=true,type=text", "a","store=true,type=text", "b","store=true,type=text", "my.nested.field","store=true,type=text") - ).actionGet(); - - tc.admin().indices().putMapping(new PutMappingRequest("c") - .source("_source","enabled=false","content","store=true,type=text","field1","store=true,type=text", "field2","store=true,type=text", "a","store=true,type=text", "b","store=true,type=text", "my.nested.field","store=true,type=text") - ).actionGet(); - - tc.admin().indices().putMapping(new PutMappingRequest("test") - .source("_source","enabled=false","content","store=true,type=text","field1","store=true,type=text", "field2","store=true,type=text", "a","store=true,type=text", "b","store=true,type=text", "my.nested.field","store=true,type=text") - ).actionGet(); - - tc.admin().indices().putMapping(new PutMappingRequest("u") - .source("_source","enabled=false","content","store=true,type=text","field1","store=true,type=text", "field2","store=true,type=text", "a","store=true,type=text", "b","store=true,type=text", "my.nested.field","store=true,type=text") - ).actionGet(); - - for(int i=0; i<50;i++) { - tc.index(new IndexRequest("a").id(i+"").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":"+i+"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("c").id(i+"").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":"+i+"}", XContentType.JSON)).actionGet(); + tc.admin() + .indices() + .putMapping( + new PutMappingRequest("a").source( + "_source", + "enabled=false", + "content", + "store=true,type=text", + "field1", + "store=true,type=text", + "field2", + "store=true,type=text", + "a", + "store=true,type=text", + "b", + "store=true,type=text", + "my.nested.field", + "store=true,type=text" + ) + ) + .actionGet(); + + tc.admin() + .indices() + .putMapping( + new PutMappingRequest("c").source( + "_source", + "enabled=false", + "content", + "store=true,type=text", + "field1", + "store=true,type=text", + "field2", + "store=true,type=text", + "a", + "store=true,type=text", + "b", + "store=true,type=text", + "my.nested.field", + "store=true,type=text" + ) + ) + .actionGet(); + + tc.admin() + .indices() + .putMapping( + new PutMappingRequest("test").source( + "_source", + "enabled=false", + "content", + "store=true,type=text", + "field1", + "store=true,type=text", + "field2", + "store=true,type=text", + "a", + "store=true,type=text", + "b", + "store=true,type=text", + "my.nested.field", + "store=true,type=text" + ) + ) + .actionGet(); + + tc.admin() + .indices() + .putMapping( + new PutMappingRequest("u").source( + "_source", + "enabled=false", + "content", + "store=true,type=text", + "field1", + "store=true,type=text", + "field2", + "store=true,type=text", + "a", + "store=true,type=text", + "b", + "store=true,type=text", + "my.nested.field", + "store=true,type=text" + ) + ) + .actionGet(); + + for (int i = 0; i < 50; i++) { + tc.index( + new IndexRequest("a").id(i + "") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":" + i + "}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("c").id(i + "") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":" + i + "}", XContentType.JSON) + ).actionGet(); } } - //setup complex mapping with parent child and nested fields - + // setup complex mapping with parent child and nested fields RestHelper rh = nonSslRestHelper(); System.out.println("############ check shards"); System.out.println(rh.executeGetRequest("_cat/shards?v", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ _bulk"); - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator(); + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator(); System.out.println(rh.executePostRequest("_bulk?refresh=true", bulkBody, encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ _bulk"); - bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator(); + bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator(); System.out.println(rh.executePostRequest("_bulk?refresh=true", bulkBody, encodeBasicHeader("nagilum", "nagilum"))); - System.out.println("############ cat indices"); - //cluster:monitor/state - //cluster:monitor/health - //indices:monitor/stats + // cluster:monitor/state + // cluster:monitor/health + // indices:monitor/stats System.out.println(rh.executeGetRequest("_cat/indices", encodeBasicHeader("nagilum", "nagilum"))); - System.out.println("############ _search"); - //indices:data/read/search + // indices:data/read/search System.out.println(rh.executeGetRequest("_search", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ get 1"); - //indices:data/read/get + // indices:data/read/get System.out.println(rh.executeGetRequest("a/b/1", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ get 5"); System.out.println(rh.executeGetRequest("a/b/5", encodeBasicHeader("nagilum", "nagilum"))); @@ -164,71 +261,68 @@ public void testHTTPTraceNoSource() throws Exception { System.out.println(rh.executeGetRequest("a/b/17", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ index (+create index)"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executePostRequest("u/b/1?refresh=true", "{}",encodeBasicHeader("nagilum", "nagilum"))); + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println(rh.executePostRequest("u/b/1?refresh=true", "{}", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ index only"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executePostRequest("u/b/2?refresh=true", "{}",encodeBasicHeader("nagilum", "nagilum"))); - + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println(rh.executePostRequest("u/b/2?refresh=true", "{}", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ delete"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executeDeleteRequest("u/b/2?refresh=true",encodeBasicHeader("nagilum", "nagilum"))); + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println(rh.executeDeleteRequest("u/b/2?refresh=true", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ msearch"); - String msearchBody = - "{\"index\":\"a\", \"type\":\"b\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"a\", \"type\":\"b\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"public\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - + String msearchBody = "{\"index\":\"a\", \"type\":\"b\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"a\", \"type\":\"b\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"public\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); System.out.println(rh.executePostRequest("_msearch", msearchBody, encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ mget"); - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"a\","+ - "\"_id\" : \"1\""+ - " },"+ - " {"+ - "\"_index\" : \"a\","+ - " \"_id\" : \"12\""+ - "},"+ - " {"+ - "\"_index\" : \"a\","+ - " \"_id\" : \"13\""+ - "},"+" {"+ - "\"_index\" : \"a\","+ - " \"_id\" : \"14\""+ - "}"+ - "]"+ - "}"; + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"a\"," + + "\"_id\" : \"1\"" + + " }," + + " {" + + "\"_index\" : \"a\"," + + " \"_id\" : \"12\"" + + "}," + + " {" + + "\"_index\" : \"a\"," + + " \"_id\" : \"13\"" + + "}," + + " {" + + "\"_index\" : \"a\"," + + " \"_id\" : \"14\"" + + "}" + + "]" + + "}"; System.out.println(rh.executePostRequest("_mget?refresh=true", mgetBody, encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ delete by query"); - String dbqBody = "{"+ - ""+ - " \"query\": { "+ - " \"match\": {"+ - " \"content\": 12"+ - " }"+ - " }"+ - "}"; + String dbqBody = "{" + "" + " \"query\": { " + " \"match\": {" + " \"content\": 12" + " }" + " }" + "}"; System.out.println(rh.executePostRequest("a/b/_delete_by_query", dbqBody, encodeBasicHeader("nagilum", "nagilum"))); @@ -237,28 +331,56 @@ public void testHTTPTraceNoSource() throws Exception { @Test public void testHTTPSingle() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".worf", "knuddel","nonexists") + final Settings settings = Settings.builder() + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".worf", "knuddel", "nonexists") .build(); - setup(settings); - final RestHelper rh = nonSslRestHelper(); + setup(settings); + final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf")) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))) + .actionGet(); } @@ -275,16 +397,24 @@ public void testHTTPSingle() throws Exception { System.out.println("########end pause2"); System.out.println("############ _bulk"); - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"myindex\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"myindex\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator(); + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"myindex\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"myindex\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator(); System.out.println(rh.executePostRequest("_bulk?refresh=true", bulkBody, encodeBasicHeader("nagilum", "nagilum")).getBody()); System.out.println("############ _end"); @@ -293,33 +423,42 @@ public void testHTTPSingle() throws Exception { @Test public void testSearchScroll() throws Exception { - final Settings settings = Settings.builder() - .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS+".worf", "knuddel","nonexists") + final Settings settings = Settings.builder() + .putList(ConfigConstants.SECURITY_AUTHCZ_REST_IMPERSONATION_USERS + ".worf", "knuddel", "nonexists") .build(); - setup(settings); - final RestHelper rh = nonSslRestHelper(); + setup(settings); + final RestHelper rh = nonSslRestHelper(); try (Client tc = getClient()) { - for(int i=0; i<3; i++) - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + for (int i = 0; i < 3; i++) + tc.index( + new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); } - System.out.println("########search"); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executeGetRequest("vulcangov/_search?scroll=1m&pretty=true", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("vulcangov/_search?scroll=1m&pretty=true", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode() + ); System.out.println(res.getBody()); int start = res.getBody().indexOf("_scroll_id") + 15; - String scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start+1)); + String scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start + 1)); System.out.println(scrollid); System.out.println("########search scroll"); - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executePostRequest("/_search/scroll?pretty=true", "{\"scroll_id\" : \""+scrollid+"\"}", encodeBasicHeader("nagilum", "nagilum"))).getStatusCode()); - + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "/_search/scroll?pretty=true", + "{\"scroll_id\" : \"" + scrollid + "\"}", + encodeBasicHeader("nagilum", "nagilum") + )).getStatusCode() + ); System.out.println("########search done"); - } @Test @@ -329,53 +468,64 @@ public void testHTTPTrace() throws Exception { try (Client tc = getClient()) { - for(int i=0; i<50;i++) { - tc.index(new IndexRequest("a").id(i+"").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":"+i+"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("c").id(i+"").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":"+i+"}", XContentType.JSON)).actionGet(); + for (int i = 0; i < 50; i++) { + tc.index( + new IndexRequest("a").id(i + "") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":" + i + "}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("c").id(i + "") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":" + i + "}", XContentType.JSON) + ).actionGet(); } } - - - RestHelper rh = nonSslRestHelper(); System.out.println("############ check shards"); System.out.println(rh.executeGetRequest("_cat/shards?v", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ _bulk"); - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator(); + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator(); System.out.println(rh.executePostRequest("_bulk?refresh=true", bulkBody, encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ _bulk"); - bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }"+System.lineSeparator(); + bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"2\" } }" + + System.lineSeparator(); System.out.println(rh.executePostRequest("_bulk?refresh=true", bulkBody, encodeBasicHeader("nagilum", "nagilum"))); - System.out.println("############ cat indices"); - //cluster:monitor/state - //cluster:monitor/health - //indices:monitor/stats + // cluster:monitor/state + // cluster:monitor/health + // indices:monitor/stats System.out.println(rh.executeGetRequest("_cat/indices", encodeBasicHeader("nagilum", "nagilum"))); - System.out.println("############ _search"); - //indices:data/read/search + // indices:data/read/search System.out.println(rh.executeGetRequest("_search", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ get 1"); - //indices:data/read/get + // indices:data/read/get System.out.println(rh.executeGetRequest("a/b/1", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ get 5"); System.out.println(rh.executeGetRequest("a/b/5", encodeBasicHeader("nagilum", "nagilum"))); @@ -383,106 +533,107 @@ public void testHTTPTrace() throws Exception { System.out.println(rh.executeGetRequest("a/b/17", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ index (+create index)"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executePostRequest("u/b/1?refresh=true", "{}",encodeBasicHeader("nagilum", "nagilum"))); + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println(rh.executePostRequest("u/b/1?refresh=true", "{}", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ index only"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executePostRequest("u/b/2?refresh=true", "{}",encodeBasicHeader("nagilum", "nagilum"))); + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println(rh.executePostRequest("u/b/2?refresh=true", "{}", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ update"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executePostRequest("u/b/2/_update?refresh=true", "{\"doc\" : {\"a\":1}}",encodeBasicHeader("nagilum", "nagilum"))); + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println( + rh.executePostRequest("u/b/2/_update?refresh=true", "{\"doc\" : {\"a\":1}}", encodeBasicHeader("nagilum", "nagilum")) + ); System.out.println("############ update2"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executePostRequest("u/b/2/_update?refresh=true", "{\"doc\" : {\"a\":44, \"b\":55}}",encodeBasicHeader("nagilum", "nagilum"))); + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println( + rh.executePostRequest("u/b/2/_update?refresh=true", "{\"doc\" : {\"a\":44, \"b\":55}}", encodeBasicHeader("nagilum", "nagilum")) + ); System.out.println("############ update3"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executePostRequest("u/b/2/_update?refresh=true", "{\"doc\" : {\"b\":66}}",encodeBasicHeader("nagilum", "nagilum"))); - + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println( + rh.executePostRequest("u/b/2/_update?refresh=true", "{\"doc\" : {\"b\":66}}", encodeBasicHeader("nagilum", "nagilum")) + ); System.out.println("############ delete"); - //indices:data/write/index - //indices:data/write/bulk - //indices:admin/create - //indices:data/write/bulk[s] - System.out.println(rh.executeDeleteRequest("u/b/2?refresh=true",encodeBasicHeader("nagilum", "nagilum"))); + // indices:data/write/index + // indices:data/write/bulk + // indices:admin/create + // indices:data/write/bulk[s] + System.out.println(rh.executeDeleteRequest("u/b/2?refresh=true", encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ reindex"); - String reindex = - "{"+ - " \"source\": {"+ - " \"index\": \"a\""+ - " },"+ - " \"dest\": {"+ - " \"index\": \"new_a\""+ - " }"+ - "}"; + String reindex = "{" + + " \"source\": {" + + " \"index\": \"a\"" + + " }," + + " \"dest\": {" + + " \"index\": \"new_a\"" + + " }" + + "}"; System.out.println(rh.executePostRequest("_reindex", reindex, encodeBasicHeader("nagilum", "nagilum"))); - System.out.println("############ msearch"); - String msearchBody = - "{\"index\":\"a\", \"type\":\"b\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"a\", \"type\":\"b\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"public\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - + String msearchBody = "{\"index\":\"a\", \"type\":\"b\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"a\", \"type\":\"b\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"public\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); System.out.println(rh.executePostRequest("_msearch", msearchBody, encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ mget"); - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"a\","+ - "\"_id\" : \"1\""+ - " },"+ - " {"+ - "\"_index\" : \"a\","+ - " \"_id\" : \"12\""+ - "},"+ - " {"+ - "\"_index\" : \"a\","+ - " \"_id\" : \"13\""+ - "},"+" {"+ - "\"_index\" : \"a\","+ - " \"_id\" : \"14\""+ - "}"+ - "]"+ - "}"; + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"a\"," + + "\"_id\" : \"1\"" + + " }," + + " {" + + "\"_index\" : \"a\"," + + " \"_id\" : \"12\"" + + "}," + + " {" + + "\"_index\" : \"a\"," + + " \"_id\" : \"13\"" + + "}," + + " {" + + "\"_index\" : \"a\"," + + " \"_id\" : \"14\"" + + "}" + + "]" + + "}"; System.out.println(rh.executePostRequest("_mget?refresh=true", mgetBody, encodeBasicHeader("nagilum", "nagilum"))); System.out.println("############ delete by query"); - String dbqBody = "{"+ - ""+ - " \"query\": { "+ - " \"match\": {"+ - " \"content\": 12"+ - " }"+ - " }"+ - "}"; + String dbqBody = "{" + "" + " \"query\": { " + " \"match\": {" + " \"content\": 12" + " }" + " }" + "}"; System.out.println(rh.executePostRequest("a/b/_delete_by_query", dbqBody, encodeBasicHeader("nagilum", "nagilum"))); diff --git a/src/test/java/org/opensearch/security/TransportUserInjectorIntegTest.java b/src/test/java/org/opensearch/security/TransportUserInjectorIntegTest.java index fc61a3f127..8b5259eb81 100644 --- a/src/test/java/org/opensearch/security/TransportUserInjectorIntegTest.java +++ b/src/test/java/org/opensearch/security/TransportUserInjectorIntegTest.java @@ -55,52 +55,69 @@ public UserInjectorPlugin(final Settings settings, final Path configPath) { } @Override - public Collection createComponents(Client client, ClusterService clusterService, ThreadPool threadPool, - ResourceWatcherService resourceWatcherService, ScriptService scriptService, - NamedXContentRegistry xContentRegistry, Environment environment, - NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry, - IndexNameExpressionResolver indexNameExpressionResolver, - Supplier repositoriesServiceSupplier) { - if(injectedUser != null) - threadPool.getThreadContext().putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, injectedUser); + public Collection createComponents( + Client client, + ClusterService clusterService, + ThreadPool threadPool, + ResourceWatcherService resourceWatcherService, + ScriptService scriptService, + NamedXContentRegistry xContentRegistry, + Environment environment, + NodeEnvironment nodeEnvironment, + NamedWriteableRegistry namedWriteableRegistry, + IndexNameExpressionResolver indexNameExpressionResolver, + Supplier repositoriesServiceSupplier + ) { + if (injectedUser != null) threadPool.getThreadContext() + .putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, injectedUser); return new ArrayList<>(); } } @Test public void testSecurityUserInjection() throws Exception { - final Settings clusterNodeSettings = Settings.builder() - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) - .build(); + final Settings clusterNodeSettings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true).build(); setup(clusterNodeSettings, new DynamicSecurityConfig().setSecurityRolesMapping("roles_transport_inject_user.yml"), Settings.EMPTY); final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put(minimumSecuritySettings(Settings.EMPTY).get(0)) - .put("cluster.name", clusterInfo.clustername) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") - .put("path.home", "./target") - .put("node.name", "testclient") - .put("discovery.initial_state_timeout", "8s") - .put("plugins.security.allow_default_init_securityindex", "true") - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) - .build(); - + .put(minimumSecuritySettings(Settings.EMPTY).get(0)) + .put("cluster.name", clusterInfo.clustername) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") + .put("path.home", "./target") + .put("node.name", "testclient") + .put("discovery.initial_state_timeout", "8s") + .put("plugins.security.allow_default_init_securityindex", "true") + .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .build(); // 1. without user injection - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, UserInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + UserInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-1")).actionGet(); Assert.assertTrue(cir.isAcknowledged()); } - // 2. with invalid backend roles UserInjectorPlugin.injectedUser = "ttt|kkk"; Exception exception = null; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, UserInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + UserInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-2")).actionGet(); Assert.fail("Expecting exception"); @@ -111,11 +128,17 @@ public void testSecurityUserInjection() throws Exception { Assert.assertTrue(exception.getMessage().toString().contains("no permissions for [indices:admin/create]")); } - // 3. with valid backend roles for injected user UserInjectorPlugin.injectedUser = "injectedadmin|injecttest"; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, UserInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + UserInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-2")).actionGet(); Assert.assertTrue(cir.isAcknowledged()); @@ -125,25 +148,32 @@ public void testSecurityUserInjection() throws Exception { @Test public void testSecurityUserInjectionWithConfigDisabled() throws Exception { final Settings clusterNodeSettings = Settings.builder() - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, false) - .build(); + .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, false) + .build(); setup(clusterNodeSettings, new DynamicSecurityConfig().setSecurityRolesMapping("roles_transport_inject_user.yml"), Settings.EMPTY); final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put(minimumSecuritySettings(Settings.EMPTY).get(0)) - .put("cluster.name", clusterInfo.clustername) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") - .put("path.home", "./target") - .put("node.name", "testclient") - .put("discovery.initial_state_timeout", "8s") - .put("plugins.security.allow_default_init_securityindex", "true") - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, false) - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) - .build(); + .put(minimumSecuritySettings(Settings.EMPTY).get(0)) + .put("cluster.name", clusterInfo.clustername) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/cert/logs") + .put("path.home", "./target") + .put("node.name", "testclient") + .put("discovery.initial_state_timeout", "8s") + .put("plugins.security.allow_default_init_securityindex", "true") + .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, false) + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .build(); // 1. without user injection - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, UserInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + UserInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-1")).actionGet(); Assert.assertTrue(cir.isAcknowledged()); @@ -151,8 +181,15 @@ public void testSecurityUserInjectionWithConfigDisabled() throws Exception { // with invalid backend roles UserInjectorPlugin.injectedUser = "ttt|kkk"; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, UserInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + UserInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); CreateIndexResponse cir = node.client().admin().indices().create(new CreateIndexRequest("captain-logs-2")).actionGet(); // Should pass as the user injection is disabled diff --git a/src/test/java/org/opensearch/security/UtilTests.java b/src/test/java/org/opensearch/security/UtilTests.java index 16baf932cc..2127ada55f 100644 --- a/src/test/java/org/opensearch/security/UtilTests.java +++ b/src/test/java/org/opensearch/security/UtilTests.java @@ -86,109 +86,124 @@ public void testWildcardMatcherClassesCaseInsensitive() { @Test public void testWildcardMatchers() { - assertTrue(!WildcardMatcher.from("a*?").test( "a")); - assertTrue(WildcardMatcher.from("a*?").test( "aa")); - assertTrue(WildcardMatcher.from("a*?").test( "ab")); - //assertTrue(WildcardMatcher.pattern("a*?").test( "abb")); - assertTrue(WildcardMatcher.from("*my*index").test( "myindex")); - assertTrue(!WildcardMatcher.from("*my*index").test( "myindex1")); - assertTrue(WildcardMatcher.from("*my*index?").test( "myindex1")); - assertTrue(WildcardMatcher.from("*my*index").test( "this_is_my_great_index")); - assertTrue(!WildcardMatcher.from("*my*index").test( "MYindex")); - assertTrue(!WildcardMatcher.from("?kibana").test( "kibana")); - assertTrue(WildcardMatcher.from("?kibana").test( ".kibana")); - assertTrue(!WildcardMatcher.from("?kibana").test( "kibana.")); - assertTrue(WildcardMatcher.from("?kibana?").test( "?kibana.")); - assertTrue(WildcardMatcher.from("/(\\d{3}-?\\d{2}-?\\d{4})/").test( "123-45-6789")); - assertTrue(!WildcardMatcher.from("(\\d{3}-?\\d{2}-?\\d{4})").test( "123-45-6789")); - assertTrue(WildcardMatcher.from("/\\S*/").test( "abc")); - assertTrue(WildcardMatcher.from("abc").test( "abc")); - assertTrue(!WildcardMatcher.from("ABC").test( "abc")); + assertTrue(!WildcardMatcher.from("a*?").test("a")); + assertTrue(WildcardMatcher.from("a*?").test("aa")); + assertTrue(WildcardMatcher.from("a*?").test("ab")); + // assertTrue(WildcardMatcher.pattern("a*?").test( "abb")); + assertTrue(WildcardMatcher.from("*my*index").test("myindex")); + assertTrue(!WildcardMatcher.from("*my*index").test("myindex1")); + assertTrue(WildcardMatcher.from("*my*index?").test("myindex1")); + assertTrue(WildcardMatcher.from("*my*index").test("this_is_my_great_index")); + assertTrue(!WildcardMatcher.from("*my*index").test("MYindex")); + assertTrue(!WildcardMatcher.from("?kibana").test("kibana")); + assertTrue(WildcardMatcher.from("?kibana").test(".kibana")); + assertTrue(!WildcardMatcher.from("?kibana").test("kibana.")); + assertTrue(WildcardMatcher.from("?kibana?").test("?kibana.")); + assertTrue(WildcardMatcher.from("/(\\d{3}-?\\d{2}-?\\d{4})/").test("123-45-6789")); + assertTrue(!WildcardMatcher.from("(\\d{3}-?\\d{2}-?\\d{4})").test("123-45-6789")); + assertTrue(WildcardMatcher.from("/\\S*/").test("abc")); + assertTrue(WildcardMatcher.from("abc").test("abc")); + assertTrue(!WildcardMatcher.from("ABC").test("abc")); } @Test public void testMapFromArray() { - Map map = SecurityUtils.mapFromArray((Object)null); + Map map = SecurityUtils.mapFromArray((Object) null); assertTrue(map == null); - + map = SecurityUtils.mapFromArray("key"); assertTrue(map == null); map = SecurityUtils.mapFromArray("key", "value", "otherkey"); assertTrue(map == null); - + map = SecurityUtils.mapFromArray("key", "value"); - assertNotNull(map); + assertNotNull(map); assertEquals(1, map.size()); assertEquals("value", map.get("key")); map = SecurityUtils.mapFromArray("key", "value", "key", "value"); - assertNotNull(map); + assertNotNull(map); assertEquals(1, map.size()); assertEquals("value", map.get("key")); map = SecurityUtils.mapFromArray("key1", "value1", "key2", "value2"); - assertNotNull(map); + assertNotNull(map); assertEquals(2, map.size()); assertEquals("value1", map.get("key1")); assertEquals("value2", map.get("key2")); } - + @Test public void testEnvReplace() { Settings settings = Settings.EMPTY; - assertEquals("abv${env.MYENV}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV}xyz",settings)); - assertEquals("abv${envbc.MYENV}xyz", SecurityUtils.replaceEnvVars("abv${envbc.MYENV}xyz",settings)); - assertEquals("abvtTtxyz", SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz",settings)); - assertTrue(OpenBSDBCrypt.checkPassword(SecurityUtils.replaceEnvVars("${envbc.MYENV:-tTt}",settings), "tTt".toCharArray())); - assertEquals("abvtTtxyzxxx", SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz${env.MYENV:-xxx}",settings)); - assertTrue(SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz${envbc.MYENV:-xxx}",settings).startsWith("abvtTtxyz$2y$")); - assertEquals("abv${env.MYENV:tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV:tTt}xyz",settings)); - assertEquals("abv${env.MYENV-tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV-tTt}xyz",settings)); - //assertEquals("abvabcdefgxyz", SecurityUtils.replaceEnvVars("abv${envbase64.B64TEST}xyz",settings)); + assertEquals("abv${env.MYENV}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV}xyz", settings)); + assertEquals("abv${envbc.MYENV}xyz", SecurityUtils.replaceEnvVars("abv${envbc.MYENV}xyz", settings)); + assertEquals("abvtTtxyz", SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz", settings)); + assertTrue(OpenBSDBCrypt.checkPassword(SecurityUtils.replaceEnvVars("${envbc.MYENV:-tTt}", settings), "tTt".toCharArray())); + assertEquals("abvtTtxyzxxx", SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz${env.MYENV:-xxx}", settings)); + assertTrue(SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz${envbc.MYENV:-xxx}", settings).startsWith("abvtTtxyz$2y$")); + assertEquals("abv${env.MYENV:tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV:tTt}xyz", settings)); + assertEquals("abv${env.MYENV-tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV-tTt}xyz", settings)); + // assertEquals("abvabcdefgxyz", SecurityUtils.replaceEnvVars("abv${envbase64.B64TEST}xyz",settings)); Map env = System.getenv(); assertTrue(env.size() > 0); - + boolean checked = false; - for(String k: env.keySet()) { - String val=System.getenv().get(k); - if(val == null || val.isEmpty()) { + for (String k : env.keySet()) { + String val = System.getenv().get(k); + if (val == null || val.isEmpty()) { continue; } - assertEquals("abv"+val+"xyz", SecurityUtils.replaceEnvVars("abv${env."+k+"}xyz",settings)); - assertEquals("abv${"+k+"}xyz", SecurityUtils.replaceEnvVars("abv${"+k+"}xyz",settings)); - assertEquals("abv"+val+"xyz", SecurityUtils.replaceEnvVars("abv${env."+k+":-k182765ggh}xyz",settings)); - assertEquals("abv"+val+"xyzabv"+val+"xyz", SecurityUtils.replaceEnvVars("abv${env."+k+"}xyzabv${env."+k+"}xyz",settings)); - assertEquals("abv"+val+"xyz", SecurityUtils.replaceEnvVars("abv${env."+k+":-k182765ggh}xyz",settings)); - assertTrue(OpenBSDBCrypt.checkPassword(SecurityUtils.replaceEnvVars("${envbc."+k+"}",settings), val.toCharArray())); + assertEquals("abv" + val + "xyz", SecurityUtils.replaceEnvVars("abv${env." + k + "}xyz", settings)); + assertEquals("abv${" + k + "}xyz", SecurityUtils.replaceEnvVars("abv${" + k + "}xyz", settings)); + assertEquals("abv" + val + "xyz", SecurityUtils.replaceEnvVars("abv${env." + k + ":-k182765ggh}xyz", settings)); + assertEquals( + "abv" + val + "xyzabv" + val + "xyz", + SecurityUtils.replaceEnvVars("abv${env." + k + "}xyzabv${env." + k + "}xyz", settings) + ); + assertEquals("abv" + val + "xyz", SecurityUtils.replaceEnvVars("abv${env." + k + ":-k182765ggh}xyz", settings)); + assertTrue(OpenBSDBCrypt.checkPassword(SecurityUtils.replaceEnvVars("${envbc." + k + "}", settings), val.toCharArray())); checked = true; } - + assertTrue(checked); } - + @Test public void testNoEnvReplace() { Settings settings = Settings.builder().put(ConfigConstants.SECURITY_DISABLE_ENVVAR_REPLACEMENT, true).build(); - assertEquals("abv${env.MYENV}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV}xyz",settings)); - assertEquals("abv${envbc.MYENV}xyz", SecurityUtils.replaceEnvVars("abv${envbc.MYENV}xyz",settings)); - assertEquals("abv${env.MYENV:-tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz",settings)); - assertEquals("abv${env.MYENV:-tTt}xyz${env.MYENV:-xxx}", SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz${env.MYENV:-xxx}",settings)); - assertFalse(SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz${envbc.MYENV:-xxx}",settings).startsWith("abvtTtxyz$2y$")); - assertEquals("abv${env.MYENV:tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV:tTt}xyz",settings)); - assertEquals("abv${env.MYENV-tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV-tTt}xyz",settings)); + assertEquals("abv${env.MYENV}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV}xyz", settings)); + assertEquals("abv${envbc.MYENV}xyz", SecurityUtils.replaceEnvVars("abv${envbc.MYENV}xyz", settings)); + assertEquals("abv${env.MYENV:-tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz", settings)); + assertEquals( + "abv${env.MYENV:-tTt}xyz${env.MYENV:-xxx}", + SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz${env.MYENV:-xxx}", settings) + ); + assertFalse(SecurityUtils.replaceEnvVars("abv${env.MYENV:-tTt}xyz${envbc.MYENV:-xxx}", settings).startsWith("abvtTtxyz$2y$")); + assertEquals("abv${env.MYENV:tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV:tTt}xyz", settings)); + assertEquals("abv${env.MYENV-tTt}xyz", SecurityUtils.replaceEnvVars("abv${env.MYENV-tTt}xyz", settings)); Map env = System.getenv(); assertTrue(env.size() > 0); - - for(String k: env.keySet()) { - assertEquals("abv${env."+k+"}xyz", SecurityUtils.replaceEnvVars("abv${env."+k+"}xyz",settings)); - assertEquals("abv${"+k+"}xyz", SecurityUtils.replaceEnvVars("abv${"+k+"}xyz",settings)); - assertEquals("abv${env."+k+":-k182765ggh}xyz", SecurityUtils.replaceEnvVars("abv${env."+k+":-k182765ggh}xyz",settings)); - assertEquals("abv${env."+k+"}xyzabv${env."+k+"}xyz", SecurityUtils.replaceEnvVars("abv${env."+k+"}xyzabv${env."+k+"}xyz",settings)); - assertEquals("abv${env."+k+":-k182765ggh}xyz", SecurityUtils.replaceEnvVars("abv${env."+k+":-k182765ggh}xyz",settings)); + + for (String k : env.keySet()) { + assertEquals("abv${env." + k + "}xyz", SecurityUtils.replaceEnvVars("abv${env." + k + "}xyz", settings)); + assertEquals("abv${" + k + "}xyz", SecurityUtils.replaceEnvVars("abv${" + k + "}xyz", settings)); + assertEquals( + "abv${env." + k + ":-k182765ggh}xyz", + SecurityUtils.replaceEnvVars("abv${env." + k + ":-k182765ggh}xyz", settings) + ); + assertEquals( + "abv${env." + k + "}xyzabv${env." + k + "}xyz", + SecurityUtils.replaceEnvVars("abv${env." + k + "}xyzabv${env." + k + "}xyz", settings) + ); + assertEquals( + "abv${env." + k + ":-k182765ggh}xyz", + SecurityUtils.replaceEnvVars("abv${env." + k + ":-k182765ggh}xyz", settings) + ); } } } diff --git a/src/test/java/org/opensearch/security/auditlog/AbstractAuditlogiUnitTest.java b/src/test/java/org/opensearch/security/auditlog/AbstractAuditlogiUnitTest.java index 14ae6aa81e..f567a90ec8 100644 --- a/src/test/java/org/opensearch/security/auditlog/AbstractAuditlogiUnitTest.java +++ b/src/test/java/org/opensearch/security/auditlog/AbstractAuditlogiUnitTest.java @@ -45,8 +45,10 @@ protected final void setup(Settings settings) throws Exception { // Separate the cluster defaults from audit settings that will be applied after the cluster is up settings.keySet().forEach(key -> { final boolean moveToAuditConfig = Arrays.stream(AuditConfig.Filter.FilterEntries.values()) - .anyMatch(entry -> entry.getKeyWithNamespace().equalsIgnoreCase(key) || entry.getLegacyKeyWithNamespace().equalsIgnoreCase(key)) - || DEPRECATED_KEYS.stream().anyMatch(key::equalsIgnoreCase); + .anyMatch( + entry -> entry.getKeyWithNamespace().equalsIgnoreCase(key) || entry.getLegacyKeyWithNamespace().equalsIgnoreCase(key) + ) + || DEPRECATED_KEYS.stream().anyMatch(key::equalsIgnoreCase); if (moveToAuditConfig) { auditConfigSettings.put(key, settings.get(key)); } else { @@ -64,10 +66,8 @@ protected Settings defaultNodeSettings(Settings additionalSettings) { Settings.Builder builder = Settings.builder(); builder.put("plugins.security.ssl.http.enabled", true) - .put("plugins.security.ssl.http.keystore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")); + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")); return builder.put(additionalSettings).build(); } @@ -87,7 +87,7 @@ protected void setupStarfleetIndex() throws Exception { protected boolean validateMsgs(final Collection msgs) { boolean valid = true; - for(AuditMessage msg: msgs) { + for (AuditMessage msg : msgs) { valid = validateMsg(msg) && valid; } return valid; @@ -99,15 +99,15 @@ protected boolean validateMsg(final AuditMessage msg) { protected boolean validateJson(final String json) { - if(json == null || json.isEmpty()) { + if (json == null || json.isEmpty()) { return false; } try { JsonNode node = DefaultObjectMapper.objectMapper.readTree(json); - if(node.get("audit_request_body") != null) { - System.out.println(" Check audit_request_body for validity: "+node.get("audit_request_body").asText()); + if (node.get("audit_request_body") != null) { + System.out.println(" Check audit_request_body for validity: " + node.get("audit_request_body").asText()); DefaultObjectMapper.objectMapper.readTree(node.get("audit_request_body").asText()); } diff --git a/src/test/java/org/opensearch/security/auditlog/AuditTestUtils.java b/src/test/java/org/opensearch/security/auditlog/AuditTestUtils.java index 507ebc1409..98f5fab88e 100644 --- a/src/test/java/org/opensearch/security/auditlog/AuditTestUtils.java +++ b/src/test/java/org/opensearch/security/auditlog/AuditTestUtils.java @@ -62,7 +62,8 @@ public static AbstractAuditLog createAuditLog( final Client clientProvider, final ThreadPool threadPool, final IndexNameExpressionResolver resolver, - final ClusterService clusterService) { + final ClusterService clusterService + ) { AuditLogImpl auditLog = new AuditLogImpl(settings, configPath, clientProvider, threadPool, resolver, clusterService); AuditConfig auditConfig = AuditConfig.from(settings); auditLog.setConfig(auditConfig); diff --git a/src/test/java/org/opensearch/security/auditlog/compliance/ComplianceAuditlogTest.java b/src/test/java/org/opensearch/security/auditlog/compliance/ComplianceAuditlogTest.java index dd53cd16a8..361c3cc313 100644 --- a/src/test/java/org/opensearch/security/auditlog/compliance/ComplianceAuditlogTest.java +++ b/src/test/java/org/opensearch/security/auditlog/compliance/ComplianceAuditlogTest.java @@ -54,14 +54,14 @@ public class ComplianceAuditlogTest extends AbstractAuditlogiUnitTest { @Test public void testSourceFilter() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, "emp") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, "emp") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setup(additionalSettings); final boolean sendAdminCertificate = rh.sendAdminCertificate; @@ -74,18 +74,18 @@ public void testSourceFilter() throws Exception { rh.sendAdminCertificate = sendAdminCertificate; rh.keystore = keystore; - String search = "{" + - " \"_source\":[" + - " \"Gender\""+ - " ]," + - " \"from\":0," + - " \"size\":3," + - " \"query\":{" + - " \"term\":{" + - " \"Salary\": 300" + - " }" + - " }" + - "}"; + String search = "{" + + " \"_source\":[" + + " \"Gender\"" + + " ]," + + " \"from\":0," + + " \"size\":3," + + " \"query\":{" + + " \"term\":{" + + " \"Salary\": 300" + + " }" + + " }" + + "}"; final AuditMessage message = TestAuditlogImpl.doThenWaitForMessage(() -> { final HttpResponse response = rh.executePostRequest("_search?pretty", search, encodeBasicHeader("admin", "admin")); @@ -102,9 +102,7 @@ public void testSourceFilter() throws Exception { @Test public void testComplianceEnable() throws Exception { - Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .build(); + Settings additionalSettings = Settings.builder().put("plugins.security.audit.type", TestAuditlogImpl.class.getName()).build(); setup(additionalSettings); @@ -112,7 +110,14 @@ public void testComplianceEnable() throws Exception { rh.keystore = "auditlog/kirk-keystore.jks"; // watch emp for write - AuditConfig auditConfig = new AuditConfig(true, AuditConfig.Filter.DEFAULT , ComplianceConfig.from(ImmutableMap.of("enabled", true, "write_watched_indices", Collections.singletonList("emp")), additionalSettings)); + AuditConfig auditConfig = new AuditConfig( + true, + AuditConfig.Filter.DEFAULT, + ComplianceConfig.from( + ImmutableMap.of("enabled", true, "write_watched_indices", Collections.singletonList("emp")), + additionalSettings + ) + ); updateAuditConfig(AuditTestUtils.createAuditPayload(auditConfig)); // make an event happen @@ -122,23 +127,36 @@ public void testComplianceEnable() throws Exception { rh.executePutRequest("emp/_doc/0?refresh", "{\"Designation\" : \"CEO\", \"Gender\" : \"female\", \"Salary\" : 100}"); System.out.println(rh.executeGetRequest("_cat/shards?v")); }, 7); - } catch (final MessagesNotFoundException ex) { + } catch (final MessagesNotFoundException ex) { // indices:admin/mapping/auto_put can be logged twice, this handles if they were not found assertThat("Too many missing audit log messages", ex.getMissingCount(), equalTo(2)); messages = ex.getFoundMessages(); } - messages.stream().filter(msg -> msg.getCategory().equals(AuditCategory.COMPLIANCE_DOC_WRITE)) - .findFirst().orElseThrow(() -> new RuntimeException("Missing COMPLIANCE message")); + messages.stream() + .filter(msg -> msg.getCategory().equals(AuditCategory.COMPLIANCE_DOC_WRITE)) + .findFirst() + .orElseThrow(() -> new RuntimeException("Missing COMPLIANCE message")); - final List indexCreation = messages.stream().filter(msg -> "indices:admin/auto_create".equals(msg.getPrivilege())).collect(Collectors.toList()); + final List indexCreation = messages.stream() + .filter(msg -> "indices:admin/auto_create".equals(msg.getPrivilege())) + .collect(Collectors.toList()); assertThat(indexCreation.size(), equalTo(2)); - final List mappingCreation = messages.stream().filter(msg -> "indices:admin/mapping/auto_put".equals(msg.getPrivilege())).collect(Collectors.toList()); + final List mappingCreation = messages.stream() + .filter(msg -> "indices:admin/mapping/auto_put".equals(msg.getPrivilege())) + .collect(Collectors.toList()); assertThat(mappingCreation.size(), anyOf(equalTo(4), equalTo(2))); - + // disable compliance - auditConfig = new AuditConfig(true, AuditConfig.Filter.DEFAULT , ComplianceConfig.from(ImmutableMap.of("enabled", false, "write_watched_indices", Collections.singletonList("emp")), additionalSettings)); + auditConfig = new AuditConfig( + true, + AuditConfig.Filter.DEFAULT, + ComplianceConfig.from( + ImmutableMap.of("enabled", false, "write_watched_indices", Collections.singletonList("emp")), + additionalSettings + ) + ); updateAuditConfig(AuditTestUtils.createAuditPayload(auditConfig)); // trigger an event that it not captured by the audit log @@ -154,15 +172,15 @@ public void testComplianceEnable() throws Exception { public void testSourceFilterMsearch() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - //.put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, "emp") - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, "emp") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + // .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, "emp") + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, "emp") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setup(additionalSettings); final boolean sendAdminCertificate = rh.sendAdminCertificate; @@ -175,33 +193,38 @@ public void testSourceFilterMsearch() throws Exception { rh.sendAdminCertificate = sendAdminCertificate; rh.keystore = keystore; - String search = "{}"+System.lineSeparator() - + "{" + - " \"_source\":[" + - " \"Gender\""+ - " ]," + - " \"from\":0," + - " \"size\":3," + - " \"query\":{" + - " \"term\":{" + - " \"Salary\": 300" + - " }" + - " }" + - "}"+System.lineSeparator()+ - - "{}"+System.lineSeparator() - + "{" + - " \"_source\":[" + - " \"Designation\""+ - " ]," + - " \"from\":0," + - " \"size\":3," + - " \"query\":{" + - " \"term\":{" + - " \"Salary\": 200" + - " }" + - " }" + - "}"+System.lineSeparator(); + String search = "{}" + + System.lineSeparator() + + "{" + + " \"_source\":[" + + " \"Gender\"" + + " ]," + + " \"from\":0," + + " \"size\":3," + + " \"query\":{" + + " \"term\":{" + + " \"Salary\": 300" + + " }" + + " }" + + "}" + + System.lineSeparator() + + + + "{}" + + System.lineSeparator() + + "{" + + " \"_source\":[" + + " \"Designation\"" + + " ]," + + " \"from\":0," + + " \"size\":3," + + " \"query\":{" + + " \"term\":{" + + " \"Salary\": 200" + + " }" + + " }" + + "}" + + System.lineSeparator(); final List messages = TestAuditlogImpl.doThenWaitForMessages(() -> { HttpResponse response = rh.executePostRequest("_msearch?pretty", search, encodeBasicHeader("admin", "admin")); @@ -209,8 +232,10 @@ public void testSourceFilterMsearch() throws Exception { Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); }, 2); - - final AuditMessage desginationMsg = messages.stream().filter(msg -> msg.getRequestBody().contains("Designation")).findFirst().orElseThrow(); + final AuditMessage desginationMsg = messages.stream() + .filter(msg -> msg.getRequestBody().contains("Designation")) + .findFirst() + .orElseThrow(); assertThat(desginationMsg.getCategory(), equalTo(AuditCategory.COMPLIANCE_DOC_READ)); assertThat(desginationMsg.getRequestBody(), containsString("Designation")); assertThat(desginationMsg.getRequestBody(), not(containsString("Salary"))); @@ -227,23 +252,31 @@ public void testSourceFilterMsearch() throws Exception { public void testInternalConfig() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setup(additionalSettings); - final List expectedDocumentsTypes = List.of("config", "actiongroups", "internalusers", "roles", "rolesmapping", "tenants", "audit"); + final List expectedDocumentsTypes = List.of( + "config", + "actiongroups", + "internalusers", + "roles", + "rolesmapping", + "tenants", + "audit" + ); final List messages = TestAuditlogImpl.doThenWaitForMessages(() -> { try (RestHighLevelClient restHighLevelClient = getRestClient(clusterInfo, "kirk-keystore.jks", "truststore.jks")) { - for (IndexRequest ir: new DynamicSecurityConfig().setSecurityRoles("roles_2.yml").getDynamicConfig(getResourceFolder())) { + for (IndexRequest ir : new DynamicSecurityConfig().setSecurityRoles("roles_2.yml").getDynamicConfig(getResourceFolder())) { restHighLevelClient.index(ir, RequestOptions.DEFAULT); GetResponse getDocumentResponse = restHighLevelClient.get(new GetRequest(ir.index(), ir.id()), RequestOptions.DEFAULT); assertThat(getDocumentResponse.isExists(), equalTo(true)); @@ -262,7 +295,8 @@ public void testInternalConfig() throws Exception { messages.stream().collect(Collectors.groupingBy(AuditMessage::getDocId)).entrySet().forEach((e) -> { final String docId = e.getKey(); final List messagesByDocId = e.getValue(); - assertThat("Doc " + docId + " should have a read/write config message", + assertThat( + "Doc " + docId + " should have a read/write config message", messagesByDocId.stream().map(AuditMessage::getCategory).collect(Collectors.toList()), equalTo(List.of(AuditCategory.COMPLIANCE_INTERNAL_CONFIG_WRITE, AuditCategory.COMPLIANCE_INTERNAL_CONFIG_READ)) ); @@ -275,15 +309,15 @@ public void testInternalConfig() throws Exception { public void testExternalConfig() throws Exception { final Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); final List messages = TestAuditlogImpl.doThenWaitForMessages(() -> { try { @@ -293,7 +327,7 @@ public void testExternalConfig() throws Exception { } try (Client tc = getClient()) { - for(IndexRequest ir: new DynamicSecurityConfig().setSecurityRoles("roles_2.yml").getDynamicConfig(getResourceFolder())) { + for (IndexRequest ir : new DynamicSecurityConfig().setSecurityRoles("roles_2.yml").getDynamicConfig(getResourceFolder())) { tc.index(ir).actionGet(); } } @@ -319,41 +353,46 @@ public void testExternalConfig() throws Exception { public void testUpdate() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, "finance") - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, "humanresources,Designation,FirstName,LastName") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, "finance") + .put( + ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, + "humanresources,Designation,FirstName,LastName" + ) + .build(); setup(additionalSettings); - try (Client tc = getClient()) { - tc.prepareIndex("humanresources") - .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .setSource("Age", 456) - .execute() - .actionGet(); + tc.prepareIndex("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).setSource("Age", 456).execute().actionGet(); } final MessagesNotFoundException ex1 = assertThrows(MessagesNotFoundException.class, () -> { TestAuditlogImpl.doThenWaitForMessage(() -> { final String body = "{\"doc\": {\"Age\":123}}"; - final HttpResponse response = rh.executePostRequest("humanresources/_doc/100?pretty", body, encodeBasicHeader("admin", "admin")); + final HttpResponse response = rh.executePostRequest( + "humanresources/_doc/100?pretty", + body, + encodeBasicHeader("admin", "admin") + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); }); }); assertThat(ex1.getMissingCount(), equalTo(1)); - final MessagesNotFoundException ex2 = assertThrows(MessagesNotFoundException.class, () -> { TestAuditlogImpl.doThenWaitForMessage(() -> { final String body = "{\"doc\": {\"Age\":456}}"; - final HttpResponse response = rh.executePostRequest("humanresources/_update/100?pretty", body, encodeBasicHeader("admin", "admin")); + final HttpResponse response = rh.executePostRequest( + "humanresources/_update/100?pretty", + body, + encodeBasicHeader("admin", "admin") + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); }); }); @@ -367,34 +406,38 @@ public void testUpdate() throws Exception { public void testWriteHistory() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, "humanresources") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, "humanresources") + .build(); setup(additionalSettings); try (Client tc = getClient()) { - tc.prepareIndex("humanresources") - .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .setSource("Age", 456) - .execute() - .actionGet(); + tc.prepareIndex("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).setSource("Age", 456).execute().actionGet(); } TestAuditlogImpl.doThenWaitForMessage(() -> { final String body = "{\"doc\": {\"Age\":123}}"; - final HttpResponse response = rh.executePostRequest("humanresources/_doc/100?pretty", body, encodeBasicHeader("admin", "admin")); + final HttpResponse response = rh.executePostRequest( + "humanresources/_doc/100?pretty", + body, + encodeBasicHeader("admin", "admin") + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); }); Assert.assertTrue(TestAuditlogImpl.sb.toString().split(".*audit_compliance_diff_content.*replace.*").length == 1); TestAuditlogImpl.doThenWaitForMessage(() -> { final String body = "{\"doc\": {\"Age\":555}}"; - final HttpResponse response = rh.executePostRequest("humanresources/_update/100?pretty", body, encodeBasicHeader("admin", "admin")); + final HttpResponse response = rh.executePostRequest( + "humanresources/_update/100?pretty", + body, + encodeBasicHeader("admin", "admin") + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); }); Assert.assertTrue(TestAuditlogImpl.sb.toString().split(".*audit_compliance_diff_content.*replace.*").length == 1); diff --git a/src/test/java/org/opensearch/security/auditlog/compliance/ComplianceConfigTest.java b/src/test/java/org/opensearch/security/auditlog/compliance/ComplianceConfigTest.java index a40e94ad28..467475212b 100644 --- a/src/test/java/org/opensearch/security/auditlog/compliance/ComplianceConfigTest.java +++ b/src/test/java/org/opensearch/security/auditlog/compliance/ComplianceConfigTest.java @@ -50,19 +50,21 @@ public void testConfig() { // arrange final String testSalt = "abcdefghijklmnop"; final Settings settings = Settings.builder() - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_METADATA_ONLY, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_METADATA_ONLY, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) - .put(ConfigConstants.SECURITY_COMPLIANCE_SALT, testSalt) - .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, "write_index1", "write_index_pattern*") - .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, "read_index1,field1,field2", "read_index_pattern*,field1,field_pattern*") - .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_IGNORE_USERS, - "test-user-1", "test-user-2") - .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, - "test-user-3", "test-user-4") - .build(); + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_METADATA_ONLY, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_METADATA_ONLY, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) + .put(ConfigConstants.SECURITY_COMPLIANCE_SALT, testSalt) + .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_WATCHED_INDICES, "write_index1", "write_index_pattern*") + .putList( + ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_WATCHED_FIELDS, + "read_index1,field1,field2", + "read_index_pattern*,field1,field_pattern*" + ) + .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_IGNORE_USERS, "test-user-1", "test-user-2") + .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, "test-user-3", "test-user-4") + .build(); // act final ComplianceConfig complianceConfig = ComplianceConfig.from(settings); @@ -74,8 +76,14 @@ public void testConfig() { assertTrue(complianceConfig.shouldLogReadMetadataOnly()); assertTrue(complianceConfig.shouldLogWriteMetadataOnly()); assertFalse(complianceConfig.shouldLogDiffsForWrite()); - assertEquals(WildcardMatcher.from(ImmutableSet.of("test-user-1", "test-user-2")), complianceConfig.getIgnoredComplianceUsersForReadMatcher()); - assertEquals(WildcardMatcher.from(ImmutableSet.of("test-user-3", "test-user-4")), complianceConfig.getIgnoredComplianceUsersForWriteMatcher()); + assertEquals( + WildcardMatcher.from(ImmutableSet.of("test-user-1", "test-user-2")), + complianceConfig.getIgnoredComplianceUsersForReadMatcher() + ); + assertEquals( + WildcardMatcher.from(ImmutableSet.of("test-user-3", "test-user-4")), + complianceConfig.getIgnoredComplianceUsersForWriteMatcher() + ); // test write history assertTrue(complianceConfig.writeHistoryEnabledForIndex(".opendistro_security")); @@ -105,11 +113,9 @@ public void testConfig() { public void testNone() { // arrange final Settings settings = Settings.builder() - .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_IGNORE_USERS, - "NONE") - .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, - "NONE") - .build(); + .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_IGNORE_USERS, "NONE") + .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, "NONE") + .build(); // act final ComplianceConfig complianceConfig = ComplianceConfig.from(settings); // assert @@ -121,11 +127,9 @@ public void testNone() { public void testEmpty() { // arrange final Settings settings = Settings.builder() - .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_IGNORE_USERS, - Collections.emptyList()) - .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, - Collections.emptyList()) - .build(); + .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_READ_IGNORE_USERS, Collections.emptyList()) + .putList(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, Collections.emptyList()) + .build(); // act final ComplianceConfig complianceConfig = ComplianceConfig.from(settings); // assert diff --git a/src/test/java/org/opensearch/security/auditlog/compliance/RestApiComplianceAuditlogTest.java b/src/test/java/org/opensearch/security/auditlog/compliance/RestApiComplianceAuditlogTest.java index 37ef283ccb..519237bd8e 100644 --- a/src/test/java/org/opensearch/security/auditlog/compliance/RestApiComplianceAuditlogTest.java +++ b/src/test/java/org/opensearch/security/auditlog/compliance/RestApiComplianceAuditlogTest.java @@ -29,25 +29,29 @@ public class RestApiComplianceAuditlogTest extends AbstractAuditlogiUnitTest { public void testRestApiRolesEnabled() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setup(additionalSettings); TestAuditlogImpl.clear(); String body = "{ \"password\":\"some new password\",\"backend_roles\":[\"role1\",\"role2\"] }"; - HttpResponse response = rh.executePutRequest("_opendistro/_security/api/internalusers/compuser?pretty", body, encodeBasicHeader("admin", "admin")); + HttpResponse response = rh.executePutRequest( + "_opendistro/_security/api/internalusers/compuser?pretty", + body, + encodeBasicHeader("admin", "admin") + ); Thread.sleep(1500); System.out.println(TestAuditlogImpl.sb.toString()); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); - Assert.assertTrue(TestAuditlogImpl.messages.size()+"",TestAuditlogImpl.messages.size() == 1); + Assert.assertTrue(TestAuditlogImpl.messages.size() + "", TestAuditlogImpl.messages.size() == 1); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("audit_request_effective_user")); Assert.assertFalse(TestAuditlogImpl.sb.toString().contains("COMPLIANCE_INTERNAL_CONFIG_READ")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("COMPLIANCE_INTERNAL_CONFIG_WRITE")); @@ -59,15 +63,15 @@ public void testRestApiRolesEnabled() throws Exception { public void testRestApiRolesDisabled() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setup(additionalSettings); TestAuditlogImpl.clear(); @@ -82,7 +86,7 @@ public void testRestApiRolesDisabled() throws Exception { Thread.sleep(1500); System.out.println(TestAuditlogImpl.sb.toString()); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); - Assert.assertTrue(TestAuditlogImpl.messages.size()+"",TestAuditlogImpl.messages.size() == 1); + Assert.assertTrue(TestAuditlogImpl.messages.size() + "", TestAuditlogImpl.messages.size() == 1); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("audit_request_effective_user")); Assert.assertFalse(TestAuditlogImpl.sb.toString().contains("COMPLIANCE_INTERNAL_CONFIG_READ")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("COMPLIANCE_INTERNAL_CONFIG_WRITE")); @@ -95,15 +99,15 @@ public void testRestApiRolesDisabled() throws Exception { public void testRestApiRolesDisabledGet() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setup(additionalSettings); TestAuditlogImpl.clear(); @@ -125,21 +129,19 @@ public void testRestApiRolesDisabledGet() throws Exception { Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } - - @Test public void testAutoInit() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setup(additionalSettings); @@ -157,42 +159,45 @@ public void testAutoInit() throws Exception { public void testRestApiNewUser() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, "admin") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_IGNORE_USERS, "admin") + .build(); setup(additionalSettings); TestAuditlogImpl.clear(); String body = "{ \"password\":\"some new password\",\"backend_roles\":[\"role1\",\"role2\"] }"; System.out.println("exec"); - HttpResponse response = rh.executePutRequest("_opendistro/_security/api/internalusers/compuser?pretty", - body, encodeBasicHeader("admin", "admin")); + HttpResponse response = rh.executePutRequest( + "_opendistro/_security/api/internalusers/compuser?pretty", + body, + encodeBasicHeader("admin", "admin") + ); Thread.sleep(1500); System.out.println(TestAuditlogImpl.sb.toString()); Assert.assertEquals(response.getBody(), HttpStatus.SC_CREATED, response.getStatusCode()); - Assert.assertTrue(TestAuditlogImpl.messages.size()+"", TestAuditlogImpl.messages.isEmpty()); + Assert.assertTrue(TestAuditlogImpl.messages.size() + "", TestAuditlogImpl.messages.isEmpty()); } @Test public void testRestInternalConfigRead() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setup(additionalSettings); TestAuditlogImpl.clear(); @@ -206,7 +211,7 @@ public void testRestInternalConfigRead() throws Exception { Thread.sleep(1500); System.out.println(TestAuditlogImpl.sb.toString()); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - Assert.assertTrue(TestAuditlogImpl.messages.size()+"",TestAuditlogImpl.messages.size() == 1); + Assert.assertTrue(TestAuditlogImpl.messages.size() + "", TestAuditlogImpl.messages.size() == 1); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("audit_request_effective_user")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("COMPLIANCE_INTERNAL_CONFIG_READ")); Assert.assertFalse(TestAuditlogImpl.sb.toString().contains("COMPLIANCE_INTERNAL_CONFIG_WRITE")); @@ -217,13 +222,13 @@ public void testRestInternalConfigRead() throws Exception { @Test public void testBCryptHashRedaction() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) + .build(); setup(settings); rh.sendAdminCertificate = true; rh.keystore = "kirk-keystore.jks"; @@ -242,7 +247,7 @@ public void testBCryptHashRedaction() throws Exception { // create internal user and verify no BCrypt hash is present in audit logs TestAuditlogImpl.clear(); - rh.executePutRequest("/_opendistro/_security/api/internalusers/test", "{ \"password\":\"some new user password\"}"); + rh.executePutRequest("/_opendistro/_security/api/internalusers/test", "{ \"password\":\"some new user password\"}"); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); Assert.assertFalse(AuditMessage.BCRYPT_HASH.matcher(TestAuditlogImpl.sb.toString()).matches()); } diff --git a/src/test/java/org/opensearch/security/auditlog/config/AuditConfigFilterTest.java b/src/test/java/org/opensearch/security/auditlog/config/AuditConfigFilterTest.java index 4b4676d852..fad4cabbc5 100644 --- a/src/test/java/org/opensearch/security/auditlog/config/AuditConfigFilterTest.java +++ b/src/test/java/org/opensearch/security/auditlog/config/AuditConfigFilterTest.java @@ -65,19 +65,25 @@ public void testDefault() { public void testConfig() { // arrange final Settings settings = Settings.builder() - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_LOG_REQUEST_BODY, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_INDICES, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_EXCLUDE_SENSITIVE_HEADERS, false) - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_REQUESTS, "test-request") - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "test-user") - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, - BAD_HEADERS.toString(), SSL_EXCEPTION.toString()) - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, - FAILED_LOGIN.toString(), MISSING_PRIVILEGES.toString()) - .build(); + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_LOG_REQUEST_BODY, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_INDICES, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_EXCLUDE_SENSITIVE_HEADERS, false) + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_REQUESTS, "test-request") + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "test-user") + .putList( + ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, + BAD_HEADERS.toString(), + SSL_EXCEPTION.toString() + ) + .putList( + ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, + FAILED_LOGIN.toString(), + MISSING_PRIVILEGES.toString() + ) + .build(); // act final AuditConfig.Filter auditConfigFilter = AuditConfig.Filter.from(settings); // assert @@ -97,12 +103,10 @@ public void testConfig() { public void testNone() { // arrange final Settings settings = Settings.builder() - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "NONE") - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, - "None") - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, - "none") - .build(); + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "NONE") + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "None") + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "none") + .build(); // act final AuditConfig.Filter auditConfigFilter = AuditConfig.Filter.from(settings); // assert @@ -115,13 +119,11 @@ public void testNone() { public void testEmpty() { // arrange final Settings settings = Settings.builder() - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, Collections.emptyList()) - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_REQUESTS, Collections.emptyList()) - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, - Collections.emptyList()) - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, - Collections.emptyList()) - .build(); + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, Collections.emptyList()) + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_REQUESTS, Collections.emptyList()) + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, Collections.emptyList()) + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, Collections.emptyList()) + .build(); // act final AuditConfig.Filter auditConfigFilter = AuditConfig.Filter.from(settings); // assert @@ -130,7 +132,6 @@ public void testEmpty() { assertTrue(auditConfigFilter.getDisabledTransportCategories().isEmpty()); } - @Test public void testFilterEntries() { assertThat(FilterEntries.ENABLE_REST.getKey(), equalTo("enable_rest")); @@ -147,16 +148,14 @@ public void fromSettingBoolean() { .put(entry.getKeyWithNamespace(), false) .put(entry.getLegacyKeyWithNamespace(), true) .build(); - assertThat(AuditConfig.Filter.fromSettingBoolean(settings1, entry, true), equalTo(false)); + assertThat(AuditConfig.Filter.fromSettingBoolean(settings1, entry, true), equalTo(false)); // Use fallback key - final Settings settings2 = Settings.builder() - .put(entry.getLegacyKeyWithNamespace(), false) - .build(); - assertThat(AuditConfig.Filter.fromSettingBoolean(settings2, entry, true), equalTo(false)); + final Settings settings2 = Settings.builder().put(entry.getLegacyKeyWithNamespace(), false).build(); + assertThat(AuditConfig.Filter.fromSettingBoolean(settings2, entry, true), equalTo(false)); // Use default - assertThat(AuditConfig.Filter.fromSettingBoolean(Settings.builder().build(), entry, true), equalTo(true)); + assertThat(AuditConfig.Filter.fromSettingBoolean(Settings.builder().build(), entry, true), equalTo(true)); } @Test @@ -165,67 +164,65 @@ public void fromSettingStringSet() { // Use primary key final Settings settings1 = Settings.builder() - .putList(entry.getKeyWithNamespace(), "abc") - .putList(entry.getLegacyKeyWithNamespace(), "def") - .build(); + .putList(entry.getKeyWithNamespace(), "abc") + .putList(entry.getLegacyKeyWithNamespace(), "def") + .build(); assertThat(AuditConfig.Filter.fromSettingStringSet(settings1, entry, List.of("xyz")), equalTo(ImmutableSet.of("abc"))); // Use fallback key - final Settings settings2 = Settings.builder() - .putList(entry.getLegacyKeyWithNamespace(), "def") - .build(); + final Settings settings2 = Settings.builder().putList(entry.getLegacyKeyWithNamespace(), "def").build(); assertThat(AuditConfig.Filter.fromSettingStringSet(settings2, entry, List.of("xyz")), equalTo(ImmutableSet.of("def"))); // Use default - assertThat(AuditConfig.Filter.fromSettingStringSet(Settings.builder().build(), entry, List.of("xyz")), equalTo(ImmutableSet.of("xyz"))); + assertThat( + AuditConfig.Filter.fromSettingStringSet(Settings.builder().build(), entry, List.of("xyz")), + equalTo(ImmutableSet.of("xyz")) + ); } @Test public void fromSettingParseAuditCategory() { final FilterEntries entry = FilterEntries.DISABLE_REST_CATEGORIES; - final Function> parse = (settings) -> - AuditCategory.parse(AuditConfig.Filter.fromSettingStringSet(settings, entry, ConfigConstants.OPENDISTRO_SECURITY_AUDIT_DISABLED_CATEGORIES_DEFAULT)); + final Function> parse = (settings) -> AuditCategory.parse( + AuditConfig.Filter.fromSettingStringSet(settings, entry, ConfigConstants.OPENDISTRO_SECURITY_AUDIT_DISABLED_CATEGORIES_DEFAULT) + ); final Settings noValues = Settings.builder().build(); assertThat(parse.apply(noValues), equalTo(ImmutableSet.of(AUTHENTICATED, GRANTED_PRIVILEGES))); - final Settings legacySettingNone = Settings.builder() - .put(entry.getLegacyKeyWithNamespace(), "NONE") - .build(); + final Settings legacySettingNone = Settings.builder().put(entry.getLegacyKeyWithNamespace(), "NONE").build(); assertThat(parse.apply(legacySettingNone), equalTo(ImmutableSet.of())); - final Settings legacySettingValue = Settings.builder() - .put(entry.getLegacyKeyWithNamespace(), AUTHENTICATED.name()) - .build(); + final Settings legacySettingValue = Settings.builder().put(entry.getLegacyKeyWithNamespace(), AUTHENTICATED.name()).build(); assertThat(parse.apply(legacySettingValue), equalTo(ImmutableSet.of(AUTHENTICATED))); final Settings legacySettingMultipleValues = Settings.builder() - .putList(entry.getLegacyKeyWithNamespace(), AUTHENTICATED.name(), BAD_HEADERS.name()) - .build(); + .putList(entry.getLegacyKeyWithNamespace(), AUTHENTICATED.name(), BAD_HEADERS.name()) + .build(); assertThat(parse.apply(legacySettingMultipleValues), equalTo(ImmutableSet.of(AUTHENTICATED, BAD_HEADERS))); final Settings settingNone = Settings.builder() - .put(entry.getKeyWithNamespace(), "NONE") - .put(entry.getLegacyKeyWithNamespace(), FAILED_LOGIN.name()) - .build(); + .put(entry.getKeyWithNamespace(), "NONE") + .put(entry.getLegacyKeyWithNamespace(), FAILED_LOGIN.name()) + .build(); assertThat(parse.apply(settingNone), equalTo(ImmutableSet.of())); final Settings settingValue = Settings.builder() - .put(entry.getKeyWithNamespace(), AUTHENTICATED.name()) - .put(entry.getLegacyKeyWithNamespace(), FAILED_LOGIN.name()) - .build(); + .put(entry.getKeyWithNamespace(), AUTHENTICATED.name()) + .put(entry.getLegacyKeyWithNamespace(), FAILED_LOGIN.name()) + .build(); assertThat(parse.apply(settingValue), equalTo(ImmutableSet.of(AUTHENTICATED))); final Settings settingMultipleValues = Settings.builder() - .putList(entry.getKeyWithNamespace(), AUTHENTICATED.name(), BAD_HEADERS.name()) - .put(entry.getLegacyKeyWithNamespace(), FAILED_LOGIN.name()) - .build(); + .putList(entry.getKeyWithNamespace(), AUTHENTICATED.name(), BAD_HEADERS.name()) + .put(entry.getLegacyKeyWithNamespace(), FAILED_LOGIN.name()) + .build(); assertThat(parse.apply(settingMultipleValues), equalTo(ImmutableSet.of(AUTHENTICATED, BAD_HEADERS))); final Settings settingMultipleValuesString = Settings.builder() - .put(entry.getKeyWithNamespace(), AUTHENTICATED.name() + "," + BAD_HEADERS.name()) - .put(entry.getLegacyKeyWithNamespace(), FAILED_LOGIN.name()) - .build(); + .put(entry.getKeyWithNamespace(), AUTHENTICATED.name() + "," + BAD_HEADERS.name()) + .put(entry.getLegacyKeyWithNamespace(), FAILED_LOGIN.name()) + .build(); assertThat(parse.apply(settingMultipleValues), equalTo(ImmutableSet.of(AUTHENTICATED, BAD_HEADERS))); } } diff --git a/src/test/java/org/opensearch/security/auditlog/config/AuditConfigSerializeTest.java b/src/test/java/org/opensearch/security/auditlog/config/AuditConfigSerializeTest.java index d7ba321ea9..8cc19fa0f5 100644 --- a/src/test/java/org/opensearch/security/auditlog/config/AuditConfigSerializeTest.java +++ b/src/test/java/org/opensearch/security/auditlog/config/AuditConfigSerializeTest.java @@ -60,33 +60,33 @@ public void testDefaultSerialize() throws IOException { final String json = objectMapper.writeValueAsString(audit); final XContentBuilder jsonBuilder = XContentFactory.jsonBuilder() - .startObject() - .field("enabled", true) - .startObject("audit") - .field("enable_rest", true) - .field("disabled_rest_categories", ImmutableList.of( "AUTHENTICATED", "GRANTED_PRIVILEGES")) - .field("enable_transport", true) - .field("disabled_transport_categories", ImmutableList.of( "AUTHENTICATED", "GRANTED_PRIVILEGES")) - .field("resolve_bulk_requests", false) - .field("log_request_body", true) - .field("resolve_indices", true) - .field("exclude_sensitive_headers", true) - .field("ignore_users", Collections.singletonList("kibanaserver")) - .field("ignore_requests", Collections.emptyList()) - .endObject() - .startObject("compliance") - .field("enabled", true) - .field("external_config", false) - .field("internal_config", false) - .field("read_metadata_only", false) - .field("read_watched_fields", Collections.emptyMap()) - .field("read_ignore_users", Collections.singletonList("kibanaserver")) - .field("write_metadata_only", false) - .field("write_log_diffs", false) - .field("write_watched_indices", Collections.emptyList()) - .field("write_ignore_users", Collections.singletonList("kibanaserver")) - .endObject() - .endObject(); + .startObject() + .field("enabled", true) + .startObject("audit") + .field("enable_rest", true) + .field("disabled_rest_categories", ImmutableList.of("AUTHENTICATED", "GRANTED_PRIVILEGES")) + .field("enable_transport", true) + .field("disabled_transport_categories", ImmutableList.of("AUTHENTICATED", "GRANTED_PRIVILEGES")) + .field("resolve_bulk_requests", false) + .field("log_request_body", true) + .field("resolve_indices", true) + .field("exclude_sensitive_headers", true) + .field("ignore_users", Collections.singletonList("kibanaserver")) + .field("ignore_requests", Collections.emptyList()) + .endObject() + .startObject("compliance") + .field("enabled", true) + .field("external_config", false) + .field("internal_config", false) + .field("read_metadata_only", false) + .field("read_watched_fields", Collections.emptyMap()) + .field("read_ignore_users", Collections.singletonList("kibanaserver")) + .field("write_metadata_only", false) + .field("write_log_diffs", false) + .field("write_watched_indices", Collections.emptyList()) + .field("write_ignore_users", Collections.singletonList("kibanaserver")) + .endObject() + .endObject(); assertTrue(compareJson(Strings.toString(jsonBuilder), json)); } @@ -121,33 +121,33 @@ public void testDefaultDeserialize() throws IOException { public void testDeserialize() throws IOException { // arrange final XContentBuilder jsonBuilder = XContentFactory.jsonBuilder() - .startObject() - .field("enabled", true) - .startObject("audit") - .field("enable_rest", true) - .field("disabled_rest_categories", Collections.singletonList("AUTHENTICATED")) - .field("enable_transport", true) - .field("disabled_transport_categories", Collections.singletonList("SSL_EXCEPTION")) - .field("resolve_bulk_requests", true) - .field("log_request_body", true) - .field("resolve_indices", true) - .field("exclude_sensitive_headers", true) - .field("ignore_users", Collections.singletonList("test-user-1")) - .field("ignore_requests", Collections.singletonList("test-request")) - .endObject() - .startObject("compliance") - .field("enabled", true) - .field("external_config", true) - .field("internal_config", true) - .field("read_metadata_only", true) - .field("read_watched_fields", Collections.singletonMap("test-read-watch-field", Collections.singleton("test-field-1"))) - .field("read_ignore_users", Collections.singletonList("test-user-2")) - .field("write_metadata_only", true) - .field("write_log_diffs", false) - .field("write_watched_indices", Collections.singletonList("test-write-watch-index")) - .field("write_ignore_users", Collections.singletonList("test-user-3")) - .endObject() - .endObject(); + .startObject() + .field("enabled", true) + .startObject("audit") + .field("enable_rest", true) + .field("disabled_rest_categories", Collections.singletonList("AUTHENTICATED")) + .field("enable_transport", true) + .field("disabled_transport_categories", Collections.singletonList("SSL_EXCEPTION")) + .field("resolve_bulk_requests", true) + .field("log_request_body", true) + .field("resolve_indices", true) + .field("exclude_sensitive_headers", true) + .field("ignore_users", Collections.singletonList("test-user-1")) + .field("ignore_requests", Collections.singletonList("test-request")) + .endObject() + .startObject("compliance") + .field("enabled", true) + .field("external_config", true) + .field("internal_config", true) + .field("read_metadata_only", true) + .field("read_watched_fields", Collections.singletonMap("test-read-watch-field", Collections.singleton("test-field-1"))) + .field("read_ignore_users", Collections.singletonList("test-user-2")) + .field("write_metadata_only", true) + .field("write_log_diffs", false) + .field("write_watched_indices", Collections.singletonList("test-write-watch-index")) + .field("write_ignore_users", Collections.singletonList("test-user-3")) + .endObject() + .endObject(); final String json = Strings.toString(jsonBuilder); // act @@ -168,48 +168,80 @@ public void testDeserialize() throws IOException { assertEquals(WildcardMatcher.from(Collections.singleton("test-user-1")), audit.getIgnoredAuditUsersMatcher()); assertEquals(WildcardMatcher.from(Collections.singleton("test-request")), audit.getIgnoredAuditRequestsMatcher()); assertTrue(configCompliance.shouldLogReadMetadataOnly()); - assertEquals(WildcardMatcher.from(Collections.singleton("test-user-2")), configCompliance.getIgnoredComplianceUsersForReadMatcher()); - assertEquals(Collections.singletonMap(WildcardMatcher.from("test-read-watch-field"), Collections.singleton("test-field-1")), configCompliance.getReadEnabledFields()); + assertEquals( + WildcardMatcher.from(Collections.singleton("test-user-2")), + configCompliance.getIgnoredComplianceUsersForReadMatcher() + ); + assertEquals( + Collections.singletonMap(WildcardMatcher.from("test-read-watch-field"), Collections.singleton("test-field-1")), + configCompliance.getReadEnabledFields() + ); assertTrue(configCompliance.shouldLogWriteMetadataOnly()); assertFalse(configCompliance.shouldLogDiffsForWrite()); - assertEquals(WildcardMatcher.from(Collections.singleton("test-user-3")), configCompliance.getIgnoredComplianceUsersForWriteMatcher()); + assertEquals( + WildcardMatcher.from(Collections.singleton("test-user-3")), + configCompliance.getIgnoredComplianceUsersForWriteMatcher() + ); assertEquals(WildcardMatcher.from("test-write-watch-index"), configCompliance.getWatchedWriteIndicesMatcher()); } @Test public void testSerialize() throws IOException { // arrange - final AuditConfig.Filter audit = new AuditConfig.Filter(true, true, true, true, true, true, ImmutableSet.of("ignore-user-1", "ignore-user-2"), ImmutableSet.of("ignore-request-1"), EnumSet.of(AuditCategory.FAILED_LOGIN, AuditCategory.GRANTED_PRIVILEGES), EnumSet.of(AUTHENTICATED)); - final ComplianceConfig compliance = new ComplianceConfig(true, true, true, true, Collections.singletonMap("test-read-watch-field-1", Collections.emptyList()), Collections.singleton("test-user-1"), true, false,Collections.singletonList("test-write-watch-index"), Collections.singleton("test-user-2"), Settings.EMPTY); + final AuditConfig.Filter audit = new AuditConfig.Filter( + true, + true, + true, + true, + true, + true, + ImmutableSet.of("ignore-user-1", "ignore-user-2"), + ImmutableSet.of("ignore-request-1"), + EnumSet.of(AuditCategory.FAILED_LOGIN, AuditCategory.GRANTED_PRIVILEGES), + EnumSet.of(AUTHENTICATED) + ); + final ComplianceConfig compliance = new ComplianceConfig( + true, + true, + true, + true, + Collections.singletonMap("test-read-watch-field-1", Collections.emptyList()), + Collections.singleton("test-user-1"), + true, + false, + Collections.singletonList("test-write-watch-index"), + Collections.singleton("test-user-2"), + Settings.EMPTY + ); final AuditConfig auditConfig = new AuditConfig(true, audit, compliance); final XContentBuilder jsonBuilder = XContentFactory.jsonBuilder() - .startObject() - .field("enabled", true) - .startObject("audit") - .field("enable_rest", true) - .field("disabled_rest_categories", ImmutableList.of("FAILED_LOGIN", "GRANTED_PRIVILEGES")) - .field("enable_transport", true) - .field("disabled_transport_categories", Collections.singletonList("AUTHENTICATED")) - .field("resolve_bulk_requests", true) - .field("log_request_body", true) - .field("resolve_indices", true) - .field("exclude_sensitive_headers", true) - .field("ignore_users", ImmutableList.of("ignore-user-1", "ignore-user-2")) - .field("ignore_requests", Collections.singletonList("ignore-request-1")) - .endObject() - .startObject("compliance") - .field("enabled", true) - .field("external_config", true) - .field("internal_config", true) - .field("read_metadata_only", true) - .field("read_watched_fields", Collections.singletonMap("test-read-watch-field-1", Collections.emptyList())) - .field("read_ignore_users", Collections.singletonList("test-user-1")) - .field("write_metadata_only", true) - .field("write_log_diffs", false) - .field("write_watched_indices", Collections.singletonList("test-write-watch-index")) - .field("write_ignore_users", Collections.singletonList("test-user-2")) - .endObject() - .endObject(); + .startObject() + .field("enabled", true) + .startObject("audit") + .field("enable_rest", true) + .field("disabled_rest_categories", ImmutableList.of("FAILED_LOGIN", "GRANTED_PRIVILEGES")) + .field("enable_transport", true) + .field("disabled_transport_categories", Collections.singletonList("AUTHENTICATED")) + .field("resolve_bulk_requests", true) + .field("log_request_body", true) + .field("resolve_indices", true) + .field("exclude_sensitive_headers", true) + .field("ignore_users", ImmutableList.of("ignore-user-1", "ignore-user-2")) + .field("ignore_requests", Collections.singletonList("ignore-request-1")) + .endObject() + .startObject("compliance") + .field("enabled", true) + .field("external_config", true) + .field("internal_config", true) + .field("read_metadata_only", true) + .field("read_watched_fields", Collections.singletonMap("test-read-watch-field-1", Collections.emptyList())) + .field("read_ignore_users", Collections.singletonList("test-user-1")) + .field("write_metadata_only", true) + .field("write_log_diffs", false) + .field("write_watched_indices", Collections.singletonList("test-write-watch-index")) + .field("write_ignore_users", Collections.singletonList("test-user-2")) + .endObject() + .endObject(); // act final String json = objectMapper.writeValueAsString(auditConfig); @@ -225,33 +257,33 @@ public void testNullSerialize() throws IOException { final ComplianceConfig compliance = ComplianceConfig.from(Collections.emptyMap(), Settings.EMPTY); final AuditConfig auditConfig = new AuditConfig(true, audit, compliance); final XContentBuilder jsonBuilder = XContentFactory.jsonBuilder() - .startObject() - .field("enabled", true) - .startObject("audit") - .field("enable_rest", true) - .field("disabled_rest_categories", ImmutableList.of("AUTHENTICATED", "GRANTED_PRIVILEGES")) - .field("enable_transport", true) - .field("disabled_transport_categories", ImmutableList.of("AUTHENTICATED", "GRANTED_PRIVILEGES")) - .field("resolve_bulk_requests", false) - .field("log_request_body", true) - .field("resolve_indices", true) - .field("exclude_sensitive_headers", true) - .field("ignore_users", ImmutableList.of("kibanaserver")) - .field("ignore_requests", Collections.emptyList()) - .endObject() - .startObject("compliance") - .field("enabled", true) - .field("external_config", false) - .field("internal_config", false) - .field("read_metadata_only", false) - .field("read_watched_fields", Collections.emptyMap()) - .field("read_ignore_users", Collections.singletonList("kibanaserver")) - .field("write_metadata_only", false) - .field("write_log_diffs", false) - .field("write_watched_indices", Collections.emptyList()) - .field("write_ignore_users", Collections.singletonList("kibanaserver")) - .endObject() - .endObject(); + .startObject() + .field("enabled", true) + .startObject("audit") + .field("enable_rest", true) + .field("disabled_rest_categories", ImmutableList.of("AUTHENTICATED", "GRANTED_PRIVILEGES")) + .field("enable_transport", true) + .field("disabled_transport_categories", ImmutableList.of("AUTHENTICATED", "GRANTED_PRIVILEGES")) + .field("resolve_bulk_requests", false) + .field("log_request_body", true) + .field("resolve_indices", true) + .field("exclude_sensitive_headers", true) + .field("ignore_users", ImmutableList.of("kibanaserver")) + .field("ignore_requests", Collections.emptyList()) + .endObject() + .startObject("compliance") + .field("enabled", true) + .field("external_config", false) + .field("internal_config", false) + .field("read_metadata_only", false) + .field("read_watched_fields", Collections.emptyMap()) + .field("read_ignore_users", Collections.singletonList("kibanaserver")) + .field("write_metadata_only", false) + .field("write_log_diffs", false) + .field("write_watched_indices", Collections.emptyList()) + .field("write_ignore_users", Collections.singletonList("kibanaserver")) + .endObject() + .endObject(); // act final String json = objectMapper.writeValueAsString(auditConfig); @@ -262,10 +294,7 @@ public void testNullSerialize() throws IOException { @Test public void testNullDeSerialize() throws IOException { // arrange - final String json = "{" + - "\"audit\":{}," + - "\"compliance\":{}" + - "}"; + final String json = "{" + "\"audit\":{}," + "\"compliance\":{}" + "}"; // act final AuditConfig auditConfig = objectMapper.readValue(json, AuditConfig.class); @@ -287,36 +316,38 @@ public void testNullDeSerialize() throws IOException { public void testCustomSettings() throws IOException { // arrange final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_CONFIG_INDEX_NAME, "test-security-index") - .put(ConfigConstants.SECURITY_AUDIT_TYPE_DEFAULT, "internal_opensearch") - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_OPENSEARCH_INDEX, - "test-auditlog-index") - .build(); + .put(ConfigConstants.SECURITY_CONFIG_INDEX_NAME, "test-security-index") + .put(ConfigConstants.SECURITY_AUDIT_TYPE_DEFAULT, "internal_opensearch") + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_OPENSEARCH_INDEX, + "test-auditlog-index" + ) + .build(); final ObjectMapper customObjectMapper = new ObjectMapper(); InjectableValues.Std iv = new InjectableValues.Std(); iv.addValue(Settings.class, settings); customObjectMapper.setInjectableValues(iv); final XContentBuilder jsonBuilder = XContentFactory.jsonBuilder() - .startObject() - .field("enabled", true) - .startObject("audit") - .field("enable_rest", true) - .field("enable_transport", true) - .field("resolve_bulk_requests", true) - .field("log_request_body", true) - .field("resolve_indices", true) - .field("exclude_sensitive_headers", true) - .endObject() - .startObject("compliance") - .field("enabled", true) - .field("external_config", true) - .field("internal_config", true) - .field("read_metadata_only", true) - .field("write_metadata_only", true) - .field("write_log_diffs", false) - .endObject() - .endObject(); + .startObject() + .field("enabled", true) + .startObject("audit") + .field("enable_rest", true) + .field("enable_transport", true) + .field("resolve_bulk_requests", true) + .field("log_request_body", true) + .field("resolve_indices", true) + .field("exclude_sensitive_headers", true) + .endObject() + .startObject("compliance") + .field("enabled", true) + .field("external_config", true) + .field("internal_config", true) + .field("read_metadata_only", true) + .field("write_metadata_only", true) + .field("write_log_diffs", false) + .endObject() + .endObject(); final String json = Strings.toString(jsonBuilder); // act diff --git a/src/test/java/org/opensearch/security/auditlog/config/ThreadPoolConfigTest.java b/src/test/java/org/opensearch/security/auditlog/config/ThreadPoolConfigTest.java index 914163a7f3..83c5e9ae2a 100644 --- a/src/test/java/org/opensearch/security/auditlog/config/ThreadPoolConfigTest.java +++ b/src/test/java/org/opensearch/security/auditlog/config/ThreadPoolConfigTest.java @@ -74,9 +74,9 @@ public void testConfig() { public void testGenerationFromSettings() { // arrange Settings settings = Settings.builder() - .put("plugins.security.audit.threadpool.size", "8") - .put("plugins.security.audit.threadpool.max_queue_len", "50") - .build(); + .put("plugins.security.audit.threadpool.size", "8") + .put("plugins.security.audit.threadpool.max_queue_len", "50") + .build(); // assert ThreadPoolConfig config = ThreadPoolConfig.getConfig(settings); diff --git a/src/test/java/org/opensearch/security/auditlog/helper/ErroneousHttpHandler.java b/src/test/java/org/opensearch/security/auditlog/helper/ErroneousHttpHandler.java index 120232825b..4ba106ddd9 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/ErroneousHttpHandler.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/ErroneousHttpHandler.java @@ -17,8 +17,8 @@ import org.apache.hc.core5.http.protocol.HttpContext; public class ErroneousHttpHandler implements HttpRequestHandler { - @Override - public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) { - response.setCode(404); - } + @Override + public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) { + response.setCode(404); + } } diff --git a/src/test/java/org/opensearch/security/auditlog/helper/FailingSink.java b/src/test/java/org/opensearch/security/auditlog/helper/FailingSink.java index 8557314ab1..0c915810e1 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/FailingSink.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/FailingSink.java @@ -21,10 +21,10 @@ public FailingSink(String name, Settings settings, String sinkPrefix, AuditLogSi super(name, settings, null, fallbackSink); } - @Override - protected boolean doStore(AuditMessage msg) { - return false; - } + @Override + protected boolean doStore(AuditMessage msg) { + return false; + } @Override public boolean isHandlingBackpressure() { diff --git a/src/test/java/org/opensearch/security/auditlog/helper/LoggingSink.java b/src/test/java/org/opensearch/security/auditlog/helper/LoggingSink.java index 63b4e71958..8125acd8c4 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/LoggingSink.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/LoggingSink.java @@ -20,16 +20,15 @@ public class LoggingSink extends AuditLogSink { - public List messages = new ArrayList(100); + public List messages = new ArrayList(100); public StringBuffer sb = new StringBuffer(); public LoggingSink(String name, Settings settings, String settingsPrefix, AuditLogSink fallbackSink) { super(name, settings, null, fallbackSink); } - public boolean doStore(AuditMessage msg) { - sb.append(msg.toPrettyString()+System.lineSeparator()); + sb.append(msg.toPrettyString() + System.lineSeparator()); messages.add(msg); return true; } diff --git a/src/test/java/org/opensearch/security/auditlog/helper/MockAuditMessageFactory.java b/src/test/java/org/opensearch/security/auditlog/helper/MockAuditMessageFactory.java index c0c24107ef..7e67fc374c 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/MockAuditMessageFactory.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/MockAuditMessageFactory.java @@ -26,14 +26,14 @@ public class MockAuditMessageFactory { - public static AuditMessage validAuditMessage() { - return validAuditMessage(AuditCategory.FAILED_LOGIN); - } + public static AuditMessage validAuditMessage() { + return validAuditMessage(AuditCategory.FAILED_LOGIN); + } - public static AuditMessage validAuditMessage(AuditCategory category) { + public static AuditMessage validAuditMessage(AuditCategory category) { - ClusterService cs = mock(ClusterService.class); - DiscoveryNode dn = mock(DiscoveryNode.class); + ClusterService cs = mock(ClusterService.class); + DiscoveryNode dn = mock(DiscoveryNode.class); when(dn.getHostAddress()).thenReturn("hostaddress"); when(dn.getId()).thenReturn("hostaddress"); @@ -41,13 +41,13 @@ public static AuditMessage validAuditMessage(AuditCategory category) { when(cs.localNode()).thenReturn(dn); when(cs.getClusterName()).thenReturn(new ClusterName("testcluster")); - TransportAddress ta = new TransportAddress(new InetSocketAddress("8.8.8.8",80)); + TransportAddress ta = new TransportAddress(new InetSocketAddress("8.8.8.8", 80)); - AuditMessage msg = new AuditMessage(category, cs, Origin.TRANSPORT, Origin.TRANSPORT); - msg.addEffectiveUser("John Doe"); - msg.addRemoteAddress(ta); - msg.addRequestType("IndexRequest"); - return msg; - } + AuditMessage msg = new AuditMessage(category, cs, Origin.TRANSPORT, Origin.TRANSPORT); + msg.addEffectiveUser("John Doe"); + msg.addRemoteAddress(ta); + msg.addRequestType("IndexRequest"); + return msg; + } } diff --git a/src/test/java/org/opensearch/security/auditlog/helper/MockRestRequest.java b/src/test/java/org/opensearch/security/auditlog/helper/MockRestRequest.java index 6328c94352..d2b15750ff 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/MockRestRequest.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/MockRestRequest.java @@ -20,8 +20,8 @@ public class MockRestRequest extends RestRequest { public MockRestRequest() { - //NamedXContentRegistry xContentRegistry, Map params, String path, - //Map> headers, HttpRequest httpRequest, HttpChannel httpChannel + // NamedXContentRegistry xContentRegistry, Map params, String path, + // Map> headers, HttpRequest httpRequest, HttpChannel httpChannel super(NamedXContentRegistry.EMPTY, Collections.emptyMap(), "", Collections.emptyMap(), null, null); } diff --git a/src/test/java/org/opensearch/security/auditlog/helper/MyOwnAuditLog.java b/src/test/java/org/opensearch/security/auditlog/helper/MyOwnAuditLog.java index d1138c7c9b..8df27f0d1d 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/MyOwnAuditLog.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/MyOwnAuditLog.java @@ -23,19 +23,26 @@ public class MyOwnAuditLog extends AuditLogSink { - public MyOwnAuditLog(final String name, final Settings settings, final String settingsPrefix, final Path configPath, final ThreadPool threadPool, - final IndexNameExpressionResolver resolver, final ClusterService clusterService, AuditLogSink fallbackSink) { + public MyOwnAuditLog( + final String name, + final Settings settings, + final String settingsPrefix, + final Path configPath, + final ThreadPool threadPool, + final IndexNameExpressionResolver resolver, + final ClusterService clusterService, + AuditLogSink fallbackSink + ) { super(name, settings, settingsPrefix, fallbackSink); } @Override - public void close() throws IOException { - - } + public void close() throws IOException { + } - public boolean doStore(AuditMessage msg) { - return true; - } + public boolean doStore(AuditMessage msg) { + return true; + } } diff --git a/src/test/java/org/opensearch/security/auditlog/helper/RetrySink.java b/src/test/java/org/opensearch/security/auditlog/helper/RetrySink.java index f26188bed7..0d41111f25 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/RetrySink.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/RetrySink.java @@ -28,8 +28,8 @@ public RetrySink(String name, Settings settings, String sinkPrefix, AuditLogSink @Override protected synchronized boolean doStore(AuditMessage msg) { - if(failCount++ < 5) { - log.debug("Fail "+failCount); + if (failCount++ < 5) { + log.debug("Fail " + failCount); return false; } log.debug("doStore ok"); diff --git a/src/test/java/org/opensearch/security/auditlog/helper/SlowSink.java b/src/test/java/org/opensearch/security/auditlog/helper/SlowSink.java index f291b76cda..376c29cf80 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/SlowSink.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/SlowSink.java @@ -21,13 +21,12 @@ public SlowSink(String name, Settings settings, Settings sinkSetting, AuditLogSi super(name, settings, null, fallbackSink); } - public boolean doStore(AuditMessage msg) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } return true; } diff --git a/src/test/java/org/opensearch/security/auditlog/helper/TestHttpHandler.java b/src/test/java/org/opensearch/security/auditlog/helper/TestHttpHandler.java index d888949e46..d4f68e8291 100644 --- a/src/test/java/org/opensearch/security/auditlog/helper/TestHttpHandler.java +++ b/src/test/java/org/opensearch/security/auditlog/helper/TestHttpHandler.java @@ -23,22 +23,22 @@ import org.apache.hc.core5.http.protocol.HttpContext; public class TestHttpHandler implements HttpRequestHandler { - public String method; - public String uri; - public String body; + public String method; + public String uri; + public String body; - @Override - public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, IOException { - this.method = request.getMethod(); - this.uri = request.getRequestUri(); + @Override + public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context) throws HttpException, IOException { + this.method = request.getMethod(); + this.uri = request.getRequestUri(); - HttpEntity entity = request.getEntity(); - body = EntityUtils.toString(entity, StandardCharsets.UTF_8); - } + HttpEntity entity = request.getEntity(); + body = EntityUtils.toString(entity, StandardCharsets.UTF_8); + } - public void reset() { - this.body = null; - this.uri = null; - this.method = null; - } + public void reset() { + this.body = null; + this.uri = null; + this.method = null; + } } diff --git a/src/test/java/org/opensearch/security/auditlog/impl/AuditCategoryTest.java b/src/test/java/org/opensearch/security/auditlog/impl/AuditCategoryTest.java index abd8260fa7..18670f42cf 100644 --- a/src/test/java/org/opensearch/security/auditlog/impl/AuditCategoryTest.java +++ b/src/test/java/org/opensearch/security/auditlog/impl/AuditCategoryTest.java @@ -42,19 +42,32 @@ public AuditCategoryParseTest(List input, EnumSet expecte @Parameterized.Parameters public static Collection data() { - return Arrays.asList(new Object[][]{ - {Arrays.asList(), EnumSet.noneOf(AuditCategory.class)}, - {Arrays.asList("BAD_HEADERS"), EnumSet.of(BAD_HEADERS)}, - {Arrays.asList("bad_headers"), EnumSet.of(BAD_HEADERS)}, - {Arrays.asList("bAd_HeAdErS"), EnumSet.of(BAD_HEADERS)}, - {Arrays.asList("bAd_HeAdErS"), EnumSet.of(BAD_HEADERS)}, - {Arrays.asList("BAD_HEADERS", "AUTHENTICATED"), EnumSet.of(BAD_HEADERS, AUTHENTICATED)}, - {Arrays.asList("BAD_HEADERS", "FAILED_LOGIN", "MISSING_PRIVILEGES", "GRANTED_PRIVILEGES", - "OPENDISTRO_SECURITY_INDEX_ATTEMPT", "SSL_EXCEPTION", "AUTHENTICATED", "INDEX_EVENT", - "COMPLIANCE_DOC_READ", "COMPLIANCE_DOC_WRITE", "COMPLIANCE_EXTERNAL_CONFIG", - "COMPLIANCE_INTERNAL_CONFIG_READ", "COMPLIANCE_INTERNAL_CONFIG_WRITE" - ), EnumSet.allOf(AuditCategory.class)}, - }); + return Arrays.asList( + new Object[][] { + { Arrays.asList(), EnumSet.noneOf(AuditCategory.class) }, + { Arrays.asList("BAD_HEADERS"), EnumSet.of(BAD_HEADERS) }, + { Arrays.asList("bad_headers"), EnumSet.of(BAD_HEADERS) }, + { Arrays.asList("bAd_HeAdErS"), EnumSet.of(BAD_HEADERS) }, + { Arrays.asList("bAd_HeAdErS"), EnumSet.of(BAD_HEADERS) }, + { Arrays.asList("BAD_HEADERS", "AUTHENTICATED"), EnumSet.of(BAD_HEADERS, AUTHENTICATED) }, + { + Arrays.asList( + "BAD_HEADERS", + "FAILED_LOGIN", + "MISSING_PRIVILEGES", + "GRANTED_PRIVILEGES", + "OPENDISTRO_SECURITY_INDEX_ATTEMPT", + "SSL_EXCEPTION", + "AUTHENTICATED", + "INDEX_EVENT", + "COMPLIANCE_DOC_READ", + "COMPLIANCE_DOC_WRITE", + "COMPLIANCE_EXTERNAL_CONFIG", + "COMPLIANCE_INTERNAL_CONFIG_READ", + "COMPLIANCE_INTERNAL_CONFIG_WRITE" + ), + EnumSet.allOf(AuditCategory.class) }, } + ); } @Test @@ -75,10 +88,9 @@ public AuditCategoryExceptionTest(List input) { @Parameterized.Parameters public static Collection data() { - return Arrays.asList(new Object[][]{ - {Arrays.asList("BAD_INPUT")}, - {Arrays.asList("BAD_HEADERS", "bad_category", "AUTHENTICATED")}, - }); + return Arrays.asList( + new Object[][] { { Arrays.asList("BAD_INPUT") }, { Arrays.asList("BAD_HEADERS", "bad_category", "AUTHENTICATED") }, } + ); } @Test(expected = IllegalArgumentException.class) diff --git a/src/test/java/org/opensearch/security/auditlog/impl/AuditMessageTest.java b/src/test/java/org/opensearch/security/auditlog/impl/AuditMessageTest.java index da408f1000..6bfaf32816 100644 --- a/src/test/java/org/opensearch/security/auditlog/impl/AuditMessageTest.java +++ b/src/test/java/org/opensearch/security/auditlog/impl/AuditMessageTest.java @@ -38,17 +38,25 @@ public class AuditMessageTest { private static final Map> TEST_REST_HEADERS = ImmutableMap.of( - "authorization", ImmutableList.of("test-1"), - "Authorization", ImmutableList.of("test-2"), - "AuThOrIzAtIoN", ImmutableList.of("test-3"), - "test-header", ImmutableList.of("test-4") + "authorization", + ImmutableList.of("test-1"), + "Authorization", + ImmutableList.of("test-2"), + "AuThOrIzAtIoN", + ImmutableList.of("test-3"), + "test-header", + ImmutableList.of("test-4") ); private static final Map TEST_TRANSPORT_HEADERS = ImmutableMap.of( - "authorization", "test-1", - "Authorization", "test-2", - "AuThOrIzAtIoN","test-3", - "test-header", "test-4" + "authorization", + "test-1", + "Authorization", + "test-2", + "AuThOrIzAtIoN", + "test-3", + "test-header", + "test-4" ); private AuditMessage message; @@ -58,10 +66,7 @@ public void setUp() { final ClusterService clusterServiceMock = mock(ClusterService.class); when(clusterServiceMock.localNode()).thenReturn(mock(DiscoveryNode.class)); when(clusterServiceMock.getClusterName()).thenReturn(mock(ClusterName.class)); - message = new AuditMessage(AuditCategory.AUTHENTICATED, - clusterServiceMock, - AuditLog.Origin.REST, - AuditLog.Origin.REST); + message = new AuditMessage(AuditCategory.AUTHENTICATED, clusterServiceMock, AuditLog.Origin.REST, AuditLog.Origin.REST); } @Test @@ -131,7 +136,7 @@ public void testBCryptHashIsRedacted() { assertEquals("Diff is __HASH__", message.getAsMap().get(AuditMessage.COMPLIANCE_DIFF_CONTENT)); // test tuple redaction - final ByteBuffer[] byteBuffers = new ByteBuffer[]{ ByteBuffer.wrap(("Hash in tuple is " + hash1).getBytes()) }; + final ByteBuffer[] byteBuffers = new ByteBuffer[] { ByteBuffer.wrap(("Hash in tuple is " + hash1).getBytes()) }; BytesReference ref = BytesReference.fromByteBuffers(byteBuffers); message.addSecurityConfigTupleToRequestBody(new Tuple<>(XContentType.JSON, ref), internalUsersDocId); assertEquals("Hash in tuple is __HASH__", message.getAsMap().get(AuditMessage.REQUEST_BODY)); diff --git a/src/test/java/org/opensearch/security/auditlog/impl/AuditlogTest.java b/src/test/java/org/opensearch/security/auditlog/impl/AuditlogTest.java index e72b85694f..cd4ced3523 100644 --- a/src/test/java/org/opensearch/security/auditlog/impl/AuditlogTest.java +++ b/src/test/java/org/opensearch/security/auditlog/impl/AuditlogTest.java @@ -49,9 +49,9 @@ public void setup() { @Test public void testClusterHealthRequest() { Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .build(); AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", new ClusterHealthRequest(), null); @@ -62,13 +62,13 @@ public void testClusterHealthRequest() { public void testSearchRequest() { SearchRequest sr = new SearchRequest(); - sr.indices("index1","logstash*"); + sr.indices("index1", "logstash*"); Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .build(); - AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .build(); + AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", sr, null); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); @@ -78,12 +78,12 @@ public void testSearchRequest() { public void testSslException() { Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .build(); - AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .build(); + AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); TestAuditlogImpl.clear(); al.logSSLException(null, new Exception("test rest")); al.logSSLException(null, new Exception("test rest"), null, null); @@ -97,14 +97,14 @@ public void testRetry() { RetrySink.init(); Settings settings = Settings.builder() - .put("plugins.security.audit.type", RetrySink.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.SECURITY_AUDIT_RETRY_COUNT, 10) - .put(ConfigConstants.SECURITY_AUDIT_RETRY_DELAY_MS, 500) - .build(); - AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + .put("plugins.security.audit.type", RetrySink.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.SECURITY_AUDIT_RETRY_COUNT, 10) + .put(ConfigConstants.SECURITY_AUDIT_RETRY_DELAY_MS, 500) + .build(); + AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); al.logSSLException(null, new Exception("test retry")); Assert.assertNotNull(RetrySink.getMsg()); Assert.assertTrue(RetrySink.getMsg().toJson().contains("test retry")); @@ -116,36 +116,32 @@ public void testNoRetry() { RetrySink.init(); Settings settings = Settings.builder() - .put("plugins.security.audit.type", RetrySink.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.SECURITY_AUDIT_RETRY_COUNT, 0) - .put(ConfigConstants.SECURITY_AUDIT_RETRY_DELAY_MS, 500) - .build(); - AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + .put("plugins.security.audit.type", RetrySink.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.SECURITY_AUDIT_RETRY_COUNT, 0) + .put(ConfigConstants.SECURITY_AUDIT_RETRY_DELAY_MS, 500) + .build(); + AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); al.logSSLException(null, new Exception("test retry")); Assert.assertNull(RetrySink.getMsg()); } @Test public void testRestFilterEnabledCheck() { - final Settings settings = Settings.builder() - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .build(); - final AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); - for (AuditCategory category: AuditCategory.values()) { + final Settings settings = Settings.builder().put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false).build(); + final AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + for (AuditCategory category : AuditCategory.values()) { Assert.assertFalse(al.checkRestFilter(category, "user", mock(RestRequest.class))); } } @Test public void testTransportFilterEnabledCheck() { - final Settings settings = Settings.builder() - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .build(); - final AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); - for (AuditCategory category: AuditCategory.values()) { + final Settings settings = Settings.builder().put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false).build(); + final AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + for (AuditCategory category : AuditCategory.values()) { Assert.assertFalse(al.checkTransportFilter(category, "action", "user", mock(TransportRequest.class))); } } @@ -153,11 +149,11 @@ public void testTransportFilterEnabledCheck() { @Test public void testTransportFilterMonitorActionsCheck() { final Settings settings = Settings.builder() - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .build(); - final AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); - for (AuditCategory category: AuditCategory.values()) { + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .build(); + final AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + for (AuditCategory category : AuditCategory.values()) { Assert.assertTrue(al.checkTransportFilter(category, "cluster:monitor/any", "user", mock(TransportRequest.class))); Assert.assertTrue(al.checkTransportFilter(category, "indices:data/any", "user", mock(TransportRequest.class))); Assert.assertFalse(al.checkTransportFilter(category, "internal:any", "user", mock(TransportRequest.class))); diff --git a/src/test/java/org/opensearch/security/auditlog/impl/DelegateTest.java b/src/test/java/org/opensearch/security/auditlog/impl/DelegateTest.java index a88c73e3bf..fa176a2011 100644 --- a/src/test/java/org/opensearch/security/auditlog/impl/DelegateTest.java +++ b/src/test/java/org/opensearch/security/auditlog/impl/DelegateTest.java @@ -22,28 +22,28 @@ import org.opensearch.security.auditlog.sink.InternalOpenSearchSink; public class DelegateTest { - @Test - public void auditLogTypeTest() throws Exception{ - testAuditType("DeBUg", DebugSink.class); - testAuditType("intERnal_OpenSearch", InternalOpenSearchSink.class); - testAuditType("EXTERnal_OpenSearch", ExternalOpenSearchSink.class); - testAuditType("org.opensearch.security.auditlog.sink.MyOwnAuditLog", MyOwnAuditLog.class); - testAuditType("org.opensearch.security.auditlog.sink.MyOwnAuditLog", null); - testAuditType("idonotexist", null); - } + @Test + public void auditLogTypeTest() throws Exception { + testAuditType("DeBUg", DebugSink.class); + testAuditType("intERnal_OpenSearch", InternalOpenSearchSink.class); + testAuditType("EXTERnal_OpenSearch", ExternalOpenSearchSink.class); + testAuditType("org.opensearch.security.auditlog.sink.MyOwnAuditLog", MyOwnAuditLog.class); + testAuditType("org.opensearch.security.auditlog.sink.MyOwnAuditLog", null); + testAuditType("idonotexist", null); + } - private void testAuditType(String type, Class expectedClass) throws Exception { - Builder settingsBuilder = Settings.builder(); - settingsBuilder.put("plugins.security.audit.type", type); - settingsBuilder.put("path.home", "."); - AuditLogImpl auditLog = new AuditLogImpl(settingsBuilder.build(), null, null, null, null, null); - auditLog.close(); -// if (expectedClass != null) { -// Assert.assertNotNull("delegate is null for type: "+type,auditLog.delegate); -// Assert.assertEquals(expectedClass, auditLog.delegate.getClass()); -// } else { -// Assert.assertNull(auditLog.delegate); -// } + private void testAuditType(String type, Class expectedClass) throws Exception { + Builder settingsBuilder = Settings.builder(); + settingsBuilder.put("plugins.security.audit.type", type); + settingsBuilder.put("path.home", "."); + AuditLogImpl auditLog = new AuditLogImpl(settingsBuilder.build(), null, null, null, null, null); + auditLog.close(); + // if (expectedClass != null) { + // Assert.assertNotNull("delegate is null for type: "+type,auditLog.delegate); + // Assert.assertEquals(expectedClass, auditLog.delegate.getClass()); + // } else { + // Assert.assertNull(auditLog.delegate); + // } - } + } } diff --git a/src/test/java/org/opensearch/security/auditlog/impl/DisabledCategoriesTest.java b/src/test/java/org/opensearch/security/auditlog/impl/DisabledCategoriesTest.java index db7d3da0fb..2a37749fbe 100644 --- a/src/test/java/org/opensearch/security/auditlog/impl/DisabledCategoriesTest.java +++ b/src/test/java/org/opensearch/security/auditlog/impl/DisabledCategoriesTest.java @@ -45,8 +45,8 @@ public class DisabledCategoriesTest { ClusterService cs = mock(ClusterService.class); DiscoveryNode dn = mock(DiscoveryNode.class); - @Rule - public ExpectedException thrown = ExpectedException.none(); + @Rule + public ExpectedException thrown = ExpectedException.none(); @Before public void setup() { @@ -58,195 +58,220 @@ public void setup() { TestAuditlogImpl.clear(); } - @Test - public void invalidRestCategoryConfigurationTest() { - thrown.expect(IllegalArgumentException.class); + @Test + public void invalidRestCategoryConfigurationTest() { + thrown.expect(IllegalArgumentException.class); - Builder settingsBuilder = Settings.builder(); - settingsBuilder.put("plugins.security.audit.type", TestAuditlogImpl.class.getName()); + Builder settingsBuilder = Settings.builder(); + settingsBuilder.put("plugins.security.audit.type", TestAuditlogImpl.class.getName()); settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "nonexistent"); - AuditTestUtils.createAuditLog(settingsBuilder.build(), null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); - } - - @Test - public void invalidTransportCategoryConfigurationTest() { - thrown.expect(IllegalArgumentException.class); - - Builder settingsBuilder = Settings.builder(); - settingsBuilder.put("plugins.security.audit.type", TestAuditlogImpl.class.getName()); - settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "nonexistent"); - AuditTestUtils.createAuditLog(settingsBuilder.build(), null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); - } - - @Test - public void invalidConfigurationTest() { - Builder settingsBuilder = Settings.builder(); - settingsBuilder.put("plugins.security.audit.type", "debug"); - settingsBuilder.put("plugins.security.audit.config.disabled_categories", "nonexistant, bad_headers"); - AbstractAuditLog auditLog = AuditTestUtils.createAuditLog(settingsBuilder.build(), null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); - logAll(auditLog); - String result = TestAuditlogImpl.sb.toString(); - Assert.assertFalse(categoriesPresentInLog(result, AuditCategory.BAD_HEADERS)); - } - - @Test - public void enableAllCategoryTest() throws Exception { - final Builder settingsBuilder = Settings.builder(); - - settingsBuilder.put("plugins.security.audit.type", TestAuditlogImpl.class.getName()); - settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE"); + AuditTestUtils.createAuditLog(settingsBuilder.build(), null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + } + + @Test + public void invalidTransportCategoryConfigurationTest() { + thrown.expect(IllegalArgumentException.class); + + Builder settingsBuilder = Settings.builder(); + settingsBuilder.put("plugins.security.audit.type", TestAuditlogImpl.class.getName()); + settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "nonexistent"); + AuditTestUtils.createAuditLog(settingsBuilder.build(), null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); + } + + @Test + public void invalidConfigurationTest() { + Builder settingsBuilder = Settings.builder(); + settingsBuilder.put("plugins.security.audit.type", "debug"); + settingsBuilder.put("plugins.security.audit.config.disabled_categories", "nonexistant, bad_headers"); + AbstractAuditLog auditLog = AuditTestUtils.createAuditLog( + settingsBuilder.build(), + null, + null, + AbstractSecurityUnitTest.MOCK_POOL, + null, + cs + ); + logAll(auditLog); + String result = TestAuditlogImpl.sb.toString(); + Assert.assertFalse(categoriesPresentInLog(result, AuditCategory.BAD_HEADERS)); + } + + @Test + public void enableAllCategoryTest() throws Exception { + final Builder settingsBuilder = Settings.builder(); + + settingsBuilder.put("plugins.security.audit.type", TestAuditlogImpl.class.getName()); + settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE"); settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE"); - // we use the debug output, no OpenSearch client is needed. Also, we - // do not need to close. - AbstractAuditLog auditLog = AuditTestUtils.createAuditLog(settingsBuilder.build(), null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); - logAll(auditLog); - - // we're using the ExecutorService in AuditLogImpl, so we need to wait - // until all tasks are finished before we can check the result - auditLog.close(); - - String result = TestAuditlogImpl.sb.toString(); - - Assert.assertTrue(AuditCategory.values()+"#"+result, categoriesPresentInLog(result, filterComplianceCategories(AuditCategory.values()))); - - Assert.assertThat(result, containsString("testuser.rest.succeededlogin")); - Assert.assertThat(result, containsString("testuser.rest.failedlogin")); - Assert.assertThat(result, containsString("privilege.missing")); - Assert.assertThat(result, containsString("action.indexattempt")); - Assert.assertThat(result, containsString("action.transport.ssl")); - Assert.assertThat(result, containsString("action.success")); - Assert.assertThat(result, containsString("Empty")); - } - - @Test - public void disableSingleCategoryTest() throws Exception { - for (AuditCategory category : AuditCategory.values()) { - TestAuditlogImpl.clear(); - checkCategoriesDisabled(category); - } - } - - @Test - public void disableAllCategoryTest() throws Exception{ - checkCategoriesDisabled(AuditCategory.values()); - } - - @Test - public void disableSomeCategoryTest() throws Exception{ - checkCategoriesDisabled(AuditCategory.AUTHENTICATED, AuditCategory.BAD_HEADERS, AuditCategory.FAILED_LOGIN); - } - - /*@After - public void restoreOut() { - System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out))); - }*/ - - protected void checkCategoriesDisabled(AuditCategory... disabledCategories) throws Exception { - - List categoryNames = new LinkedList<>(); - for (AuditCategory category : disabledCategories) { - categoryNames.add(category.name().toLowerCase()); - } - String disabledCategoriesString = Joiner.on(",").join(categoryNames); - - Builder settingsBuilder = Settings.builder(); - settingsBuilder.put("plugins.security.audit.type", TestAuditlogImpl.class.getName()); - settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, disabledCategoriesString); - settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, disabledCategoriesString); + // we use the debug output, no OpenSearch client is needed. Also, we + // do not need to close. + AbstractAuditLog auditLog = AuditTestUtils.createAuditLog( + settingsBuilder.build(), + null, + null, + AbstractSecurityUnitTest.MOCK_POOL, + null, + cs + ); + logAll(auditLog); + + // we're using the ExecutorService in AuditLogImpl, so we need to wait + // until all tasks are finished before we can check the result + auditLog.close(); + + String result = TestAuditlogImpl.sb.toString(); + + Assert.assertTrue( + AuditCategory.values() + "#" + result, + categoriesPresentInLog(result, filterComplianceCategories(AuditCategory.values())) + ); + + Assert.assertThat(result, containsString("testuser.rest.succeededlogin")); + Assert.assertThat(result, containsString("testuser.rest.failedlogin")); + Assert.assertThat(result, containsString("privilege.missing")); + Assert.assertThat(result, containsString("action.indexattempt")); + Assert.assertThat(result, containsString("action.transport.ssl")); + Assert.assertThat(result, containsString("action.success")); + Assert.assertThat(result, containsString("Empty")); + } + + @Test + public void disableSingleCategoryTest() throws Exception { + for (AuditCategory category : AuditCategory.values()) { + TestAuditlogImpl.clear(); + checkCategoriesDisabled(category); + } + } + + @Test + public void disableAllCategoryTest() throws Exception { + checkCategoriesDisabled(AuditCategory.values()); + } + @Test + public void disableSomeCategoryTest() throws Exception { + checkCategoriesDisabled(AuditCategory.AUTHENTICATED, AuditCategory.BAD_HEADERS, AuditCategory.FAILED_LOGIN); + } - // we use the debug output, no OpenSearch client is needed. Also, we - // do not need to close. - AbstractAuditLog auditLog = AuditTestUtils.createAuditLog(settingsBuilder.build(), null, null, AbstractSecurityUnitTest.MOCK_POOL, null, cs); - logAll(auditLog); + /*@After + public void restoreOut() { + System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out))); + }*/ - auditLog.close(); + protected void checkCategoriesDisabled(AuditCategory... disabledCategories) throws Exception { - String result = TestAuditlogImpl.sb.toString(); + List categoryNames = new LinkedList<>(); + for (AuditCategory category : disabledCategories) { + categoryNames.add(category.name().toLowerCase()); + } + String disabledCategoriesString = Joiner.on(",").join(categoryNames); - List allButDisablesCategories = new LinkedList<>(Arrays.asList(AuditCategory.values())); - allButDisablesCategories.removeAll(Arrays.asList(disabledCategories)); + Builder settingsBuilder = Settings.builder(); + settingsBuilder.put("plugins.security.audit.type", TestAuditlogImpl.class.getName()); + settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, disabledCategoriesString); + settingsBuilder.put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, disabledCategoriesString); - System.out.println(result+"###"+disabledCategoriesString); - Assert.assertFalse(categoriesPresentInLog(result, disabledCategories)); - Assert.assertTrue(categoriesPresentInLog(result, filterComplianceCategories(allButDisablesCategories.toArray(new AuditCategory[] {})))); - } + // we use the debug output, no OpenSearch client is needed. Also, we + // do not need to close. + AbstractAuditLog auditLog = AuditTestUtils.createAuditLog( + settingsBuilder.build(), + null, + null, + AbstractSecurityUnitTest.MOCK_POOL, + null, + cs + ); + logAll(auditLog); + + auditLog.close(); + + String result = TestAuditlogImpl.sb.toString(); + + List allButDisablesCategories = new LinkedList<>(Arrays.asList(AuditCategory.values())); + allButDisablesCategories.removeAll(Arrays.asList(disabledCategories)); + + System.out.println(result + "###" + disabledCategoriesString); + Assert.assertFalse(categoriesPresentInLog(result, disabledCategories)); + Assert.assertTrue( + categoriesPresentInLog(result, filterComplianceCategories(allButDisablesCategories.toArray(new AuditCategory[] {}))) + ); + } - protected boolean categoriesPresentInLog(String result, AuditCategory... categories) { - // since we're logging a JSON structure, whitespaces between keys and - // values must not matter - result = result.replaceAll(" ", ""); - for (AuditCategory category : categories) { - if(!result.contains("\""+AuditMessage.CATEGORY+"\":\""+category.name()+"\"")) { - System.out.println("MISSING: "+category.name()); - return false; - } - } - return true; - } + protected boolean categoriesPresentInLog(String result, AuditCategory... categories) { + // since we're logging a JSON structure, whitespaces between keys and + // values must not matter + result = result.replaceAll(" ", ""); + for (AuditCategory category : categories) { + if (!result.contains("\"" + AuditMessage.CATEGORY + "\":\"" + category.name() + "\"")) { + System.out.println("MISSING: " + category.name()); + return false; + } + } + return true; + } - protected void logAll(AuditLog auditLog) { - logRestFailedLogin(auditLog); - logRestBadHeaders(auditLog); - logRestSSLException(auditLog); - logRestSucceededLogin(auditLog); + protected void logAll(AuditLog auditLog) { + logRestFailedLogin(auditLog); + logRestBadHeaders(auditLog); + logRestSSLException(auditLog); + logRestSucceededLogin(auditLog); - logMissingPrivileges(auditLog); - logSecurityIndexAttempt(auditLog); - logAuthenticatedRequest(auditLog); + logMissingPrivileges(auditLog); + logSecurityIndexAttempt(auditLog); + logAuthenticatedRequest(auditLog); - logTransportSSLException(auditLog); - logTransportBadHeaders(auditLog); + logTransportSSLException(auditLog); + logTransportBadHeaders(auditLog); - logIndexEvent(auditLog); + logIndexEvent(auditLog); } - protected void logRestSucceededLogin(AuditLog auditLog) { - auditLog.logSucceededLogin("testuser.rest.succeededlogin", false, "testuser.rest.succeededlogin", new MockRestRequest()); - } + protected void logRestSucceededLogin(AuditLog auditLog) { + auditLog.logSucceededLogin("testuser.rest.succeededlogin", false, "testuser.rest.succeededlogin", new MockRestRequest()); + } protected void logRestFailedLogin(AuditLog auditLog) { - auditLog.logFailedLogin("testuser.rest.failedlogin", false, "testuser.rest.failedlogin", new MockRestRequest()); + auditLog.logFailedLogin("testuser.rest.failedlogin", false, "testuser.rest.failedlogin", new MockRestRequest()); } protected void logMissingPrivileges(AuditLog auditLog) { - auditLog.logMissingPrivileges("privilege.missing", new TransportRequest.Empty(), null); + auditLog.logMissingPrivileges("privilege.missing", new TransportRequest.Empty(), null); } protected void logTransportBadHeaders(AuditLog auditLog) { - auditLog.logBadHeaders(new TransportRequest.Empty(),"action", null); + auditLog.logBadHeaders(new TransportRequest.Empty(), "action", null); } protected void logRestBadHeaders(AuditLog auditLog) { - auditLog.logBadHeaders(new MockRestRequest()); + auditLog.logBadHeaders(new MockRestRequest()); } protected void logSecurityIndexAttempt(AuditLog auditLog) { - auditLog.logSecurityIndexAttempt(new TransportRequest.Empty(), "action.indexattempt", null); + auditLog.logSecurityIndexAttempt(new TransportRequest.Empty(), "action.indexattempt", null); } protected void logRestSSLException(AuditLog auditLog) { - auditLog.logSSLException(new MockRestRequest(), new Exception()); + auditLog.logSSLException(new MockRestRequest(), new Exception()); } protected void logTransportSSLException(AuditLog auditLog) { - auditLog.logSSLException(new TransportRequest.Empty(), new Exception(), "action.transport.ssl", null); + auditLog.logSSLException(new TransportRequest.Empty(), new Exception(), "action.transport.ssl", null); } protected void logAuthenticatedRequest(AuditLog auditLog) { - auditLog.logGrantedPrivileges("action.success", new TransportRequest.Empty(), null); + auditLog.logGrantedPrivileges("action.success", new TransportRequest.Empty(), null); } - protected void logIndexEvent(AuditLog auditLog) { - auditLog.logIndexEvent("indices:admin/test/action", new TransportRequest.Empty(), null); - } + protected void logIndexEvent(AuditLog auditLog) { + auditLog.logIndexEvent("indices:admin/test/action", new TransportRequest.Empty(), null); + } private static final AuditCategory[] filterComplianceCategories(AuditCategory[] cats) { List retval = new ArrayList(); - for(AuditCategory c: cats) { - if(!c.toString().startsWith("COMPLIANCE")) { + for (AuditCategory c : cats) { + if (!c.toString().startsWith("COMPLIANCE")) { retval.add(c); } } diff --git a/src/test/java/org/opensearch/security/auditlog/impl/IgnoreAuditUsersTest.java b/src/test/java/org/opensearch/security/auditlog/impl/IgnoreAuditUsersTest.java index 9939db53d8..036482e8f3 100644 --- a/src/test/java/org/opensearch/security/auditlog/impl/IgnoreAuditUsersTest.java +++ b/src/test/java/org/opensearch/security/auditlog/impl/IgnoreAuditUsersTest.java @@ -61,16 +61,21 @@ public static void initSearchRequest() { sr.indices("index1", "logstash*"); } - - @Test public void testConfiguredIgnoreUser() { Settings settings = Settings.builder() - .put("opendistro_security.audit.ignore_users", ignoreUser) - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .build(); - AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_USER, ignoreUserObj), null, cs); + .put("opendistro_security.audit.ignore_users", ignoreUser) + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .build(); + AbstractAuditLog al = AuditTestUtils.createAuditLog( + settings, + null, + null, + newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_USER, ignoreUserObj), + null, + cs + ); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", sr, null); Assert.assertEquals(0, TestAuditlogImpl.messages.size()); @@ -79,12 +84,19 @@ public void testConfiguredIgnoreUser() { @Test public void testNonConfiguredIgnoreUser() { Settings settings = Settings.builder() - .put("opendistro_security.audit.ignore_users", nonIgnoreUser) - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); - AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_USER, ignoreUserObj), null, cs); + .put("opendistro_security.audit.ignore_users", nonIgnoreUser) + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); + AbstractAuditLog al = AuditTestUtils.createAuditLog( + settings, + null, + null, + newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_USER, ignoreUserObj), + null, + cs + ); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", sr, null); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); @@ -93,11 +105,18 @@ public void testNonConfiguredIgnoreUser() { @Test public void testNonExistingIgnoreUser() { Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); - AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_USER, ignoreUserObj), null, cs); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); + AbstractAuditLog al = AuditTestUtils.createAuditLog( + settings, + null, + null, + newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_USER, ignoreUserObj), + null, + cs + ); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", sr, null); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); @@ -108,78 +127,122 @@ public void testWildcards() { SearchRequest sr = new SearchRequest(); User user = new User("John Doe"); - //sr.putInContext(ConfigConstants.OPENDISTRO_SECURITY_USER, user); - //sr.putInContext(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, "8.8.8.8"); - //sr.putInContext(ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, "CN=kirk,OU=client,O=client,L=test,C=DE"); - //sr.putHeader("myheader", "hval"); - sr.indices("index1","logstash*"); - //sr.source("{\"query\": false}"); + // sr.putInContext(ConfigConstants.OPENDISTRO_SECURITY_USER, user); + // sr.putInContext(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, "8.8.8.8"); + // sr.putInContext(ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, "CN=kirk,OU=client,O=client,L=test,C=DE"); + // sr.putHeader("myheader", "hval"); + sr.indices("index1", "logstash*"); + // sr.source("{\"query\": false}"); Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .putList("opendistro_security.audit.ignore_users", "*") - .build(); - - TransportAddress ta = new TransportAddress(new InetSocketAddress("8.8.8.8",80)); - - AbstractAuditLog al = AuditTestUtils.createAuditLog(settings, null, null, newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, ta, - ConfigConstants.OPENDISTRO_SECURITY_USER, new User("John Doe"), - ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, "CN=kirk,OU=client,O=client,L=test,C=DE" - ), null, cs); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .putList("opendistro_security.audit.ignore_users", "*") + .build(); + + TransportAddress ta = new TransportAddress(new InetSocketAddress("8.8.8.8", 80)); + + AbstractAuditLog al = AuditTestUtils.createAuditLog( + settings, + null, + null, + newThreadPool( + ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, + ta, + ConfigConstants.OPENDISTRO_SECURITY_USER, + new User("John Doe"), + ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, + "CN=kirk,OU=client,O=client,L=test,C=DE" + ), + null, + cs + ); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", sr, null); Assert.assertEquals(0, TestAuditlogImpl.messages.size()); settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .putList("opendistro_security.audit.ignore_users", "xxx") - .build(); - al = AuditTestUtils.createAuditLog(settings, null, null, newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, ta, - ConfigConstants.OPENDISTRO_SECURITY_USER, new User("John Doe"), - ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, "CN=kirk,OU=client,O=client,L=test,C=DE" - ), null, cs); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .putList("opendistro_security.audit.ignore_users", "xxx") + .build(); + al = AuditTestUtils.createAuditLog( + settings, + null, + null, + newThreadPool( + ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, + ta, + ConfigConstants.OPENDISTRO_SECURITY_USER, + new User("John Doe"), + ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, + "CN=kirk,OU=client,O=client,L=test,C=DE" + ), + null, + cs + ); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", sr, null); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .putList("opendistro_security.audit.ignore_users", "John Doe","Capatin Kirk") - .build(); - al = AuditTestUtils.createAuditLog(settings, null, null, newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, ta, - ConfigConstants.OPENDISTRO_SECURITY_USER, new User("John Doe"), - ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, "CN=kirk,OU=client,O=client,L=test,C=DE" - ), null, cs); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .putList("opendistro_security.audit.ignore_users", "John Doe", "Capatin Kirk") + .build(); + al = AuditTestUtils.createAuditLog( + settings, + null, + null, + newThreadPool( + ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, + ta, + ConfigConstants.OPENDISTRO_SECURITY_USER, + new User("John Doe"), + ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, + "CN=kirk,OU=client,O=client,L=test,C=DE" + ), + null, + cs + ); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", sr, null); al.logSecurityIndexAttempt(sr, "indices:data/read/search", null); - al.logMissingPrivileges("indices:data/read/search",sr, null); + al.logMissingPrivileges("indices:data/read/search", sr, null); Assert.assertEquals(TestAuditlogImpl.messages.toString(), 0, TestAuditlogImpl.messages.size()); settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .putList("opendistro_security.audit.ignore_users", "Wil Riker","Capatin Kirk") - .build(); - al = AuditTestUtils.createAuditLog(settings, null, null, newThreadPool(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, ta, - ConfigConstants.OPENDISTRO_SECURITY_USER, new User("John Doe"), - ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, "CN=kirk,OU=client,O=client,L=test,C=DE" - ), null, cs); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .putList("opendistro_security.audit.ignore_users", "Wil Riker", "Capatin Kirk") + .build(); + al = AuditTestUtils.createAuditLog( + settings, + null, + null, + newThreadPool( + ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS, + ta, + ConfigConstants.OPENDISTRO_SECURITY_USER, + new User("John Doe"), + ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_PRINCIPAL, + "CN=kirk,OU=client,O=client,L=test,C=DE" + ), + null, + cs + ); TestAuditlogImpl.clear(); al.logGrantedPrivileges("indices:data/read/search", sr, null); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); } private static ThreadPool newThreadPool(Object... transients) { - ThreadPool tp = new ThreadPool(Settings.builder().put("node.name", "mock").build()); - for(int i=0;i 0); // disable - auditConfig = new AuditConfig(false, AuditConfig.Filter.from(ImmutableMap.of("disabled_rest_categories", Collections.emptySet(), "disabled_transport_categories", Collections.emptySet())) , ComplianceConfig.DEFAULT); + auditConfig = new AuditConfig( + false, + AuditConfig.Filter.from( + ImmutableMap.of("disabled_rest_categories", Collections.emptySet(), "disabled_transport_categories", Collections.emptySet()) + ), + ComplianceConfig.DEFAULT + ); updateAuditConfig(AuditTestUtils.createAuditPayload(auditConfig)); // assert no auditing @@ -83,7 +93,7 @@ public void testSimpleAuthenticatedSetting() throws Exception { final Settings settings = Settings.builder() .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) .put(FilterEntries.DISABLE_TRANSPORT_CATEGORIES.getKeyWithNamespace(), "NONE") - .build(); + .build(); verifyAuthenticated(settings); } @@ -99,13 +109,10 @@ public void testSimpleAuthenticatedLegacySetting() throws Exception { private void verifyAuthenticated(final Settings settings) throws Exception { setup(settings); - - final List messages = TestAuditlogImpl.doThenWaitForMessages( - () -> { - final HttpResponse response = rh.executeGetRequest("_search", encodeBasicHeader("admin", "admin")); - assertThat(response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - }, - /* expectedCount*/ 1); + final List messages = TestAuditlogImpl.doThenWaitForMessages(() -> { + final HttpResponse response = rh.executeGetRequest("_search", encodeBasicHeader("admin", "admin")); + assertThat(response.getStatusCode(), equalTo(HttpStatus.SC_OK)); + }, /* expectedCount*/ 1); assertThat(messages.size(), equalTo(1)); @@ -116,30 +123,32 @@ private void verifyAuthenticated(final Settings settings) throws Exception { @Test public void testSSLPlainText() throws Exception { - //if this fails permanently look in the logs for an abstract method error or method not found error. - //needs proper ssl plugin version + // if this fails permanently look in the logs for an abstract method error or method not found error. + // needs proper ssl plugin version Settings additionalSettings = Settings.builder() - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); final List messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - final RuntimeException ex = Assert.assertThrows(RuntimeException.class, - () -> nonSslRestHelper().executeGetRequest("_search", encodeBasicHeader("admin", "admin"))); + final RuntimeException ex = Assert.assertThrows( + RuntimeException.class, + () -> nonSslRestHelper().executeGetRequest("_search", encodeBasicHeader("admin", "admin")) + ); Assert.assertEquals("org.apache.hc.core5.http.NoHttpResponseException", ex.getCause().getClass().getName()); - }, 1); /* no retry on NotSslRecordException exceptions */ + }, 1); /* no retry on NotSslRecordException exceptions */ // All of the messages should be the same as the http client is attempting multiple times. messages.stream().forEach((message) -> { Assert.assertEquals(AuditCategory.SSL_EXCEPTION, message.getCategory()); Assert.assertTrue(message.getExceptionStackTrace().contains("not an SSL/TLS record")); - }); + }); Assert.assertTrue(validateMsgs(messages)); } @@ -147,10 +156,10 @@ public void testSSLPlainText() throws Exception { public void testTaskId() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); setupStarfleetIndex(); @@ -169,8 +178,10 @@ public void testTaskId() throws Exception { Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("\"audit_request_effective_user\" : \"admin\"")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("REST")); Assert.assertFalse(TestAuditlogImpl.sb.toString().toLowerCase().contains("authorization")); - Assert.assertEquals(TestAuditlogImpl.messages.get(1).getAsMap().get(AuditMessage.TASK_ID), - TestAuditlogImpl.messages.get(1).getAsMap().get(AuditMessage.TASK_ID)); + Assert.assertEquals( + TestAuditlogImpl.messages.get(1).getAsMap().get(AuditMessage.TASK_ID), + TestAuditlogImpl.messages.get(1).getAsMap().get(AuditMessage.TASK_ID) + ); Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } @@ -178,10 +189,10 @@ public void testTaskId() throws Exception { public void testDefaultsRest() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); setupStarfleetIndex(); @@ -206,11 +217,11 @@ public void testDefaultsRest() throws Exception { @Test public void testGrantedPrivilegesRest() throws Exception { final Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "AUTHENTICATED") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.SECURITY_RESTAPI_ROLES_ENABLED, "opendistro_security_all_access") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "AUTHENTICATED") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .build(); setup(additionalSettings); setupStarfleetIndex(); @@ -221,10 +232,10 @@ public void testGrantedPrivilegesRest() throws Exception { @Test public void testMissingPrivilegesRest() throws Exception { final Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "AUTHENTICATED") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "AUTHENTICATED") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .build(); setup(additionalSettings); setupStarfleetIndex(); @@ -237,7 +248,7 @@ private void testPrivilegeRest(final int expectedStatus, final String endpoint, Assert.assertEquals(expectedStatus, response.getStatusCode()); final String auditlog = TestAuditlogImpl.sb.toString(); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); - Assert.assertTrue(auditlog.contains("\"audit_category\" : \"" + category +"\"")); + Assert.assertTrue(auditlog.contains("\"audit_category\" : \"" + category + "\"")); Assert.assertTrue(auditlog.contains("\"audit_rest_request_path\" : \"" + endpoint + "\"")); Assert.assertTrue(auditlog.contains("\"audit_request_effective_user\" : \"admin\"")); } @@ -246,12 +257,12 @@ private void testPrivilegeRest(final int expectedStatus, final String endpoint, public void testAuthenticated() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); setupStarfleetIndex(); @@ -273,9 +284,7 @@ public void testAuthenticated() throws Exception { @Test public void testNonAuthenticated() throws Exception { - Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .build(); + Settings additionalSettings = Settings.builder().put("plugins.security.audit.type", TestAuditlogImpl.class.getName()).build(); setup(additionalSettings); setupStarfleetIndex(); @@ -303,28 +312,26 @@ public void testWrongUser() throws Exception { HttpResponse response = rh.executeGetRequest("", encodeBasicHeader("wronguser", "admin")); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getStatusCode()); Thread.sleep(500); - Assert.assertTrue(TestAuditlogImpl.sb.toString(),TestAuditlogImpl.sb.toString().contains("FAILED_LOGIN")); - Assert.assertTrue(TestAuditlogImpl.sb.toString(),TestAuditlogImpl.sb.toString().contains("wronguser")); - Assert.assertTrue(TestAuditlogImpl.sb.toString(),TestAuditlogImpl.sb.toString().contains(AuditMessage.UTC_TIMESTAMP)); - Assert.assertFalse(TestAuditlogImpl.sb.toString(),TestAuditlogImpl.sb.toString().contains("AUTHENTICATED")); + Assert.assertTrue(TestAuditlogImpl.sb.toString(), TestAuditlogImpl.sb.toString().contains("FAILED_LOGIN")); + Assert.assertTrue(TestAuditlogImpl.sb.toString(), TestAuditlogImpl.sb.toString().contains("wronguser")); + Assert.assertTrue(TestAuditlogImpl.sb.toString(), TestAuditlogImpl.sb.toString().contains(AuditMessage.UTC_TIMESTAMP)); + Assert.assertFalse(TestAuditlogImpl.sb.toString(), TestAuditlogImpl.sb.toString().contains("AUTHENTICATED")); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } - public void testUnknownAuthorization() throws Exception { HttpResponse response = rh.executeGetRequest("", encodeBasicHeader("unknown", "unknown")); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getStatusCode()); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("FAILED_LOGIN")); - Assert.assertFalse(TestAuditlogImpl.sb.toString(),TestAuditlogImpl.sb.toString().contains("Basic dW5rbm93bjp1bmtub3du")); + Assert.assertFalse(TestAuditlogImpl.sb.toString(), TestAuditlogImpl.sb.toString().contains("Basic dW5rbm93bjp1bmtub3du")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains(AuditMessage.UTC_TIMESTAMP)); Assert.assertFalse(TestAuditlogImpl.sb.toString().contains("AUTHENTICATED")); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } - public void testUnauthenticated() throws Exception { System.out.println("#### testUnauthenticated"); @@ -349,7 +356,6 @@ public void testJustAuthenticated() throws Exception { Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } - public void testSecurityIndexAttempt() throws Exception { HttpResponse response = rh.executePutRequest(".opendistro_security/_doc/0", "{}", encodeBasicHeader("admin", "admin")); @@ -363,10 +369,13 @@ public void testSecurityIndexAttempt() throws Exception { Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } - public void testBadHeader() throws Exception { - HttpResponse response = rh.executeGetRequest("", new BasicHeader("_opendistro_security_bad", "bad"), encodeBasicHeader("admin", "admin")); + HttpResponse response = rh.executeGetRequest( + "", + new BasicHeader("_opendistro_security_bad", "bad"), + encodeBasicHeader("admin", "admin") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); Assert.assertFalse(TestAuditlogImpl.sb.toString(), TestAuditlogImpl.sb.toString().contains("AUTHENTICATED")); Assert.assertTrue(TestAuditlogImpl.sb.toString(), TestAuditlogImpl.sb.toString().contains("BAD_HEADERS")); @@ -375,7 +384,6 @@ public void testBadHeader() throws Exception { Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } - public void testMissingPriv() throws Exception { HttpResponse response = rh.executeGetRequest("sf/_search", encodeBasicHeader("worf", "worf")); @@ -390,13 +398,16 @@ public void testMissingPriv() throws Exception { Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } - public void testMsearch() throws Exception { + public void testMsearch() throws Exception { - String msearch = - "{\"index\":\"sf\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":0,\"query\":{\"match_all\":{}}}"+System.lineSeparator()+ - "{\"index\":\"sf\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":0,\"query\":{\"match_all\":{}}}"+System.lineSeparator(); + String msearch = "{\"index\":\"sf\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":0,\"query\":{\"match_all\":{}}}" + + System.lineSeparator() + + "{\"index\":\"sf\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":0,\"query\":{\"match_all\":{}}}" + + System.lineSeparator(); System.out.println("##### msaerch"); HttpResponse response = rh.executePostRequest("_msearch?pretty", msearch, encodeBasicHeader("admin", "admin")); @@ -409,24 +420,31 @@ public void testMsearch() throws Exception { Assert.assertEquals(TestAuditlogImpl.sb.toString(), 4, TestAuditlogImpl.messages.size()); Assert.assertFalse(TestAuditlogImpl.sb.toString().toLowerCase().contains("authorization")); Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); - } - + } public void testBulkAuth() throws Exception { System.out.println("#### testBulkAuth"); - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"worf\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - - "{ \"update\" : {\"_id\" : \"1\", \"_index\" : \"test\"} }"+System.lineSeparator()+ - "{ \"doc\" : {\"field\" : \"valuex\"} }"+System.lineSeparator()+ - "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"create\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value3x\" }"+System.lineSeparator(); - + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"worf\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + + + "{ \"update\" : {\"_id\" : \"1\", \"_index\" : \"test\"} }" + + System.lineSeparator() + + "{ \"doc\" : {\"field\" : \"valuex\"} }" + + System.lineSeparator() + + "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"create\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value3x\" }" + + System.lineSeparator(); HttpResponse response = rh.executePostRequest("_bulk", bulkBody, encodeBasicHeader("admin", "admin")); System.out.println(TestAuditlogImpl.sb.toString()); @@ -438,24 +456,33 @@ public void testBulkAuth() throws Exception { Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("IndexRequest")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("audit_trace_task_parent_id")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("audit_trace_task_id")); - //may vary because we log shardrequests which are not predictable here + // may vary because we log shardrequests which are not predictable here Assert.assertTrue(TestAuditlogImpl.messages.size() >= 17); Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } public void testBulkNonAuth() throws Exception { - String bulkBody = - "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \"worf\", \"_id\" : \"2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator()+ - - "{ \"update\" : {\"_id\" : \"1\", \"_index\" : \"test\"} }"+System.lineSeparator()+ - "{ \"doc\" : {\"field\" : \"valuex\"} }"+System.lineSeparator()+ - "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"create\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value3x\" }"+System.lineSeparator(); + String bulkBody = "{ \"index\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \"worf\", \"_id\" : \"2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator() + + + + "{ \"update\" : {\"_id\" : \"1\", \"_index\" : \"test\"} }" + + System.lineSeparator() + + "{ \"doc\" : {\"field\" : \"valuex\"} }" + + System.lineSeparator() + + "{ \"delete\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"create\" : { \"_index\" : \"test\", \"_id\" : \"1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value3x\" }" + + System.lineSeparator(); HttpResponse response = rh.executePostRequest("_bulk", bulkBody, encodeBasicHeader("worf", "worf")); System.out.println(response.getBody()); @@ -468,22 +495,21 @@ public void testBulkNonAuth() throws Exception { Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("MISSING_PRIVILEGES")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("indices:data/write/bulk[s]")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("IndexRequest")); - //may vary because we log shardrequests which are not predictable here + // may vary because we log shardrequests which are not predictable here Assert.assertTrue(TestAuditlogImpl.messages.size() >= 7); Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } public void testUpdateSettings() throws Exception { - String json = - "{"+ - "\"persistent\" : {"+ - "\"indices.recovery.*\" : null"+ - "},"+ - "\"transient\" : {"+ - "\"indices.recovery.*\" : null"+ - "}"+ - "}"; + String json = "{" + + "\"persistent\" : {" + + "\"indices.recovery.*\" : null" + + "}," + + "\"transient\" : {" + + "\"indices.recovery.*\" : null" + + "}" + + "}"; HttpResponse response = rh.executePutRequest("_cluster/settings", json, encodeBasicHeader("admin", "admin")); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); @@ -491,7 +517,7 @@ public void testUpdateSettings() throws Exception { Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("AUTHENTICATED")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("cluster:admin/settings/update")); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("indices.recovery.*")); - //may vary because we log may hit cluster manager directly or not + // may vary because we log may hit cluster manager directly or not Assert.assertTrue(TestAuditlogImpl.messages.size() > 1); Assert.assertTrue(validateMsgs(TestAuditlogImpl.messages)); } @@ -500,14 +526,14 @@ public void testUpdateSettings() throws Exception { public void testIndexPattern() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", "internal_opensearch") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_LOG_REQUEST_BODY, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_INDICES, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .put("plugins.security.audit.threadpool.size", 10) //must be greater 0 - .put("plugins.security.audit.config.index", "'auditlog-'YYYY.MM.dd.ss") - .build(); + .put("plugins.security.audit.type", "internal_opensearch") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_LOG_REQUEST_BODY, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_INDICES, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .put("plugins.security.audit.threadpool.size", 10) // must be greater 0 + .put("plugins.security.audit.config.index", "'auditlog-'YYYY.MM.dd.ss") + .build(); setup(additionalSettings); setupStarfleetIndex(); @@ -527,31 +553,59 @@ public void testIndexPattern() throws Exception { public void testAliases() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); try (Client tc = getClient()) { tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf")) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))) + .actionGet(); } TestAuditlogImpl.clear(); @@ -571,34 +625,56 @@ public void testAliases() throws Exception { public void testScroll() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); try (Client tc = getClient()) { - for(int i=0; i<3; i++) - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + for (int i = 0; i < 3; i++) + tc.index( + new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); } TestAuditlogImpl.clear(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executeGetRequest("vulcangov/_search?scroll=1m&pretty=true", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("vulcangov/_search?scroll=1m&pretty=true", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); int start = res.getBody().indexOf("_scroll_id") + 15; - String scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start+1)); - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executePostRequest("/_search/scroll?pretty=true", "{\"scroll_id\" : \""+scrollid+"\"}", encodeBasicHeader("admin", "admin"))).getStatusCode()); + String scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start + 1)); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "/_search/scroll?pretty=true", + "{\"scroll_id\" : \"" + scrollid + "\"}", + encodeBasicHeader("admin", "admin") + )).getStatusCode() + ); Assert.assertEquals(4, TestAuditlogImpl.messages.size()); - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executeGetRequest("vulcangov/_search?scroll=1m&pretty=true", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("vulcangov/_search?scroll=1m&pretty=true", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); start = res.getBody().indexOf("_scroll_id") + 15; - scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start+1)); - TestAuditlogImpl.clear(); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res=rh.executePostRequest("/_search/scroll?pretty=true", "{\"scroll_id\" : \""+scrollid+"\"}", encodeBasicHeader("admin2", "admin"))).getStatusCode()); + scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start + 1)); + TestAuditlogImpl.clear(); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePostRequest( + "/_search/scroll?pretty=true", + "{\"scroll_id\" : \"" + scrollid + "\"}", + encodeBasicHeader("admin2", "admin") + )).getStatusCode() + ); Thread.sleep(1000); System.out.println(TestAuditlogImpl.sb.toString()); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains("InternalScrollSearchRequest")); @@ -611,21 +687,25 @@ public void testScroll() throws Exception { public void testAliasResolution() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); - try (Client tc = getClient()) { - for(int i=0; i<3; i++) - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().alias("thealias").index("vulcangov"))).actionGet(); + for (int i = 0; i < 3; i++) + tc.index( + new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().alias("thealias").index("vulcangov"))) + .actionGet(); } TestAuditlogImpl.clear(); @@ -644,17 +724,21 @@ public void testAliasResolution() throws Exception { public void testAliasBadHeaders() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); TestAuditlogImpl.clear(); - HttpResponse response = rh.executeGetRequest("_search?pretty", new BasicHeader("_opendistro_security_user", "xxx"), encodeBasicHeader("admin", "admin")); + HttpResponse response = rh.executeGetRequest( + "_search?pretty", + new BasicHeader("_opendistro_security_user", "xxx"), + encodeBasicHeader("admin", "admin") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); System.out.println(TestAuditlogImpl.sb.toString()); Assert.assertFalse(TestAuditlogImpl.sb.toString().contains("YWRtaW46YWRtaW4")); @@ -669,13 +753,13 @@ public void testAliasBadHeaders() throws Exception { public void testIndexCloseDelete() throws Exception { Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .build(); setup(additionalSettings); @@ -701,24 +785,33 @@ public void testIndexCloseDelete() throws Exception { public void testDeleteByQuery() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .build(); setup(settings); try (Client tc = getClient()) { - for(int i=0; i<3; i++) - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); + for (int i = 0; i < 3; i++) + tc.index( + new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); } TestAuditlogImpl.clear(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executePostRequest("/vulcango*/_delete_by_query?refresh=true&wait_for_completion=true&pretty=true", "{\"query\" : {\"match_all\" : {}}}", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "/vulcango*/_delete_by_query?refresh=true&wait_for_completion=true&pretty=true", + "{\"query\" : {\"match_all\" : {}}}", + encodeBasicHeader("admin", "admin") + )).getStatusCode() + ); assertContains(res, "*\"deleted\" : 3,*"); String auditlogContents = TestAuditlogImpl.sb.toString(); Assert.assertTrue(auditlogContents.contains("indices:data/write/delete/byquery")); @@ -729,21 +822,29 @@ public void testDeleteByQuery() throws Exception { @Test public void testIndexRequests() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "AUTHENTICATED,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_LOG_REQUEST_BODY, true) - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "AUTHENTICATED,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_LOG_REQUEST_BODY, true) + .build(); setup(settings); // test create index TestAuditlogImpl.clear(); - rh.executePutRequest("/twitter", "{\"settings\":{\"index\":{\"number_of_shards\":3,\"number_of_replicas\":2}}}", encodeBasicHeader("admin", "admin")); + rh.executePutRequest( + "/twitter", + "{\"settings\":{\"index\":{\"number_of_shards\":3,\"number_of_replicas\":2}}}", + encodeBasicHeader("admin", "admin") + ); String auditlogs = TestAuditlogImpl.sb.toString(); Assert.assertTrue(auditlogs.contains("\"audit_category\" : \"INDEX_EVENT\"")); Assert.assertTrue(auditlogs.contains("\"audit_transport_request_type\" : \"CreateIndexRequest\",")); - Assert.assertTrue(auditlogs.contains("\"audit_request_body\" : \"{\\\"index\\\":{\\\"number_of_shards\\\":\\\"3\\\",\\\"number_of_replicas\\\":\\\"2\\\"}}\"")); + Assert.assertTrue( + auditlogs.contains( + "\"audit_request_body\" : \"{\\\"index\\\":{\\\"number_of_shards\\\":\\\"3\\\",\\\"number_of_replicas\\\":\\\"2\\\"}}\"" + ) + ); // test update index TestAuditlogImpl.clear(); @@ -755,7 +856,11 @@ public void testIndexRequests() throws Exception { // test put mapping TestAuditlogImpl.clear(); - rh.executePutRequest("/twitter/_mapping", "{\"properties\":{\"message\":{\"type\":\"keyword\"}}}", encodeBasicHeader("admin", "admin")); + rh.executePutRequest( + "/twitter/_mapping", + "{\"properties\":{\"message\":{\"type\":\"keyword\"}}}", + encodeBasicHeader("admin", "admin") + ); auditlogs = TestAuditlogImpl.sb.toString(); Assert.assertTrue(auditlogs.contains("\"audit_category\" : \"INDEX_EVENT\"")); Assert.assertTrue(auditlogs.contains("\"audit_transport_request_type\" : \"PutMappingRequest\",")); @@ -776,50 +881,41 @@ private String messageRestRequestMethod(AuditMessage msg) { @Test public void testRestMethod() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "NONE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .build(); setup(settings); final Header adminHeader = encodeBasicHeader("admin", "admin"); List messages; // test GET - messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - rh.executeGetRequest("test", adminHeader); - }, 1); + messages = TestAuditlogImpl.doThenWaitForMessages(() -> { rh.executeGetRequest("test", adminHeader); }, 1); Assert.assertEquals(GET, messages.get(0).getRequestMethod()); // test PUT - messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - rh.executePutRequest("test/_doc/0", "{}", adminHeader); - }, 1); + messages = TestAuditlogImpl.doThenWaitForMessages(() -> { rh.executePutRequest("test/_doc/0", "{}", adminHeader); }, 1); Assert.assertEquals(PUT, messages.get(0).getRequestMethod()); // test DELETE - messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - rh.executeDeleteRequest("test", adminHeader); - }, 1); + messages = TestAuditlogImpl.doThenWaitForMessages(() -> { rh.executeDeleteRequest("test", adminHeader); }, 1); Assert.assertEquals(DELETE, messages.get(0).getRequestMethod()); // test POST - messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - rh.executePostRequest("test/_doc", "{}", adminHeader); - }, 1); + messages = TestAuditlogImpl.doThenWaitForMessages(() -> { rh.executePostRequest("test/_doc", "{}", adminHeader); }, 1); Assert.assertEquals(POST, messages.get(0).getRequestMethod()); // test PATCH - messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - rh.executePatchRequest("/_opendistro/_security/api/audit", "[]"); - }, 1); + messages = TestAuditlogImpl.doThenWaitForMessages(() -> { rh.executePatchRequest("/_opendistro/_security/api/audit", "[]"); }, 1); Assert.assertEquals(PATCH, messages.get(0).getRequestMethod()); // test MISSING_PRIVILEGES // admin does not have REST role here - messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - rh.executePatchRequest("/_opendistro/_security/api/audit", "[]", adminHeader); - }, 2); + messages = TestAuditlogImpl.doThenWaitForMessages( + () -> { rh.executePatchRequest("/_opendistro/_security/api/audit", "[]", adminHeader); }, + 2 + ); // The intital request is authenicated Assert.assertEquals(PATCH, messages.get(0).getRequestMethod()); Assert.assertEquals(AuditCategory.AUTHENTICATED, messages.get(0).getCategory()); @@ -828,16 +924,15 @@ public void testRestMethod() throws Exception { Assert.assertEquals(AuditCategory.MISSING_PRIVILEGES, messages.get(1).getCategory()); // test AUTHENTICATED - messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - rh.executeGetRequest("test", adminHeader); - }, 1); + messages = TestAuditlogImpl.doThenWaitForMessages(() -> { rh.executeGetRequest("test", adminHeader); }, 1); Assert.assertEquals(AuditCategory.AUTHENTICATED, messages.get(0).getCategory()); Assert.assertEquals(GET, messages.get(0).getRequestMethod()); // test FAILED_LOGIN - messages = TestAuditlogImpl.doThenWaitForMessages(() -> { - rh.executeGetRequest("test", encodeBasicHeader("random", "random")); - }, 1); + messages = TestAuditlogImpl.doThenWaitForMessages( + () -> { rh.executeGetRequest("test", encodeBasicHeader("random", "random")); }, + 1 + ); Assert.assertEquals(AuditCategory.FAILED_LOGIN, messages.get(0).getCategory()); Assert.assertEquals(GET, messages.get(0).getRequestMethod()); @@ -852,11 +947,11 @@ public void testRestMethod() throws Exception { @Test public void testSensitiveMethodRedaction() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "AUTHENTICATED") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "AUTHENTICATED") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .build(); setup(settings); rh.sendAdminCertificate = true; final String expectedRequestBody = "\"audit_request_body\" : \"__SENSITIVE__\""; @@ -869,19 +964,28 @@ public void testSensitiveMethodRedaction() throws Exception { // test PUT internal users API TestAuditlogImpl.clear(); - rh.executePutRequest("/_opendistro/_security/api/internalusers/test1", "{\"password\":\"new-pass\", \"backend_roles\":[], \"attributes\": {}}"); + rh.executePutRequest( + "/_opendistro/_security/api/internalusers/test1", + "{\"password\":\"new-pass\", \"backend_roles\":[], \"attributes\": {}}" + ); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains(expectedRequestBody)); // test PATCH internal users API TestAuditlogImpl.clear(); - rh.executePatchRequest("/_opendistro/_security/api/internalusers/test1", "[{\"op\":\"add\", \"path\":\"/password\", \"value\": \"test-pass\"}]"); + rh.executePatchRequest( + "/_opendistro/_security/api/internalusers/test1", + "[{\"op\":\"add\", \"path\":\"/password\", \"value\": \"test-pass\"}]" + ); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains(expectedRequestBody)); // test PUT users API TestAuditlogImpl.clear(); - rh.executePutRequest("/_opendistro/_security/api/user/test2", "{\"password\":\"new-pass\", \"backend_roles\":[], \"attributes\": {}}"); + rh.executePutRequest( + "/_opendistro/_security/api/user/test2", + "{\"password\":\"new-pass\", \"backend_roles\":[], \"attributes\": {}}" + ); Assert.assertEquals(1, TestAuditlogImpl.messages.size()); Assert.assertTrue(TestAuditlogImpl.sb.toString().contains(expectedRequestBody)); } diff --git a/src/test/java/org/opensearch/security/auditlog/integration/SSLAuditlogTest.java b/src/test/java/org/opensearch/security/auditlog/integration/SSLAuditlogTest.java index 56fd17ddff..3eb49dc794 100644 --- a/src/test/java/org/opensearch/security/auditlog/integration/SSLAuditlogTest.java +++ b/src/test/java/org/opensearch/security/auditlog/integration/SSLAuditlogTest.java @@ -31,7 +31,9 @@ public class SSLAuditlogTest extends AbstractAuditlogiUnitTest { private ClusterInfo monitoringClusterInfo; private RestHelper rhMon; - private final ClusterHelper monitoringCluster = new ClusterHelper("mon_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()); + private final ClusterHelper monitoringCluster = new ClusterHelper( + "mon_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime() + ); @After @Override @@ -48,36 +50,53 @@ public void tearDown() { private void setupMonitoring() throws Exception { Assert.assertNull("No monitoring cluster", monitoringClusterInfo); - monitoringClusterInfo = monitoringCluster.startCluster(minimumSecuritySettings(defaultNodeSettings(Settings.EMPTY)), ClusterConfiguration.DEFAULT); + monitoringClusterInfo = monitoringCluster.startCluster( + minimumSecuritySettings(defaultNodeSettings(Settings.EMPTY)), + ClusterConfiguration.DEFAULT + ); initialize(monitoringCluster, monitoringClusterInfo, new DynamicSecurityConfig()); rhMon = new RestHelper(monitoringClusterInfo, getResourceFolder()); } - @Test public void testExternalPemUserPass() throws Exception { setupMonitoring(); Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", "external_opensearch") - .put("plugins.security.audit.config.http_endpoints", monitoringClusterInfo.httpHost+":"+monitoringClusterInfo.httpPort) - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "*spock*","admin", "CN=kirk,OU=client,O=client,L=Test,C=DE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL, true) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL_CLIENT_AUTH, false) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMTRUSTEDCAS_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/chain-ca.pem")) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMCERT_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.crtfull.pem")) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMKEY_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.key.pem")) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_USERNAME, - "admin") - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PASSWORD, - "admin") - .build(); + .put("plugins.security.audit.type", "external_opensearch") + .put("plugins.security.audit.config.http_endpoints", monitoringClusterInfo.httpHost + ":" + monitoringClusterInfo.httpPort) + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "*spock*", "admin", "CN=kirk,OU=client,O=client,L=Test,C=DE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL, true) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL_CLIENT_AUTH, + false + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/chain-ca.pem") + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.crtfull.pem") + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.key.pem") + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_USERNAME, + "admin" + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PASSWORD, + "admin" + ) + .build(); setup(additionalSettings); HttpResponse response = rh.executeGetRequest("_search"); @@ -99,20 +118,31 @@ public void testExternalPemClientAuth() throws Exception { setupMonitoring(); Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", "external_opensearch") - .put("plugins.security.audit.config.http_endpoints", monitoringClusterInfo.httpHost+":"+monitoringClusterInfo.httpPort) - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "*spock*","admin", "CN=kirk,OU=client,O=client,L=Test,C=DE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL, true) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL_CLIENT_AUTH, true) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMTRUSTEDCAS_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/chain-ca.pem")) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMCERT_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/kirk.crtfull.pem")) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMKEY_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/kirk.key.pem")) - .build(); + .put("plugins.security.audit.type", "external_opensearch") + .put("plugins.security.audit.config.http_endpoints", monitoringClusterInfo.httpHost + ":" + monitoringClusterInfo.httpPort) + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "*spock*", "admin", "CN=kirk,OU=client,O=client,L=Test,C=DE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL, true) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL_CLIENT_AUTH, + true + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/chain-ca.pem") + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/kirk.crtfull.pem") + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/kirk.key.pem") + ) + .build(); setup(additionalSettings); HttpResponse response = rh.executeGetRequest("_search"); @@ -133,19 +163,26 @@ public void testExternalPemUserPassTp() throws Exception { setupMonitoring(); Settings additionalSettings = Settings.builder() - .put("plugins.security.audit.type", "external_opensearch") - .put("plugins.security.audit.config.http_endpoints", monitoringClusterInfo.httpHost+":"+monitoringClusterInfo.httpPort) - .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "*spock*","admin", "CN=kirk,OU=client,O=client,L=Test,C=DE") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL, true) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMTRUSTEDCAS_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/chain-ca.pem")) - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_USERNAME, - "admin") - .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PASSWORD, - "admin") - .build(); + .put("plugins.security.audit.type", "external_opensearch") + .put("plugins.security.audit.config.http_endpoints", monitoringClusterInfo.httpHost + ":" + monitoringClusterInfo.httpPort) + .putList(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_IGNORE_USERS, "*spock*", "admin", "CN=kirk,OU=client,O=client,L=Test,C=DE") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, true) + .put(ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_ENABLE_SSL, true) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/chain-ca.pem") + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_USERNAME, + "admin" + ) + .put( + ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT_PREFIX + ConfigConstants.SECURITY_AUDIT_EXTERNAL_OPENSEARCH_PASSWORD, + "admin" + ) + .build(); setup(additionalSettings); HttpResponse response = rh.executeGetRequest("_search"); diff --git a/src/test/java/org/opensearch/security/auditlog/integration/TestAuditlogImpl.java b/src/test/java/org/opensearch/security/auditlog/integration/TestAuditlogImpl.java index ba094e23a1..7a3cd45f5b 100644 --- a/src/test/java/org/opensearch/security/auditlog/integration/TestAuditlogImpl.java +++ b/src/test/java/org/opensearch/security/auditlog/integration/TestAuditlogImpl.java @@ -42,7 +42,7 @@ public synchronized boolean doStore(AuditMessage msg) { // Ignore any messages that are sent before TestAuditlogImpl is waiting. return true; } - sb.append(msg.toPrettyString()+System.lineSeparator()); + sb.append(msg.toPrettyString() + System.lineSeparator()); messagesRef.get().add(msg); countDownRef.get().countDown(); return true; @@ -81,14 +81,11 @@ public static List doThenWaitForMessages(final Runnable action, fi try { Thread.sleep(100); if (missedMessages.size() != 0) { - final String missedMessagesErrorMessage = new StringBuilder() - .append("Audit messages were missed! ") - .append("Found " + (missedMessages.size()) + " messages.") - .append("Messages found during this time: \n\n") - .append(missedMessages.stream() - .map(AuditMessage::toString) - .collect(Collectors.joining("\n"))) - .toString(); + final String missedMessagesErrorMessage = new StringBuilder().append("Audit messages were missed! ") + .append("Found " + (missedMessages.size()) + " messages.") + .append("Messages found during this time: \n\n") + .append(missedMessages.stream().map(AuditMessage::toString).collect(Collectors.joining("\n"))) + .toString(); throw new RuntimeException(missedMessagesErrorMessage); } @@ -134,6 +131,7 @@ public static class MessagesNotFoundException extends RuntimeException { private final int expectedCount; private final int missingCount; private final List foundMessages; + public MessagesNotFoundException(final int expectedCount, List foundMessages) { super(MessagesNotFoundException.createDetailMessage(expectedCount, foundMessages)); this.expectedCount = expectedCount; @@ -154,14 +152,11 @@ public List getFoundMessages() { } private static String createDetailMessage(final int expectedCount, final List foundMessages) { - return new StringBuilder() - .append("Did not receive all " + expectedCount + " audit messages after a short wait. ") - .append("Missing " + (expectedCount - foundMessages.size()) + " messages.") - .append("Messages found during this time: \n\n") - .append(foundMessages.stream() - .map(AuditMessage::toString) - .collect(Collectors.joining("\n"))) - .toString(); + return new StringBuilder().append("Did not receive all " + expectedCount + " audit messages after a short wait. ") + .append("Missing " + (expectedCount - foundMessages.size()) + " messages.") + .append("Messages found during this time: \n\n") + .append(foundMessages.stream().map(AuditMessage::toString).collect(Collectors.joining("\n"))) + .toString(); } } } diff --git a/src/test/java/org/opensearch/security/auditlog/routing/FallbackTest.java b/src/test/java/org/opensearch/security/auditlog/routing/FallbackTest.java index 0cd48f6009..cf76dbc343 100644 --- a/src/test/java/org/opensearch/security/auditlog/routing/FallbackTest.java +++ b/src/test/java/org/opensearch/security/auditlog/routing/FallbackTest.java @@ -32,96 +32,99 @@ public class FallbackTest extends AbstractAuditlogiUnitTest { - @Test - public void testFallback() throws Exception { - Settings.Builder settingsBuilder = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/fallback.yml")); - - Settings settings = settingsBuilder.put("path.home", ".").put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE").build(); - - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); - - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.MISSING_PRIVILEGES); - router.route(msg); - - // endpoint 1 is failing, endoint2 and default work - List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); - Assert.assertEquals(3, sinks.size()); - // this sink has failed, message must be logged to fallback sink - AuditLogSink sink = sinks.get(0); - Assert.assertEquals("endpoint1", sink.getName()); - Assert.assertEquals(FailingSink.class, sink.getClass()); - sink = sink.getFallbackSink(); - Assert.assertEquals("fallback", sink.getName()); - Assert.assertEquals(LoggingSink.class, sink.getClass()); - LoggingSink loggingSkin = (LoggingSink) sink; - Assert.assertEquals(msg, loggingSkin.messages.get(0)); - // this sink succeeds - sink = sinks.get(1); - Assert.assertEquals("endpoint2", sink.getName()); - Assert.assertEquals(LoggingSink.class, sink.getClass()); - loggingSkin = (LoggingSink) sink; - Assert.assertEquals(msg, loggingSkin.messages.get(0)); - // default sink also succeeds - sink = sinks.get(2); - Assert.assertEquals("default", sink.getName()); - Assert.assertEquals(LoggingSink.class, sink.getClass()); - loggingSkin = (LoggingSink) sink; - Assert.assertEquals(msg, loggingSkin.messages.get(0)); - - // has only one end point which fails - router = createMessageRouterComplianceEnabled(settings); - msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.COMPLIANCE_DOC_READ); - router.route(msg); - sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ); - sink = sinks.get(0); - Assert.assertEquals("endpoint3", sink.getName()); - Assert.assertEquals(FailingSink.class, sink.getClass()); - sink = sink.getFallbackSink(); - Assert.assertEquals("fallback", sink.getName()); - Assert.assertEquals(LoggingSink.class, sink.getClass()); - loggingSkin = (LoggingSink) sink; - Assert.assertEquals(msg, loggingSkin.messages.get(0)); - - // has only default which succeeds - router = createMessageRouterComplianceEnabled(settings); - msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.COMPLIANCE_DOC_WRITE); - router.route(msg); - sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_WRITE); - sink = sinks.get(0); - Assert.assertEquals("default", sink.getName()); - Assert.assertEquals(LoggingSink.class, sink.getClass()); - loggingSkin = (LoggingSink) sink; - Assert.assertEquals(1, loggingSkin.messages.size()); - Assert.assertEquals(msg, loggingSkin.messages.get(0)); - // fallback must be empty - sink = sink.getFallbackSink(); - Assert.assertEquals("fallback", sink.getName()); - Assert.assertEquals(LoggingSink.class, sink.getClass()); - loggingSkin = (LoggingSink) sink; - Assert.assertEquals(0, loggingSkin.messages.size()); - - // test non configured categories, must be logged to default only - router = createMessageRouterComplianceEnabled(settings); - msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.FAILED_LOGIN); - router.route(msg); - Assert.assertNull(router.categorySinks.get(AuditCategory.FAILED_LOGIN)); - loggingSkin = (LoggingSink) router.defaultSink; - Assert.assertEquals(1, loggingSkin.messages.size()); - Assert.assertEquals(msg, loggingSkin.messages.get(0)); - // all others must be empty - assertLoggingSinksEmpty(router); - - } - - private void assertLoggingSinksEmpty(AuditMessageRouter router) { - // get all sinks - List allSinks = router.categorySinks.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); - allSinks = allSinks.stream().filter(sink -> (sink instanceof LoggingSink)).collect(Collectors.toList()); - allSinks.removeAll(Collections.singleton(router.defaultSink)); - for(AuditLogSink sink : allSinks) { - LoggingSink loggingSink = (LoggingSink)sink; - Assert.assertEquals(0, loggingSink.messages.size()); - } - } + @Test + public void testFallback() throws Exception { + Settings.Builder settingsBuilder = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/fallback.yml")); + + Settings settings = settingsBuilder.put("path.home", ".") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .build(); + + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.MISSING_PRIVILEGES); + router.route(msg); + + // endpoint 1 is failing, endoint2 and default work + List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); + Assert.assertEquals(3, sinks.size()); + // this sink has failed, message must be logged to fallback sink + AuditLogSink sink = sinks.get(0); + Assert.assertEquals("endpoint1", sink.getName()); + Assert.assertEquals(FailingSink.class, sink.getClass()); + sink = sink.getFallbackSink(); + Assert.assertEquals("fallback", sink.getName()); + Assert.assertEquals(LoggingSink.class, sink.getClass()); + LoggingSink loggingSkin = (LoggingSink) sink; + Assert.assertEquals(msg, loggingSkin.messages.get(0)); + // this sink succeeds + sink = sinks.get(1); + Assert.assertEquals("endpoint2", sink.getName()); + Assert.assertEquals(LoggingSink.class, sink.getClass()); + loggingSkin = (LoggingSink) sink; + Assert.assertEquals(msg, loggingSkin.messages.get(0)); + // default sink also succeeds + sink = sinks.get(2); + Assert.assertEquals("default", sink.getName()); + Assert.assertEquals(LoggingSink.class, sink.getClass()); + loggingSkin = (LoggingSink) sink; + Assert.assertEquals(msg, loggingSkin.messages.get(0)); + + // has only one end point which fails + router = createMessageRouterComplianceEnabled(settings); + msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.COMPLIANCE_DOC_READ); + router.route(msg); + sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ); + sink = sinks.get(0); + Assert.assertEquals("endpoint3", sink.getName()); + Assert.assertEquals(FailingSink.class, sink.getClass()); + sink = sink.getFallbackSink(); + Assert.assertEquals("fallback", sink.getName()); + Assert.assertEquals(LoggingSink.class, sink.getClass()); + loggingSkin = (LoggingSink) sink; + Assert.assertEquals(msg, loggingSkin.messages.get(0)); + + // has only default which succeeds + router = createMessageRouterComplianceEnabled(settings); + msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.COMPLIANCE_DOC_WRITE); + router.route(msg); + sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_WRITE); + sink = sinks.get(0); + Assert.assertEquals("default", sink.getName()); + Assert.assertEquals(LoggingSink.class, sink.getClass()); + loggingSkin = (LoggingSink) sink; + Assert.assertEquals(1, loggingSkin.messages.size()); + Assert.assertEquals(msg, loggingSkin.messages.get(0)); + // fallback must be empty + sink = sink.getFallbackSink(); + Assert.assertEquals("fallback", sink.getName()); + Assert.assertEquals(LoggingSink.class, sink.getClass()); + loggingSkin = (LoggingSink) sink; + Assert.assertEquals(0, loggingSkin.messages.size()); + + // test non configured categories, must be logged to default only + router = createMessageRouterComplianceEnabled(settings); + msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.FAILED_LOGIN); + router.route(msg); + Assert.assertNull(router.categorySinks.get(AuditCategory.FAILED_LOGIN)); + loggingSkin = (LoggingSink) router.defaultSink; + Assert.assertEquals(1, loggingSkin.messages.size()); + Assert.assertEquals(msg, loggingSkin.messages.get(0)); + // all others must be empty + assertLoggingSinksEmpty(router); + + } + + private void assertLoggingSinksEmpty(AuditMessageRouter router) { + // get all sinks + List allSinks = router.categorySinks.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + allSinks = allSinks.stream().filter(sink -> (sink instanceof LoggingSink)).collect(Collectors.toList()); + allSinks.removeAll(Collections.singleton(router.defaultSink)); + for (AuditLogSink sink : allSinks) { + LoggingSink loggingSink = (LoggingSink) sink; + Assert.assertEquals(0, loggingSink.messages.size()); + } + } } diff --git a/src/test/java/org/opensearch/security/auditlog/routing/PerfTest.java b/src/test/java/org/opensearch/security/auditlog/routing/PerfTest.java index c71a4dc951..f308db21fc 100644 --- a/src/test/java/org/opensearch/security/auditlog/routing/PerfTest.java +++ b/src/test/java/org/opensearch/security/auditlog/routing/PerfTest.java @@ -24,28 +24,28 @@ import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.test.helper.file.FileHelper; - public class PerfTest extends AbstractAuditlogiUnitTest { - @Test - @Ignore(value="jvm crash on cci") - public void testPerf() throws Exception { - Settings.Builder settingsBuilder = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/perftest.yml")); - - Settings settings = settingsBuilder.put("path.home", ".") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .build(); - - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); - int limit = 150000; - while(limit > 0) { - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.MISSING_PRIVILEGES); - router.route(msg); - limit--; - } - LoggingSink loggingSink = (LoggingSink)router.defaultSink.getFallbackSink(); - int currentSize = loggingSink.messages.size(); - Assert.assertTrue(currentSize > 0); - } + @Test + @Ignore(value = "jvm crash on cci") + public void testPerf() throws Exception { + Settings.Builder settingsBuilder = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/perftest.yml")); + + Settings settings = settingsBuilder.put("path.home", ".") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .build(); + + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + int limit = 150000; + while (limit > 0) { + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.MISSING_PRIVILEGES); + router.route(msg); + limit--; + } + LoggingSink loggingSink = (LoggingSink) router.defaultSink.getFallbackSink(); + int currentSize = loggingSink.messages.size(); + Assert.assertTrue(currentSize > 0); + } } diff --git a/src/test/java/org/opensearch/security/auditlog/routing/RouterTest.java b/src/test/java/org/opensearch/security/auditlog/routing/RouterTest.java index 49d603884f..9ab7c0f93c 100644 --- a/src/test/java/org/opensearch/security/auditlog/routing/RouterTest.java +++ b/src/test/java/org/opensearch/security/auditlog/routing/RouterTest.java @@ -31,45 +31,46 @@ import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.test.helper.file.FileHelper; -public class RouterTest extends AbstractAuditlogiUnitTest{ - - - @Test - public void testValidConfiguration() throws Exception { - Settings settings = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_valid.yml")).build(); - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); - // default - Assert.assertEquals("default", router.defaultSink.getName()); - Assert.assertEquals(ExternalOpenSearchSink.class, router.defaultSink.getClass()); - // test category sinks - List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); - Assert.assertNotNull(sinks); - // 3, since we include default as well - Assert.assertEquals(3, sinks.size()); - Assert.assertEquals("endpoint1", sinks.get(0).getName()); - Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); - Assert.assertEquals("endpoint2", sinks.get(1).getName()); - Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(1).getClass()); - Assert.assertEquals("default", sinks.get(2).getName()); - Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(2).getClass()); - sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ); - // 1, since we do not include default - Assert.assertEquals(1, sinks.size()); - Assert.assertEquals("endpoint3", sinks.get(0).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(0).getClass()); - } +public class RouterTest extends AbstractAuditlogiUnitTest { + + @Test + public void testValidConfiguration() throws Exception { + Settings settings = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_valid.yml")) + .build(); + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + // default + Assert.assertEquals("default", router.defaultSink.getName()); + Assert.assertEquals(ExternalOpenSearchSink.class, router.defaultSink.getClass()); + // test category sinks + List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); + Assert.assertNotNull(sinks); + // 3, since we include default as well + Assert.assertEquals(3, sinks.size()); + Assert.assertEquals("endpoint1", sinks.get(0).getName()); + Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); + Assert.assertEquals("endpoint2", sinks.get(1).getName()); + Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(1).getClass()); + Assert.assertEquals("default", sinks.get(2).getName()); + Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(2).getClass()); + sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ); + // 1, since we do not include default + Assert.assertEquals(1, sinks.size()); + Assert.assertEquals("endpoint3", sinks.get(0).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(0).getClass()); + } @Test public void testMessageRouting() throws Exception { - Settings.Builder settingsBuilder = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/routing.yml")); + Settings.Builder settingsBuilder = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/routing.yml")); - Settings settings = settingsBuilder - .put("path.home", ".") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") - .build(); + Settings settings = settingsBuilder.put("path.home", ".") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "NONE") + .build(); - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); AuditMessage msg = MockAuditMessageFactory.validAuditMessage(AuditCategory.MISSING_PRIVILEGES); router.route(msg); testMessageDeliveredForCategory(router, msg, AuditCategory.MISSING_PRIVILEGES, "endpoint1", "endpoint2", "default"); @@ -96,35 +97,40 @@ public void testMessageRouting() throws Exception { } - private void testMessageDeliveredForCategory(AuditMessageRouter router, AuditMessage msg, AuditCategory categoryToCheck, String ... sinkNames) { - Map> sinksForCategory = router.categorySinks; - for(AuditCategory category : AuditCategory.values()) { - List sinks = sinksForCategory.get(category); - if (sinks == null) { - continue; - } - if (category.equals(categoryToCheck)) { - // each sink must contain our message - for(AuditLogSink sink : sinks) { - LoggingSink logSink = (LoggingSink)sink; - Assert.assertEquals(1, logSink.messages.size()); - Assert.assertEquals(msg, logSink.messages.get(0)); - Assert.assertTrue(logSink.sb.length() > 0); - Assert.assertTrue(Arrays.stream(sinkNames).anyMatch(sink.getName()::equals)); - } - } else { - // make sure sinks are empty for all other categories, exclude default - for(AuditLogSink sink : sinks) { - // default is configured for multiple categories, skip - if (sink.getName().equals("default")) { - continue; - } - LoggingSink logSink = (LoggingSink)sink; - Assert.assertEquals(0, logSink.messages.size()); - Assert.assertTrue(logSink.sb.length() == 0); - } - } - } + private void testMessageDeliveredForCategory( + AuditMessageRouter router, + AuditMessage msg, + AuditCategory categoryToCheck, + String... sinkNames + ) { + Map> sinksForCategory = router.categorySinks; + for (AuditCategory category : AuditCategory.values()) { + List sinks = sinksForCategory.get(category); + if (sinks == null) { + continue; + } + if (category.equals(categoryToCheck)) { + // each sink must contain our message + for (AuditLogSink sink : sinks) { + LoggingSink logSink = (LoggingSink) sink; + Assert.assertEquals(1, logSink.messages.size()); + Assert.assertEquals(msg, logSink.messages.get(0)); + Assert.assertTrue(logSink.sb.length() > 0); + Assert.assertTrue(Arrays.stream(sinkNames).anyMatch(sink.getName()::equals)); + } + } else { + // make sure sinks are empty for all other categories, exclude default + for (AuditLogSink sink : sinks) { + // default is configured for multiple categories, skip + if (sink.getName().equals("default")) { + continue; + } + LoggingSink logSink = (LoggingSink) sink; + Assert.assertEquals(0, logSink.messages.size()); + Assert.assertTrue(logSink.sb.length() == 0); + } + } + } } } diff --git a/src/test/java/org/opensearch/security/auditlog/routing/RoutingConfigurationTest.java b/src/test/java/org/opensearch/security/auditlog/routing/RoutingConfigurationTest.java index f33d52c663..8ddb79bcba 100644 --- a/src/test/java/org/opensearch/security/auditlog/routing/RoutingConfigurationTest.java +++ b/src/test/java/org/opensearch/security/auditlog/routing/RoutingConfigurationTest.java @@ -28,139 +28,155 @@ import org.opensearch.security.auditlog.sink.InternalOpenSearchSink; import org.opensearch.security.test.helper.file.FileHelper; -public class RoutingConfigurationTest extends AbstractAuditlogiUnitTest{ - - @Test - public void testValidConfiguration() throws Exception { - Settings settings = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_valid.yml")).build(); - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); - // default - Assert.assertEquals("default", router.defaultSink.getName()); - Assert.assertEquals(ExternalOpenSearchSink.class, router.defaultSink.getClass()); - // test category sinks - List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); - Assert.assertNotNull(sinks); - // 3, since we include default as well - Assert.assertEquals(3, sinks.size()); - Assert.assertEquals("endpoint1", sinks.get(0).getName()); - Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); - Assert.assertEquals("endpoint2", sinks.get(1).getName()); - Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(1).getClass()); - Assert.assertEquals("default", sinks.get(2).getName()); - Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(2).getClass()); - sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ); - // 1, since we do not include default - Assert.assertEquals(1, sinks.size()); - Assert.assertEquals("endpoint3", sinks.get(0).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(0).getClass()); - } - - @Test - public void testNoDefaultSink() throws Exception { - Settings settings = Settings.builder().loadFromPath(Objects.requireNonNull(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_no_default.yml"))).build(); - AuditMessageRouter router = new AuditMessageRouter(settings, null, null, null); - // no default sink, audit log not enabled - Assert.assertEquals(false, router.isEnabled()); - Assert.assertEquals(null, router.defaultSink); - Assert.assertEquals(null, router.categorySinks); - // make sure no exception is thrown - router.route(MockAuditMessageFactory.validAuditMessage()); - } - - @Test - public void testMissingEndpoints() throws Exception { - Settings settings = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_wrong_endpoint_names.yml")).build(); - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); - // fallback to debug sink if no default is given - Assert.assertEquals(InternalOpenSearchSink.class, router.defaultSink.getClass()); - // missing configuration for endpoint2 / External ES. Fallback to - // localhost - List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); - // 2 valid endpoints - Assert.assertEquals(2, sinks.size()); - Assert.assertEquals("endpoint1", sinks.get(0).getName()); - Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); - Assert.assertEquals("endpoint3", sinks.get(1).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(1).getClass()); - sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_WRITE); - Assert.assertEquals(1, sinks.size()); - Assert.assertEquals("default", sinks.get(0).getName()); - Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); - // no valid end points for category, must use default - Assert.assertNull(router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ)); - } - - @Test - public void testWrongCategories() throws Exception { - Settings settings = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_wrong_categories.yml")).build(); - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); - // no default sink, we fall back to debug sink - Assert.assertEquals(DebugSink.class, router.defaultSink.getClass()); - - List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); - // 3, since default is not valid but replaced with Debug - Assert.assertEquals(3, sinks.size()); - Assert.assertEquals("default", sinks.get(0).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(0).getClass()); - Assert.assertEquals("endpoint1", sinks.get(1).getName()); - Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(1).getClass()); - Assert.assertEquals("endpoint2", sinks.get(2).getName()); - Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(2).getClass()); - - sinks = router.categorySinks.get(AuditCategory.GRANTED_PRIVILEGES); - Assert.assertEquals(3, sinks.size()); - Assert.assertEquals("endpoint1", sinks.get(0).getName()); - Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); - Assert.assertEquals("endpoint3", sinks.get(1).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(1).getClass()); - Assert.assertEquals("default", sinks.get(2).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(2).getClass()); - - sinks = router.categorySinks.get(AuditCategory.AUTHENTICATED); - Assert.assertEquals(1, sinks.size()); - Assert.assertEquals("endpoint1", sinks.get(0).getName()); - Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); - - // bad headers has no valid endpoint, so we use default - Assert.assertNull(router.categorySinks.get(AuditCategory.BAD_HEADERS)); - - // failed login has no endpoint configuration, so we use default - Assert.assertNull(router.categorySinks.get(AuditCategory.FAILED_LOGIN)); - - } - - @Test - public void testWrongEndpointTypes() throws Exception { - Settings settings = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_wrong_endpoint_types.yml")).build(); - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); - // debug sink not valid, fallback to debug - Assert.assertEquals(DebugSink.class, router.defaultSink.getClass()); - - List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); - // 2 valid endpoints in config, default falls back to debug - Assert.assertEquals(3, sinks.size()); - Assert.assertEquals("endpoint2", sinks.get(0).getName()); - Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(0).getClass()); - Assert.assertEquals("endpoint3", sinks.get(1).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(1).getClass()); - Assert.assertEquals("default", sinks.get(2).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(2).getClass()); - - sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_WRITE); - Assert.assertEquals(1, sinks.size()); - Assert.assertEquals("default", sinks.get(0).getName()); - Assert.assertEquals(DebugSink.class, sinks.get(0).getClass()); - - // no valid endpoints for category, must fallback to default - Assert.assertNull(router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ)); - } - - @Test - public void testNoMultipleEndpointsConfiguration() throws Exception { - Settings settings = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/sink/configuration_no_multiple_endpoints.yml")).build(); - AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); - ThreadPoolConfig config = router.storagePool.getConfig(); - Assert.assertEquals(5, config.getThreadPoolSize()); - Assert.assertEquals(200000, config.getThreadPoolMaxQueueLen()); - } +public class RoutingConfigurationTest extends AbstractAuditlogiUnitTest { + + @Test + public void testValidConfiguration() throws Exception { + Settings settings = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_valid.yml")) + .build(); + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + // default + Assert.assertEquals("default", router.defaultSink.getName()); + Assert.assertEquals(ExternalOpenSearchSink.class, router.defaultSink.getClass()); + // test category sinks + List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); + Assert.assertNotNull(sinks); + // 3, since we include default as well + Assert.assertEquals(3, sinks.size()); + Assert.assertEquals("endpoint1", sinks.get(0).getName()); + Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); + Assert.assertEquals("endpoint2", sinks.get(1).getName()); + Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(1).getClass()); + Assert.assertEquals("default", sinks.get(2).getName()); + Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(2).getClass()); + sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ); + // 1, since we do not include default + Assert.assertEquals(1, sinks.size()); + Assert.assertEquals("endpoint3", sinks.get(0).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(0).getClass()); + } + + @Test + public void testNoDefaultSink() throws Exception { + Settings settings = Settings.builder() + .loadFromPath( + Objects.requireNonNull( + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_no_default.yml") + ) + ) + .build(); + AuditMessageRouter router = new AuditMessageRouter(settings, null, null, null); + // no default sink, audit log not enabled + Assert.assertEquals(false, router.isEnabled()); + Assert.assertEquals(null, router.defaultSink); + Assert.assertEquals(null, router.categorySinks); + // make sure no exception is thrown + router.route(MockAuditMessageFactory.validAuditMessage()); + } + + @Test + public void testMissingEndpoints() throws Exception { + Settings settings = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_wrong_endpoint_names.yml")) + .build(); + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + // fallback to debug sink if no default is given + Assert.assertEquals(InternalOpenSearchSink.class, router.defaultSink.getClass()); + // missing configuration for endpoint2 / External ES. Fallback to + // localhost + List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); + // 2 valid endpoints + Assert.assertEquals(2, sinks.size()); + Assert.assertEquals("endpoint1", sinks.get(0).getName()); + Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); + Assert.assertEquals("endpoint3", sinks.get(1).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(1).getClass()); + sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_WRITE); + Assert.assertEquals(1, sinks.size()); + Assert.assertEquals("default", sinks.get(0).getName()); + Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); + // no valid end points for category, must use default + Assert.assertNull(router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ)); + } + + @Test + public void testWrongCategories() throws Exception { + Settings settings = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_wrong_categories.yml")) + .build(); + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + // no default sink, we fall back to debug sink + Assert.assertEquals(DebugSink.class, router.defaultSink.getClass()); + + List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); + // 3, since default is not valid but replaced with Debug + Assert.assertEquals(3, sinks.size()); + Assert.assertEquals("default", sinks.get(0).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(0).getClass()); + Assert.assertEquals("endpoint1", sinks.get(1).getName()); + Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(1).getClass()); + Assert.assertEquals("endpoint2", sinks.get(2).getName()); + Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(2).getClass()); + + sinks = router.categorySinks.get(AuditCategory.GRANTED_PRIVILEGES); + Assert.assertEquals(3, sinks.size()); + Assert.assertEquals("endpoint1", sinks.get(0).getName()); + Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); + Assert.assertEquals("endpoint3", sinks.get(1).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(1).getClass()); + Assert.assertEquals("default", sinks.get(2).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(2).getClass()); + + sinks = router.categorySinks.get(AuditCategory.AUTHENTICATED); + Assert.assertEquals(1, sinks.size()); + Assert.assertEquals("endpoint1", sinks.get(0).getName()); + Assert.assertEquals(InternalOpenSearchSink.class, sinks.get(0).getClass()); + + // bad headers has no valid endpoint, so we use default + Assert.assertNull(router.categorySinks.get(AuditCategory.BAD_HEADERS)); + + // failed login has no endpoint configuration, so we use default + Assert.assertNull(router.categorySinks.get(AuditCategory.FAILED_LOGIN)); + + } + + @Test + public void testWrongEndpointTypes() throws Exception { + Settings settings = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/routing/configuration_wrong_endpoint_types.yml")) + .build(); + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + // debug sink not valid, fallback to debug + Assert.assertEquals(DebugSink.class, router.defaultSink.getClass()); + + List sinks = router.categorySinks.get(AuditCategory.MISSING_PRIVILEGES); + // 2 valid endpoints in config, default falls back to debug + Assert.assertEquals(3, sinks.size()); + Assert.assertEquals("endpoint2", sinks.get(0).getName()); + Assert.assertEquals(ExternalOpenSearchSink.class, sinks.get(0).getClass()); + Assert.assertEquals("endpoint3", sinks.get(1).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(1).getClass()); + Assert.assertEquals("default", sinks.get(2).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(2).getClass()); + + sinks = router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_WRITE); + Assert.assertEquals(1, sinks.size()); + Assert.assertEquals("default", sinks.get(0).getName()); + Assert.assertEquals(DebugSink.class, sinks.get(0).getClass()); + + // no valid endpoints for category, must fallback to default + Assert.assertNull(router.categorySinks.get(AuditCategory.COMPLIANCE_DOC_READ)); + } + + @Test + public void testNoMultipleEndpointsConfiguration() throws Exception { + Settings settings = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/sink/configuration_no_multiple_endpoints.yml")) + .build(); + AuditMessageRouter router = createMessageRouterComplianceEnabled(settings); + ThreadPoolConfig config = router.storagePool.getConfig(); + Assert.assertEquals(5, config.getThreadPoolSize()); + Assert.assertEquals(200000, config.getThreadPoolMaxQueueLen()); + } } diff --git a/src/test/java/org/opensearch/security/auditlog/sink/KafkaSinkTest.java b/src/test/java/org/opensearch/security/auditlog/sink/KafkaSinkTest.java index b074dd2b62..bf567c6ebe 100644 --- a/src/test/java/org/opensearch/security/auditlog/sink/KafkaSinkTest.java +++ b/src/test/java/org/opensearch/security/auditlog/sink/KafkaSinkTest.java @@ -37,6 +37,7 @@ public class KafkaSinkTest extends AbstractAuditlogiUnitTest { public static EmbeddedKafkaRule embeddedKafka = new EmbeddedKafkaRule(1, true, 1, "compliance") { // Prevents test exceptions from randomized runner, see https://bit.ly/3y17IkI private UncaughtExceptionHandler currentHandler; + @Override public void before() { currentHandler = Thread.getDefaultUncaughtExceptionHandler(); @@ -53,9 +54,9 @@ public void after() { @Test public void testKafka() throws Exception { String configYml = FileHelper.loadFile("auditlog/endpoints/sink/configuration_kafka.yml"); - configYml = configYml.replace("_RPLC_BOOTSTRAP_SERVERS_",embeddedKafka.getEmbeddedKafka().getBrokersAsString()); + configYml = configYml.replace("_RPLC_BOOTSTRAP_SERVERS_", embeddedKafka.getEmbeddedKafka().getBrokersAsString()); Settings.Builder settingsBuilder = Settings.builder().loadFromSource(configYml, YamlXContent.yamlXContent.mediaType()); - try(KafkaConsumer consumer = createConsumer()) { + try (KafkaConsumer consumer = createConsumer()) { consumer.subscribe(Arrays.asList("compliance")); Settings settings = settingsBuilder.put("path.home", ".").build(); @@ -78,7 +79,7 @@ private KafkaConsumer createConsumer() { Properties props = new Properties(); props.put("bootstrap.servers", embeddedKafka.getEmbeddedKafka().getBrokersAsString()); props.put("auto.offset.reset", "earliest"); - props.put("group.id", "mygroup"+System.currentTimeMillis()+"_"+new Random().nextDouble()); + props.put("group.id", "mygroup" + System.currentTimeMillis() + "_" + new Random().nextDouble()); props.put("key.deserializer", "org.apache.kafka.common.serialization.LongDeserializer"); props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); return new KafkaConsumer<>(props); diff --git a/src/test/java/org/opensearch/security/auditlog/sink/MockWebhookAuditLog.java b/src/test/java/org/opensearch/security/auditlog/sink/MockWebhookAuditLog.java index b93904574e..6dd019e733 100644 --- a/src/test/java/org/opensearch/security/auditlog/sink/MockWebhookAuditLog.java +++ b/src/test/java/org/opensearch/security/auditlog/sink/MockWebhookAuditLog.java @@ -15,23 +15,22 @@ public class MockWebhookAuditLog extends WebhookSink { - public String payload = null; - public String url = null; - - public MockWebhookAuditLog(Settings settings, String settingsPrefix, AuditLogSink fallback) throws Exception { - super("test", settings, settingsPrefix, null, fallback); - } - - @Override - protected boolean doPost(String url, String payload) { - this.payload = payload; - return true; - } - - - @Override - protected boolean doGet(String url) { - this.url = url; - return true; - } + public String payload = null; + public String url = null; + + public MockWebhookAuditLog(Settings settings, String settingsPrefix, AuditLogSink fallback) throws Exception { + super("test", settings, settingsPrefix, null, fallback); + } + + @Override + protected boolean doPost(String url, String payload) { + this.payload = payload; + return true; + } + + @Override + protected boolean doGet(String url) { + this.url = url; + return true; + } } diff --git a/src/test/java/org/opensearch/security/auditlog/sink/SinkProviderTLSTest.java b/src/test/java/org/opensearch/security/auditlog/sink/SinkProviderTLSTest.java index fb0f665b16..467cce5fe9 100644 --- a/src/test/java/org/opensearch/security/auditlog/sink/SinkProviderTLSTest.java +++ b/src/test/java/org/opensearch/security/auditlog/sink/SinkProviderTLSTest.java @@ -39,119 +39,132 @@ public class SinkProviderTLSTest { - protected HttpServer server = null; - - @Before - @After - public void tearDown() { - if (server != null) { - try { - server.stop(); - } catch (Exception e) { - // ignore - } - } - } - - @Test - public void testTlsConfigurationNoFallback() throws Exception { - - TestHttpHandler handler = new TestHttpHandler(); - - int port = findFreePort(); - server = ServerBootstrap.bootstrap().setListenerPort(port).setHttpProcessor(HttpProcessors.server("Test/1.1")).setSslContext(createSSLContext()).register("*", handler).create(); - - server.start(); - - Builder builder = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/sink/configuration_tls.yml")); - builder.put("path.home", "/"); - - // replace some values with absolute paths for unit tests - builder.put("plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/root-ca.pem")); - builder.put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/root-ca.pem")); - builder.put("plugins.security.audit.endpoints.endpoint2.config.webhook.ssl.pemtrustedcas_content", FileHelper.loadFile("auditlog/root-ca.pem")); - - builder.put("plugins.security.audit.config.webhook.url", "https://localhost:" + port); - builder.put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", "https://localhost:" + port); - builder.put("plugins.security.audit.endpoints.endpoint2.config.webhook.url", "https://localhost:" + port); - - - SinkProvider provider = new SinkProvider(builder.build(), null, null, null); - WebhookSink defaultSink = (WebhookSink) provider.defaultSink; - Assert.assertEquals(true, defaultSink.verifySSL); - - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - provider.allSinks.get("endpoint1").store(msg); - - Assert.assertTrue(handler.method.equals("POST")); + protected HttpServer server = null; + + @Before + @After + public void tearDown() { + if (server != null) { + try { + server.stop(); + } catch (Exception e) { + // ignore + } + } + } + + @Test + public void testTlsConfigurationNoFallback() throws Exception { + + TestHttpHandler handler = new TestHttpHandler(); + + int port = findFreePort(); + server = ServerBootstrap.bootstrap() + .setListenerPort(port) + .setHttpProcessor(HttpProcessors.server("Test/1.1")) + .setSslContext(createSSLContext()) + .register("*", handler) + .create(); + + server.start(); + + Builder builder = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/sink/configuration_tls.yml")); + builder.put("path.home", "/"); + + // replace some values with absolute paths for unit tests + builder.put( + "plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/root-ca.pem") + ); + builder.put( + "plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/root-ca.pem") + ); + builder.put( + "plugins.security.audit.endpoints.endpoint2.config.webhook.ssl.pemtrustedcas_content", + FileHelper.loadFile("auditlog/root-ca.pem") + ); + + builder.put("plugins.security.audit.config.webhook.url", "https://localhost:" + port); + builder.put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", "https://localhost:" + port); + builder.put("plugins.security.audit.endpoints.endpoint2.config.webhook.url", "https://localhost:" + port); + + SinkProvider provider = new SinkProvider(builder.build(), null, null, null); + WebhookSink defaultSink = (WebhookSink) provider.defaultSink; + Assert.assertEquals(true, defaultSink.verifySSL); + + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); + provider.allSinks.get("endpoint1").store(msg); + + Assert.assertTrue(handler.method.equals("POST")); Assert.assertTrue(handler.body != null); Assert.assertTrue(handler.body.contains("{")); assertStringContainsAllKeysAndValues(handler.body); - handler.reset(); + handler.reset(); - provider.allSinks.get("endpoint2").store(msg); + provider.allSinks.get("endpoint2").store(msg); - Assert.assertTrue(handler.method.equals("POST")); + Assert.assertTrue(handler.method.equals("POST")); Assert.assertTrue(handler.body != null); Assert.assertTrue(handler.body.contains("{")); assertStringContainsAllKeysAndValues(handler.body); - handler.reset(); + handler.reset(); - provider.defaultSink.store(msg); + provider.defaultSink.store(msg); - Assert.assertTrue(handler.method.equals("POST")); + Assert.assertTrue(handler.method.equals("POST")); Assert.assertTrue(handler.body != null); Assert.assertTrue(handler.body.contains("{")); assertStringContainsAllKeysAndValues(handler.body); server.stop(); - } - - // for TLS support on our in-memory server - private SSLContext createSSLContext() throws Exception { - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory - .getDefaultAlgorithm()); - final KeyStore trustStore = KeyStore.getInstance("JKS"); - InputStream trustStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks").toFile()); - trustStore.load(trustStream, "changeit".toCharArray()); - tmf.init(trustStore); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - final KeyStore keyStore = KeyStore.getInstance("JKS"); - InputStream keyStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks").toFile()); - - keyStore.load(keyStream, "changeit".toCharArray()); - kmf.init(keyStore, "changeit".toCharArray()); - - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); - sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - return sslContext; - } - - private void assertStringContainsAllKeysAndValues(String in) { - System.out.println(in); - Assert.assertTrue(in, in.contains(AuditMessage.FORMAT_VERSION)); - Assert.assertTrue(in, in.contains(AuditMessage.CATEGORY)); - Assert.assertTrue(in, in.contains(AuditMessage.FORMAT_VERSION)); - Assert.assertTrue(in, in.contains(AuditMessage.REMOTE_ADDRESS)); - Assert.assertTrue(in, in.contains(AuditMessage.ORIGIN)); - Assert.assertTrue(in, in.contains(AuditMessage.REQUEST_LAYER)); - Assert.assertTrue(in, in.contains(AuditMessage.TRANSPORT_REQUEST_TYPE)); - Assert.assertTrue(in, in.contains(AuditMessage.UTC_TIMESTAMP)); - Assert.assertTrue(in, in.contains(AuditCategory.FAILED_LOGIN.name())); - Assert.assertTrue(in, in.contains("FAILED_LOGIN")); - Assert.assertTrue(in, in.contains("John Doe")); - Assert.assertTrue(in, in.contains("8.8.8.8")); - //Assert.assertTrue(in, in.contains("CN=kirk,OU=client,O=client,L=test,C=DE")); - } - - private int findFreePort() { - try (ServerSocket serverSocket = new ServerSocket(0)) { - return serverSocket.getLocalPort(); - } catch (IOException e) { - throw new RuntimeException("Failed to find free port", e); - } - } + } + + // for TLS support on our in-memory server + private SSLContext createSSLContext() throws Exception { + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + final KeyStore trustStore = KeyStore.getInstance("JKS"); + InputStream trustStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks").toFile()); + trustStore.load(trustStream, "changeit".toCharArray()); + tmf.init(trustStore); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + final KeyStore keyStore = KeyStore.getInstance("JKS"); + InputStream keyStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks").toFile()); + + keyStore.load(keyStream, "changeit".toCharArray()); + kmf.init(keyStore, "changeit".toCharArray()); + + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + return sslContext; + } + + private void assertStringContainsAllKeysAndValues(String in) { + System.out.println(in); + Assert.assertTrue(in, in.contains(AuditMessage.FORMAT_VERSION)); + Assert.assertTrue(in, in.contains(AuditMessage.CATEGORY)); + Assert.assertTrue(in, in.contains(AuditMessage.FORMAT_VERSION)); + Assert.assertTrue(in, in.contains(AuditMessage.REMOTE_ADDRESS)); + Assert.assertTrue(in, in.contains(AuditMessage.ORIGIN)); + Assert.assertTrue(in, in.contains(AuditMessage.REQUEST_LAYER)); + Assert.assertTrue(in, in.contains(AuditMessage.TRANSPORT_REQUEST_TYPE)); + Assert.assertTrue(in, in.contains(AuditMessage.UTC_TIMESTAMP)); + Assert.assertTrue(in, in.contains(AuditCategory.FAILED_LOGIN.name())); + Assert.assertTrue(in, in.contains("FAILED_LOGIN")); + Assert.assertTrue(in, in.contains("John Doe")); + Assert.assertTrue(in, in.contains("8.8.8.8")); + // Assert.assertTrue(in, in.contains("CN=kirk,OU=client,O=client,L=test,C=DE")); + } + + private int findFreePort() { + try (ServerSocket serverSocket = new ServerSocket(0)) { + return serverSocket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Failed to find free port", e); + } + } } diff --git a/src/test/java/org/opensearch/security/auditlog/sink/SinkProviderTest.java b/src/test/java/org/opensearch/security/auditlog/sink/SinkProviderTest.java index 029192e097..5e3203261f 100644 --- a/src/test/java/org/opensearch/security/auditlog/sink/SinkProviderTest.java +++ b/src/test/java/org/opensearch/security/auditlog/sink/SinkProviderTest.java @@ -20,82 +20,85 @@ public class SinkProviderTest { - @Test - public void testConfiguration() throws Exception { - - Settings settings = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/sink/configuration_all_variants.yml")).build(); - SinkProvider provider = new SinkProvider(settings, null, null, null); - - // make sure we have a debug sink as fallback - Assert.assertEquals(DebugSink.class, provider.fallbackSink.getClass() ); - - AuditLogSink sink = provider.getSink("DefaULT"); - Assert.assertEquals(sink.getClass(), DebugSink.class); - - sink = provider.getSink("endpoint1"); - Assert.assertEquals(InternalOpenSearchSink.class, sink.getClass()); - - sink = provider.getSink("endpoint2"); - Assert.assertEquals(ExternalOpenSearchSink.class, sink.getClass()); - // todo: sink does not work - - sink = provider.getSink("endpoinT3"); - Assert.assertEquals(DebugSink.class, sink.getClass()); - - // no valid type - sink = provider.getSink("endpoint4"); - Assert.assertEquals(null, sink); - - sink = provider.getSink("endpoint2"); - Assert.assertEquals(ExternalOpenSearchSink.class, sink.getClass()); - // todo: sink does not work, no valid config - - // no valid type - sink = provider.getSink("endpoint6"); - Assert.assertEquals(null, sink); - - // no valid type - sink = provider.getSink("endpoint7"); - Assert.assertEquals(null, sink); - - sink = provider.getSink("endpoint8"); - Assert.assertEquals(DebugSink.class, sink.getClass()); - - // wrong type in config - sink = provider.getSink("endpoint9"); - Assert.assertEquals(ExternalOpenSearchSink.class, sink.getClass()); - - // log4j, valid configuration - sink = provider.getSink("endpoint10"); - Assert.assertEquals(Log4JSink.class, sink.getClass()); - Log4JSink lsink = (Log4JSink)sink; - Assert.assertEquals("loggername", lsink.loggerName); - Assert.assertEquals(Level.WARN, lsink.logLevel); - - // log4j, no level, fallback to default - sink = provider.getSink("endpoint11"); - Assert.assertEquals(Log4JSink.class, sink.getClass()); - lsink = (Log4JSink)sink; - Assert.assertEquals("loggername", lsink.loggerName); - Assert.assertEquals(Level.INFO, lsink.logLevel); - - // log4j, wrong level, fallback to log4j default - sink = provider.getSink("endpoint12"); - Assert.assertEquals(Log4JSink.class, sink.getClass()); - lsink = (Log4JSink)sink; - Assert.assertEquals("loggername", lsink.loggerName); - Assert.assertEquals(Level.DEBUG, lsink.logLevel); - - } - - @Test - public void testNoMultipleEndpointsConfiguration() throws Exception { - Settings settings = Settings.builder().loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/sink/configuration_no_multiple_endpoints.yml")).build(); - SinkProvider provider = new SinkProvider(settings, null, null, null); - InternalOpenSearchSink sink = (InternalOpenSearchSink)provider.defaultSink; - Assert.assertEquals("myownindex", sink.index); - Assert.assertEquals("auditevents", sink.type); - } - + @Test + public void testConfiguration() throws Exception { + + Settings settings = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/sink/configuration_all_variants.yml")) + .build(); + SinkProvider provider = new SinkProvider(settings, null, null, null); + + // make sure we have a debug sink as fallback + Assert.assertEquals(DebugSink.class, provider.fallbackSink.getClass()); + + AuditLogSink sink = provider.getSink("DefaULT"); + Assert.assertEquals(sink.getClass(), DebugSink.class); + + sink = provider.getSink("endpoint1"); + Assert.assertEquals(InternalOpenSearchSink.class, sink.getClass()); + + sink = provider.getSink("endpoint2"); + Assert.assertEquals(ExternalOpenSearchSink.class, sink.getClass()); + // todo: sink does not work + + sink = provider.getSink("endpoinT3"); + Assert.assertEquals(DebugSink.class, sink.getClass()); + + // no valid type + sink = provider.getSink("endpoint4"); + Assert.assertEquals(null, sink); + + sink = provider.getSink("endpoint2"); + Assert.assertEquals(ExternalOpenSearchSink.class, sink.getClass()); + // todo: sink does not work, no valid config + + // no valid type + sink = provider.getSink("endpoint6"); + Assert.assertEquals(null, sink); + + // no valid type + sink = provider.getSink("endpoint7"); + Assert.assertEquals(null, sink); + + sink = provider.getSink("endpoint8"); + Assert.assertEquals(DebugSink.class, sink.getClass()); + + // wrong type in config + sink = provider.getSink("endpoint9"); + Assert.assertEquals(ExternalOpenSearchSink.class, sink.getClass()); + + // log4j, valid configuration + sink = provider.getSink("endpoint10"); + Assert.assertEquals(Log4JSink.class, sink.getClass()); + Log4JSink lsink = (Log4JSink) sink; + Assert.assertEquals("loggername", lsink.loggerName); + Assert.assertEquals(Level.WARN, lsink.logLevel); + + // log4j, no level, fallback to default + sink = provider.getSink("endpoint11"); + Assert.assertEquals(Log4JSink.class, sink.getClass()); + lsink = (Log4JSink) sink; + Assert.assertEquals("loggername", lsink.loggerName); + Assert.assertEquals(Level.INFO, lsink.logLevel); + + // log4j, wrong level, fallback to log4j default + sink = provider.getSink("endpoint12"); + Assert.assertEquals(Log4JSink.class, sink.getClass()); + lsink = (Log4JSink) sink; + Assert.assertEquals("loggername", lsink.loggerName); + Assert.assertEquals(Level.DEBUG, lsink.logLevel); + + } + + @Test + public void testNoMultipleEndpointsConfiguration() throws Exception { + Settings settings = Settings.builder() + .loadFromPath(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/endpoints/sink/configuration_no_multiple_endpoints.yml")) + .build(); + SinkProvider provider = new SinkProvider(settings, null, null, null); + InternalOpenSearchSink sink = (InternalOpenSearchSink) provider.defaultSink; + Assert.assertEquals("myownindex", sink.index); + Assert.assertEquals("auditevents", sink.type); + } } diff --git a/src/test/java/org/opensearch/security/auditlog/sink/WebhookAuditLogTest.java b/src/test/java/org/opensearch/security/auditlog/sink/WebhookAuditLogTest.java index 1e327750b6..2c2af154a0 100644 --- a/src/test/java/org/opensearch/security/auditlog/sink/WebhookAuditLogTest.java +++ b/src/test/java/org/opensearch/security/auditlog/sink/WebhookAuditLogTest.java @@ -51,326 +51,354 @@ public class WebhookAuditLogTest { @Before @After public void tearDown() { - if(server != null) { + if (server != null) { try { server.stop(); } catch (Exception e) { - //ignore + // ignore } } } - @Test - public void invalidConfFallbackTest() throws Exception { - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - - // provide no settings, fallback must be used - Settings settings = Settings.builder() - .put("path.home", ".") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .build(); - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); - MockWebhookAuditLog auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, fallback); - auditlog.store(msg); - // Webhook sink has failed ... - Assert.assertEquals(null, auditlog.webhookFormat); - // ... so message must be stored in fallback - Assert.assertEquals(1, fallback.messages.size()); - Assert.assertEquals(msg, fallback.messages.get(0)); - - } - - @Test - public void formatsTest() throws Exception { - - String url = "http://localhost"; - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - - // provide no format, defaults to TEXT - Settings settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("path.home", ".") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("plugins.security.ssl.transport.enforce_hostname_verification", false) - .build(); - - MockWebhookAuditLog auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); - auditlog.store(msg); - Assert.assertEquals(WebhookFormat.TEXT, auditlog.webhookFormat); - Assert.assertEquals(ContentType.TEXT_PLAIN, auditlog.webhookFormat.getContentType()); - Assert.assertTrue(auditlog.payload, !auditlog.payload.startsWith("{\"text\":")); - - // provide faulty format, defaults to TEXT - settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "idonotexist") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); - auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); - auditlog.store(msg); - Assert.assertEquals(WebhookFormat.TEXT, auditlog.webhookFormat); - Assert.assertEquals(ContentType.TEXT_PLAIN, auditlog.webhookFormat.getContentType()); - Assert.assertTrue(auditlog.payload, !auditlog.payload.startsWith("{\"text\":")); - auditlog.close(); - - // TEXT - settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "text") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); - auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); - auditlog.store(msg); - Assert.assertEquals(WebhookFormat.TEXT, auditlog.webhookFormat); - Assert.assertEquals(ContentType.TEXT_PLAIN, auditlog.webhookFormat.getContentType()); - Assert.assertTrue(auditlog.payload, !auditlog.payload.startsWith("{\"text\":")); - Assert.assertTrue(auditlog.payload, auditlog.payload.contains(AuditMessage.UTC_TIMESTAMP)); - Assert.assertTrue(auditlog.payload, auditlog.payload.contains("audit_request_remote_address")); - - // JSON - settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "json") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); - auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); - auditlog.store(msg); - System.out.println(auditlog.payload); - Assert.assertEquals(WebhookFormat.JSON, auditlog.webhookFormat); - Assert.assertEquals(ContentType.APPLICATION_JSON, auditlog.webhookFormat.getContentType()); - Assert.assertTrue(auditlog.payload, !auditlog.payload.startsWith("{\"text\":")); - Assert.assertTrue(auditlog.payload, auditlog.payload.contains(AuditMessage.UTC_TIMESTAMP)); + @Test + public void invalidConfFallbackTest() throws Exception { + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); + + // provide no settings, fallback must be used + Settings settings = Settings.builder() + .put("path.home", ".") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .build(); + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + MockWebhookAuditLog auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, fallback); + auditlog.store(msg); + // Webhook sink has failed ... + Assert.assertEquals(null, auditlog.webhookFormat); + // ... so message must be stored in fallback + Assert.assertEquals(1, fallback.messages.size()); + Assert.assertEquals(msg, fallback.messages.get(0)); + + } + + @Test + public void formatsTest() throws Exception { + + String url = "http://localhost"; + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); + + // provide no format, defaults to TEXT + Settings settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("path.home", ".") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("plugins.security.ssl.transport.enforce_hostname_verification", false) + .build(); + + MockWebhookAuditLog auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); + auditlog.store(msg); + Assert.assertEquals(WebhookFormat.TEXT, auditlog.webhookFormat); + Assert.assertEquals(ContentType.TEXT_PLAIN, auditlog.webhookFormat.getContentType()); + Assert.assertTrue(auditlog.payload, !auditlog.payload.startsWith("{\"text\":")); + + // provide faulty format, defaults to TEXT + settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "idonotexist") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); + auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); + auditlog.store(msg); + Assert.assertEquals(WebhookFormat.TEXT, auditlog.webhookFormat); + Assert.assertEquals(ContentType.TEXT_PLAIN, auditlog.webhookFormat.getContentType()); + Assert.assertTrue(auditlog.payload, !auditlog.payload.startsWith("{\"text\":")); + auditlog.close(); + + // TEXT + settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "text") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); + auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); + auditlog.store(msg); + Assert.assertEquals(WebhookFormat.TEXT, auditlog.webhookFormat); + Assert.assertEquals(ContentType.TEXT_PLAIN, auditlog.webhookFormat.getContentType()); + Assert.assertTrue(auditlog.payload, !auditlog.payload.startsWith("{\"text\":")); + Assert.assertTrue(auditlog.payload, auditlog.payload.contains(AuditMessage.UTC_TIMESTAMP)); + Assert.assertTrue(auditlog.payload, auditlog.payload.contains("audit_request_remote_address")); + + // JSON + settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "json") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); + auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); + auditlog.store(msg); + System.out.println(auditlog.payload); + Assert.assertEquals(WebhookFormat.JSON, auditlog.webhookFormat); + Assert.assertEquals(ContentType.APPLICATION_JSON, auditlog.webhookFormat.getContentType()); + Assert.assertTrue(auditlog.payload, !auditlog.payload.startsWith("{\"text\":")); + Assert.assertTrue(auditlog.payload, auditlog.payload.contains(AuditMessage.UTC_TIMESTAMP)); Assert.assertTrue(auditlog.payload, auditlog.payload.contains("audit_request_remote_address")); - // SLACK - settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "slack") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); - auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); - auditlog.store(msg); - Assert.assertEquals(WebhookFormat.SLACK, auditlog.webhookFormat); - Assert.assertEquals(ContentType.APPLICATION_JSON, auditlog.webhookFormat.getContentType()); - Assert.assertTrue(auditlog.payload, auditlog.payload.startsWith("{\"text\":")); - Assert.assertTrue(auditlog.payload, auditlog.payload.contains(AuditMessage.UTC_TIMESTAMP)); + // SLACK + settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "slack") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); + auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null); + auditlog.store(msg); + Assert.assertEquals(WebhookFormat.SLACK, auditlog.webhookFormat); + Assert.assertEquals(ContentType.APPLICATION_JSON, auditlog.webhookFormat.getContentType()); + Assert.assertTrue(auditlog.payload, auditlog.payload.startsWith("{\"text\":")); + Assert.assertTrue(auditlog.payload, auditlog.payload.contains(AuditMessage.UTC_TIMESTAMP)); Assert.assertTrue(auditlog.payload, auditlog.payload.contains("audit_request_remote_address")); - } - - - - @Test - public void invalidUrlTest() throws Exception { - - String url = "faultyurl"; - - final Settings settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "slack") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null);; - MockWebhookAuditLog auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, fallback); - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - auditlog.store(msg); - Assert.assertEquals(null, auditlog.url); - Assert.assertEquals(null, auditlog.payload); - Assert.assertEquals(null, auditlog.webhookUrl); - // message must be stored in fallback - Assert.assertEquals(1, fallback.messages.size()); - Assert.assertEquals(msg, fallback.messages.get(0)); - } - - @Test - public void noServerRunningHttpTest() throws Exception { - String url = "http://localhost:8080/endpoint"; - - Settings settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "slack") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); - - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null);; - WebhookSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - auditlog.store(msg); - // can't connect, no server running ... - Assert.assertEquals("http://localhost:8080/endpoint", auditlog.webhookUrl); - // ... message must be stored in fallback - Assert.assertEquals(1, fallback.messages.size()); - Assert.assertEquals(msg, fallback.messages.get(0)); - } - - - @Test - public void postGetHttpTest() throws Exception { - TestHttpHandler handler = new TestHttpHandler(); - - int port = findFreePort(); - server = ServerBootstrap.bootstrap() - .setListenerPort(port) - .setHttpProcessor(HttpProcessors.server("Test/1.1")) - .register("*", handler) - .create(); - - server.start(); - - String url = "http://localhost:" + port + "/endpoint"; - - // SLACK - Settings settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "slack") - .put("path.home", ".") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .build(); - - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null);; - WebhookSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - auditlog.store(msg); - Assert.assertTrue(handler.method.equals("POST")); - Assert.assertTrue(handler.body != null); - Assert.assertTrue(handler.body.startsWith("{\"text\":")); - assertStringContainsAllKeysAndValues(handler.body); - // no message stored on fallback - Assert.assertEquals(0, fallback.messages.size()); - handler.reset(); - - // TEXT - settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "texT") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); - - auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); - auditlog.store(msg); - Assert.assertTrue(handler.method.equals("POST")); - Assert.assertTrue(handler.body != null); - System.out.println(handler.body); - Assert.assertFalse(handler.body.contains("{")); - assertStringContainsAllKeysAndValues(handler.body); - handler.reset(); - - // JSON - settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "JSon") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); - - auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); - auditlog.store(msg); - Assert.assertTrue(handler.method.equals("POST")); - Assert.assertTrue(handler.body != null); - Assert.assertTrue(handler.body.contains("{")); - assertStringContainsAllKeysAndValues(handler.body); - handler.reset(); - - // URL POST - settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "URL_PARAMETER_POST") - .put("path.home", ".") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .build(); - - auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); - auditlog.store(msg); - Assert.assertTrue(handler.method.equals("POST")); - Assert.assertTrue(handler.body.equals("")); - Assert.assertTrue(!handler.body.contains("{")); - assertStringContainsAllKeysAndValues(URLDecoder.decode(handler.uri, StandardCharsets.UTF_8.displayName())); - handler.reset(); - - // URL GET - settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "URL_PARAMETER_GET") - .put("path.home", ".") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .build(); - - auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); - auditlog.store(msg); - Assert.assertTrue(handler.method.equals("GET")); - Assert.assertEquals(null, handler.body); - assertStringContainsAllKeysAndValues(URLDecoder.decode(handler.uri, StandardCharsets.UTF_8.displayName())); - server.awaitTermination(TimeValue.ofSeconds(3)); - } - - @Test - public void httpsTestWithoutTLSServer() throws Exception { - - TestHttpHandler handler = new TestHttpHandler(); - - int port = findFreePort(); - server = ServerBootstrap.bootstrap() - .setListenerPort(port) - .setHttpProcessor(HttpProcessors.server("Test/1.1")) - .register("*", handler) - .create(); - - server.start(); - - String url = "https://localhost:" + port + "/endpoint"; - - Settings settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "slack") - .put("path.home", ".") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .build(); - - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null);; - WebhookSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); - AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - auditlog.store(msg); - Assert.assertTrue(handler.method == null); - Assert.assertTrue(handler.body == null); - Assert.assertTrue(handler.uri == null); - // ... so message must be stored in fallback - Assert.assertEquals(1, fallback.messages.size()); - Assert.assertEquals(msg, fallback.messages.get(0)); - server.awaitTermination(TimeValue.ofSeconds(3)); - } - - - @Test + } + + @Test + public void invalidUrlTest() throws Exception { + + String url = "faultyurl"; + + final Settings settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "slack") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + ; + MockWebhookAuditLog auditlog = new MockWebhookAuditLog(settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, fallback); + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); + auditlog.store(msg); + Assert.assertEquals(null, auditlog.url); + Assert.assertEquals(null, auditlog.payload); + Assert.assertEquals(null, auditlog.webhookUrl); + // message must be stored in fallback + Assert.assertEquals(1, fallback.messages.size()); + Assert.assertEquals(msg, fallback.messages.get(0)); + } + + @Test + public void noServerRunningHttpTest() throws Exception { + String url = "http://localhost:8080/endpoint"; + + Settings settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "slack") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); + + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + ; + WebhookSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); + auditlog.store(msg); + // can't connect, no server running ... + Assert.assertEquals("http://localhost:8080/endpoint", auditlog.webhookUrl); + // ... message must be stored in fallback + Assert.assertEquals(1, fallback.messages.size()); + Assert.assertEquals(msg, fallback.messages.get(0)); + } + + @Test + public void postGetHttpTest() throws Exception { + TestHttpHandler handler = new TestHttpHandler(); + + int port = findFreePort(); + server = ServerBootstrap.bootstrap() + .setListenerPort(port) + .setHttpProcessor(HttpProcessors.server("Test/1.1")) + .register("*", handler) + .create(); + + server.start(); + + String url = "http://localhost:" + port + "/endpoint"; + + // SLACK + Settings settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "slack") + .put("path.home", ".") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .build(); + + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + ; + WebhookSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); + auditlog.store(msg); + Assert.assertTrue(handler.method.equals("POST")); + Assert.assertTrue(handler.body != null); + Assert.assertTrue(handler.body.startsWith("{\"text\":")); + assertStringContainsAllKeysAndValues(handler.body); + // no message stored on fallback + Assert.assertEquals(0, fallback.messages.size()); + handler.reset(); + + // TEXT + settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "texT") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); + + auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); + auditlog.store(msg); + Assert.assertTrue(handler.method.equals("POST")); + Assert.assertTrue(handler.body != null); + System.out.println(handler.body); + Assert.assertFalse(handler.body.contains("{")); + assertStringContainsAllKeysAndValues(handler.body); + handler.reset(); + + // JSON + settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "JSon") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); + + auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); + auditlog.store(msg); + Assert.assertTrue(handler.method.equals("POST")); + Assert.assertTrue(handler.body != null); + Assert.assertTrue(handler.body.contains("{")); + assertStringContainsAllKeysAndValues(handler.body); + handler.reset(); + + // URL POST + settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "URL_PARAMETER_POST") + .put("path.home", ".") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .build(); + + auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); + auditlog.store(msg); + Assert.assertTrue(handler.method.equals("POST")); + Assert.assertTrue(handler.body.equals("")); + Assert.assertTrue(!handler.body.contains("{")); + assertStringContainsAllKeysAndValues(URLDecoder.decode(handler.uri, StandardCharsets.UTF_8.displayName())); + handler.reset(); + + // URL GET + settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "URL_PARAMETER_GET") + .put("path.home", ".") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .build(); + + auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); + auditlog.store(msg); + Assert.assertTrue(handler.method.equals("GET")); + Assert.assertEquals(null, handler.body); + assertStringContainsAllKeysAndValues(URLDecoder.decode(handler.uri, StandardCharsets.UTF_8.displayName())); + server.awaitTermination(TimeValue.ofSeconds(3)); + } + + @Test + public void httpsTestWithoutTLSServer() throws Exception { + + TestHttpHandler handler = new TestHttpHandler(); + + int port = findFreePort(); + server = ServerBootstrap.bootstrap() + .setListenerPort(port) + .setHttpProcessor(HttpProcessors.server("Test/1.1")) + .register("*", handler) + .create(); + + server.start(); + + String url = "https://localhost:" + port + "/endpoint"; + + Settings settings = Settings.builder() + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "slack") + .put("path.home", ".") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .build(); + + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + ; + WebhookSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); + AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); + auditlog.store(msg); + Assert.assertTrue(handler.method == null); + Assert.assertTrue(handler.body == null); + Assert.assertTrue(handler.uri == null); + // ... so message must be stored in fallback + Assert.assertEquals(1, fallback.messages.size()); + Assert.assertEquals(msg, fallback.messages.get(0)); + server.awaitTermination(TimeValue.ofSeconds(3)); + } + + @Test public void httpsTest() throws Exception { TestHttpHandler handler = new TestHttpHandler(); - int port = findFreePort(); + int port = findFreePort(); server = ServerBootstrap.bootstrap() - .setListenerPort(port) - .setHttpProcessor(HttpProcessors.server("Test/1.1")) - .setSslContext(createSSLContext()) - .register("*", handler) - .create(); + .setListenerPort(port) + .setHttpProcessor(HttpProcessors.server("Test/1.1")) + .setSslContext(createSSLContext()) + .register("*", handler) + .create(); server.start(); AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); @@ -379,30 +407,30 @@ public void httpsTest() throws Exception { // try with ssl verification on, no trust ca, must fail Settings settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "slack") - .put("path.home", ".") - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .build(); - - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); - WebhookSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "slack") + .put("path.home", ".") + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .build(); + + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + WebhookSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); Assert.assertNull(handler.body); Assert.assertNull(handler.body); - // message must be stored in fallback - Assert.assertEquals(1, fallback.messages.size()); - Assert.assertEquals(msg, fallback.messages.get(0)); + // message must be stored in fallback + Assert.assertEquals(1, fallback.messages.size()); + Assert.assertEquals(msg, fallback.messages.get(0)); // disable ssl verification, no ca, call must succeed handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put("plugins.security.audit.config.webhook.ssl.verify", false) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put("plugins.security.audit.config.webhook.ssl.verify", false) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertTrue(handler.method.equals("POST")); @@ -413,12 +441,15 @@ public void httpsTest() throws Exception { // enable ssl verification, provide correct trust ca, call must succeed handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertTrue(handler.method.equals("POST")); @@ -429,48 +460,54 @@ public void httpsTest() throws Exception { // enable ssl verification, provide wrong trust ca, call must succeed handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore_fail.jks")) - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore_fail.jks") + ) + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); Assert.assertNull(handler.body); Assert.assertNull(handler.body); - server.awaitTermination(TimeValue.ofSeconds(3)); + server.awaitTermination(TimeValue.ofSeconds(3)); } - @Test + @Test public void httpsTestPemDefault() throws Exception { final int port = findFreePort(); - TestHttpHandler handler = new TestHttpHandler(); + TestHttpHandler handler = new TestHttpHandler(); server = ServerBootstrap.bootstrap() - .setListenerPort(port) - .setHttpProcessor(HttpProcessors.server("Test/1.1")) - .setSslContext(createSSLContext()) - .register("*", handler) - .create(); + .setListenerPort(port) + .setHttpProcessor(HttpProcessors.server("Test/1.1")) + .setSslContext(createSSLContext()) + .register("*", handler) + .create(); server.start(); AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); String url = "https://localhost:" + port + "/endpoint"; // test default with filepath handler.reset(); Settings settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put("plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/root-ca.pem")) - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put( + "plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/root-ca.pem") + ) + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); AuditLogSink auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertTrue(handler.method.equals("POST")); @@ -481,12 +518,15 @@ public void httpsTestPemDefault() throws Exception { // test default with missing filepath and fallback to correct Security settings handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertTrue(handler.method.equals("POST")); @@ -497,13 +537,16 @@ public void httpsTestPemDefault() throws Exception { // test default with wrong filepath and fallback to wrong Security settings handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put("plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", "wrong") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore_fail.jks")) - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put("plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", "wrong") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore_fail.jks") + ) + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); @@ -513,12 +556,12 @@ public void httpsTestPemDefault() throws Exception { // test default with wrong/no filepath and no fallback to Security settings, must fail handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", "wrong") - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", "wrong") + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); @@ -528,12 +571,15 @@ public void httpsTestPemDefault() throws Exception { // test default with existing but wrong PEM, no fallback handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put("plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.crt.pem")) - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put( + "plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.crt.pem") + ) + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); @@ -543,49 +589,58 @@ public void httpsTestPemDefault() throws Exception { // test default with existing but wrong PEM, fallback present but pemtrustedcas_filepath takes precedence and must fail handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.config.webhook.url", url) - .put("plugins.security.audit.config.webhook.format", "jSoN") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.crt.pem")) - .put("plugins.security.audit.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.config.webhook.url", url) + .put("plugins.security.audit.config.webhook.format", "jSoN") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put( + "plugins.security.audit.config.webhook.ssl.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.crt.pem") + ) + .put("plugins.security.audit.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, ConfigConstants.SECURITY_AUDIT_CONFIG_DEFAULT, null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); Assert.assertNull(handler.body); Assert.assertNull(handler.body); - server.awaitTermination(TimeValue.ofSeconds(3)); - } + server.awaitTermination(TimeValue.ofSeconds(3)); + } - @Test + @Test public void httpsTestPemEndpoint() throws Exception { TestHttpHandler handler = new TestHttpHandler(); - int port = findFreePort(); + int port = findFreePort(); server = ServerBootstrap.bootstrap() - .setListenerPort(port) - .setHttpProcessor(HttpProcessors.server("Test/1.1")) - .setSslContext(createSSLContext()) - .register("*", handler) - .create(); + .setListenerPort(port) + .setHttpProcessor(HttpProcessors.server("Test/1.1")) + .setSslContext(createSSLContext()) + .register("*", handler) + .create(); server.start(); AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); String url = "https://localhost:" + port + "/endpoint"; // test default with filepath handler.reset(); Settings settings = Settings.builder() - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/root-ca.pem")) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") + .put( + "plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/root-ca.pem") + ) + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); AuditLogSink auditlog = new WebhookSink("name", settings, "plugins.security.audit.endpoints.endpoint1.config", null, fallback); auditlog.store(msg); Assert.assertTrue(handler.method.equals("POST")); @@ -596,12 +651,15 @@ public void httpsTestPemEndpoint() throws Exception { // test default with missing filepath and fallback to correct Security settings handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks") + ) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, "plugins.security.audit.endpoints.endpoint1.config", null, fallback); auditlog.store(msg); Assert.assertTrue(handler.method.equals("POST")); @@ -612,12 +670,15 @@ public void httpsTestPemEndpoint() throws Exception { // test default with wrong filepath and fallback to wrong Security settings handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore_fail.jks")) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore_fail.jks") + ) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, "plugins.security.audit.endpoints.endpoint1.config", null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); @@ -627,11 +688,11 @@ public void httpsTestPemEndpoint() throws Exception { // test default with wrong/no filepath and no fallback to Security settings, must fail handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, "plugins.security.audit.endpoints.endpoint1.config", null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); @@ -641,49 +702,55 @@ public void httpsTestPemEndpoint() throws Exception { // test default with existing but wrong PEM, no fallback handler.reset(); settings = Settings.builder() - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.pemtrustedcas_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.crt.pem")) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) + .put( + "plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.pemtrustedcas_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("auditlog/spock.crt.pem") + ) + .put("path.home", ".") + .build(); auditlog = new WebhookSink("name", settings, "plugins.security.audit.endpoints.endpoint1.config", null, fallback); auditlog.store(msg); Assert.assertNull(handler.method); Assert.assertNull(handler.body); Assert.assertNull(handler.body); - server.awaitTermination(TimeValue.ofSeconds(3)); - } + server.awaitTermination(TimeValue.ofSeconds(3)); + } - @Test + @Test public void httpsTestPemContentEndpoint() throws Exception { TestHttpHandler handler = new TestHttpHandler(); - int port = findFreePort(); + int port = findFreePort(); server = ServerBootstrap.bootstrap() - .setListenerPort(port) - .setHttpProcessor(HttpProcessors.server("Test/1.1")) - .setSslContext(createSSLContext()) - .register("*", handler) - .create(); + .setListenerPort(port) + .setHttpProcessor(HttpProcessors.server("Test/1.1")) + .setSslContext(createSSLContext()) + .register("*", handler) + .create(); server.start(); AuditMessage msg = MockAuditMessageFactory.validAuditMessage(); - LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); + LoggingSink fallback = new LoggingSink("test", Settings.EMPTY, null, null); String url = "https://localhost:" + port + "/endpoint"; - // test with filecontent + // test with filecontent handler.reset(); Settings settings = Settings.builder() - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.pemtrustedcas_content", FileHelper.loadFile("auditlog/root-ca.pem")) - .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) - .put("path.home", ".") - .build(); + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.url", url) + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.format", "jSoN") + .put( + "plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.pemtrustedcas_content", + FileHelper.loadFile("auditlog/root-ca.pem") + ) + .put("plugins.security.audit.endpoints.endpoint1.config.webhook.ssl.verify", true) + .put("path.home", ".") + .build(); AuditLogSink auditlog = new WebhookSink("name", settings, "plugins.security.audit.endpoints.endpoint1.config", null, fallback); auditlog.store(msg); @@ -692,52 +759,51 @@ public void httpsTestPemContentEndpoint() throws Exception { Assert.assertTrue(handler.body.contains("{")); assertStringContainsAllKeysAndValues(handler.body); - server.awaitTermination(TimeValue.ofSeconds(3)); - } - - // for TLS support on our in-memory server - private SSLContext createSSLContext() throws Exception { - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory - .getDefaultAlgorithm()); - final KeyStore trustStore = KeyStore.getInstance("JKS"); - InputStream trustStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks").toFile()); - trustStore.load(trustStream, "changeit".toCharArray()); - tmf.init(trustStore); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - final KeyStore keyStore = KeyStore.getInstance("JKS"); - InputStream keyStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks").toFile()); - - keyStore.load(keyStream, "changeit".toCharArray()); - kmf.init(keyStore, "changeit".toCharArray()); - - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); - sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - return sslContext; - } - - private void assertStringContainsAllKeysAndValues(String in) { - System.out.println(in); - Assert.assertTrue(in, in.contains(AuditMessage.FORMAT_VERSION)); - Assert.assertTrue(in, in.contains(AuditMessage.CATEGORY)); - Assert.assertTrue(in, in.contains(AuditMessage.FORMAT_VERSION)); - Assert.assertTrue(in, in.contains(AuditMessage.REMOTE_ADDRESS)); - Assert.assertTrue(in, in.contains(AuditMessage.ORIGIN)); - Assert.assertTrue(in, in.contains(AuditMessage.REQUEST_LAYER)); - Assert.assertTrue(in, in.contains(AuditMessage.TRANSPORT_REQUEST_TYPE)); - Assert.assertTrue(in, in.contains(AuditMessage.UTC_TIMESTAMP)); - Assert.assertTrue(in, in.contains(AuditCategory.FAILED_LOGIN.name())); - Assert.assertTrue(in, in.contains("FAILED_LOGIN")); - Assert.assertTrue(in, in.contains("John Doe")); - Assert.assertTrue(in, in.contains("8.8.8.8")); - //Assert.assertTrue(in, in.contains("CN=kirk,OU=client,O=client,L=test,C=DE")); - } - - private int findFreePort() { - try (ServerSocket serverSocket = new ServerSocket(0)) { - return serverSocket.getLocalPort(); - } catch (IOException e) { - throw new RuntimeException("Failed to find free port", e); - } - } + server.awaitTermination(TimeValue.ofSeconds(3)); + } + + // for TLS support on our in-memory server + private SSLContext createSSLContext() throws Exception { + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + final KeyStore trustStore = KeyStore.getInstance("JKS"); + InputStream trustStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks").toFile()); + trustStore.load(trustStream, "changeit".toCharArray()); + tmf.init(trustStore); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + final KeyStore keyStore = KeyStore.getInstance("JKS"); + InputStream keyStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks").toFile()); + + keyStore.load(keyStream, "changeit".toCharArray()); + kmf.init(keyStore, "changeit".toCharArray()); + + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + return sslContext; + } + + private void assertStringContainsAllKeysAndValues(String in) { + System.out.println(in); + Assert.assertTrue(in, in.contains(AuditMessage.FORMAT_VERSION)); + Assert.assertTrue(in, in.contains(AuditMessage.CATEGORY)); + Assert.assertTrue(in, in.contains(AuditMessage.FORMAT_VERSION)); + Assert.assertTrue(in, in.contains(AuditMessage.REMOTE_ADDRESS)); + Assert.assertTrue(in, in.contains(AuditMessage.ORIGIN)); + Assert.assertTrue(in, in.contains(AuditMessage.REQUEST_LAYER)); + Assert.assertTrue(in, in.contains(AuditMessage.TRANSPORT_REQUEST_TYPE)); + Assert.assertTrue(in, in.contains(AuditMessage.UTC_TIMESTAMP)); + Assert.assertTrue(in, in.contains(AuditCategory.FAILED_LOGIN.name())); + Assert.assertTrue(in, in.contains("FAILED_LOGIN")); + Assert.assertTrue(in, in.contains("John Doe")); + Assert.assertTrue(in, in.contains("8.8.8.8")); + // Assert.assertTrue(in, in.contains("CN=kirk,OU=client,O=client,L=test,C=DE")); + } + + private int findFreePort() { + try (ServerSocket serverSocket = new ServerSocket(0)) { + return serverSocket.getLocalPort(); + } catch (IOException e) { + throw new RuntimeException("Failed to find free port", e); + } + } } diff --git a/src/test/java/org/opensearch/security/auth/InternalAuthBackendTests.java b/src/test/java/org/opensearch/security/auth/InternalAuthBackendTests.java index 3821be7038..c059c890ab 100644 --- a/src/test/java/org/opensearch/security/auth/InternalAuthBackendTests.java +++ b/src/test/java/org/opensearch/security/auth/InternalAuthBackendTests.java @@ -51,7 +51,7 @@ private char[] createArrayFromPasswordBytes(byte[] password) { CharBuffer buf = StandardCharsets.UTF_8.decode(wrap); char[] array = new char[buf.limit()]; buf.get(array); - Arrays.fill(password, (byte)0); + Arrays.fill(password, (byte) 0); return array; } @@ -68,12 +68,11 @@ public void testHashActionWithValidUserValidPassword() { char[] array = createArrayFromPasswordBytes(validPasswordBytes); - when(internalUsersModel.getHash(validUsernameAuth.getUsername())).thenReturn(hash); when(internalUsersModel.exists(validUsernameAuth.getUsername())).thenReturn(true); doReturn(true).when(internalAuthenticationBackend).passwordMatchesHash(Mockito.any(String.class), Mockito.any(char[].class)); - //Act + // Act internalAuthenticationBackend.authenticate(validUsernameAuth); verify(internalAuthenticationBackend, times(1)).passwordMatchesHash(hash, array); @@ -95,9 +94,11 @@ public void testHashActionWithValidUserInvalidPassword() { when(internalUsersModel.getHash("admin")).thenReturn(hash); when(internalUsersModel.exists("admin")).thenReturn(true); - OpenSearchSecurityException ex = Assert.assertThrows(OpenSearchSecurityException.class, - () -> internalAuthenticationBackend.authenticate(validUsernameAuth)); - assert(ex.getMessage().contains("password does not match")); + OpenSearchSecurityException ex = Assert.assertThrows( + OpenSearchSecurityException.class, + () -> internalAuthenticationBackend.authenticate(validUsernameAuth) + ); + assert (ex.getMessage().contains("password does not match")); verify(internalAuthenticationBackend, times(1)).passwordMatchesHash(hash, array); } @@ -114,11 +115,13 @@ public void testHashActionWithInvalidUserValidPassword() { char[] array = createArrayFromPasswordBytes(validPasswordBytes); when(internalUsersModel.exists("ertyuiykgjjfguyifdghc")).thenReturn(false); - when(internalAuthenticationBackend.passwordMatchesHash(hash, array)).thenReturn(true); //Say that the password is correct + when(internalAuthenticationBackend.passwordMatchesHash(hash, array)).thenReturn(true); // Say that the password is correct - OpenSearchSecurityException ex = Assert.assertThrows(OpenSearchSecurityException.class, - () -> internalAuthenticationBackend.authenticate(invalidUsernameAuth)); - assert(ex.getMessage().contains("not found")); + OpenSearchSecurityException ex = Assert.assertThrows( + OpenSearchSecurityException.class, + () -> internalAuthenticationBackend.authenticate(invalidUsernameAuth) + ); + assert (ex.getMessage().contains("not found")); verify(internalAuthenticationBackend, times(1)).passwordMatchesHash(hash, array); } @@ -136,10 +139,11 @@ public void testHashActionWithInvalidUserInvalidPassword() { when(internalUsersModel.exists("ertyuiykgjjfguyifdghc")).thenReturn(false); - - OpenSearchSecurityException ex = Assert.assertThrows(OpenSearchSecurityException.class, - () -> internalAuthenticationBackend.authenticate(invalidUsernameAuth)); + OpenSearchSecurityException ex = Assert.assertThrows( + OpenSearchSecurityException.class, + () -> internalAuthenticationBackend.authenticate(invalidUsernameAuth) + ); verify(internalAuthenticationBackend, times(1)).passwordMatchesHash(hash, array); - assert(ex.getMessage().contains("not found")); + assert (ex.getMessage().contains("not found")); } } diff --git a/src/test/java/org/opensearch/security/auth/RolesInjectorTest.java b/src/test/java/org/opensearch/security/auth/RolesInjectorTest.java index 0656f9ccd1..63eb32f862 100644 --- a/src/test/java/org/opensearch/security/auth/RolesInjectorTest.java +++ b/src/test/java/org/opensearch/security/auth/RolesInjectorTest.java @@ -34,7 +34,6 @@ import static org.mockito.Mockito.mock; import static org.opensearch.security.support.ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES; - public class RolesInjectorTest { private TransportRequest transportRequest; @@ -76,13 +75,7 @@ public void testInjected() { @Test public void testCorruptedInjection() { - List corruptedStrs = Arrays.asList( - "invalid", - "role_1,role_2", - " | ", - " ", - "|" - ); + List corruptedStrs = Arrays.asList("invalid", "role_1,role_2", " | ", " ", "|"); corruptedStrs.forEach(name -> { ThreadContext threadContext = new ThreadContext(Settings.EMPTY); diff --git a/src/test/java/org/opensearch/security/auth/UserInjectorTest.java b/src/test/java/org/opensearch/security/auth/UserInjectorTest.java index 09bc1653a4..e9570b1455 100644 --- a/src/test/java/org/opensearch/security/auth/UserInjectorTest.java +++ b/src/test/java/org/opensearch/security/auth/UserInjectorTest.java @@ -43,9 +43,7 @@ public class UserInjectorTest { @Before public void setup() { threadPool = mock(ThreadPool.class); - Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true) - .build(); + Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_INJECT_USER_ENABLED, true).build(); threadContext = new ThreadContext(settings); Mockito.when(threadPool.getThreadContext()).thenReturn(threadContext); transportRequest = mock(TransportRequest.class); diff --git a/src/test/java/org/opensearch/security/auth/blocking/HeapBasedClientBlockRegistryTest.java b/src/test/java/org/opensearch/security/auth/blocking/HeapBasedClientBlockRegistryTest.java index 391b48ed70..3adc7a577f 100644 --- a/src/test/java/org/opensearch/security/auth/blocking/HeapBasedClientBlockRegistryTest.java +++ b/src/test/java/org/opensearch/security/auth/blocking/HeapBasedClientBlockRegistryTest.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.blocking; @@ -23,33 +23,33 @@ import static org.junit.Assert.assertTrue; public class HeapBasedClientBlockRegistryTest { - + @Test - public void simpleTest() throws Exception { + public void simpleTest() throws Exception { HeapBasedClientBlockRegistry registry = new HeapBasedClientBlockRegistry<>(50, 3, String.class); - + assertFalse(registry.isBlocked("a")); registry.block("a"); assertTrue(registry.isBlocked("a")); - + registry.block("b"); assertTrue(registry.isBlocked("a")); assertTrue(registry.isBlocked("b")); - + registry.block("c"); assertTrue(registry.isBlocked("a")); assertTrue(registry.isBlocked("b")); assertTrue(registry.isBlocked("c")); - + registry.block("d"); assertFalse(registry.isBlocked("a")); assertTrue(registry.isBlocked("b")); assertTrue(registry.isBlocked("c")); assertTrue(registry.isBlocked("d")); } - + @Test - public void expiryTest() throws Exception { + public void expiryTest() throws Exception { HeapBasedClientBlockRegistry registry = new HeapBasedClientBlockRegistry<>(50, 3, String.class); assertFalse(registry.isBlocked("a")); diff --git a/src/test/java/org/opensearch/security/auth/limiting/AddressBasedRateLimiterTest.java b/src/test/java/org/opensearch/security/auth/limiting/AddressBasedRateLimiterTest.java index bd0cadfa6c..827bfa24b6 100644 --- a/src/test/java/org/opensearch/security/auth/limiting/AddressBasedRateLimiterTest.java +++ b/src/test/java/org/opensearch/security/auth/limiting/AddressBasedRateLimiterTest.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.limiting; diff --git a/src/test/java/org/opensearch/security/auth/limiting/HeapBasedRateTrackerTest.java b/src/test/java/org/opensearch/security/auth/limiting/HeapBasedRateTrackerTest.java index d3383f2dbe..c92c328564 100644 --- a/src/test/java/org/opensearch/security/auth/limiting/HeapBasedRateTrackerTest.java +++ b/src/test/java/org/opensearch/security/auth/limiting/HeapBasedRateTrackerTest.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.limiting; @@ -26,11 +26,11 @@ import static org.junit.Assert.assertTrue; public class HeapBasedRateTrackerTest { - + @Test - public void simpleTest() throws Exception { + public void simpleTest() throws Exception { HeapBasedRateTracker tracker = new HeapBasedRateTracker<>(100, 5, 100_000); - + assertFalse(tracker.track("a")); assertFalse(tracker.track("a")); assertFalse(tracker.track("a")); @@ -38,12 +38,12 @@ public void simpleTest() throws Exception { assertTrue(tracker.track("a")); } - + @Test @Ignore // https://github.com/opensearch-project/security/issues/2193 - public void expiryTest() throws Exception { + public void expiryTest() throws Exception { HeapBasedRateTracker tracker = new HeapBasedRateTracker<>(100, 5, 100_000); - + assertFalse(tracker.track("a")); assertFalse(tracker.track("a")); assertFalse(tracker.track("a")); @@ -55,38 +55,37 @@ public void expiryTest() throws Exception { assertFalse(tracker.track("b")); assertFalse(tracker.track("b")); assertTrue(tracker.track("b")); - - assertFalse(tracker.track("c")); - + + assertFalse(tracker.track("c")); + Thread.sleep(50); - - assertFalse(tracker.track("c")); - assertFalse(tracker.track("c")); - assertFalse(tracker.track("c")); - - Thread.sleep(55); - - assertFalse(tracker.track("c")); - assertTrue(tracker.track("c")); - - assertFalse(tracker.track("a")); - + + assertFalse(tracker.track("c")); + assertFalse(tracker.track("c")); + assertFalse(tracker.track("c")); + Thread.sleep(55); - assertFalse(tracker.track("c")); - assertFalse(tracker.track("c")); - assertTrue(tracker.track("c")); - + assertFalse(tracker.track("c")); + assertTrue(tracker.track("c")); + + assertFalse(tracker.track("a")); + + Thread.sleep(55); + assertFalse(tracker.track("c")); + assertFalse(tracker.track("c")); + assertTrue(tracker.track("c")); + } - + @Test @Ignore // https://github.com/opensearch-project/security/issues/2193 - public void maxTwoTriesTest() throws Exception { + public void maxTwoTriesTest() throws Exception { HeapBasedRateTracker tracker = new HeapBasedRateTracker<>(100, 2, 100_000); - + assertFalse(tracker.track("a")); assertTrue(tracker.track("a")); - + assertFalse(tracker.track("b")); Thread.sleep(50); assertTrue(tracker.track("b")); diff --git a/src/test/java/org/opensearch/security/auth/limiting/UserNameBasedRateLimiterTest.java b/src/test/java/org/opensearch/security/auth/limiting/UserNameBasedRateLimiterTest.java index 9e7d95fd00..e42d2bd1b8 100644 --- a/src/test/java/org/opensearch/security/auth/limiting/UserNameBasedRateLimiterTest.java +++ b/src/test/java/org/opensearch/security/auth/limiting/UserNameBasedRateLimiterTest.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2019 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.auth.limiting; diff --git a/src/test/java/org/opensearch/security/authtoken/jwt/JwtVendorTest.java b/src/test/java/org/opensearch/security/authtoken/jwt/JwtVendorTest.java index 3330477721..55ce10df65 100644 --- a/src/test/java/org/opensearch/security/authtoken/jwt/JwtVendorTest.java +++ b/src/test/java/org/opensearch/security/authtoken/jwt/JwtVendorTest.java @@ -27,8 +27,7 @@ public class JwtVendorTest { @Test public void testCreateJwkFromSettings() throws Exception { - Settings settings = Settings.builder() - .put("signing_key", "abc123").build(); + Settings settings = Settings.builder().put("signing_key", "abc123").build(); JsonWebKey jwk = JwtVendor.createJwkFromSettings(settings); Assert.assertEquals("HS512", jwk.getAlgorithm()); @@ -36,10 +35,9 @@ public void testCreateJwkFromSettings() throws Exception { Assert.assertEquals("abc123", jwk.getProperty("k")); } - @Test (expected = Exception.class) - public void testCreateJwkFromSettingsWithoutSigningKey() throws Exception{ - Settings settings = Settings.builder() - .put("jwt", "").build(); + @Test(expected = Exception.class) + public void testCreateJwkFromSettingsWithoutSigningKey() throws Exception { + Settings settings = Settings.builder().put("jwt", "").build(); JwtVendor.createJwkFromSettings(settings); } @@ -51,9 +49,9 @@ public void testCreateJwtWithRoles() throws Exception { List roles = List.of("IT", "HR"); String expectedRoles = "IT,HR"; Integer expirySeconds = 300; - LongSupplier currentTime = () -> (int)100; + LongSupplier currentTime = () -> (int) 100; String claimsEncryptionKey = RandomStringUtils.randomAlphanumeric(16); - Settings settings = Settings.builder().put("signing_key", "abc123").put("encryption_key", claimsEncryptionKey).build(); + Settings settings = Settings.builder().put("signing_key", "abc123").put("encryption_key", claimsEncryptionKey).build(); Long expectedExp = currentTime.getAsLong() + (expirySeconds * 1000); JwtVendor jwtVendor = new JwtVendor(settings, currentTime); @@ -72,45 +70,45 @@ public void testCreateJwtWithRoles() throws Exception { Assert.assertEquals(expectedRoles, EncryptionDecryptionUtil.decrypt(claimsEncryptionKey, jwt.getClaim("er").toString())); } - @Test (expected = Exception.class) + @Test(expected = Exception.class) public void testCreateJwtWithBadExpiry() throws Exception { String issuer = "cluster_0"; String subject = "admin"; String audience = "audience_0"; - List roles = List.of("admin"); + List roles = List.of("admin"); Integer expirySeconds = -300; String claimsEncryptionKey = RandomStringUtils.randomAlphanumeric(16); - Settings settings = Settings.builder().put("signing_key", "abc123").put("encryption_key", claimsEncryptionKey).build(); + Settings settings = Settings.builder().put("signing_key", "abc123").put("encryption_key", claimsEncryptionKey).build(); JwtVendor jwtVendor = new JwtVendor(settings); jwtVendor.createJwt(issuer, subject, audience, expirySeconds, roles); } - @Test (expected = Exception.class) + @Test(expected = Exception.class) public void testCreateJwtWithBadEncryptionKey() throws Exception { String issuer = "cluster_0"; String subject = "admin"; String audience = "audience_0"; - List roles = List.of("admin"); + List roles = List.of("admin"); Integer expirySeconds = 300; - Settings settings = Settings.builder().put("signing_key", "abc123").build(); + Settings settings = Settings.builder().put("signing_key", "abc123").build(); JwtVendor jwtVendor = new JwtVendor(settings); jwtVendor.createJwt(issuer, subject, audience, expirySeconds, roles); } - @Test (expected = Exception.class) + @Test(expected = Exception.class) public void testCreateJwtWithBadRoles() throws Exception { String issuer = "cluster_0"; String subject = "admin"; String audience = "audience_0"; - List roles = null; + List roles = null; Integer expirySecond = 300; String claimsEncryptionKey = RandomStringUtils.randomAlphanumeric(16); - Settings settings = Settings.builder().put("signing_key", "abc123").put("encryption_key", claimsEncryptionKey).build(); + Settings settings = Settings.builder().put("signing_key", "abc123").put("encryption_key", claimsEncryptionKey).build(); JwtVendor jwtVendor = new JwtVendor(settings); diff --git a/src/test/java/org/opensearch/security/cache/CachingTest.java b/src/test/java/org/opensearch/security/cache/CachingTest.java index 5276196856..4bff91a1f3 100644 --- a/src/test/java/org/opensearch/security/cache/CachingTest.java +++ b/src/test/java/org/opensearch/security/cache/CachingTest.java @@ -23,7 +23,7 @@ import org.opensearch.security.test.helper.rest.RestHelper; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class CachingTest extends SingleClusterTest{ +public class CachingTest extends SingleClusterTest { @Override protected String getResourceFolder() { @@ -84,16 +84,28 @@ public void testRestCachingWithImpersonation() throws Exception { final Settings settings = Settings.builder().putList("plugins.security.authcz.rest_impersonation_user.dummy", "*").build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings); final RestHelper rh = nonSslRestHelper(); - HttpResponse res = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", new BasicHeader("opendistro_security_impersonate_as", "impuser")); + HttpResponse res = rh.executeGetRequest( + "_opendistro/_security/authinfo?pretty", + new BasicHeader("opendistro_security_impersonate_as", "impuser") + ); System.out.println(res.getBody()); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - res = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", new BasicHeader("opendistro_security_impersonate_as", "impuser")); + res = rh.executeGetRequest( + "_opendistro/_security/authinfo?pretty", + new BasicHeader("opendistro_security_impersonate_as", "impuser") + ); System.out.println(res.getBody()); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - res = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", new BasicHeader("opendistro_security_impersonate_as", "impuser")); + res = rh.executeGetRequest( + "_opendistro/_security/authinfo?pretty", + new BasicHeader("opendistro_security_impersonate_as", "impuser") + ); System.out.println(res.getBody()); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); - res = rh.executeGetRequest("_opendistro/_security/authinfo?pretty", new BasicHeader("opendistro_security_impersonate_as", "impuser2")); + res = rh.executeGetRequest( + "_opendistro/_security/authinfo?pretty", + new BasicHeader("opendistro_security_impersonate_as", "impuser2") + ); System.out.println(res.getBody()); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); diff --git a/src/test/java/org/opensearch/security/cache/DummyAuthenticationBackend.java b/src/test/java/org/opensearch/security/cache/DummyAuthenticationBackend.java index f41ddade65..5e7980f431 100644 --- a/src/test/java/org/opensearch/security/cache/DummyAuthenticationBackend.java +++ b/src/test/java/org/opensearch/security/cache/DummyAuthenticationBackend.java @@ -19,14 +19,12 @@ import org.opensearch.security.user.AuthCredentials; import org.opensearch.security.user.User; - public class DummyAuthenticationBackend implements AuthenticationBackend { private static volatile long authCount; private static volatile long existsCount; - public DummyAuthenticationBackend(final Settings settings, final Path configPath) { - } + public DummyAuthenticationBackend(final Settings settings, final Path configPath) {} @Override public String getType() { @@ -54,7 +52,7 @@ public static long getExistsCount() { } public static void reset() { - authCount=0; - existsCount=0; + authCount = 0; + existsCount = 0; } } diff --git a/src/test/java/org/opensearch/security/cache/DummyAuthorizer.java b/src/test/java/org/opensearch/security/cache/DummyAuthorizer.java index 4c489f0c00..8f8a507cb8 100644 --- a/src/test/java/org/opensearch/security/cache/DummyAuthorizer.java +++ b/src/test/java/org/opensearch/security/cache/DummyAuthorizer.java @@ -19,13 +19,11 @@ import org.opensearch.security.user.AuthCredentials; import org.opensearch.security.user.User; - public class DummyAuthorizer implements AuthorizationBackend { private static volatile long count; - public DummyAuthorizer(final Settings settings, final Path configPath) { - } + public DummyAuthorizer(final Settings settings, final Path configPath) {} @Override public String getType() { @@ -44,7 +42,7 @@ public static long getCount() { } public static void reset() { - count=0; + count = 0; } } diff --git a/src/test/java/org/opensearch/security/cache/DummyHTTPAuthenticator.java b/src/test/java/org/opensearch/security/cache/DummyHTTPAuthenticator.java index 48bead257b..55c2e789c6 100644 --- a/src/test/java/org/opensearch/security/cache/DummyHTTPAuthenticator.java +++ b/src/test/java/org/opensearch/security/cache/DummyHTTPAuthenticator.java @@ -25,8 +25,7 @@ public class DummyHTTPAuthenticator implements HTTPAuthenticator { private static volatile long count; - public DummyHTTPAuthenticator(final Settings settings, final Path configPath) { - } + public DummyHTTPAuthenticator(final Settings settings, final Path configPath) {} @Override public String getType() { @@ -49,6 +48,6 @@ public static long getCount() { } public static void reset() { - count=0; + count = 0; } } diff --git a/src/test/java/org/opensearch/security/ccstest/CrossClusterMinimalRoundtripSearchTests.java b/src/test/java/org/opensearch/security/ccstest/CrossClusterMinimalRoundtripSearchTests.java index 292a0d38d8..db948b77df 100644 --- a/src/test/java/org/opensearch/security/ccstest/CrossClusterMinimalRoundtripSearchTests.java +++ b/src/test/java/org/opensearch/security/ccstest/CrossClusterMinimalRoundtripSearchTests.java @@ -13,5 +13,7 @@ public class CrossClusterMinimalRoundtripSearchTests extends CrossClusterSearchTests { @Override - protected boolean ccsMinimizeRoundtrips() { return true; } + protected boolean ccsMinimizeRoundtrips() { + return true; + } } diff --git a/src/test/java/org/opensearch/security/ccstest/CrossClusterSearchTests.java b/src/test/java/org/opensearch/security/ccstest/CrossClusterSearchTests.java index 64e73202c7..fad6c77a1a 100644 --- a/src/test/java/org/opensearch/security/ccstest/CrossClusterSearchTests.java +++ b/src/test/java/org/opensearch/security/ccstest/CrossClusterSearchTests.java @@ -67,15 +67,21 @@ import static org.hamcrest.Matchers.not; public class CrossClusterSearchTests extends AbstractSecurityUnitTest { - - private final ClusterHelper cl1 = new ClusterHelper("crl1_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()); - private final ClusterHelper cl2 = new ClusterHelper("crl2_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()); + + private final ClusterHelper cl1 = new ClusterHelper( + "crl1_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime() + ); + private final ClusterHelper cl2 = new ClusterHelper( + "crl2_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime() + ); private ClusterInfo cl1Info; private ClusterInfo cl2Info; private RestHelper rh1; private RestHelper rh2; - protected boolean ccsMinimizeRoundtrips() { return false; }; + protected boolean ccsMinimizeRoundtrips() { + return false; + }; private static class ClusterTransportClientSettings extends Tuple { @@ -84,9 +90,7 @@ public ClusterTransportClientSettings() { } public ClusterTransportClientSettings(Settings clusterSettings, Settings transportSettings) { - super(Settings.builder() - .put(clusterSettings) - .putList("node.roles", "remote_cluster_client").build(), transportSettings); + super(Settings.builder().put(clusterSettings).putList("node.roles", "remote_cluster_client").build(), transportSettings); } public Settings clusterSettings() { @@ -106,10 +110,13 @@ private void setupCcs(DynamicSecurityConfig dynamicSecurityConfig) throws Except setupCcs(dynamicSecurityConfig, new ClusterTransportClientSettings(), new ClusterTransportClientSettings()); } - private void setupCcs(DynamicSecurityConfig dynamicSecurityConfig, - ClusterTransportClientSettings cluster1Settings, ClusterTransportClientSettings cluster2Settings) throws Exception { + private void setupCcs( + DynamicSecurityConfig dynamicSecurityConfig, + ClusterTransportClientSettings cluster1Settings, + ClusterTransportClientSettings cluster2Settings + ) throws Exception { - System.setProperty("security.display_lic_none","true"); + System.setProperty("security.display_lic_none", "true"); Tuple cluster2 = setupCluster(cl2, cluster2Settings, dynamicSecurityConfig); cl2Info = cluster2.v1(); @@ -120,19 +127,17 @@ private void setupCcs(DynamicSecurityConfig dynamicSecurityConfig, rh1 = cluster1.v2(); final String seed = cl2Info.nodeHost + ":" + cl2Info.nodePort; - String json = - "{" + - "\"persistent\" : {" + - "\"cluster.remote.cross_cluster_two.seeds\" : [\"" + seed + "\"]" + - "}" + - "}"; - + String json = "{" + "\"persistent\" : {" + "\"cluster.remote.cross_cluster_two.seeds\" : [\"" + seed + "\"]" + "}" + "}"; HttpResponse response = rh1.executePutRequest("_cluster/settings", json, encodeBasicHeader("sarek", "sarek")); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); } - private Tuple setupCluster(ClusterHelper ch, ClusterTransportClientSettings cluster, DynamicSecurityConfig dynamicSecurityConfig) throws Exception { + private Tuple setupCluster( + ClusterHelper ch, + ClusterTransportClientSettings cluster, + DynamicSecurityConfig dynamicSecurityConfig + ) throws Exception { NodeSettingsSupplier settings = minimumSecuritySettings(cluster.clusterSettings()); ClusterInfo clusterInfo = ch.startCluster(settings, ClusterConfiguration.DEFAULT); initialize(ch, clusterInfo, dynamicSecurityConfig); @@ -143,63 +148,93 @@ private Tuple setupCluster(ClusterHelper ch, ClusterTra System.out.println("### " + ch.getClusterName() + " complete ###"); return new Tuple<>(clusterInfo, rh); } - + @After public void tearDown() throws Exception { cl1.stopCluster(); cl2.stopCluster(); } - + @Test public void testCcs() throws Exception { setupCcs(); - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("nagilum","nagilum")).getBody(); + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("nagilum", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("nagilum","nagilum")).getBody(); + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("nagilum", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### query 1"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("nagilum", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("crl1")); Assert.assertTrue(ccs.getBody().contains("crl2")); Assert.assertTrue(ccs.getBody().contains("twitter")); - System.out.println("###################### query 4"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:xx,xx/xx/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:xx,xx/xx/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("nagilum", "nagilum") + ); System.out.println(ccs.getBody()); - //TODO fix exception nesting - //Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, ccs.getStatusCode()); - //Assert.assertTrue(ccs.getBody().contains("Can not filter indices; index cross_cluster_two:xx exists but there is also a remote cluster named: cross_cluster_two")); + // TODO fix exception nesting + // Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, ccs.getStatusCode()); + // Assert.assertTrue(ccs.getBody().contains("Can not filter indices; index cross_cluster_two:xx exists but there is also a remote + // cluster named: cross_cluster_two")); System.out.println("###################### query 5"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:abcnonext/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:abcnonext/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("nagilum", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, ccs.getStatusCode()); Assert.assertTrue(ccs.getBody().contains("index_not_found_exception")); System.out.println("###################### query 6"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter,twutter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter,twutter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("nagilum", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); @@ -213,168 +248,279 @@ public void testCcs() throws Exception { public void testCcsNonadmin() throws Exception { setupCcs(); - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("twitter").alias("coordalias"))).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("twitter").alias("coordalias"))) + .actionGet(); } - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("twitter").alias("remotealias"))).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("twitter").alias("remotealias"))) + .actionGet(); } HttpResponse ccs = null; System.out.println("###################### query 1"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); System.out.println("###################### query 2"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twit*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twit*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - System.out.println("###################### query 3"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter,twitter,twutter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter,twitter,twutter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); System.out.println("###################### query 4"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter,twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter,twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertTrue(ccs.getBody().contains("crl1_")); Assert.assertTrue(ccs.getBody().contains("crl2_")); System.out.println("###################### query 5"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twutter,twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twutter,twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); System.out.println("###################### query 6"); - String msearchBody = - "{}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + String msearchBody = "{}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:twitter,twitter/_msearch?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), msearchBody, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:twitter,twitter/_msearch?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + msearchBody, + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); System.out.println("###################### query 7"); - msearchBody = - "{}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + msearchBody = "{}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:twitter/_msearch?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), msearchBody, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:twitter/_msearch?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + msearchBody, + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("_all/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "_all/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter,twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter,twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("*:*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "*:*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("hfghgtdhfhuth/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "hfghgtdhfhuth/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("hfghgtdhfhuth*/_search", encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "hfghgtdhfhuth*/_search", + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - Assert.assertTrue(ccs.getBody().contains("\"hits\":[]")); //TODO: Change for 25.0 to be forbidden (Indices options) + Assert.assertTrue(ccs.getBody().contains("\"hits\":[]")); // TODO: Change for 25.0 to be forbidden (Indices options) - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest(":*/_search", encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest(":*/_search", encodeBasicHeader("worf", "worf")); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - Assert.assertTrue(ccs.getBody().contains("\"hits\":[]")); //TODO: Change for 25.0 to be forbidden (Indices options) + Assert.assertTrue(ccs.getBody().contains("\"hits\":[]")); // TODO: Change for 25.0 to be forbidden (Indices options) - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("*:/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "*:/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:%3Clogstash-%7Bnow%2Fd%7D%3E,%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:%3Clogstash-%7Bnow%2Fd%7D%3E,%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips=" + + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:remotealias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:remotealias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:remotealias,coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:remotealias,coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:remotealias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:remotealias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); System.out.println("#### Alias both"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:remotealias,coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:remotealias,coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("notexist,coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "notexist,coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - //TODO Fix for 25.0 to resolve coordalias (Indices options) + // TODO Fix for 25.0 to resolve coordalias (Indices options) - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("crusherw","crusherw")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("crusherw", "crusherw") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); @@ -384,176 +530,291 @@ public void testCcsNonadmin() throws Exception { public void testCcsNonadminDnfof() throws Exception { setupCcs(new DynamicSecurityConfig().setConfig("config_dnfof.yml")); - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("twitter").alias("coordalias"))).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("twitter").alias("coordalias"))) + .actionGet(); } - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("twitter").alias("remotealias"))).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("twitter").alias("remotealias"))) + .actionGet(); } HttpResponse ccs = null; System.out.println("###################### query 1"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("crl1_")); Assert.assertTrue(ccs.getBody().contains("crl2_")); System.out.println("###################### query 2"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twit*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twit*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - System.out.println("###################### query 3"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter,twitter,twutter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter,twitter,twutter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("twutter")); System.out.println("###################### query 4"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter,twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter,twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertTrue(ccs.getBody().contains("crl1_")); Assert.assertTrue(ccs.getBody().contains("crl2_")); System.out.println("###################### query 5"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twutter,twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twutter,twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); System.out.println("###################### query 6"); - String msearchBody = - "{}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + String msearchBody = "{}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:twitter,twitter/_msearch?pretty", msearchBody, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:twitter,twitter/_msearch?pretty", + msearchBody, + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); System.out.println("###################### query 7"); - msearchBody = - "{}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + msearchBody = "{}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:twitter/_msearch?pretty", msearchBody, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:twitter/_msearch?pretty", + msearchBody, + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("_all/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "_all/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter,twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter,twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); System.out.println("#####*"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:*,*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:*,*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertTrue(ccs.getBody().contains("crl1_")); Assert.assertTrue(ccs.getBody().contains("crl2_")); - //wildcard in remote cluster names - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("*cross*:*twit*,*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + // wildcard in remote cluster names + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "*cross*:*twit*,*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter,t*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter,t*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("*:*/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "*:*/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("hfghgtdhfhuth/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "hfghgtdhfhuth/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("hfghgtdhfhuth*/_search", encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "hfghgtdhfhuth*/_search", + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - Assert.assertTrue(ccs.getBody().contains("\"hits\":[]")); //TODO: Change for 25.0 to be forbidden (Indices options) + Assert.assertTrue(ccs.getBody().contains("\"hits\":[]")); // TODO: Change for 25.0 to be forbidden (Indices options) - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest(":*/_search", encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest(":*/_search", encodeBasicHeader("worf", "worf")); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - Assert.assertTrue(ccs.getBody().contains("\"hits\":[]")); //TODO: Change for 25.0 to be forbidden (Indices options) + Assert.assertTrue(ccs.getBody().contains("\"hits\":[]")); // TODO: Change for 25.0 to be forbidden (Indices options) - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("*:/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "*:/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:%3Clogstash-%7Bnow%2Fd%7D%3E,%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:%3Clogstash-%7Bnow%2Fd%7D%3E,%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty&ccs_minimize_roundtrips=" + + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:remotealias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:remotealias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:remotealias,coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("worf","worf")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:remotealias,coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("worf", "worf") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:remotealias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:remotealias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:remotealias,coordalias/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:remotealias,coordalias/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("crusherw","crusherw")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("crusherw", "crusherw") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); } @@ -562,21 +823,33 @@ public void testCcsNonadminDnfof() throws Exception { public void testCcsEmptyCoord() throws Exception { setupCcs(); - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### query 1"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:twitter/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:twitter/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("twitter", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); @@ -590,74 +863,120 @@ public void testCcsEmptyCoord() throws Exception { public void testCcsDashboardsAggregations() throws Exception { setupCcs(); - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("coordinating").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("coordinating").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } - try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("remote").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("remote").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### kibana indices agg"); String dashboardsIndicesAgg = "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":100}}}}"; - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertFalse(ccs.getBody().contains("cross_cluster_two")); Assert.assertTrue(ccs.getBody().contains("coordinating")); Assert.assertTrue(ccs.getBody().contains("abc")); Assert.assertFalse(ccs.getBody().contains("remote")); - ccs = new RestHelper(cl2Info, false, false, getResourceFolder()).executePostRequest("*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl2Info, false, false, getResourceFolder()).executePostRequest( + "*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertFalse(ccs.getBody().contains("cross_cluster_two")); Assert.assertFalse(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); Assert.assertTrue(ccs.getBody().contains("remote")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:remo*,coo*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:remo*,coo*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two")); Assert.assertTrue(ccs.getBody().contains("remote")); Assert.assertTrue(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:remote/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:remote/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two")); Assert.assertTrue(ccs.getBody().contains("remote")); Assert.assertFalse(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two")); Assert.assertTrue(ccs.getBody().contains("remote")); Assert.assertFalse(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:*,*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:*,*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two")); Assert.assertTrue(ccs.getBody().contains("remote")); Assert.assertTrue(ccs.getBody().contains("coordinating")); Assert.assertTrue(ccs.getBody().contains("abc")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:remo*,ab*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:remo*,ab*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two")); @@ -670,35 +989,59 @@ public void testCcsDashboardsAggregations() throws Exception { public void testCcsDashboardsAggregationsNonAdminDnfof() throws Exception { setupCcs(new DynamicSecurityConfig().setConfig("config_dnfof.yml")); - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("coordinating").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("coordinating").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } - try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("remote").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("analytics").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("remote").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("analytics").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### kibana indices agg"); String dashboardsIndicesAgg = "{\"size\":0,\"aggs\":{\"indices\":{\"terms\":{\"field\":\"_index\",\"size\":100}}}}"; - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertFalse(ccs.getBody().contains("cross_cluster_two")); @@ -708,7 +1051,11 @@ public void testCcsDashboardsAggregationsNonAdminDnfof() throws Exception { Assert.assertFalse(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); Assert.assertFalse(ccs.getBody().contains("remote")); - ccs = new RestHelper(cl2Info, false, false, getResourceFolder()).executePostRequest("*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl2Info, false, false, getResourceFolder()).executePostRequest( + "*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertFalse(ccs.getBody().contains("cross_cluster_two")); @@ -718,7 +1065,11 @@ public void testCcsDashboardsAggregationsNonAdminDnfof() throws Exception { Assert.assertFalse(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); Assert.assertFalse(ccs.getBody().contains("remote")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:*,*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:*,*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two:analytics")); @@ -726,9 +1077,17 @@ public void testCcsDashboardsAggregationsNonAdminDnfof() throws Exception { Assert.assertFalse(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); Assert.assertFalse(ccs.getBody().contains("remote")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:remo*,coo*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:remo*,coo*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:ana*,twi*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:ana*,twi*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two:analytics")); @@ -736,7 +1095,11 @@ public void testCcsDashboardsAggregationsNonAdminDnfof() throws Exception { Assert.assertFalse(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); Assert.assertFalse(ccs.getBody().contains("remote")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:ana*,xyz*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:ana*,xyz*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two:analytics")); @@ -744,9 +1107,17 @@ public void testCcsDashboardsAggregationsNonAdminDnfof() throws Exception { Assert.assertFalse(ccs.getBody().contains("coordinating")); Assert.assertFalse(ccs.getBody().contains("abc")); Assert.assertFalse(ccs.getBody().contains("remote")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:ana*,xyz/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:ana*,xyz/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:*/_search?pretty", dashboardsIndicesAgg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:*/_search?pretty", + dashboardsIndicesAgg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("cross_cluster_two:analytics")); @@ -760,30 +1131,48 @@ public void testCcsDashboardsAggregationsNonAdminDnfof() throws Exception { public void testCcsAggregations() throws Exception { setupCcs(); - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("coordinating").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("coordinating").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } - try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("remote").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("remote").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### aggs"); final String agg = "{\"size\":0,\"aggs\":{\"clusteragg\":{\"terms\":{\"field\":\"cluster.keyword\",\"size\":100}}}}"; - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("*:*,*/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "*:*,*/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("\"timed_out\" : false")); @@ -791,7 +1180,11 @@ public void testCcsAggregations() throws Exception { Assert.assertTrue(ccs.getBody().contains("crl2")); Assert.assertTrue(ccs.getBody().contains("\"doc_count\" : 2")); Assert.assertTrue(ccs.getBody().contains("\"doc_count\" : 1")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("coordin*/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "coordin*/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("\"timed_out\" : false")); @@ -799,7 +1192,11 @@ public void testCcsAggregations() throws Exception { Assert.assertFalse(ccs.getBody().contains("crl2")); Assert.assertFalse(ccs.getBody().contains("\"doc_count\" : 2")); Assert.assertTrue(ccs.getBody().contains("\"doc_count\" : 1")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:remo*/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:remo*/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("\"timed_out\" : false")); @@ -807,55 +1204,107 @@ public void testCcsAggregations() throws Exception { Assert.assertTrue(ccs.getBody().contains("crl2")); Assert.assertFalse(ccs.getBody().contains("\"doc_count\" : 2")); Assert.assertTrue(ccs.getBody().contains("\"doc_count\" : 1")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:notfound,*/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:notfound,*/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:*,notfound/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:*,notfound/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:notfound,notfound/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:notfound,notfound/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:notfou*,*/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode());//TODO: Change for 25.0 to be forbidden (Indices options) - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:*,notfou*/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode());//TODO: Change for 25.0 to be forbidden (Indices options) - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:not*,notf*/_search?pretty", agg, encodeBasicHeader("nagilum","nagilum")); - Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode());//TODO: Change for 25.0 to be forbidden (Indices options) + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:notfou*,*/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); + Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode());// TODO: Change for 25.0 to be forbidden (Indices options) + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:*,notfou*/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); + Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode());// TODO: Change for 25.0 to be forbidden (Indices options) + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:not*,notf*/_search?pretty", + agg, + encodeBasicHeader("nagilum", "nagilum") + ); + Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode());// TODO: Change for 25.0 to be forbidden (Indices options) } @Test public void testCcsAggregationsDnfof() throws Exception { setupCcs(new DynamicSecurityConfig().setConfig("config_dnfof.yml")); - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("twitter", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("coordinating").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("coordinating").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("abc").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } - try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("remote").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("analytics").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("remote").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("analytics").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### aggs"); final String agg = "{\"size\":0,\"aggs\":{\"clusteragg\":{\"terms\":{\"field\":\"cluster.keyword\",\"size\":100}}}}"; - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:notfound,*/_search?pretty", agg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:notfound,*/_search?pretty", + agg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:notfound*,*/_search?pretty", agg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:notfound*,*/_search?pretty", + agg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("security_exception")); Assert.assertTrue(ccs.getBody().contains("\"timed_out\" : false")); @@ -863,58 +1312,97 @@ public void testCcsAggregationsDnfof() throws Exception { Assert.assertFalse(ccs.getBody().contains("crl2")); Assert.assertFalse(ccs.getBody().contains("\"doc_count\" : 2")); Assert.assertTrue(ccs.getBody().contains("\"doc_count\" : 1")); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:*,notfound/_search?pretty", agg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:*,notfound/_search?pretty", + agg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:notfound,notfound/_search?pretty", agg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:notfound,notfound/_search?pretty", + agg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:notfou*,*/_search?pretty", agg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:notfou*,*/_search?pretty", + agg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:*,notfou*/_search?pretty", agg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:*,notfou*/_search?pretty", + agg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("cross_cluster_two:not*,notf*/_search?pretty", agg, encodeBasicHeader("twitter","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "cross_cluster_two:not*,notf*/_search?pretty", + agg, + encodeBasicHeader("twitter", "nagilum") + ); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); } - private ClusterTransportClientSettings getBaseSettingsWithDifferentCert() { Settings cluster = Settings.builder() .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("node-untspec5-keystore.p12")) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("node-untspec5-keystore.p12") + ) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "1") .put(ConfigConstants.SECURITY_NODES_DN_DYNAMIC_CONFIG_ENABLED, true) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_TYPE, "PKCS12") - .putList(ConfigConstants.SECURITY_NODES_DN, - "EMAILADDRESS=unt@tst.com,CN=node-untspec5.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE")//, "CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") - .putList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, + .putList( + ConfigConstants.SECURITY_NODES_DN, + "EMAILADDRESS=unt@tst.com,CN=node-untspec5.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE" + )// , "CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + .putList( + ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, "EMAILADDRESS=unt@xxx.com,CN=node-untspec6.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE", - "CN=kirk,OU=client,O=client,l=tEst, C=De") - .put(ConfigConstants.SECURITY_CERT_OID,"1.2.3.4.5.6") + "CN=kirk,OU=client,O=client,l=tEst, C=De" + ) + .put(ConfigConstants.SECURITY_CERT_OID, "1.2.3.4.5.6") .build(); Settings transport = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("node-untspec6-keystore.p12")) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("node-untspec6-keystore.p12") + ) .build(); return new ClusterTransportClientSettings(cluster, transport); } private void populateBaseData(ClusterTransportClientSettings cluster1, ClusterTransportClientSettings cluster2) throws Exception { - final String cl1BodyMain = rh1.executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl1BodyMain = rh1.executeGetRequest("", encodeBasicHeader("twitter", "nagilum")).getBody(); Assert.assertTrue(cl1BodyMain, cl1BodyMain.contains("crl1")); - final String cl2BodyMain = rh2.executeGetRequest("", encodeBasicHeader("twitter","nagilum")).getBody(); + final String cl2BodyMain = rh2.executeGetRequest("", encodeBasicHeader("twitter", "nagilum")).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } } @@ -939,9 +1427,11 @@ public void testCcsWithDiffCertsWithNodesDnStaticallyAdded() throws Exception { ClusterTransportClientSettings cluster2 = getBaseSettingsWithDifferentCert(); Settings updatedCluster2 = Settings.builder() .put(cluster2.clusterSettings()) - .putList(ConfigConstants.SECURITY_NODES_DN, + .putList( + ConfigConstants.SECURITY_NODES_DN, "EMAILADDRESS=unt@tst.com,CN=node-untspec5.example.com,OU=SSL,O=Te\\, st,L=Test,C=DE", - "CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + "CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE" + ) .build(); cluster2 = new ClusterTransportClientSettings(updatedCluster2, cluster2.transportClientSettings()); @@ -966,9 +1456,11 @@ public void testCcsWithDiffCertsWithNodesDnDynamicallyAdded() throws Exception { setupCcs(new DynamicSecurityConfig().setSecurityNodesDn("nodes_dn_empty.yml"), cluster1, cluster2); - HttpResponse response = rh2.executePutRequest("_opendistro/_security/api/nodesdn/connection1", + HttpResponse response = rh2.executePutRequest( + "_opendistro/_security/api/nodesdn/connection1", "{\"nodes_dn\": [\"CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE\"]}", - encodeBasicHeader("sarek", "sarek")); + encodeBasicHeader("sarek", "sarek") + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_CREATED)); populateBaseData(cluster1, cluster2); @@ -988,41 +1480,59 @@ public void testCcsWithDiffCertsWithNodesDnDynamicallyAdded() throws Exception { public void testCcsWithRoleInjection() throws Exception { setupCcs(new DynamicSecurityConfig().setSecurityRoles("roles.yml")); - Assert.assertEquals(cl1Info.numNodes, cl1.nodeClient().admin().cluster().health( - new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, cl1.nodeClient().admin().cluster(). - health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); - - Assert.assertEquals(cl2Info.numNodes, cl2.nodeClient().admin().cluster().health( - new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, cl2.nodeClient().admin().cluster(). - health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); + Assert.assertEquals( + cl1Info.numNodes, + cl1.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + cl1.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); + + Assert.assertEquals( + cl2Info.numNodes, + cl2.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + cl2.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } final Settings.Builder clusterClientSettings = Settings.builder().putList("node.roles", "remote_cluster_client"); - final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(clusterClientSettings, false, false) - .put(minimumSecuritySettings(Settings.EMPTY).get(0)) - .put("cluster.name", cl1Info.clustername) - .put("path.data", "./target/data/" + cl1Info.clustername + "/cert/data") - .put("path.logs", "./target/data/" + cl1Info.clustername + "/cert/logs") - .put("path.home", "./target") - .put("node.name", "testclient") - .put("discovery.initial_state_timeout", "8s") - .put("plugins.security.allow_default_init_securityindex", "true") - .putList("discovery.zen.ping.unicast.hosts", cl1Info.nodeHost + ":" + cl1Info.nodePort) - .build(); + final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(clusterClientSettings, false, false) + .put(minimumSecuritySettings(Settings.EMPTY).get(0)) + .put("cluster.name", cl1Info.clustername) + .put("path.data", "./target/data/" + cl1Info.clustername + "/cert/data") + .put("path.logs", "./target/data/" + cl1Info.clustername + "/cert/logs") + .put("path.home", "./target") + .put("node.name", "testclient") + .put("discovery.initial_state_timeout", "8s") + .put("plugins.security.allow_default_init_securityindex", "true") + .putList("discovery.zen.ping.unicast.hosts", cl1Info.nodeHost + ":" + cl1Info.nodePort) + .build(); OpenSearchSecurityException exception = null; System.out.println("###################### with invalid role injection"); - //1. With invalid roles injection + // 1. With invalid roles injection RolesInjectorIntegTest.RolesInjectorPlugin.injectedRoles = "invalid_user|invalid_role"; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, RolesInjectorIntegTest.RolesInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + RolesInjectorIntegTest.RolesInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); Client remoteClient = node.client().getRemoteClusterClient("cross_cluster_two"); GetRequest getReq = new GetRequest("twitter", "0"); @@ -1039,10 +1549,17 @@ public void testCcsWithRoleInjection() throws Exception { Assert.assertTrue(exception.getMessage().contains("no permissions for")); System.out.println("###################### with valid role injection"); - //2. With valid roles injection + // 2. With valid roles injection RolesInjectorIntegTest.RolesInjectorPlugin.injectedRoles = "valid_user|opendistro_security_all_access"; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, - OpenSearchSecurityPlugin.class, RolesInjectorIntegTest.RolesInjectorPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + RolesInjectorIntegTest.RolesInjectorPlugin.class + ).start() + ) { waitForInit(node.client()); Client remoteClient = node.client().getRemoteClusterClient("cross_cluster_two"); GetRequest getReq = new GetRequest("twitter", "0"); diff --git a/src/test/java/org/opensearch/security/ccstest/RemoteReindexTests.java b/src/test/java/org/opensearch/security/ccstest/RemoteReindexTests.java index 0d6efe1bb9..3c49548cf3 100644 --- a/src/test/java/org/opensearch/security/ccstest/RemoteReindexTests.java +++ b/src/test/java/org/opensearch/security/ccstest/RemoteReindexTests.java @@ -45,78 +45,98 @@ import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; public class RemoteReindexTests extends AbstractSecurityUnitTest { - - private final ClusterHelper cl1 = new ClusterHelper("crl1_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()); - private final ClusterHelper cl2 = new ClusterHelper("crl2_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()); + + private final ClusterHelper cl1 = new ClusterHelper( + "crl1_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime() + ); + private final ClusterHelper cl2 = new ClusterHelper( + "crl2_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime() + ); private ClusterInfo cl1Info; private ClusterInfo cl2Info; - - private void setupReindex() throws Exception { - - System.setProperty("security.display_lic_none","true"); - + + private void setupReindex() throws Exception { + + System.setProperty("security.display_lic_none", "true"); + cl2Info = cl2.startCluster(minimumSecuritySettings(Settings.EMPTY), ClusterConfiguration.DEFAULT); initialize(cl2, cl2Info); - + cl1Info = cl1.startCluster(minimumSecuritySettings(crossClusterNodeSettings(cl2Info)), ClusterConfiguration.DEFAULT); initialize(cl1, cl1Info); } - + @After public void tearDown() throws Exception { cl1.stopCluster(); cl2.stopCluster(); } - + private Settings crossClusterNodeSettings(ClusterInfo remote) { - Settings.Builder builder = Settings.builder() - .putList("reindex.remote.whitelist", remote.httpHost+":"+remote.httpPort); + Settings.Builder builder = Settings.builder().putList("reindex.remote.whitelist", remote.httpHost + ":" + remote.httpPort); return builder.build(); } - - //TODO add ssl tests - //https://github.com/elastic/elasticsearch/issues/27267 - + + // TODO add ssl tests + // https://github.com/elastic/elasticsearch/issues/27267 + @Test public void testNonSSLReindex() throws Exception { setupReindex(); - - final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("nagilum","nagilum")).getBody(); + + final String cl1BodyMain = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("nagilum", "nagilum") + ).getBody(); Assert.assertTrue(cl1BodyMain.contains("crl1")); - + try (Client tc = cl1.nodeClient()) { tc.admin().indices().create(new CreateIndexRequest("twutter")).actionGet(); } - - final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest("", encodeBasicHeader("nagilum","nagilum")).getBody(); + + final String cl2BodyMain = new RestHelper(cl2Info, false, false, getResourceFolder()).executeGetRequest( + "", + encodeBasicHeader("nagilum", "nagilum") + ).getBody(); Assert.assertTrue(cl2BodyMain.contains("crl2")); - + try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } - - String reindex = "{"+ - "\"source\": {"+ - "\"remote\": {"+ - "\"host\": \"http://"+cl2Info.httpHost+":"+cl2Info.httpPort+"\","+ - "\"username\": \"nagilum\","+ - "\"password\": \"nagilum\""+ - "},"+ - "\"index\": \"twitter\","+ - "\"size\": 10"+ - "},"+ - "\"dest\": {"+ - "\"index\": \"twutter\""+ - "}"+ - "}"; - + + String reindex = "{" + + "\"source\": {" + + "\"remote\": {" + + "\"host\": \"http://" + + cl2Info.httpHost + + ":" + + cl2Info.httpPort + + "\"," + + "\"username\": \"nagilum\"," + + "\"password\": \"nagilum\"" + + "}," + + "\"index\": \"twitter\"," + + "\"size\": 10" + + "}," + + "\"dest\": {" + + "\"index\": \"twutter\"" + + "}" + + "}"; + System.out.println(reindex); - + HttpResponse ccs = null; - + System.out.println("###################### reindex"); - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest("_reindex?pretty", reindex, encodeBasicHeader("nagilum","nagilum")); + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executePostRequest( + "_reindex?pretty", + reindex, + encodeBasicHeader("nagilum", "nagilum") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertTrue(ccs.getBody().contains("created\" : 1")); diff --git a/src/test/java/org/opensearch/security/configuration/SaltTest.java b/src/test/java/org/opensearch/security/configuration/SaltTest.java index 01ddf3de56..8af7501810 100644 --- a/src/test/java/org/opensearch/security/configuration/SaltTest.java +++ b/src/test/java/org/opensearch/security/configuration/SaltTest.java @@ -44,9 +44,7 @@ public void testDefault() { public void testConfig() { // arrange final String testSalt = "abcdefghijklmnop"; - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_COMPLIANCE_SALT, testSalt) - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_COMPLIANCE_SALT, testSalt).build(); // act final Salt salt = Salt.from(settings); @@ -60,9 +58,7 @@ public void testConfig() { public void testSaltUsesOnlyFirst16Bytes() { // arrange final String testSalt = "abcdefghijklmnopqrstuvwxyz"; - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_COMPLIANCE_SALT, testSalt) - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_COMPLIANCE_SALT, testSalt).build(); // act final Salt salt = Salt.from(settings); @@ -79,9 +75,7 @@ public void testSaltThrowsExceptionWhenInsufficientBytesProvided() { // arrange final String testSalt = "abcd"; - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_COMPLIANCE_SALT, testSalt) - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_COMPLIANCE_SALT, testSalt).build(); // act final Salt salt = Salt.from(settings); } @@ -93,7 +87,7 @@ public void testSaltThrowsExceptionWhenInsufficientBytesArrayProvided() { thrown.expectMessage("Provided compliance salt must contain 16 bytes"); // act - new Salt(new byte[]{1, 2, 3, 4, 5}); + new Salt(new byte[] { 1, 2, 3, 4, 5 }); } @Test @@ -103,12 +97,12 @@ public void testSaltThrowsExceptionWhenExcessBytesArrayProvided() { thrown.expectMessage("Provided compliance salt must contain 16 bytes"); // act - new Salt(new byte[]{1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5}); + new Salt(new byte[] { 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 }); } @Test public void testSaltThrowsNoExceptionWhenCorrectBytesArrayProvided() { // act - new Salt(new byte[]{1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1}); + new Salt(new byte[] { 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1 }); } } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/AbstractDlsFlsTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/AbstractDlsFlsTest.java index 06d428a483..dfe96bb55d 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/AbstractDlsFlsTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/AbstractDlsFlsTest.java @@ -58,58 +58,56 @@ protected final void setup(Settings override, DynamicSecurityConfig dynamicSecur Settings settings = Settings.builder().put(ConfigConstants.SECURITY_AUDIT_TYPE_DEFAULT, "debug").put(override).build(); setup(Settings.EMPTY, dynamicSecurityConfig, settings, true); - try(Client tc = getClient()) { + try (Client tc = getClient()) { populateData(tc); } rh = nonSslRestHelper(); } - + protected SearchResponse executeSearch(String indexName, String user, String password) throws Exception { - HttpResponse response = rh.executeGetRequest("/"+indexName+"/_search?from=0&size=50&pretty", - encodeBasicHeader(user, password)); - Assert.assertEquals(200, response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - LoggingDeprecationHandler.INSTANCE, response.getBody()); - return SearchResponse.fromXContent(xcp); + HttpResponse response = rh.executeGetRequest("/" + indexName + "/_search?from=0&size=50&pretty", encodeBasicHeader(user, password)); + Assert.assertEquals(200, response.getStatusCode()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + return SearchResponse.fromXContent(xcp); } protected GetResponse executeGet(String indexName, String id, String user, String password) throws Exception { - HttpResponse response = rh.executeGetRequest("/"+indexName+"/_doc/"+id, encodeBasicHeader(user, password)); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - LoggingDeprecationHandler.INSTANCE, response.getBody()); - return GetResponse.fromXContent(xcp); + HttpResponse response = rh.executeGetRequest("/" + indexName + "/_doc/" + id, encodeBasicHeader(user, password)); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + return GetResponse.fromXContent(xcp); } - - protected MultiSearchResponse executeMSearchMatchAll(String user, String password, String ... indexName) throws Exception { - StringBuilder body = new StringBuilder(); - - for (String index : indexName) { - body.append("{\"index\": \"").append(index).append("\"}\n"); - body.append("{\"query\" : {\"match_all\" : {}}}\n"); - } - - HttpResponse response = rh.executePostRequest("/_msearch?pretty", body.toString(), - encodeBasicHeader(user, password)); - Assert.assertEquals(200, response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - LoggingDeprecationHandler.INSTANCE, response.getBody()); - return MultiSearchResponse.fromXContext(xcp); + + protected MultiSearchResponse executeMSearchMatchAll(String user, String password, String... indexName) throws Exception { + StringBuilder body = new StringBuilder(); + + for (String index : indexName) { + body.append("{\"index\": \"").append(index).append("\"}\n"); + body.append("{\"query\" : {\"match_all\" : {}}}\n"); + } + + HttpResponse response = rh.executePostRequest("/_msearch?pretty", body.toString(), encodeBasicHeader(user, password)); + Assert.assertEquals(200, response.getStatusCode()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + return MultiSearchResponse.fromXContext(xcp); } protected MultiGetResponse executeMGet(String user, String password, Map indicesAndIds) throws Exception { - - Set indexAndIdJson = new HashSet<>(); - for (Map.Entry indexAndId : indicesAndIds.entrySet()) { - indexAndIdJson.add("{ \"_index\": \""+indexAndId.getKey()+"\", \"_id\": \""+indexAndId.getValue()+"\" }"); - } - String body = "{ \"docs\": ["+ String.join(",", indexAndIdJson) +"] }"; - - HttpResponse response = rh.executePostRequest("/_mget?pretty", body,encodeBasicHeader(user, password)); - Assert.assertEquals(200, response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - LoggingDeprecationHandler.INSTANCE, response.getBody()); - return MultiGetResponse.fromXContent(xcp); + + Set indexAndIdJson = new HashSet<>(); + for (Map.Entry indexAndId : indicesAndIds.entrySet()) { + indexAndIdJson.add("{ \"_index\": \"" + indexAndId.getKey() + "\", \"_id\": \"" + indexAndId.getValue() + "\" }"); + } + String body = "{ \"docs\": [" + String.join(",", indexAndIdJson) + "] }"; + + HttpResponse response = rh.executePostRequest("/_mget?pretty", body, encodeBasicHeader(user, password)); + Assert.assertEquals(200, response.getStatusCode()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + return MultiGetResponse.fromXContent(xcp); } abstract void populateData(Client tc); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/CCReplicationTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/CCReplicationTest.java index 4cd6987b5a..079afa65bd 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/CCReplicationTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/CCReplicationTest.java @@ -73,18 +73,24 @@ public class CCReplicationTest extends AbstractDlsFlsTest { public static class MockReplicationPlugin extends Plugin implements ActionPlugin { public static String injectedRoles = null; - public MockReplicationPlugin() { - } + public MockReplicationPlugin() {} @Override - public Collection createComponents(Client client, ClusterService clusterService, ThreadPool threadPool, - ResourceWatcherService resourceWatcherService, ScriptService scriptService, - NamedXContentRegistry xContentRegistry, Environment environment, - NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry, + public Collection createComponents( + Client client, + ClusterService clusterService, + ThreadPool threadPool, + ResourceWatcherService resourceWatcherService, + ScriptService scriptService, + NamedXContentRegistry xContentRegistry, + Environment environment, + NodeEnvironment nodeEnvironment, + NamedWriteableRegistry namedWriteableRegistry, IndexNameExpressionResolver indexNameExpressionResolver, - Supplier repositoriesServiceSupplier) { - if(injectedRoles != null) - threadPool.getThreadContext().putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES, injectedRoles); + Supplier repositoriesServiceSupplier + ) { + if (injectedRoles != null) threadPool.getThreadContext() + .putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES, injectedRoles); return new ArrayList<>(); } @@ -97,6 +103,7 @@ public Collection createComponents(Client client, ClusterService cluster public static class MockReplicationAction extends ActionType { public static final MockReplicationAction INSTANCE = new MockReplicationAction(); public static final String NAME = "indices:admin/plugins/replication/file_chunk"; + private MockReplicationAction() { super(NAME, AcknowledgedResponse::new); } @@ -104,6 +111,7 @@ private MockReplicationAction() { public static class MockReplicationRequest extends AcknowledgedRequest implements Replaceable { private String index; + public MockReplicationRequest(String index) { this.index = index; } @@ -131,7 +139,7 @@ public IndicesRequest indices(String... strings) { @Override public String[] indices() { - return new String[]{index}; + return new String[] { index }; } @Override @@ -148,8 +156,7 @@ public boolean includeDataStreams() { public static class TransportMockReplicationAction extends HandledTransportAction { @Inject - public TransportMockReplicationAction(TransportService transportService, - ActionFilters actionFilters) { + public TransportMockReplicationAction(TransportService transportService, ActionFilters actionFilters) { super(MockReplicationAction.NAME, transportService, actionFilters, MockReplicationRequest::new); } @@ -159,33 +166,54 @@ protected void doExecute(Task task, MockReplicationRequest request, ActionListen } } - //Wait for the security plugin to load roles. + // Wait for the security plugin to load roles. private void waitOrThrow(Client client, String index) throws Exception { waitForInit(client); client.execute(MockReplicationAction.INSTANCE, new MockReplicationRequest(index)).actionGet(); } void populateData(Client tc) { - tc.index(new IndexRequest("hr-dls").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"User\": \"testuser\",\"Date\":\"2021-01-18T17:27:20Z\",\"Designation\":\"HR\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("hr-fls").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"User\": \"adminuser\",\"Date\":\"2021-01-18T17:27:20Z\",\"Designation\":\"CEO\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("hr-masking").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"User\": \"maskeduser\",\"Date\":\"2021-01-18T17:27:20Z\",\"Designation\":\"CEO\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("hr-normal").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"User\": \"employee1\",\"Date\":\"2021-01-18T17:27:20Z\",\"Designation\":\"EMPLOYEE\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("hr-dls").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"User\": \"testuser\",\"Date\":\"2021-01-18T17:27:20Z\",\"Designation\":\"HR\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("hr-fls").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"User\": \"adminuser\",\"Date\":\"2021-01-18T17:27:20Z\",\"Designation\":\"CEO\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("hr-masking").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"User\": \"maskeduser\",\"Date\":\"2021-01-18T17:27:20Z\",\"Designation\":\"CEO\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("hr-normal").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"User\": \"employee1\",\"Date\":\"2021-01-18T17:27:20Z\",\"Designation\":\"EMPLOYEE\"}", XContentType.JSON) + ).actionGet(); } @Test public void testReplication() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig().setSecurityRoles("roles_ccreplication.yml"), Settings.EMPTY); - Assert.assertEquals(clusterInfo.numNodes, clusterHelper.nodeClient().admin().cluster().health( - new ClusterHealthRequest().waitForGreenStatus()).actionGet().getNumberOfNodes()); - Assert.assertEquals(ClusterHealthStatus.GREEN, clusterHelper.nodeClient().admin().cluster(). - health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus()); + Assert.assertEquals( + clusterInfo.numNodes, + clusterHelper.nodeClient() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForGreenStatus()) + .actionGet() + .getNumberOfNodes() + ); + Assert.assertEquals( + ClusterHealthStatus.GREEN, + clusterHelper.nodeClient().admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet().getStatus() + ); - final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) + final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) .put(minimumSecuritySettings(Settings.EMPTY).get(0)) .put("cluster.name", clusterInfo.clustername) .put("path.data", "./target/data/" + clusterInfo.clustername + "/cert/data") @@ -199,39 +227,79 @@ public void testReplication() throws Exception { // Set roles for the user MockReplicationPlugin.injectedRoles = "ccr_user|opendistro_security_human_resources_trainee"; - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, MockReplicationPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + MockReplicationPlugin.class + ).start() + ) { waitOrThrow(node.client(), "hr-dls"); Assert.fail("Expecting exception"); } catch (OpenSearchSecurityException ex) { log.warn(ex.getMessage()); Assert.assertNotNull(ex); - Assert.assertTrue(ex.getMessage().contains("Cross Cluster Replication is not supported when FLS or DLS or Fieldmasking is activated")); + Assert.assertTrue( + ex.getMessage().contains("Cross Cluster Replication is not supported when FLS or DLS or Fieldmasking is activated") + ); Assert.assertEquals(ex.status(), RestStatus.FORBIDDEN); } - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, MockReplicationPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + MockReplicationPlugin.class + ).start() + ) { waitOrThrow(node.client(), "hr-fls"); Assert.fail("Expecting exception"); } catch (OpenSearchSecurityException ex) { log.warn(ex.getMessage()); Assert.assertNotNull(ex); - Assert.assertTrue(ex.getMessage().contains("Cross Cluster Replication is not supported when FLS or DLS or Fieldmasking is activated")); + Assert.assertTrue( + ex.getMessage().contains("Cross Cluster Replication is not supported when FLS or DLS or Fieldmasking is activated") + ); Assert.assertEquals(ex.status(), RestStatus.FORBIDDEN); } - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, MockReplicationPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + MockReplicationPlugin.class + ).start() + ) { waitOrThrow(node.client(), "hr-masking"); Assert.fail("Expecting exception"); } catch (OpenSearchSecurityException ex) { log.warn(ex.getMessage()); Assert.assertNotNull(ex); - Assert.assertTrue(ex.getMessage().contains("Cross Cluster Replication is not supported when FLS or DLS or Fieldmasking is activated")); + Assert.assertTrue( + ex.getMessage().contains("Cross Cluster Replication is not supported when FLS or DLS or Fieldmasking is activated") + ); Assert.assertEquals(ex.status(), RestStatus.FORBIDDEN); } - try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, MockReplicationPlugin.class).start()) { + try ( + Node node = new PluginAwareNode( + false, + tcSettings, + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + MockReplicationPlugin.class + ).start() + ) { waitOrThrow(node.client(), "hr-normal"); - AcknowledgedResponse res = node.client().execute(MockReplicationAction.INSTANCE, new MockReplicationRequest("hr-normal")).actionGet(); + AcknowledgedResponse res = node.client() + .execute(MockReplicationAction.INSTANCE, new MockReplicationRequest("hr-normal")) + .actionGet(); Assert.assertTrue(res.isAcknowledged()); } } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/CustomFieldMaskedComplexMappingTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/CustomFieldMaskedComplexMappingTest.java index bbc7bd5479..9be61b30b7 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/CustomFieldMaskedComplexMappingTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/CustomFieldMaskedComplexMappingTest.java @@ -25,19 +25,20 @@ import org.opensearch.security.test.helper.file.FileHelper; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class CustomFieldMaskedComplexMappingTest extends AbstractDlsFlsTest{ - +public class CustomFieldMaskedComplexMappingTest extends AbstractDlsFlsTest { @Override protected void populateData(Client tc) { try { - tc.admin().indices().create(new CreateIndexRequest("logs").mapping(FileHelper.loadFile("dlsfls/masked_field_mapping.json"), XContentType.JSON)).actionGet(); - + tc.admin() + .indices() + .create(new CreateIndexRequest("logs").mapping(FileHelper.loadFile("dlsfls/masked_field_mapping.json"), XContentType.JSON)) + .actionGet(); byte[] data = FileHelper.loadFile("dlsfls/logs_bulk_data.json").getBytes(StandardCharsets.UTF_8); BulkRequest br = new BulkRequest().add(data, 0, data.length, XContentType.JSON).setRefreshPolicy(RefreshPolicy.IMMEDIATE); - if(tc.bulk(br).actionGet().hasFailures()) { + if (tc.bulk(br).actionGet().hasFailures()) { Assert.fail("bulk import failed"); } Thread.sleep(1000); @@ -54,17 +55,17 @@ public void testComplexMappingAggregationsRace() throws Exception { setup(); - - String query = "{"+ - "\"aggs\" : {"+ - "\"ips\" : { \"terms\" : { \"field\" : \"machine.os.keyword\", \"size\": 1002, \"show_term_doc_count_error\": true } }"+ - "}"+ - "}"; - - + String query = "{" + + "\"aggs\" : {" + + "\"ips\" : { \"terms\" : { \"field\" : \"machine.os.keyword\", \"size\": 1002, \"show_term_doc_count_error\": true } }" + + "}" + + "}"; HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("win 8")); @@ -84,16 +85,22 @@ public void testComplexMappingAggregationsRace() throws Exception { Assert.assertFalse(res.getBody().contains("88783587fef7")); Assert.assertFalse(res.getBody().contains("c1f04335d9f41")); - for(int i=0;i<10;i++) { - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("user_masked_nowc1", "password"))).getStatusCode()); + for (int i = 0; i < 10; i++) { + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("user_masked_nowc1", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); } + for (int i = 0; i < 10; i++) { - - for(int i=0;i<10;i++) { - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("user_masked_nowc", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("user_masked_nowc", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("\"aaa")); @@ -115,21 +122,18 @@ public void testComplexMappingAggregationsRace() throws Exception { Assert.assertFalse(res.getBody().contains("osx")); Assert.assertFalse(res.getBody().contains("win 7")); - - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); - - + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); } - - - - - - for(int i=0;i<10;i++) { - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + for (int i = 0; i < 10; i++) { + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/logs/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("win 8")); Assert.assertTrue(res.getBody().contains("win xp")); Assert.assertTrue(res.getBody().contains("ios")); @@ -157,14 +161,27 @@ public void testComplexMappingSearch() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logs/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode()); - Assert.assertFalse(res.getBody().contains("88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166")); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logs/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); + Assert.assertFalse( + res.getBody() + .contains( + "88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166" + ) + ); Assert.assertFalse(res.getBody().contains("e90a2fdf7b1939ec06e294321fd7d23e1a70d8fc080a3f85d0f3bf08c205b53")); Assert.assertFalse(res.getBody().contains("*.*.*.*")); Assert.assertFalse(res.getBody().contains("430a65d4b9c51de7192e048b2639db0de5c56f1901afccc2a01ef97f6a769a38")); Assert.assertFalse(res.getBody().contains("7f48bb3636edf546a75968ca7cd0bdfe63e9ce7af04ef7cb642931fa15d2d7a3")); Assert.assertFalse(res.getBody().contains("https://www.static.co/downloads/beats/metricbeat")); - Assert.assertFalse(res.getBody().contains("eb551beb79792f3366b3623495bb0d9acf85055e63d4f48ade024289f9aa782fc7bd215b6ed3452d3d3ff3eccd8a7f5e8f55b8d0ef245c7ccbf8b747e0be9807")); + Assert.assertFalse( + res.getBody() + .contains( + "eb551beb79792f3366b3623495bb0d9acf85055e63d4f48ade024289f9aa782fc7bd215b6ed3452d3d3ff3eccd8a7f5e8f55b8d0ef245c7ccbf8b747e0be9807" + ) + ); Assert.assertFalse(res.getBody().contains("XXX.XXX.XXX.XXX")); Assert.assertFalse(res.getBody().contains("ANONYMIZED_BROWSER")); Assert.assertFalse(res.getBody().contains("69ce5643cf2abe2dec163330161e669")); @@ -172,32 +189,59 @@ public void testComplexMappingSearch() throws Exception { Assert.assertTrue(res.getBody().contains("win xp")); Assert.assertTrue(res.getBody().contains("\"timestamp\" : \"2018-07-22T20:45:16.163Z")); - for(int i=0;i<10;i++) { - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logs/_search?pretty&size=100", encodeBasicHeader("user_masked_nowc", "password"))).getStatusCode()); - Assert.assertTrue(res.getBody().contains("88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166")); - Assert.assertTrue(res.getBody().contains("e90a2fdf7b1939ec06e294321fd7d23e1a70d8fc080a3f85d0f3bf08c205b53")); - Assert.assertTrue(res.getBody().contains("*.*.*.*")); - Assert.assertTrue(res.getBody().contains("430a65d4b9c51de7192e048b2639db0de5c56f1901afccc2a01ef97f6a769a38")); - Assert.assertTrue(res.getBody().contains("7f48bb3636edf546a75968ca7cd0bdfe63e9ce7af04ef7cb642931fa15d2d7a3")); - Assert.assertTrue(res.getBody().contains("https://www.static.co/downloads/beats/metricbeat")); - Assert.assertTrue(res.getBody().contains("eb551beb79792f3366b3623495bb0d9acf85055e63d4f48ade024289f9aa782fc7bd215b6ed3452d3d3ff3eccd8a7f5e8f55b8d0ef245c7ccbf8b747e0be9807")); - Assert.assertTrue(res.getBody().contains("XXX.XXX.XXX.XXX")); - Assert.assertTrue(res.getBody().contains("ANONYMIZED_BROWSER")); - Assert.assertTrue(res.getBody().contains("69ce5643cf2abe2dec163330161e669")); - Assert.assertTrue(res.getBody().contains("0b50856e97a54df444ff8f7c73c67fc3109aa234")); - Assert.assertFalse(res.getBody().contains("win xp")); - Assert.assertFalse(res.getBody().contains("\"timestamp\" : \"2018-07-22T20:45:16.163Z")); + for (int i = 0; i < 10; i++) { + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logs/_search?pretty&size=100", encodeBasicHeader("user_masked_nowc", "password"))) + .getStatusCode() + ); + Assert.assertTrue( + res.getBody() + .contains( + "88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166" + ) + ); + Assert.assertTrue(res.getBody().contains("e90a2fdf7b1939ec06e294321fd7d23e1a70d8fc080a3f85d0f3bf08c205b53")); + Assert.assertTrue(res.getBody().contains("*.*.*.*")); + Assert.assertTrue(res.getBody().contains("430a65d4b9c51de7192e048b2639db0de5c56f1901afccc2a01ef97f6a769a38")); + Assert.assertTrue(res.getBody().contains("7f48bb3636edf546a75968ca7cd0bdfe63e9ce7af04ef7cb642931fa15d2d7a3")); + Assert.assertTrue(res.getBody().contains("https://www.static.co/downloads/beats/metricbeat")); + Assert.assertTrue( + res.getBody() + .contains( + "eb551beb79792f3366b3623495bb0d9acf85055e63d4f48ade024289f9aa782fc7bd215b6ed3452d3d3ff3eccd8a7f5e8f55b8d0ef245c7ccbf8b747e0be9807" + ) + ); + Assert.assertTrue(res.getBody().contains("XXX.XXX.XXX.XXX")); + Assert.assertTrue(res.getBody().contains("ANONYMIZED_BROWSER")); + Assert.assertTrue(res.getBody().contains("69ce5643cf2abe2dec163330161e669")); + Assert.assertTrue(res.getBody().contains("0b50856e97a54df444ff8f7c73c67fc3109aa234")); + Assert.assertFalse(res.getBody().contains("win xp")); + Assert.assertFalse(res.getBody().contains("\"timestamp\" : \"2018-07-22T20:45:16.163Z")); } - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logs/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode()); - Assert.assertFalse(res.getBody().contains("88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166")); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logs/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); + Assert.assertFalse( + res.getBody() + .contains( + "88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166" + ) + ); Assert.assertFalse(res.getBody().contains("e90a2fdf7b1939ec06e294321fd7d23e1a70d8fc080a3f85d0f3bf08c205b53")); Assert.assertFalse(res.getBody().contains("*.*.*.*")); Assert.assertFalse(res.getBody().contains("430a65d4b9c51de7192e048b2639db0de5c56f1901afccc2a01ef97f6a769a38")); Assert.assertFalse(res.getBody().contains("7f48bb3636edf546a75968ca7cd0bdfe63e9ce7af04ef7cb642931fa15d2d7a3")); Assert.assertFalse(res.getBody().contains("https://www.static.co/downloads/beats/metricbeat")); - Assert.assertFalse(res.getBody().contains("eb551beb79792f3366b3623495bb0d9acf85055e63d4f48ade024289f9aa782fc7bd215b6ed3452d3d3ff3eccd8a7f5e8f55b8d0ef245c7ccbf8b747e0be9807")); + Assert.assertFalse( + res.getBody() + .contains( + "eb551beb79792f3366b3623495bb0d9acf85055e63d4f48ade024289f9aa782fc7bd215b6ed3452d3d3ff3eccd8a7f5e8f55b8d0ef245c7ccbf8b747e0be9807" + ) + ); Assert.assertFalse(res.getBody().contains("XXX.XXX.XXX.XXX")); Assert.assertFalse(res.getBody().contains("ANONYMIZED_BROWSER")); Assert.assertFalse(res.getBody().contains("69ce5643cf2abe2dec163330161e669")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/CustomFieldMaskedTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/CustomFieldMaskedTest.java index 9d48e0309f..91c6115695 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/CustomFieldMaskedTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/CustomFieldMaskedTest.java @@ -25,18 +25,35 @@ public class CustomFieldMaskedTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust1\", \"street\":\"testroad\"}, \"ip_source\": \"100.100.1.1\",\"ip_dest\": \"123.123.1.1\",\"amount\": 10, \"mynum\": 1000000000000000000}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust2\", \"street\":\"testroad\"}, \"ip_source\": \"100.100.2.2\",\"ip_dest\": \"123.123.2.2\",\"amount\": 20, \"mynum\": 1000000000000000000}", XContentType.JSON)).actionGet(); - - - for (int i=0; i<30;i++) { - tc.index(new IndexRequest("deals").id("a"+i).setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust1\", \"street\":\"testroad\"}, \"ip_source\": \"200.100.1.1\",\"ip_dest\": \"123.123.1.1\",\"amount\": 10, \"mynum\": 1000000000000000000}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("deals").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust1\", \"street\":\"testroad\"}, \"ip_source\": \"100.100.1.1\",\"ip_dest\": \"123.123.1.1\",\"amount\": 10, \"mynum\": 1000000000000000000}", + XContentType.JSON + ) + ).actionGet(); + tc.index( + new IndexRequest("deals").id("2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust2\", \"street\":\"testroad\"}, \"ip_source\": \"100.100.2.2\",\"ip_dest\": \"123.123.2.2\",\"amount\": 20, \"mynum\": 1000000000000000000}", + XContentType.JSON + ) + ).actionGet(); + + for (int i = 0; i < 30; i++) { + tc.index( + new IndexRequest("deals").id("a" + i) + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust1\", \"street\":\"testroad\"}, \"ip_source\": \"200.100.1.1\",\"ip_dest\": \"123.123.1.1\",\"amount\": 10, \"mynum\": 1000000000000000000}", + XContentType.JSON + ) + ).actionGet(); } - } + } @Test public void testMaskedAggregations() throws Exception { @@ -45,23 +62,23 @@ public void testMaskedAggregations() throws Exception { String query; HttpResponse res; - //Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); - //Assert.assertTrue(res.getBody().contains("100.100")); - - query = - "{" + - "\"query\" : {" + - "\"match_all\": {" + - "}" + - "}," + - "\"aggs\" : {" + - "\"ips\" : {" + - "\"terms\" : {" + - "\"field\" : \"ip_source.keyword\"" + - "}" + - "}" + - "}"+ - "}"; + // Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, + // encodeBasicHeader("admin", "admin"))).getStatusCode()); + // Assert.assertTrue(res.getBody().contains("100.100")); + + query = "{" + + "\"query\" : {" + + "\"match_all\": {" + + "}" + + "}," + + "\"aggs\" : {" + + "\"ips\" : {" + + "\"terms\" : {" + + "\"field\" : \"ip_source.keyword\"" + + "}" + + "}" + + "}" + + "}"; res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked_custom", "password")); System.out.println(res.getBody()); Assert.assertEquals(HttpStatus.SC_OK, res.getStatusCode()); @@ -69,23 +86,22 @@ public void testMaskedAggregations() throws Exception { Assert.assertTrue(res.getBody().contains("***")); Assert.assertTrue(res.getBody().contains("XXX")); - query = - "{" + - "\"query\" : {" + - "\"match_all\": {" + - "}" + - "}," + - "\"aggs\": {" + - "\"ips\" : {" + - "\"terms\" : {" + - "\"field\" : \"ip_source.keyword\"," + - "\"order\": {" + - "\"_term\" : \"asc\"" + - "}" + - "}" + - "}" + - "}" + - "}"; + query = "{" + + "\"query\" : {" + + "\"match_all\": {" + + "}" + + "}," + + "\"aggs\": {" + + "\"ips\" : {" + + "\"terms\" : {" + + "\"field\" : \"ip_source.keyword\"," + + "\"order\": {" + + "\"_term\" : \"asc\"" + + "}" + + "}" + + "}" + + "}" + + "}"; res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked_custom", "password")); System.out.println(res.getBody()); @@ -94,23 +110,22 @@ public void testMaskedAggregations() throws Exception { Assert.assertTrue(res.getBody().contains("***")); Assert.assertTrue(res.getBody().contains("XXX")); - query = - "{" + - "\"query\" : {" + - "\"match_all\": {" + - "}" + - "}," + - "\"aggs\": {" + - "\"ips\" : {" + - "\"terms\" : {" + - "\"field\" : \"ip_source.keyword\"," + - "\"order\": {" + - "\"_term\" : \"desc\"" + - "}" + - "}" + - "}" + - "}" + - "}"; + query = "{" + + "\"query\" : {" + + "\"match_all\": {" + + "}" + + "}," + + "\"aggs\": {" + + "\"ips\" : {" + + "\"terms\" : {" + + "\"field\" : \"ip_source.keyword\"," + + "\"order\": {" + + "\"_term\" : \"desc\"" + + "}" + + "}" + + "}" + + "}" + + "}"; res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked_custom", "password")); System.out.println(res.getBody()); @@ -126,36 +141,41 @@ public void testCustomMaskedAggregationsRace() throws Exception { setup(); + String query = "{" + + "\"aggs\" : {" + + "\"ips\" : { \"terms\" : { \"field\" : \"ip_source.keyword\", \"size\": 1002, \"show_term_doc_count_error\": true } }" + + "}" + + "}"; - String query = "{"+ - "\"aggs\" : {"+ - "\"ips\" : { \"terms\" : { \"field\" : \"ip_source.keyword\", \"size\": 1002, \"show_term_doc_count_error\": true } }"+ - "}"+ - "}"; - - - - HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); - Assert.assertTrue(res.getBody().contains("100.100")); - Assert.assertTrue(res.getBody().contains("200.100")); - Assert.assertTrue(res.getBody().contains("\"doc_count\" : 30")); - Assert.assertTrue(res.getBody().contains("\"doc_count\" : 1")); - Assert.assertFalse(res.getBody().contains("***")); - Assert.assertFalse(res.getBody().contains("XXX")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked_custom", "password"))).getStatusCode()); - Assert.assertTrue(res.getBody().contains("\"doc_count\" : 31")); - Assert.assertTrue(res.getBody().contains("\"doc_count\" : 1")); - Assert.assertFalse(res.getBody().contains("100.100")); - Assert.assertFalse(res.getBody().contains("200.100")); - Assert.assertTrue(res.getBody().contains("***.100.1.XXX")); - Assert.assertTrue(res.getBody().contains("***.100.2.XXX")); - + HttpResponse res; + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); + Assert.assertTrue(res.getBody().contains("100.100")); + Assert.assertTrue(res.getBody().contains("200.100")); + Assert.assertTrue(res.getBody().contains("\"doc_count\" : 30")); + Assert.assertTrue(res.getBody().contains("\"doc_count\" : 1")); + Assert.assertFalse(res.getBody().contains("***")); + Assert.assertFalse(res.getBody().contains("XXX")); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked_custom", "password"))) + .getStatusCode() + ); + Assert.assertTrue(res.getBody().contains("\"doc_count\" : 31")); + Assert.assertTrue(res.getBody().contains("\"doc_count\" : 1")); + Assert.assertFalse(res.getBody().contains("100.100")); + Assert.assertFalse(res.getBody().contains("200.100")); + Assert.assertTrue(res.getBody().contains("***.100.1.XXX")); + Assert.assertTrue(res.getBody().contains("***.100.2.XXX")); - for(int i=0;i<10;i++) { - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + for (int i = 0; i < 10; i++) { + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("100.100")); Assert.assertTrue(res.getBody().contains("200.100")); Assert.assertTrue(res.getBody().contains("\"doc_count\" : 30")); @@ -173,18 +193,30 @@ public void testCustomMaskedSearch() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 32,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertTrue(res.getBody().contains("cust1")); Assert.assertTrue(res.getBody().contains("cust2")); Assert.assertTrue(res.getBody().contains("100.100.1.1")); Assert.assertTrue(res.getBody().contains("100.100.2.2")); - Assert.assertFalse(res.getBody().contains("8976994d0491e35f74fcac67ede9c83334a6ad34dae07c176df32f10225f93c5077ddd302c02ddd618b2406b1e4dfe50a727cbc880cfe264c552decf2d224ffc")); + Assert.assertFalse( + res.getBody() + .contains( + "8976994d0491e35f74fcac67ede9c83334a6ad34dae07c176df32f10225f93c5077ddd302c02ddd618b2406b1e4dfe50a727cbc880cfe264c552decf2d224ffc" + ) + ); Assert.assertFalse(res.getBody().contains("***")); Assert.assertFalse(res.getBody().contains("XXX")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=100", encodeBasicHeader("user_masked_custom", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=100", encodeBasicHeader("user_masked_custom", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 32,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -192,7 +224,12 @@ public void testCustomMaskedSearch() throws Exception { Assert.assertFalse(res.getBody().contains("cust2")); Assert.assertFalse(res.getBody().contains("100.100.1.1")); Assert.assertFalse(res.getBody().contains("100.100.2.2")); - Assert.assertTrue(res.getBody().contains("8976994d0491e35f74fcac67ede9c83334a6ad34dae07c176df32f10225f93c5077ddd302c02ddd618b2406b1e4dfe50a727cbc880cfe264c552decf2d224ffc")); + Assert.assertTrue( + res.getBody() + .contains( + "8976994d0491e35f74fcac67ede9c83334a6ad34dae07c176df32f10225f93c5077ddd302c02ddd618b2406b1e4dfe50a727cbc880cfe264c552decf2d224ffc" + ) + ); Assert.assertTrue(res.getBody().contains("***.100.1.XXX")); Assert.assertTrue(res.getBody().contains("123.123.1.XXX")); @@ -205,27 +242,41 @@ public void testCustomMaskedGet() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertTrue(res.getBody().contains("cust1")); Assert.assertFalse(res.getBody().contains("cust2")); Assert.assertTrue(res.getBody().contains("100.100.1.1")); Assert.assertFalse(res.getBody().contains("100.100.2.2")); - Assert.assertFalse(res.getBody().contains("8976994d0491e35f74fcac67ede9c83334a6ad34dae07c176df32f10225f93c5077ddd302c02ddd618b2406b1e4dfe50a727cbc880cfe264c552decf2d224ffc")); + Assert.assertFalse( + res.getBody() + .contains( + "8976994d0491e35f74fcac67ede9c83334a6ad34dae07c176df32f10225f93c5077ddd302c02ddd618b2406b1e4dfe50a727cbc880cfe264c552decf2d224ffc" + ) + ); Assert.assertFalse(res.getBody().contains("***")); Assert.assertFalse(res.getBody().contains("XXX")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("user_masked_custom", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("user_masked_custom", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertFalse(res.getBody().contains("cust1")); Assert.assertFalse(res.getBody().contains("cust2")); Assert.assertFalse(res.getBody().contains("100.100.1.1")); Assert.assertFalse(res.getBody().contains("100.100.2.2")); - Assert.assertTrue(res.getBody().contains("8976994d0491e35f74fcac67ede9c83334a6ad34dae07c176df32f10225f93c5077ddd302c02ddd618b2406b1e4dfe50a727cbc880cfe264c552decf2d224ffc")); + Assert.assertTrue( + res.getBody() + .contains( + "8976994d0491e35f74fcac67ede9c83334a6ad34dae07c176df32f10225f93c5077ddd302c02ddd618b2406b1e4dfe50a727cbc880cfe264c552decf2d224ffc" + ) + ); Assert.assertTrue(res.getBody().contains("***.100.1.XXX")); Assert.assertTrue(res.getBody().contains("123.123.1.XXX")); } - } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DateMathTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DateMathTest.java index 54110e911f..da4d9db867 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DateMathTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DateMathTest.java @@ -26,8 +26,7 @@ import org.opensearch.security.support.SecurityUtils; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class DateMathTest extends AbstractDlsFlsTest{ - +public class DateMathTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { @@ -35,17 +34,25 @@ protected void populateData(Client tc) { sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String date = sdf.format(new Date()); - tc.index(new IndexRequest("logstash-"+date).setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"message\":\"mymsg1a\", \"ipaddr\": \"10.0.0.0\",\"msgid\": \"12\"}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("logstash-"+date).setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"message\":\"mymsg1b\", \"ipaddr\": \"10.0.0.1\",\"msgid\": \"14\"}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("logstash-1-"+date).setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"message\":\"mymsg1c\", \"ipaddr\": \"10.0.0.2\",\"msgid\": \"12\"}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("logstash-1-"+date).setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"message\":\"mymsg1d\", \"ipaddr\": \"10.0.0.3\",\"msgid\": \"14\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("logstash-" + date).setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"message\":\"mymsg1a\", \"ipaddr\": \"10.0.0.0\",\"msgid\": \"12\"}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("logstash-" + date).setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"message\":\"mymsg1b\", \"ipaddr\": \"10.0.0.1\",\"msgid\": \"14\"}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("logstash-1-" + date).setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"message\":\"mymsg1c\", \"ipaddr\": \"10.0.0.2\",\"msgid\": \"12\"}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("logstash-1-" + date).setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"message\":\"mymsg1d\", \"ipaddr\": \"10.0.0.3\",\"msgid\": \"14\"}", XContentType.JSON) + ).actionGet(); } @Test @@ -55,7 +62,10 @@ public void testSearch() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -64,7 +74,13 @@ public void testSearch() throws Exception { Assert.assertTrue(res.getBody().contains("mymsg")); Assert.assertTrue(res.getBody().contains("msgid")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty", encodeBasicHeader("opendistro_security_logstash", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "%3Clogstash-%7Bnow%2Fd%7D%3E/_search?pretty", + encodeBasicHeader("opendistro_security_logstash", "password") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -81,13 +97,23 @@ public void testFieldCaps() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("%3Clogstash-%7Bnow%2Fd%7D%3E/_field_caps?fields=*&pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("%3Clogstash-%7Bnow%2Fd%7D%3E/_field_caps?fields=*&pretty", encodeBasicHeader("admin", "admin"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("ipaddr")); Assert.assertTrue(res.getBody().contains("message")); Assert.assertTrue(res.getBody().contains("msgid")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("%3Clogstash-%7Bnow%2Fd%7D%3E/_field_caps?fields=*&pretty", encodeBasicHeader("opendistro_security_logstash", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "%3Clogstash-%7Bnow%2Fd%7D%3E/_field_caps?fields=*&pretty", + encodeBasicHeader("opendistro_security_logstash", "password") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("ipaddr")); Assert.assertFalse(res.getBody().contains("message")); @@ -101,7 +127,10 @@ public void testSearchWc() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("logstash-*/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("logstash-*/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -110,7 +139,11 @@ public void testSearchWc() throws Exception { Assert.assertTrue(res.getBody().contains("mymsg")); Assert.assertTrue(res.getBody().contains("msgid")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("logstash-*/_search?pretty", encodeBasicHeader("opendistro_security_logstash", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("logstash-*/_search?pretty", encodeBasicHeader("opendistro_security_logstash", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -127,7 +160,10 @@ public void testSearchWc2() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("logstash-1-*,logstash-20*/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("logstash-1-*,logstash-20*/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -136,7 +172,10 @@ public void testSearchWc2() throws Exception { Assert.assertTrue(res.getBody().contains("mymsg")); Assert.assertTrue(res.getBody().contains("msgid")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("logstash-1-*,logstash-20*/_search?pretty", encodeBasicHeader("regex", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("logstash-1-*,logstash-20*/_search?pretty", encodeBasicHeader("regex", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DfmOverwritesAllTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DfmOverwritesAllTest.java index aafffb141f..580cabc66b 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DfmOverwritesAllTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DfmOverwritesAllTest.java @@ -37,17 +37,41 @@ public class DfmOverwritesAllTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("index1-1").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"field1\": 1, \"field2\": \"value-2-1\", \"field3\": \"value-3-1\", \"field4\": \"value-4-1\" }", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("index1-2").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"field1\": 2, \"field2\": \"value-2-2\", \"field3\": \"value-3-2\", \"field4\": \"value-4-2\" }", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("index1-3").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"field1\": 3, \"field2\": \"value-2-3\", \"field3\": \"value-3-3\", \"field4\": \"value-4-3\" }", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("index1-4").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"field1\": 4, \"field2\": \"value-2-4\", \"field3\": \"value-3-4\", \"field4\": \"value-4-4\" }", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("index1-1").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"field1\": 1, \"field2\": \"value-2-1\", \"field3\": \"value-3-1\", \"field4\": \"value-4-1\" }", + XContentType.JSON + ) + ).actionGet(); + + tc.index( + new IndexRequest("index1-2").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"field1\": 2, \"field2\": \"value-2-2\", \"field3\": \"value-3-2\", \"field4\": \"value-4-2\" }", + XContentType.JSON + ) + ).actionGet(); + + tc.index( + new IndexRequest("index1-3").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"field1\": 3, \"field2\": \"value-2-3\", \"field3\": \"value-3-3\", \"field4\": \"value-4-3\" }", + XContentType.JSON + ) + ).actionGet(); + + tc.index( + new IndexRequest("index1-4").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"field1\": 4, \"field2\": \"value-2-4\", \"field3\": \"value-3-4\", \"field4\": \"value-4-4\" }", + XContentType.JSON + ) + ).actionGet(); } @@ -59,15 +83,17 @@ protected void populateData(Client tc) { public void testDFMUnrestrictedUser() throws Exception { final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_DFM_EMPTY_OVERRIDES_ALL, true).build(); - setup(settings, new DynamicSecurityConfig().setConfig("securityconfig_dfm_empty_overwrites_all.yml") + setup( + settings, + new DynamicSecurityConfig().setConfig("securityconfig_dfm_empty_overwrites_all.yml") .setSecurityInternalUsers("internal_users_dfm_empty_overwrites_all.yml") .setSecurityRoles("roles_dfm_empty_overwrites_all.yml") - .setSecurityRolesMapping("rolesmapping_dfm_empty_overwrites_all.yml")); + .setSecurityRolesMapping("rolesmapping_dfm_empty_overwrites_all.yml") + ); HttpResponse response; - response = rh.executeGetRequest("/index1-*/_search?pretty", - encodeBasicHeader("admin", "password")); + response = rh.executeGetRequest("/index1-*/_search?pretty", encodeBasicHeader("admin", "password")); Assert.assertEquals(200, response.getStatusCode()); // the only document in index1-1 is filtered by DLS query, so normally no hit in index-1-1 @@ -99,21 +125,23 @@ public void testDFMUnrestrictedUser() throws Exception { public void testDFMRestrictedUser() throws Exception { final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_DFM_EMPTY_OVERRIDES_ALL, true).build(); - setup(settings, new DynamicSecurityConfig().setConfig("securityconfig_dfm_empty_overwrites_all.yml") + setup( + settings, + new DynamicSecurityConfig().setConfig("securityconfig_dfm_empty_overwrites_all.yml") .setSecurityInternalUsers("internal_users_dfm_empty_overwrites_all.yml") .setSecurityRoles("roles_dfm_empty_overwrites_all.yml") - .setSecurityRolesMapping("rolesmapping_dfm_empty_overwrites_all.yml")); + .setSecurityRolesMapping("rolesmapping_dfm_empty_overwrites_all.yml") + ); HttpResponse response; - response = rh.executeGetRequest("/index1-*/_search?pretty", - encodeBasicHeader("dfm_restricted_role", "password")); + response = rh.executeGetRequest("/index1-*/_search?pretty", encodeBasicHeader("dfm_restricted_role", "password")); Assert.assertEquals(200, response.getStatusCode()); - // the only document in index1-1 is filtered by DLS query, so no hit in index-1-1 + // the only document in index1-1 is filtered by DLS query, so no hit in index-1-1 Assert.assertFalse(response.getBody().contains("index1-1")); - // field3 and field4 - filtered out by FLS + // field3 and field4 - filtered out by FLS Assert.assertFalse(response.getBody().contains("value-3-1")); Assert.assertFalse(response.getBody().contains("value-4-1")); Assert.assertFalse(response.getBody().contains("value-3-2")); @@ -146,15 +174,20 @@ public void testDFMRestrictedAndUnrestrictedAllIndices() throws Exception { final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_DFM_EMPTY_OVERRIDES_ALL, true).build(); - setup(settings, new DynamicSecurityConfig().setConfig("securityconfig_dfm_empty_overwrites_all.yml") + setup( + settings, + new DynamicSecurityConfig().setConfig("securityconfig_dfm_empty_overwrites_all.yml") .setSecurityInternalUsers("internal_users_dfm_empty_overwrites_all.yml") .setSecurityRoles("roles_dfm_empty_overwrites_all.yml") - .setSecurityRolesMapping("rolesmapping_dfm_empty_overwrites_all.yml")); + .setSecurityRolesMapping("rolesmapping_dfm_empty_overwrites_all.yml") + ); HttpResponse response; - response = rh.executeGetRequest("/index1-*/_search?pretty", - encodeBasicHeader("dfm_restricted_and_unrestricted_all_indices_role", "password")); + response = rh.executeGetRequest( + "/index1-*/_search?pretty", + encodeBasicHeader("dfm_restricted_and_unrestricted_all_indices_role", "password") + ); Assert.assertEquals(200, response.getStatusCode()); // the only document in index1-1 is filtered by DLS query, so normally no hit in index-1-1 @@ -187,18 +220,25 @@ public void testDFMRestrictedAndUnrestrictedAllIndices() throws Exception { @Test public void testDFMRestrictedAndUnrestrictedOneIndex() throws Exception { final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_DFM_EMPTY_OVERRIDES_ALL, true).build(); - setup(settings, new DynamicSecurityConfig().setConfig("securityconfig_dfm_empty_overwrites_all.yml") + setup( + settings, + new DynamicSecurityConfig().setConfig("securityconfig_dfm_empty_overwrites_all.yml") .setSecurityInternalUsers("internal_users_dfm_empty_overwrites_all.yml") .setSecurityRoles("roles_dfm_empty_overwrites_all.yml") - .setSecurityRolesMapping("rolesmapping_dfm_empty_overwrites_all.yml")); + .setSecurityRolesMapping("rolesmapping_dfm_empty_overwrites_all.yml") + ); HttpResponse response; - response = rh.executeGetRequest("/_plugins/_security/authinfo?pretty", - encodeBasicHeader("dfm_restricted_and_unrestricted_one_index_role", "password")); + response = rh.executeGetRequest( + "/_plugins/_security/authinfo?pretty", + encodeBasicHeader("dfm_restricted_and_unrestricted_one_index_role", "password") + ); - response = rh.executeGetRequest("/index1-*/_search?pretty", - encodeBasicHeader("dfm_restricted_and_unrestricted_one_index_role", "password")); + response = rh.executeGetRequest( + "/index1-*/_search?pretty", + encodeBasicHeader("dfm_restricted_and_unrestricted_one_index_role", "password") + ); Assert.assertEquals(200, response.getStatusCode()); // we have a role that places no restrictions on index-1-1, lifting the DLS from the restricted role diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsDateMathTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsDateMathTest.java index c4105c11e9..cbd1e09e56 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsDateMathTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsDateMathTest.java @@ -27,58 +27,75 @@ import org.opensearch.security.support.ConfigConstants; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class DlsDateMathTest extends AbstractDlsFlsTest{ - +public class DlsDateMathTest extends AbstractDlsFlsTest { @Override protected void populateData(Client tc) { - - LocalDateTime yesterday = LocalDateTime.now(ZoneId.of("UTC")).minusDays(1); LocalDateTime today = LocalDateTime.now(ZoneId.of("UTC")); LocalDateTime tomorrow = LocalDateTime.now(ZoneId.of("UTC")).plusDays(1); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); - - tc.index(new IndexRequest("logstash").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"@timestamp\": \""+formatter.format(yesterday)+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"@timestamp\": \""+formatter.format(today)+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash").id("3").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"@timestamp\": \""+formatter.format(tomorrow)+"\"}", XContentType.JSON)).actionGet(); + + tc.index( + new IndexRequest("logstash").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"@timestamp\": \"" + formatter.format(yesterday) + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("logstash").id("2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"@timestamp\": \"" + formatter.format(today) + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("logstash").id("3") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"@timestamp\": \"" + formatter.format(tomorrow) + "\"}", XContentType.JSON) + ).actionGet(); } - @Test public void testDlsDateMathQuery() throws Exception { - final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_ALLOW_NOW_IN_DLS,true).build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_ALLOW_NOW_IN_DLS, true).build(); setup(settings); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash/_search?pretty", encodeBasicHeader("date_math", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash/_search?pretty", encodeBasicHeader("date_math", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 3,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); } - + @Test public void testDlsDateMathQueryNotAllowed() throws Exception { setup(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, (res = rh.executeGetRequest("/logstash/_search?pretty", encodeBasicHeader("date_math", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_BAD_REQUEST, + (res = rh.executeGetRequest("/logstash/_search?pretty", encodeBasicHeader("date_math", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("'now' is not allowed in DLS queries")); Assert.assertTrue(res.getBody().contains("error")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 3,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsFlsCrossClusterMinimalRoundtripSearchTests.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsFlsCrossClusterMinimalRoundtripSearchTests.java index 86b97c1afe..81610b0ee4 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsFlsCrossClusterMinimalRoundtripSearchTests.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsFlsCrossClusterMinimalRoundtripSearchTests.java @@ -13,5 +13,7 @@ public class DlsFlsCrossClusterMinimalRoundtripSearchTests extends DlsFlsCrossClusterSearchTest { @Override - protected boolean ccsMinimizeRoundtrips() { return true; } + protected boolean ccsMinimizeRoundtrips() { + return true; + } } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsFlsCrossClusterSearchTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsFlsCrossClusterSearchTest.java index 8fcd85f873..a86c49d21d 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsFlsCrossClusterSearchTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsFlsCrossClusterSearchTest.java @@ -31,12 +31,18 @@ public class DlsFlsCrossClusterSearchTest extends AbstractSecurityUnitTest { - private final ClusterHelper cl1 = new ClusterHelper("crl1_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()); - private final ClusterHelper cl2 = new ClusterHelper("crl2_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()); + private final ClusterHelper cl1 = new ClusterHelper( + "crl1_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime() + ); + private final ClusterHelper cl2 = new ClusterHelper( + "crl2_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime() + ); private ClusterInfo cl1Info; private ClusterInfo cl2Info; - protected boolean ccsMinimizeRoundtrips() { return false; }; + protected boolean ccsMinimizeRoundtrips() { + return false; + }; @Override protected String getResourceFolder() { @@ -45,13 +51,16 @@ protected String getResourceFolder() { private void setupCcs(String remoteRoles) throws Exception { - System.setProperty("security.display_lic_none","true"); + System.setProperty("security.display_lic_none", "true"); - cl2Info = cl2.startCluster(minimumSecuritySettings(Settings.builder().putList("node.roles", "remote_cluster_client").build()), ClusterConfiguration.DEFAULT); + cl2Info = cl2.startCluster( + minimumSecuritySettings(Settings.builder().putList("node.roles", "remote_cluster_client").build()), + ClusterConfiguration.DEFAULT + ); initialize(cl2, cl2Info, new DynamicSecurityConfig().setSecurityRoles(remoteRoles)); System.out.println("### cl2 complete ###"); - //cl1 is coordinating + // cl1 is coordinating cl1Info = cl1.startCluster(minimumSecuritySettings(crossClusterNodeSettings(cl2Info)), ClusterConfiguration.DEFAULT); System.out.println("### cl1 start ###"); initialize(cl1, cl1Info, new DynamicSecurityConfig().setSecurityRoles("roles_983.yml")); @@ -66,8 +75,8 @@ public void tearDown() throws Exception { private Settings crossClusterNodeSettings(ClusterInfo remote) { Settings.Builder builder = Settings.builder() - .putList("cluster.remote.cross_cluster_two.seeds", remote.nodeHost+":"+remote.nodePort) - .putList("node.roles", "remote_cluster_client"); + .putList("cluster.remote.cross_cluster_two.seeds", remote.nodeHost + ":" + remote.nodePort) + .putList("node.roles", "remote_cluster_client"); return builder.build(); } @@ -76,42 +85,71 @@ public void testCcs() throws Exception { setupCcs("roles_983.yml"); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\","+ - "\"Designation\": \"CEO\","+ - "\"FirstName\": \"__fn__"+cl2Info.clustername+"\","+ - "\"LastName\": \"lastname0\","+ - "\"Salary\": \"salary0\","+ - "\"SecretFiled\": \"secret0\","+ - "\"AnotherSecredField\": \"anothersecret0\","+ - "\"XXX\": \"xxx0\"" - + "}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("1") - .source("{\"cluster\": \""+cl2Info.clustername+"\","+ - "\"Designation\": \"someoneelse\","+ - "\"FirstName\": \"__fn__"+cl2Info.clustername+"\","+ - "\"LastName\": \"lastname1\","+ - "\"Salary\": \"salary1\","+ - "\"SecretFiled\": \"secret1\","+ - "\"AnotherSecredField\": \"anothersecret1\","+ - "\"XXX\": \"xxx1\"" - + "}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source( + "{\"cluster\": \"" + + cl2Info.clustername + + "\"," + + "\"Designation\": \"CEO\"," + + "\"FirstName\": \"__fn__" + + cl2Info.clustername + + "\"," + + "\"LastName\": \"lastname0\"," + + "\"Salary\": \"salary0\"," + + "\"SecretFiled\": \"secret0\"," + + "\"AnotherSecredField\": \"anothersecret0\"," + + "\"XXX\": \"xxx0\"" + + "}", + XContentType.JSON + ) + ).actionGet(); + + tc.index( + new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("1") + .source( + "{\"cluster\": \"" + + cl2Info.clustername + + "\"," + + "\"Designation\": \"someoneelse\"," + + "\"FirstName\": \"__fn__" + + cl2Info.clustername + + "\"," + + "\"LastName\": \"lastname1\"," + + "\"Salary\": \"salary1\"," + + "\"SecretFiled\": \"secret1\"," + + "\"AnotherSecredField\": \"anothersecret1\"," + + "\"XXX\": \"xxx1\"" + + "}", + XContentType.JSON + ) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### query 1"); - //on coordinating cluster - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:humanresources/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("human_resources_trainee", "password")); + // on coordinating cluster + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:humanresources/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("human_resources_trainee", "password") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("crl1")); @@ -134,42 +172,71 @@ public void testCcsDifferentConfig() throws Exception { setupCcs("roles_ccs2.yml"); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); } try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\","+ - "\"Designation\": \"CEO\","+ - "\"FirstName\": \"__fn__"+cl2Info.clustername+"\","+ - "\"LastName\": \"lastname0\","+ - "\"Salary\": \"salary0\","+ - "\"SecretFiled\": \"secret0\","+ - "\"AnotherSecredField\": \"anothersecret0\","+ - "\"XXX\": \"xxx0\"" - + "}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("1") - .source("{\"cluster\": \""+cl2Info.clustername+"\","+ - "\"Designation\": \"someoneelse\","+ - "\"FirstName\": \"__fn__"+cl2Info.clustername+"\","+ - "\"LastName\": \"lastname1\","+ - "\"Salary\": \"salary1\","+ - "\"SecretFiled\": \"secret1\","+ - "\"AnotherSecredField\": \"anothersecret1\","+ - "\"XXX\": \"xxx1\"" - + "}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source( + "{\"cluster\": \"" + + cl2Info.clustername + + "\"," + + "\"Designation\": \"CEO\"," + + "\"FirstName\": \"__fn__" + + cl2Info.clustername + + "\"," + + "\"LastName\": \"lastname0\"," + + "\"Salary\": \"salary0\"," + + "\"SecretFiled\": \"secret0\"," + + "\"AnotherSecredField\": \"anothersecret0\"," + + "\"XXX\": \"xxx0\"" + + "}", + XContentType.JSON + ) + ).actionGet(); + + tc.index( + new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("1") + .source( + "{\"cluster\": \"" + + cl2Info.clustername + + "\"," + + "\"Designation\": \"someoneelse\"," + + "\"FirstName\": \"__fn__" + + cl2Info.clustername + + "\"," + + "\"LastName\": \"lastname1\"," + + "\"Salary\": \"salary1\"," + + "\"SecretFiled\": \"secret1\"," + + "\"AnotherSecredField\": \"anothersecret1\"," + + "\"XXX\": \"xxx1\"" + + "}", + XContentType.JSON + ) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### query 1"); - //on coordinating cluster - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:humanresources/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("human_resources_trainee", "password")); + // on coordinating cluster + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:humanresources/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("human_resources_trainee", "password") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertFalse(ccs.getBody().contains("crl1")); @@ -192,64 +259,113 @@ public void testCcsDifferentConfigBoth() throws Exception { setupCcs("roles_ccs2.yml"); try (Client tc = cl1.nodeClient()) { - tc.index(new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\"}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl1Info.clustername+"\","+ - "\"Designation\": \"CEO\","+ - "\"FirstName\": \"__fn__"+cl1Info.clustername+"\","+ - "\"LastName\": \"lastname0\","+ - "\"Salary\": \"salary0\","+ - "\"SecretFiled\": \"secret3\","+ - "\"AnotherSecredField\": \"anothersecret3\","+ - "\"XXX\": \"xxx0\"" - + "}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("1") - .source("{\"cluster\": \""+cl1Info.clustername+"\","+ - "\"Designation\": \"someoneelse\","+ - "\"FirstName\": \"__fn__"+cl1Info.clustername+"\","+ - "\"LastName\": \"lastname1\","+ - "\"Salary\": \"salary1\","+ - "\"SecretFiled\": \"secret4\","+ - "\"AnotherSecredField\": \"anothersecret4\","+ - "\"XXX\": \"xxx1\"" - + "}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twitter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl1Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + + tc.index( + new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source( + "{\"cluster\": \"" + + cl1Info.clustername + + "\"," + + "\"Designation\": \"CEO\"," + + "\"FirstName\": \"__fn__" + + cl1Info.clustername + + "\"," + + "\"LastName\": \"lastname0\"," + + "\"Salary\": \"salary0\"," + + "\"SecretFiled\": \"secret3\"," + + "\"AnotherSecredField\": \"anothersecret3\"," + + "\"XXX\": \"xxx0\"" + + "}", + XContentType.JSON + ) + ).actionGet(); + + tc.index( + new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("1") + .source( + "{\"cluster\": \"" + + cl1Info.clustername + + "\"," + + "\"Designation\": \"someoneelse\"," + + "\"FirstName\": \"__fn__" + + cl1Info.clustername + + "\"," + + "\"LastName\": \"lastname1\"," + + "\"Salary\": \"salary1\"," + + "\"SecretFiled\": \"secret4\"," + + "\"AnotherSecredField\": \"anothersecret4\"," + + "\"XXX\": \"xxx1\"" + + "}", + XContentType.JSON + ) + ).actionGet(); } try (Client tc = cl2.nodeClient()) { - tc.index(new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("0") - .source("{\"cluster\": \""+cl2Info.clustername+"\","+ - "\"Designation\": \"CEO\","+ - "\"FirstName\": \"__fn__"+cl2Info.clustername+"\","+ - "\"LastName\": \"lastname0\","+ - "\"Salary\": \"salary0\","+ - "\"SecretFiled\": \"secret0\","+ - "\"AnotherSecredField\": \"anothersecret0\","+ - "\"XXX\": \"xxx0\"" - + "}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE).id("1") - .source("{\"cluster\": \""+cl2Info.clustername+"\","+ - "\"Designation\": \"someoneelse\","+ - "\"FirstName\": \"__fn__"+cl2Info.clustername+"\","+ - "\"LastName\": \"lastname1\","+ - "\"Salary\": \"salary1\","+ - "\"SecretFiled\": \"secret1\","+ - "\"AnotherSecredField\": \"anothersecret1\","+ - "\"XXX\": \"xxx1\"" - + "}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("twutter").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source("{\"cluster\": \"" + cl2Info.clustername + "\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("0") + .source( + "{\"cluster\": \"" + + cl2Info.clustername + + "\"," + + "\"Designation\": \"CEO\"," + + "\"FirstName\": \"__fn__" + + cl2Info.clustername + + "\"," + + "\"LastName\": \"lastname0\"," + + "\"Salary\": \"salary0\"," + + "\"SecretFiled\": \"secret0\"," + + "\"AnotherSecredField\": \"anothersecret0\"," + + "\"XXX\": \"xxx0\"" + + "}", + XContentType.JSON + ) + ).actionGet(); + + tc.index( + new IndexRequest("humanresources").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .id("1") + .source( + "{\"cluster\": \"" + + cl2Info.clustername + + "\"," + + "\"Designation\": \"someoneelse\"," + + "\"FirstName\": \"__fn__" + + cl2Info.clustername + + "\"," + + "\"LastName\": \"lastname1\"," + + "\"Salary\": \"salary1\"," + + "\"SecretFiled\": \"secret1\"," + + "\"AnotherSecredField\": \"anothersecret1\"," + + "\"XXX\": \"xxx1\"" + + "}", + XContentType.JSON + ) + ).actionGet(); } HttpResponse ccs = null; System.out.println("###################### query 1"); - //on coordinating cluster - ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest("cross_cluster_two:humanresources,humanresources/_search?pretty&ccs_minimize_roundtrips="+ccsMinimizeRoundtrips(), encodeBasicHeader("human_resources_trainee", "password")); + // on coordinating cluster + ccs = new RestHelper(cl1Info, false, false, getResourceFolder()).executeGetRequest( + "cross_cluster_two:humanresources,humanresources/_search?pretty&ccs_minimize_roundtrips=" + ccsMinimizeRoundtrips(), + encodeBasicHeader("human_resources_trainee", "password") + ); System.out.println(ccs.getBody()); Assert.assertEquals(HttpStatus.SC_OK, ccs.getStatusCode()); Assert.assertTrue(ccs.getBody().contains("crl1")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsNestedTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsNestedTest.java index a89d12770d..afb42d9a4a 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsNestedTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsNestedTest.java @@ -23,35 +23,47 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class DlsNestedTest extends AbstractDlsFlsTest{ +public class DlsNestedTest extends AbstractDlsFlsTest { @Override protected void populateData(Client tc) { - String mapping = "{" + - " \"mytype\" : {" + - " \"properties\" : {" + - " \"amount\" : {\"type\": \"integer\"}," + - " \"owner\" : {\"type\": \"text\"}," + - " \"my_nested_object\" : {\"type\" : \"nested\"}" + - " }" + - " }" + - " }" + - ""; - - tc.admin().indices().create(new CreateIndexRequest("deals") - .simpleMapping("amount", "type=integer", "owner", "type=text", "my_nested_object", "type=nested") - .settings(Settings.builder().put("number_of_shards", 1).put("number_of_replicas", 0).build())) - .actionGet(); - - //tc.index(new IndexRequest("deals").id("3").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - // .source("{\"amount\": 7,\"owner\": \"a\", \"my_nested_object\" : {\"name\": \"spock\"}}", XContentType.JSON)).actionGet(); - //tc.index(new IndexRequest("deals").id("4").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - // .source("{\"amount\": 8, \"my_nested_object\" : {\"name\": \"spock\"}}", XContentType.JSON)).actionGet(); - //tc.index(new IndexRequest("deals").id("5").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - // .source("{\"amount\": 1400,\"owner\": \"a\", \"my_nested_object\" : {\"name\": \"spock\"}}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"amount\": 1500,\"owner\": \"b\", \"my_nested_object\" : {\"name\": \"spock\"}}", XContentType.JSON)).actionGet(); + String mapping = "{" + + " \"mytype\" : {" + + " \"properties\" : {" + + " \"amount\" : {\"type\": \"integer\"}," + + " \"owner\" : {\"type\": \"text\"}," + + " \"my_nested_object\" : {\"type\" : \"nested\"}" + + " }" + + " }" + + " }" + + ""; + + tc.admin() + .indices() + .create( + new CreateIndexRequest("deals").simpleMapping( + "amount", + "type=integer", + "owner", + "type=text", + "my_nested_object", + "type=nested" + ).settings(Settings.builder().put("number_of_shards", 1).put("number_of_replicas", 0).build()) + ) + .actionGet(); + + // tc.index(new IndexRequest("deals").id("3").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + // .source("{\"amount\": 7,\"owner\": \"a\", \"my_nested_object\" : {\"name\": \"spock\"}}", XContentType.JSON)).actionGet(); + // tc.index(new IndexRequest("deals").id("4").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + // .source("{\"amount\": 8, \"my_nested_object\" : {\"name\": \"spock\"}}", XContentType.JSON)).actionGet(); + // tc.index(new IndexRequest("deals").id("5").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + // .source("{\"amount\": 1400,\"owner\": \"a\", \"my_nested_object\" : {\"name\": \"spock\"}}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("deals").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"amount\": 1500,\"owner\": \"b\", \"my_nested_object\" : {\"name\": \"spock\"}}", XContentType.JSON) + ).actionGet(); } @Test @@ -59,34 +71,35 @@ public void testNestedQuery() throws Exception { setup(); - - String query = "{" + - " \"query\": {" + - " \"nested\": {" + - " \"path\": \"my_nested_object\"," + - " \"query\": {" + - " \"match\": {\"my_nested_object.name\" : \"spock\"}" + - " }," + - " \"inner_hits\": {} " + - " }" + - " }" + - "}"; - + String query = "{" + + " \"query\": {" + + " \"nested\": {" + + " \"path\": \"my_nested_object\"," + + " \"query\": {" + + " \"match\": {\"my_nested_object.name\" : \"spock\"}" + + " }," + + " \"inner_hits\": {} " + + " }" + + " }" + + "}"; HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"my_nested_object\" : {")); Assert.assertTrue(res.getBody().contains("\"field\" : \"my_nested_object\",")); Assert.assertTrue(res.getBody().contains("\"offset\" : 0")); - //Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); - //System.out.println(res.getBody()); - //Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); - //Assert.assertTrue(res.getBody().contains("\"value\" : 1510.0")); - //Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); + // Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", + // "admin"))).getStatusCode()); + // System.out.println(res.getBody()); + // Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); + // Assert.assertTrue(res.getBody().contains("\"value\" : 1510.0")); + // Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); } - } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsPropsReplaceTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsPropsReplaceTest.java index 43d5ecfc5f..2e23a11d2d 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsPropsReplaceTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsPropsReplaceTest.java @@ -21,28 +21,40 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class DlsPropsReplaceTest extends AbstractDlsFlsTest{ - +public class DlsPropsReplaceTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("prop1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"prop_replace\": \"yes\", \"amount\": 1010}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("prop1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"prop_replace\": \"no\", \"amount\": 2020}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("prop2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"role\": \"prole1\", \"amount\": 3030}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("prop2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"role\": \"prole2\", \"amount\": 4040}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("prop2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"role\": \"prole3\", \"amount\": 5050}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("prop-mapped").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"securityRole\": \"opendistro_security_mapped\", \"amount\": 6060}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("prop-mapped").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"securityRole\": \"not_assigned\", \"amount\": 7070}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("prop1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"prop_replace\": \"yes\", \"amount\": 1010}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("prop1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"prop_replace\": \"no\", \"amount\": 2020}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("prop2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"role\": \"prole1\", \"amount\": 3030}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("prop2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"role\": \"prole2\", \"amount\": 4040}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("prop2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"role\": \"prole3\", \"amount\": 5050}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("prop-mapped").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"securityRole\": \"opendistro_security_mapped\", \"amount\": 6060}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("prop-mapped").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"securityRole\": \"not_assigned\", \"amount\": 7070}", XContentType.JSON) + ).actionGet(); } - @Test public void testDlsProps() throws Exception { @@ -50,15 +62,26 @@ public void testDlsProps() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/prop1,prop2/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/prop1,prop2/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 5,\n \"relation")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/prop1,prop2/_search?pretty&size=100", encodeBasicHeader("prop_replace", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/prop1,prop2/_search?pretty&size=100", encodeBasicHeader("prop_replace", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 3,\n \"relation")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/prop-mapped/_search?pretty&size=100", encodeBasicHeader("prop_replace", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/prop-mapped/_search?pretty&size=100", encodeBasicHeader("prop_replace", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"amount\" : 6060")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsScrollTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsScrollTest.java index b1d87734e5..cc7b9e305d 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsScrollTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsScrollTest.java @@ -21,53 +21,67 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class DlsScrollTest extends AbstractDlsFlsTest{ - +public class DlsScrollTest extends AbstractDlsFlsTest { @Override protected void populateData(Client tc) { - tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"amount\": 3}", XContentType.JSON)).actionGet(); //not in + tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"amount\": 3}", XContentType.JSON)) + .actionGet(); // not in - tc.index(new IndexRequest("deals").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"amount\": 10}", XContentType.JSON)).actionGet(); //not in + tc.index(new IndexRequest("deals").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"amount\": 10}", XContentType.JSON)) + .actionGet(); // not in - tc.index(new IndexRequest("deals").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"amount\": 1500}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("deals").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"amount\": 1500}", XContentType.JSON) + ).actionGet(); - tc.index(new IndexRequest("deals").id("4").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"amount\": 21500}", XContentType.JSON)).actionGet(); //not in + tc.index( + new IndexRequest("deals").id("4").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"amount\": 21500}", XContentType.JSON) + ).actionGet(); // not in - for(int i=0; i<100; i++) { - tc.index(new IndexRequest("deals").id("gen"+i).setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"amount\": 1500}", XContentType.JSON)).actionGet(); + for (int i = 0; i < 100; i++) { + tc.index( + new IndexRequest("deals").id("gen" + i) + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"amount\": 1500}", XContentType.JSON) + ).actionGet(); } } - @Test public void testDlsScroll() throws Exception { setup(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executeGetRequest("/deals/_search?scroll=1m&pretty=true&size=5", encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?scroll=1m&pretty=true&size=5", encodeBasicHeader("dept_manager", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 101,")); - int c=0; + int c = 0; - while(true) { + while (true) { int start = res.getBody().indexOf("_scroll_id") + 15; - String scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start+1)); - Assert.assertEquals(HttpStatus.SC_OK, (res=rh.executePostRequest("/_search/scroll?pretty=true", "{\"scroll\" : \"1m\", \"scroll_id\" : \""+scrollid+"\"}", encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + String scrollid = res.getBody().substring(start, res.getBody().indexOf("\"", start + 1)); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "/_search/scroll?pretty=true", + "{\"scroll\" : \"1m\", \"scroll_id\" : \"" + scrollid + "\"}", + encodeBasicHeader("dept_manager", "password") + )).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 101,")); Assert.assertFalse(res.getBody().contains("\"amount\" : 3")); Assert.assertFalse(res.getBody().contains("\"amount\" : 10")); Assert.assertFalse(res.getBody().contains("\"amount\" : 21500")); c++; - if(res.getBody().contains("\"hits\" : [ ]")) { + if (res.getBody().contains("\"hits\" : [ ]")) { break; } } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsTermLookupQueryTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsTermLookupQueryTest.java index b4a0d1f129..76112f533c 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsTermLookupQueryTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsTermLookupQueryTest.java @@ -54,543 +54,701 @@ public class DlsTermLookupQueryTest extends AbstractDlsFlsTest { - protected void populateData(Client client) { - // user access codes, basis for TLQ query - client.index(new IndexRequest("user_access_codes").id("tlq_1337").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"access_codes\": [1337] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("user_access_codes").id("tlq_42").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"access_codes\": [42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("user_access_codes").id("tlq_1337_42").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"access_codes\": [1337, 42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("user_access_codes").id("tlq_999").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"access_codes\": [999] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("user_access_codes").id("tlq_empty_access_codes") - .setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{ \"access_codes\": [] }", XContentType.JSON)) - .actionGet(); - client.index(new IndexRequest("user_access_codes").id("tlq_no_codes").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bla\": \"blub\" }", XContentType.JSON)).actionGet(); - - // need to have keyword for bu field since we're testing aggregations - client.admin().indices().create(new CreateIndexRequest("tlqdocuments")).actionGet(); - client.admin().indices() - .putMapping(new PutMappingRequest("tlqdocuments").source("bu", "type=keyword")) - .actionGet(); - - // tlqdocuments, protected by TLQ - client.index(new IndexRequest("tlqdocuments").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"AAA\", \"access_codes\": [1337] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"AAA\", \"access_codes\": [42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("3").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"AAA\", \"access_codes\": [1337, 42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("4").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"BBB\", \"access_codes\": [1337] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("5").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"BBB\", \"access_codes\": [42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("6").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"BBB\", \"access_codes\": [1337, 42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("7").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"CCC\", \"access_codes\": [1337] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("8").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"CCC\", \"access_codes\": [42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("9").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"CCC\", \"access_codes\": [1337, 42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("10").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"DDD\", \"access_codes\": [1337] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("11").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"DDD\", \"access_codes\": [42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("12").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"DDD\", \"access_codes\": [1337, 42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("13").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"EEE\", \"access_codes\": [1337] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("14").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"EEE\", \"access_codes\": [42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("15").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"EEE\", \"access_codes\": [1337, 42] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("16").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"FFF\" }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("17").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"FFF\", \"access_codes\": [12345] }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdocuments").id("18").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"bu\": \"FFF\", \"access_codes\": [12345, 6789] }", XContentType.JSON)).actionGet(); - - // we use a "bu" field here as well to test aggregations over multiple indices - client.admin().indices().create(new CreateIndexRequest("tlqdummy")).actionGet(); - client.admin().indices().putMapping(new PutMappingRequest("tlqdummy").source("bu", "type=keyword")) - .actionGet(); - - // tlqdummy, not protected by TLQ - client.index(new IndexRequest("tlqdummy").id("101").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"mykey\": \"101\", \"bu\": \"GGG\" }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdummy").id("102").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"mykey\": \"102\", \"bu\": \"GGG\" }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdummy").id("103").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"mykey\": \"103\", \"bu\": \"GGG\" }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdummy").id("104").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"mykey\": \"104\", \"bu\": \"GGG\" }", XContentType.JSON)).actionGet(); - client.index(new IndexRequest("tlqdummy").id("105").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{ \"mykey\": \"105\", \"bu\": \"GGG\" }", XContentType.JSON)).actionGet(); - - } - - // ------------------------ - // Test search and msearch - // ------------------------ - - @Test - public void testSimpleSearch_AccessCode_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - HttpResponse response = rh.executeGetRequest("/tlqdocuments/_search?pretty", - encodeBasicHeader("tlq_1337", "password")); - Assert.assertEquals(200, response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - LoggingDeprecationHandler.INSTANCE, response.getBody()); - SearchResponse searchResponse = SearchResponse.fromXContent(xcp); - // 10 docs, all need to have access code 1337 - Assert.assertEquals(searchResponse.toString(), 10, searchResponse.getHits().getTotalHits().value); - // fields need to have 1337 access code - assertAccessCodesMatch(searchResponse.getHits().getHits(), new Integer[] { 1337 }); - } - - @Test - public void testSimpleSearch_AccessCode_42() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - HttpResponse response = rh.executeGetRequest("/tlqdocuments/_search?pretty", - encodeBasicHeader("tlq_42", "password")); - Assert.assertEquals(200, response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - LoggingDeprecationHandler.INSTANCE, response.getBody()); - SearchResponse searchResponse = SearchResponse.fromXContent(xcp); - - // 10 docs, all need to have access code 42 - Assert.assertEquals(searchResponse.toString(), 10, searchResponse.getHits().getTotalHits().value); - // fields need to have 42 access code - assertAccessCodesMatch(searchResponse.getHits().getHits(), new Integer[] { 42 }); - - } - - @Test - public void testSimpleSearch_AccessCodes_1337_42() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - HttpResponse response = rh.executeGetRequest("/tlqdocuments/_search?pretty", - encodeBasicHeader("tlq_1337_42", "password")); - Assert.assertEquals(200, response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - LoggingDeprecationHandler.INSTANCE, response.getBody()); - SearchResponse searchResponse = SearchResponse.fromXContent(xcp); - - // 15 docs, all need to have either access code 1337 or 42 - Assert.assertEquals(searchResponse.toString(), 15, searchResponse.getHits().getTotalHits().value); - // fields need to have 42 or 1337 access code - assertAccessCodesMatch(searchResponse.getHits().getHits(), new Integer[] { 42, 1337 }); - - } - - @Test - public void testSimpleSearch_AccessCodes_999() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - HttpResponse response = rh.executeGetRequest("/tlqdocuments/_search?pretty", - encodeBasicHeader("tlq_999", "password")); - Assert.assertEquals(200, response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, - LoggingDeprecationHandler.INSTANCE, response.getBody()); - SearchResponse searchResponse = SearchResponse.fromXContent(xcp); - - Assert.assertEquals(searchResponse.toString(), 0, searchResponse.getHits().getTotalHits().value); - } - - @Test - public void testSimpleSearch_AccessCodes_emptyAccessCodes() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - SearchResponse searchResponse = executeSearch("tlqdocuments", "tlq_empty_access_codes", "password"); - Assert.assertEquals(searchResponse.toString(), 0, searchResponse.getHits().getTotalHits().value); - } - - @Test - public void testSimpleSearch_AccessCodes_noAccessCodes() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - SearchResponse searchResponse = executeSearch("tlqdocuments", "tlq_no_codes", "password"); - - Assert.assertEquals(searchResponse.toString(), 0, searchResponse.getHits().getTotalHits().value); - } - - @Test - public void testSimpleSearch_AllIndices_All_AccessCodes_1337() throws Exception { - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - SearchResponse searchResponse = executeSearch("_all", "tlq_1337", "password"); - - // assume hits from 2 indices: - // - tlqdocuments, must contain only docs with access code 1337 - // - tlqdummy, contains all documents - // no access to user_access_codes must be granted - - // check all 5 tlqdummy entries present, index is not protected by DLS - Set tlqdummyHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("tlqdummy")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); - - // check 10 hits with code 1337 from tlqdocuments index. All other documents - // must be filtered - Set tlqdocumentHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("tlqdocuments")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); - assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); - - // check no access to user_access_codes index - Set userAccessCodesHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("user_access_codes")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 0, userAccessCodesHits.size()); - } - - @Test - public void testSimpleSearch_AllIndicesWildcard_AccessCodes_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - SearchResponse searchResponse = executeSearch("*", "tlq_1337", "password"); - - // assume hits from 2 indices: - // - tlqdocuments, must contain only docs with access code 1337 - // - tlqdummy, contains all documents - // no access to user_access_codes must be granted - - // check all 5 tlqdummy entries present, index is not protected by DLS - Set tlqdummyHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("tlqdummy")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); - - // check 10 hits with code 1337 from tlqdocuments index. All other documents - // must be filtered - Set tlqdocumentHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("tlqdocuments")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); - assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); - - // check no access to user_access_codes index - Set userAccessCodesHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("user_access_codes")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 0, userAccessCodesHits.size()); - } - - @Test - public void testSimpleSearch_ThreeIndicesWildcard_AccessCodes_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - SearchResponse searchResponse = executeSearch("tlq*,user*", "tlq_1337", "password"); - - // assume hits from 2 indices: - // - tlqdocuments, must contain only docs with access code 1337 - // - tlqdummy, contains all documents - // no access to user_access_codes must be granted - - // check all 5 tlqdummy entries present, index is not protected by DLS - Set tlqdummyHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("tlqdummy")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); - - // check 10 hits with code 1337 from tlqdocuments index. All other documents - // must be filtered - Set tlqdocumentHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("tlqdocuments")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); - assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); - - // check no access to user_access_codes index - Set userAccessCodesHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("user_access_codes")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 0, userAccessCodesHits.size()); - - } - - @Test - public void testSimpleSearch_TwoIndicesConcreteNames_AccessCodes_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - SearchResponse searchResponse = executeSearch("tlqdocuments,tlqdummy", "tlq_1337", "password"); - - // assume hits from 2 indices: - // - tlqdocuments, must contains only 10 docs with access code 1337 - // - tlqdummy, must contains all 5 documents - - // check all 5 tlqdummy entries present, index is not protected by DLS - Set tlqdummyHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("tlqdummy")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); - - // ccheck 10 hits with code 1337 from tlqdocuments index. All other documents - // must be filtered - Set tlqdocumentHits = Arrays.asList(searchResponse.getHits().getHits()).stream() - .filter((h) -> h.getIndex().equals("tlqdocuments")).collect(Collectors.toSet()); - Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); - assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); - } - - @Test - public void testMSearch_ThreeIndices_AccessCodes_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - MultiSearchResponse searchResponse = executeMSearchMatchAll("tlq_1337", "password", "tlqdummy", "tlqdocuments", - "user_access_codes"); - - Item[] responseItems = searchResponse.getResponses(); - - // as per API order in response is the same as in the msearch request - - // check all 5 tlqdummy entries present - List tlqdummyHits = Arrays.asList(responseItems[0].getResponse().getHits().getHits()); - Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); - - // check 10 hits with code 1337 from tlqdocuments index. All other documents - // must be filtered - List tlqdocumentHits = Arrays.asList(responseItems[1].getResponse().getHits().getHits()); - Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); - assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); - - // check no access to user_access_codes index, just two indices in the response - Assert.assertTrue(responseItems[2].getResponse() == null); - Assert.assertTrue(responseItems[2].getFailure() != null); - - } - - // ------------------------ - // Test get and mget - // ------------------------ - - @Test - public void testGet_TlqDocumentsIndex_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - // user has 1337, document has 1337 - GetResponse searchResponse = executeGet("tlqdocuments", "1", "tlq_1337", "password"); - Assert.assertTrue(searchResponse != null); - Assert.assertTrue(searchResponse.isExists()); - assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337 }); - - // user has 1337, document has 42, not visible - searchResponse = executeGet("tlqdocuments", "2", "tlq_1337", "password"); - Assert.assertFalse(searchResponse.isExists()); - - // user has 1337, document has 42 and 1337 - searchResponse = executeGet("tlqdocuments", "3", "tlq_1337", "password"); - Assert.assertTrue(searchResponse != null); - Assert.assertTrue(searchResponse.isExists()); - assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337 }); - - // user has 1337, document has no access codes, not visible - searchResponse = executeGet("tlqdocuments", "16", "tlq_1337", "password"); - Assert.assertFalse(searchResponse.isExists()); - - // user has 1337, document has 12345, not visible - searchResponse = executeGet("tlqdocuments", "17", "tlq_1337", "password"); - Assert.assertFalse(searchResponse.isExists()); - - // user has 1337, document has 12345 and 6789, not visible - searchResponse = executeGet("tlqdocuments", "18", "tlq_1337", "password"); - Assert.assertFalse(searchResponse.isExists()); - - } - - @Test - public void testGet_TlqDocumentsIndex_1337_42() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - // user has 1337 and 42, document has 1337 - GetResponse searchResponse = executeGet("tlqdocuments", "1", "tlq_1337_42", "password"); - Assert.assertTrue(searchResponse != null); - Assert.assertTrue(searchResponse.isExists()); - assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337, 42 }); - - // user has 1337 and 42, document has 42 - searchResponse = executeGet("tlqdocuments", "2", "tlq_1337_42", "password"); - Assert.assertTrue(searchResponse != null); - Assert.assertTrue(searchResponse.isExists()); - assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337, 42 }); - - // user has 1337 and 42, document has 42 and 1337 - searchResponse = executeGet("tlqdocuments", "3", "tlq_1337_42", "password"); - Assert.assertTrue(searchResponse != null); - Assert.assertTrue(searchResponse.isExists()); - assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337, 42 }); - - // user has 1337 and 42, document has no access codes, not visible - searchResponse = executeGet("tlqdocuments", "16", "tlq_1337_42", "password"); - Assert.assertFalse(searchResponse.isExists()); - - // user has 1337 and 42, document has 12345, not visible - searchResponse = executeGet("tlqdocuments", "17", "tlq_1337_42", "password"); - Assert.assertFalse(searchResponse.isExists()); - - // user has 1337 and 42, document has 12345 and 6789, not visible - searchResponse = executeGet("tlqdocuments", "18", "tlq_1337_42", "password"); - Assert.assertFalse(searchResponse.isExists()); - - } - - @Test - public void testGet_TlqDummyIndex_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - // no restrictions on this index - GetResponse searchResponse = executeGet("tlqdummy", "101", "tlq_1337", "password"); - Assert.assertTrue(searchResponse != null); - Assert.assertTrue(searchResponse.isExists()); - - searchResponse = executeGet("tlqdummy", "102", "tlq_1337", "password"); - Assert.assertTrue(searchResponse != null); - Assert.assertTrue(searchResponse.isExists()); - - } - - @Test - public void testGet_UserAccessCodesIndex_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - // we expect a security exception here, user has no direct access to - // user_access_codes index - HttpResponse response = rh.executeGetRequest("/user_access_codes/_doc/tlq_1337", - encodeBasicHeader("tlq_1337", "password")); - Assert.assertEquals(403, response.getStatusCode()); - } - - @Test - public void testMGet_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - Map indicesAndIds = new HashMap<>(); - indicesAndIds.put("tlqdocuments", "1"); - indicesAndIds.put("tlqdocuments", "2"); - indicesAndIds.put("tlqdocuments", "3"); - indicesAndIds.put("tlqdocuments", "16"); - indicesAndIds.put("tlqdocuments", "17"); - indicesAndIds.put("tlqdocuments", "18"); - indicesAndIds.put("tlqdummy", "101"); - indicesAndIds.put("user_access_codes", "tlq_1337"); - - MultiGetResponse searchResponse = executeMGet("tlq_1337", "password", indicesAndIds); - - for (MultiGetItemResponse response : searchResponse.getResponses()) { - // no response from index "user_access_codes" - Assert.assertFalse(response.getIndex().equals("user_access_codes")); - switch (response.getIndex()) { - case "tlqdocuments": - Assert.assertTrue(response.getId(), response.getId().equals("1") | response.getId().equals("3")); - break; - case "tlqdummy": - Assert.assertTrue(response.getId(), response.getId().equals("101")); - break; - default: - Assert.fail("Index " + response.getIndex() + " present in mget response, but should not"); - } - } - } - -// ------------------------ -// Test aggregations -// ------------------------ - - @Test - public void testSimpleAggregation_tlqdocuments_AccessCode_1337() throws Exception { - - setup(new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") - .setSecurityInternalUsers("internal_users_tlq.yml").setSecurityRoles("roles_tlq.yml") - .setSecurityRolesMapping("roles_mapping_tlq.yml")); - - String body = "" - + " {\n" - + " \"aggs\": {\n" - + " \"buaggregation\": {\n" - + " \"terms\": {\n" - + " \"field\": \"bu\"\n" - + " }\n" - + " }\n" - + " }\n" - + " }\n" - + ""; - - // need to add typed_keys so aggregations can be parsed - // see for example: - // https://stackoverflow.com/questions/49798654/how-do-you-convert-an-elasticsearch-json-string-response-with-an-aggregation-t - HttpResponse response = rh.executePostRequest("/tlqdocuments/_search?pretty&typed_keys", body, - encodeBasicHeader("tlq_1337", "password")); - Assert.assertTrue(response.getStatusCode() == 200); - NamedXContentRegistry registry = new NamedXContentRegistry(getDefaultNamedXContents()); - XContentParser xcp = XContentType.JSON.xContent().createParser(registry, LoggingDeprecationHandler.INSTANCE, - response.getBody()); - SearchResponse searchResponse = SearchResponse.fromXContent(xcp); - - Aggregations aggs = searchResponse.getAggregations(); - Assert.assertNotNull(searchResponse.toString(), aggs); - Terms agg = aggs.get("buaggregation"); - Assert.assertTrue("Expected aggregation with name 'buaggregation'", agg != null); - // expect AAA - EEE (FFF does not match) with 2 docs each - for (String bucketName : new String[] { "AAA", "BBB", "CCC", "DDD", "EEE" }) { - Bucket bucket = agg.getBucketByKey(bucketName); - Assert.assertNotNull("Expected bucket " + bucketName + " to be present in agregations", bucket); - Assert.assertTrue("Expected doc count in bucket " + bucketName + " to be 2", bucket.getDocCount() == 2); - } - // expect FFF to be absent - Assert.assertNull("Expected bucket FFF to be absent", agg.getBucketByKey("FFF")); - } - - - public static List getDefaultNamedXContents() { - Map> map = new HashMap<>(); - map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c)); - map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c)); - List entries = map.entrySet().stream() - .map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue())) - .collect(Collectors.toList()); - return entries; - } + protected void populateData(Client client) { + // user access codes, basis for TLQ query + client.index( + new IndexRequest("user_access_codes").id("tlq_1337") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"access_codes\": [1337] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("user_access_codes").id("tlq_42") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"access_codes\": [42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("user_access_codes").id("tlq_1337_42") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"access_codes\": [1337, 42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("user_access_codes").id("tlq_999") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"access_codes\": [999] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("user_access_codes").id("tlq_empty_access_codes") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"access_codes\": [] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("user_access_codes").id("tlq_no_codes") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bla\": \"blub\" }", XContentType.JSON) + ).actionGet(); + + // need to have keyword for bu field since we're testing aggregations + client.admin().indices().create(new CreateIndexRequest("tlqdocuments")).actionGet(); + client.admin().indices().putMapping(new PutMappingRequest("tlqdocuments").source("bu", "type=keyword")).actionGet(); + + // tlqdocuments, protected by TLQ + client.index( + new IndexRequest("tlqdocuments").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"AAA\", \"access_codes\": [1337] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"AAA\", \"access_codes\": [42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("3") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"AAA\", \"access_codes\": [1337, 42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("4") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"BBB\", \"access_codes\": [1337] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("5") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"BBB\", \"access_codes\": [42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("6") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"BBB\", \"access_codes\": [1337, 42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("7") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"CCC\", \"access_codes\": [1337] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("8") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"CCC\", \"access_codes\": [42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("9") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"CCC\", \"access_codes\": [1337, 42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("10") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"DDD\", \"access_codes\": [1337] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("11") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"DDD\", \"access_codes\": [42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("12") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"DDD\", \"access_codes\": [1337, 42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("13") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"EEE\", \"access_codes\": [1337] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("14") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"EEE\", \"access_codes\": [42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("15") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"EEE\", \"access_codes\": [1337, 42] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("16") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"FFF\" }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("17") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"FFF\", \"access_codes\": [12345] }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdocuments").id("18") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"bu\": \"FFF\", \"access_codes\": [12345, 6789] }", XContentType.JSON) + ).actionGet(); + + // we use a "bu" field here as well to test aggregations over multiple indices + client.admin().indices().create(new CreateIndexRequest("tlqdummy")).actionGet(); + client.admin().indices().putMapping(new PutMappingRequest("tlqdummy").source("bu", "type=keyword")).actionGet(); + + // tlqdummy, not protected by TLQ + client.index( + new IndexRequest("tlqdummy").id("101") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"mykey\": \"101\", \"bu\": \"GGG\" }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdummy").id("102") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"mykey\": \"102\", \"bu\": \"GGG\" }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdummy").id("103") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"mykey\": \"103\", \"bu\": \"GGG\" }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdummy").id("104") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"mykey\": \"104\", \"bu\": \"GGG\" }", XContentType.JSON) + ).actionGet(); + client.index( + new IndexRequest("tlqdummy").id("105") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{ \"mykey\": \"105\", \"bu\": \"GGG\" }", XContentType.JSON) + ).actionGet(); + + } + + // ------------------------ + // Test search and msearch + // ------------------------ + + @Test + public void testSimpleSearch_AccessCode_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + HttpResponse response = rh.executeGetRequest("/tlqdocuments/_search?pretty", encodeBasicHeader("tlq_1337", "password")); + Assert.assertEquals(200, response.getStatusCode()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + SearchResponse searchResponse = SearchResponse.fromXContent(xcp); + // 10 docs, all need to have access code 1337 + Assert.assertEquals(searchResponse.toString(), 10, searchResponse.getHits().getTotalHits().value); + // fields need to have 1337 access code + assertAccessCodesMatch(searchResponse.getHits().getHits(), new Integer[] { 1337 }); + } + + @Test + public void testSimpleSearch_AccessCode_42() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + HttpResponse response = rh.executeGetRequest("/tlqdocuments/_search?pretty", encodeBasicHeader("tlq_42", "password")); + Assert.assertEquals(200, response.getStatusCode()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + SearchResponse searchResponse = SearchResponse.fromXContent(xcp); + + // 10 docs, all need to have access code 42 + Assert.assertEquals(searchResponse.toString(), 10, searchResponse.getHits().getTotalHits().value); + // fields need to have 42 access code + assertAccessCodesMatch(searchResponse.getHits().getHits(), new Integer[] { 42 }); + + } + + @Test + public void testSimpleSearch_AccessCodes_1337_42() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + HttpResponse response = rh.executeGetRequest("/tlqdocuments/_search?pretty", encodeBasicHeader("tlq_1337_42", "password")); + Assert.assertEquals(200, response.getStatusCode()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + SearchResponse searchResponse = SearchResponse.fromXContent(xcp); + + // 15 docs, all need to have either access code 1337 or 42 + Assert.assertEquals(searchResponse.toString(), 15, searchResponse.getHits().getTotalHits().value); + // fields need to have 42 or 1337 access code + assertAccessCodesMatch(searchResponse.getHits().getHits(), new Integer[] { 42, 1337 }); + + } + + @Test + public void testSimpleSearch_AccessCodes_999() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + HttpResponse response = rh.executeGetRequest("/tlqdocuments/_search?pretty", encodeBasicHeader("tlq_999", "password")); + Assert.assertEquals(200, response.getStatusCode()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + SearchResponse searchResponse = SearchResponse.fromXContent(xcp); + + Assert.assertEquals(searchResponse.toString(), 0, searchResponse.getHits().getTotalHits().value); + } + + @Test + public void testSimpleSearch_AccessCodes_emptyAccessCodes() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + SearchResponse searchResponse = executeSearch("tlqdocuments", "tlq_empty_access_codes", "password"); + Assert.assertEquals(searchResponse.toString(), 0, searchResponse.getHits().getTotalHits().value); + } + + @Test + public void testSimpleSearch_AccessCodes_noAccessCodes() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + SearchResponse searchResponse = executeSearch("tlqdocuments", "tlq_no_codes", "password"); + + Assert.assertEquals(searchResponse.toString(), 0, searchResponse.getHits().getTotalHits().value); + } + + @Test + public void testSimpleSearch_AllIndices_All_AccessCodes_1337() throws Exception { + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + SearchResponse searchResponse = executeSearch("_all", "tlq_1337", "password"); + + // assume hits from 2 indices: + // - tlqdocuments, must contain only docs with access code 1337 + // - tlqdummy, contains all documents + // no access to user_access_codes must be granted + + // check all 5 tlqdummy entries present, index is not protected by DLS + Set tlqdummyHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("tlqdummy")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); + + // check 10 hits with code 1337 from tlqdocuments index. All other documents + // must be filtered + Set tlqdocumentHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("tlqdocuments")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); + assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); + + // check no access to user_access_codes index + Set userAccessCodesHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("user_access_codes")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 0, userAccessCodesHits.size()); + } + + @Test + public void testSimpleSearch_AllIndicesWildcard_AccessCodes_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + SearchResponse searchResponse = executeSearch("*", "tlq_1337", "password"); + + // assume hits from 2 indices: + // - tlqdocuments, must contain only docs with access code 1337 + // - tlqdummy, contains all documents + // no access to user_access_codes must be granted + + // check all 5 tlqdummy entries present, index is not protected by DLS + Set tlqdummyHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("tlqdummy")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); + + // check 10 hits with code 1337 from tlqdocuments index. All other documents + // must be filtered + Set tlqdocumentHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("tlqdocuments")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); + assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); + + // check no access to user_access_codes index + Set userAccessCodesHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("user_access_codes")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 0, userAccessCodesHits.size()); + } + + @Test + public void testSimpleSearch_ThreeIndicesWildcard_AccessCodes_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + SearchResponse searchResponse = executeSearch("tlq*,user*", "tlq_1337", "password"); + + // assume hits from 2 indices: + // - tlqdocuments, must contain only docs with access code 1337 + // - tlqdummy, contains all documents + // no access to user_access_codes must be granted + + // check all 5 tlqdummy entries present, index is not protected by DLS + Set tlqdummyHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("tlqdummy")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); + + // check 10 hits with code 1337 from tlqdocuments index. All other documents + // must be filtered + Set tlqdocumentHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("tlqdocuments")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); + assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); + + // check no access to user_access_codes index + Set userAccessCodesHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("user_access_codes")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 0, userAccessCodesHits.size()); + + } + + @Test + public void testSimpleSearch_TwoIndicesConcreteNames_AccessCodes_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + SearchResponse searchResponse = executeSearch("tlqdocuments,tlqdummy", "tlq_1337", "password"); + + // assume hits from 2 indices: + // - tlqdocuments, must contains only 10 docs with access code 1337 + // - tlqdummy, must contains all 5 documents + + // check all 5 tlqdummy entries present, index is not protected by DLS + Set tlqdummyHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("tlqdummy")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); + + // ccheck 10 hits with code 1337 from tlqdocuments index. All other documents + // must be filtered + Set tlqdocumentHits = Arrays.asList(searchResponse.getHits().getHits()) + .stream() + .filter((h) -> h.getIndex().equals("tlqdocuments")) + .collect(Collectors.toSet()); + Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); + assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); + } + + @Test + public void testMSearch_ThreeIndices_AccessCodes_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + MultiSearchResponse searchResponse = executeMSearchMatchAll( + "tlq_1337", + "password", + "tlqdummy", + "tlqdocuments", + "user_access_codes" + ); + + Item[] responseItems = searchResponse.getResponses(); + + // as per API order in response is the same as in the msearch request + + // check all 5 tlqdummy entries present + List tlqdummyHits = Arrays.asList(responseItems[0].getResponse().getHits().getHits()); + Assert.assertEquals(searchResponse.toString(), 5, tlqdummyHits.size()); + + // check 10 hits with code 1337 from tlqdocuments index. All other documents + // must be filtered + List tlqdocumentHits = Arrays.asList(responseItems[1].getResponse().getHits().getHits()); + Assert.assertEquals(searchResponse.toString(), 10, tlqdocumentHits.size()); + assertAccessCodesMatch(tlqdocumentHits, new Integer[] { 1337 }); + + // check no access to user_access_codes index, just two indices in the response + Assert.assertTrue(responseItems[2].getResponse() == null); + Assert.assertTrue(responseItems[2].getFailure() != null); + + } + + // ------------------------ + // Test get and mget + // ------------------------ + + @Test + public void testGet_TlqDocumentsIndex_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + // user has 1337, document has 1337 + GetResponse searchResponse = executeGet("tlqdocuments", "1", "tlq_1337", "password"); + Assert.assertTrue(searchResponse != null); + Assert.assertTrue(searchResponse.isExists()); + assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337 }); + + // user has 1337, document has 42, not visible + searchResponse = executeGet("tlqdocuments", "2", "tlq_1337", "password"); + Assert.assertFalse(searchResponse.isExists()); + + // user has 1337, document has 42 and 1337 + searchResponse = executeGet("tlqdocuments", "3", "tlq_1337", "password"); + Assert.assertTrue(searchResponse != null); + Assert.assertTrue(searchResponse.isExists()); + assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337 }); + + // user has 1337, document has no access codes, not visible + searchResponse = executeGet("tlqdocuments", "16", "tlq_1337", "password"); + Assert.assertFalse(searchResponse.isExists()); + + // user has 1337, document has 12345, not visible + searchResponse = executeGet("tlqdocuments", "17", "tlq_1337", "password"); + Assert.assertFalse(searchResponse.isExists()); + + // user has 1337, document has 12345 and 6789, not visible + searchResponse = executeGet("tlqdocuments", "18", "tlq_1337", "password"); + Assert.assertFalse(searchResponse.isExists()); + + } + + @Test + public void testGet_TlqDocumentsIndex_1337_42() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + // user has 1337 and 42, document has 1337 + GetResponse searchResponse = executeGet("tlqdocuments", "1", "tlq_1337_42", "password"); + Assert.assertTrue(searchResponse != null); + Assert.assertTrue(searchResponse.isExists()); + assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337, 42 }); + + // user has 1337 and 42, document has 42 + searchResponse = executeGet("tlqdocuments", "2", "tlq_1337_42", "password"); + Assert.assertTrue(searchResponse != null); + Assert.assertTrue(searchResponse.isExists()); + assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337, 42 }); + + // user has 1337 and 42, document has 42 and 1337 + searchResponse = executeGet("tlqdocuments", "3", "tlq_1337_42", "password"); + Assert.assertTrue(searchResponse != null); + Assert.assertTrue(searchResponse.isExists()); + assertAccessCodesMatch(searchResponse.getSourceAsMap(), "access_codes", new Integer[] { 1337, 42 }); + + // user has 1337 and 42, document has no access codes, not visible + searchResponse = executeGet("tlqdocuments", "16", "tlq_1337_42", "password"); + Assert.assertFalse(searchResponse.isExists()); + + // user has 1337 and 42, document has 12345, not visible + searchResponse = executeGet("tlqdocuments", "17", "tlq_1337_42", "password"); + Assert.assertFalse(searchResponse.isExists()); + + // user has 1337 and 42, document has 12345 and 6789, not visible + searchResponse = executeGet("tlqdocuments", "18", "tlq_1337_42", "password"); + Assert.assertFalse(searchResponse.isExists()); + + } + + @Test + public void testGet_TlqDummyIndex_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + // no restrictions on this index + GetResponse searchResponse = executeGet("tlqdummy", "101", "tlq_1337", "password"); + Assert.assertTrue(searchResponse != null); + Assert.assertTrue(searchResponse.isExists()); + + searchResponse = executeGet("tlqdummy", "102", "tlq_1337", "password"); + Assert.assertTrue(searchResponse != null); + Assert.assertTrue(searchResponse.isExists()); + + } + + @Test + public void testGet_UserAccessCodesIndex_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + // we expect a security exception here, user has no direct access to + // user_access_codes index + HttpResponse response = rh.executeGetRequest("/user_access_codes/_doc/tlq_1337", encodeBasicHeader("tlq_1337", "password")); + Assert.assertEquals(403, response.getStatusCode()); + } + + @Test + public void testMGet_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + Map indicesAndIds = new HashMap<>(); + indicesAndIds.put("tlqdocuments", "1"); + indicesAndIds.put("tlqdocuments", "2"); + indicesAndIds.put("tlqdocuments", "3"); + indicesAndIds.put("tlqdocuments", "16"); + indicesAndIds.put("tlqdocuments", "17"); + indicesAndIds.put("tlqdocuments", "18"); + indicesAndIds.put("tlqdummy", "101"); + indicesAndIds.put("user_access_codes", "tlq_1337"); + + MultiGetResponse searchResponse = executeMGet("tlq_1337", "password", indicesAndIds); + + for (MultiGetItemResponse response : searchResponse.getResponses()) { + // no response from index "user_access_codes" + Assert.assertFalse(response.getIndex().equals("user_access_codes")); + switch (response.getIndex()) { + case "tlqdocuments": + Assert.assertTrue(response.getId(), response.getId().equals("1") | response.getId().equals("3")); + break; + case "tlqdummy": + Assert.assertTrue(response.getId(), response.getId().equals("101")); + break; + default: + Assert.fail("Index " + response.getIndex() + " present in mget response, but should not"); + } + } + } + + // ------------------------ + // Test aggregations + // ------------------------ + + @Test + public void testSimpleAggregation_tlqdocuments_AccessCode_1337() throws Exception { + + setup( + new DynamicSecurityConfig().setConfig("securityconfig_tlq.yml") + .setSecurityInternalUsers("internal_users_tlq.yml") + .setSecurityRoles("roles_tlq.yml") + .setSecurityRolesMapping("roles_mapping_tlq.yml") + ); + + String body = "" + + " {\n" + + " \"aggs\": {\n" + + " \"buaggregation\": {\n" + + " \"terms\": {\n" + + " \"field\": \"bu\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + ""; + + // need to add typed_keys so aggregations can be parsed + // see for example: + // https://stackoverflow.com/questions/49798654/how-do-you-convert-an-elasticsearch-json-string-response-with-an-aggregation-t + HttpResponse response = rh.executePostRequest( + "/tlqdocuments/_search?pretty&typed_keys", + body, + encodeBasicHeader("tlq_1337", "password") + ); + Assert.assertTrue(response.getStatusCode() == 200); + NamedXContentRegistry registry = new NamedXContentRegistry(getDefaultNamedXContents()); + XContentParser xcp = XContentType.JSON.xContent().createParser(registry, LoggingDeprecationHandler.INSTANCE, response.getBody()); + SearchResponse searchResponse = SearchResponse.fromXContent(xcp); + + Aggregations aggs = searchResponse.getAggregations(); + Assert.assertNotNull(searchResponse.toString(), aggs); + Terms agg = aggs.get("buaggregation"); + Assert.assertTrue("Expected aggregation with name 'buaggregation'", agg != null); + // expect AAA - EEE (FFF does not match) with 2 docs each + for (String bucketName : new String[] { "AAA", "BBB", "CCC", "DDD", "EEE" }) { + Bucket bucket = agg.getBucketByKey(bucketName); + Assert.assertNotNull("Expected bucket " + bucketName + " to be present in agregations", bucket); + Assert.assertTrue("Expected doc count in bucket " + bucketName + " to be 2", bucket.getDocCount() == 2); + } + // expect FFF to be absent + Assert.assertNull("Expected bucket FFF to be absent", agg.getBucketByKey("FFF")); + } + + public static List getDefaultNamedXContents() { + Map> map = new HashMap<>(); + map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c)); + map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c)); + List entries = map.entrySet() + .stream() + .map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue())) + .collect(Collectors.toList()); + return entries; + } } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsTest.java index 5405146263..a9361d275a 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/DlsTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/DlsTest.java @@ -24,16 +24,16 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class DlsTest extends AbstractDlsFlsTest{ - +public class DlsTest extends AbstractDlsFlsTest { @Override protected void populateData(Client tc) { - tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"amount\": 10}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"amount\": 1500}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"amount\": 10}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("deals").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"amount\": 1500}", XContentType.JSON) + ).actionGet(); try { Thread.sleep(3000); @@ -51,23 +51,28 @@ public void testDlsAggregations() throws Exception { setup(); - - String query = "{"+ - "\"query\" : {"+ - "\"match_all\": {}"+ - "},"+ - "\"aggs\" : {"+ - "\"thesum\" : { \"sum\" : { \"field\" : \"amount\" } }"+ - "}"+ - "}"; + String query = "{" + + "\"query\" : {" + + "\"match_all\": {}" + + "}," + + "\"aggs\" : {" + + "\"thesum\" : { \"sum\" : { \"field\" : \"amount\" } }" + + "}" + + "}"; HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"value\" : 1500.0")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"value\" : 1510.0")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -93,67 +98,88 @@ public void testDls() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertEquals(res.getHeaders().toString(), 2, res.getHeaders().size()); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - String query = - "{"+ - "\"query\": {"+ - "\"range\" : {"+ - "\"amount\" : {"+ - "\"gte\" : 8,"+ - "\"lte\" : 20,"+ - "\"boost\" : 3.0"+ - "}"+ - "}"+ - "}"+ - "}"; - + "{" + + "\"query\": {" + + "\"range\" : {" + + "\"amount\" : {" + + "\"gte\" : 8," + + "\"lte\" : 20," + + "\"boost\" : 3.0" + + "}" + + "}" + + "}" + + "}"; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 0,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); query = - "{"+ - "\"query\": {"+ - "\"range\" : {"+ - "\"amount\" : {"+ - "\"gte\" : 100,"+ - "\"lte\" : 2000,"+ - "\"boost\" : 2.0"+ - "}"+ - "}"+ - "}"+ - "}"; - + "{" + + "\"query\": {" + + "\"range\" : {" + + "\"amount\" : {" + + "\"gte\" : 100," + + "\"lte\" : 2000," + + "\"boost\" : 2.0" + + "}" + + "}" + + "}" + + "}"; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?q=amount:10&pretty", encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?q=amount:10&pretty", encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 0,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -166,45 +192,57 @@ public void testDls() throws Exception { res = rh.executeGetRequest("/deals/_doc/1?pretty", encodeBasicHeader("dept_manager", "password")); Assert.assertTrue(res.getBody().contains("\"found\" : true")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"count\" : 2,")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"count\" : 1,")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - - //mget - //msearch - String msearchBody = - "{\"index\":\"deals\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"deals\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + // mget + // msearch + String msearchBody = "{\"index\":\"deals\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"deals\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("_opendistro_security_dls_query")); Assert.assertFalse(res.getBody().contains("_opendistro_security_fls_fields")); Assert.assertTrue(res.getBody().contains("\"amount\" : 1500")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"deals\","+ - "\"_id\" : \"1\""+ - " },"+ - " {"+ - "\"_index\" : \"deals\","+ - " \"_id\" : \"2\""+ - "}"+ - "]"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"deals\"," + + "\"_id\" : \"1\"" + + " }," + + " {" + + "\"_index\" : \"deals\"," + + " \"_id\" : \"2\"" + + "}" + + "]" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("_opendistro_security_dls_query")); Assert.assertFalse(res.getBody().contains("_opendistro_security_fls_fields")); Assert.assertTrue(res.getBody().contains("amount")); @@ -220,26 +258,26 @@ public void testNonDls() throws Exception { HttpResponse res; String query = - "{"+ - "\"_source\": false,"+ - "\"query\": {"+ - "\"range\" : {"+ - "\"amount\" : {"+ - "\"gte\" : 100,"+ - "\"lte\" : 2000,"+ - "\"boost\" : 2.0"+ - "}"+ - "}"+ - "}"+ - "}"; - - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + "{" + + "\"_source\": false," + + "\"query\": {" + + "\"range\" : {" + + "\"amount\" : {" + + "\"gte\" : 100," + + "\"lte\" : 2000," + + "\"boost\" : 2.0" + + "}" + + "}" + + "}" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - - } @Test @@ -248,11 +286,17 @@ public void testDlsCache() throws Exception { setup(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -271,69 +315,86 @@ public void testDlsWithMinDocCountZeroAggregations() throws Exception { client.admin().indices().create(new CreateIndexRequest("logs").simpleMapping("termX", "type=keyword")).actionGet(); for (int i = 0; i < 3; i++) { - client.index(new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("amount", i, "termX", "A", "timestamp", "2022-01-06T09:05:00Z")).actionGet(); - client.index(new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("amount", i, "termX", "B", "timestamp", "2022-01-06T09:08:00Z")).actionGet(); - client.index(new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("amount", i, "termX", "C", "timestamp", "2022-01-06T09:09:00Z")).actionGet(); - client.index(new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("amount", i, "termX", "D", "timestamp", "2022-01-06T09:10:00Z")).actionGet(); + client.index( + new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("amount", i, "termX", "A", "timestamp", "2022-01-06T09:05:00Z") + ).actionGet(); + client.index( + new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("amount", i, "termX", "B", "timestamp", "2022-01-06T09:08:00Z") + ).actionGet(); + client.index( + new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("amount", i, "termX", "C", "timestamp", "2022-01-06T09:09:00Z") + ).actionGet(); + client.index( + new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("amount", i, "termX", "D", "timestamp", "2022-01-06T09:10:00Z") + ).actionGet(); } - client.index(new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("amount", 0, "termX", "E", "timestamp", "2022-01-06T09:11:00Z")).actionGet(); + client.index( + new IndexRequest("logs").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("amount", 0, "termX", "E", "timestamp", "2022-01-06T09:11:00Z") + ).actionGet(); } // Terms Aggregation - // Non-admin user with setting "min_doc_count":0. Expected to get error message "min_doc_count 0 is not supported when DLS is activated". + // Non-admin user with setting "min_doc_count":0. Expected to get error message "min_doc_count 0 is not supported when DLS is + // activated". String query1 = "{\n" - + " \"size\":0,\n" - + " \"query\":{\n" - + " \"bool\":{\n" - + " \"must\":[\n" - + " {\n" - + " \"range\":{\n" - + " \"amount\":{\"gte\":1,\"lte\":100}\n" - + " }\n" - + " }\n" - + " ]\n" - + " }\n" - + " },\n" - + " \"aggs\":{\n" - + " \"a\": {\n" - + " \"terms\": {\n" - + " \"field\": \"termX\",\n" - + " \"min_doc_count\":0,\n" - + "\"size\": 10,\n" - + "\"order\": { \"_count\": \"desc\" }\n" - + " }\n" - + " }\n" - + " }\n" - + "}"; + + " \"size\":0,\n" + + " \"query\":{\n" + + " \"bool\":{\n" + + " \"must\":[\n" + + " {\n" + + " \"range\":{\n" + + " \"amount\":{\"gte\":1,\"lte\":100}\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"aggs\":{\n" + + " \"a\": {\n" + + " \"terms\": {\n" + + " \"field\": \"termX\",\n" + + " \"min_doc_count\":0,\n" + + "\"size\": 10,\n" + + "\"order\": { \"_count\": \"desc\" }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; HttpResponse response1 = rh.executePostRequest("logs*/_search", query1, encodeBasicHeader("dept_manager", "password")); Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response1.getStatusCode()); Assert.assertTrue(response1.getBody(), response1.getBody().contains("min_doc_count 0 is not supported when DLS is activated")); - // Non-admin user without setting "min_doc_count". Expected to only have access to buckets for dept_manager excluding E with 0 doc_count". + // Non-admin user without setting "min_doc_count". Expected to only have access to buckets for dept_manager excluding E with 0 + // doc_count". String query2 = "{\n" - + " \"size\":0,\n" - + " \"query\":{\n" - + " \"bool\":{\n" - + " \"must\":[\n" - + " {\n" - + " \"range\":{\n" - + " \"amount\":{\"gte\":1,\"lte\":100}\n" - + " }\n" - + " }\n" - + " ]\n" - + " }\n" - + " },\n" - + " \"aggs\":{\n" - + " \"a\": {\n" - + " \"terms\": {\n" - + " \"field\": \"termX\",\n" - + "\"size\": 10,\n" - + "\"order\": { \"_count\": \"desc\" }\n" - + " }\n" - + " }\n" - + " }\n" - + "}"; + + " \"size\":0,\n" + + " \"query\":{\n" + + " \"bool\":{\n" + + " \"must\":[\n" + + " {\n" + + " \"range\":{\n" + + " \"amount\":{\"gte\":1,\"lte\":100}\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"aggs\":{\n" + + " \"a\": {\n" + + " \"terms\": {\n" + + " \"field\": \"termX\",\n" + + "\"size\": 10,\n" + + "\"order\": { \"_count\": \"desc\" }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; HttpResponse response2 = rh.executePostRequest("logs*/_search", query2, encodeBasicHeader("dept_manager", "password")); @@ -366,7 +427,8 @@ public void testDlsWithMinDocCountZeroAggregations() throws Exception { // Significant Text Aggregation is not impacted. // Non-admin user with setting "min_doc_count=0". Expected to only have access to buckets for dept_manager". - String query3 = "{\"size\":100,\"aggregations\":{\"significant_termX\":{\"significant_terms\":{\"field\":\"termX.keyword\",\"min_doc_count\":0}}}}"; + String query3 = + "{\"size\":100,\"aggregations\":{\"significant_termX\":{\"significant_terms\":{\"field\":\"termX.keyword\",\"min_doc_count\":0}}}}"; HttpResponse response5 = rh.executePostRequest("logs*/_search", query3, encodeBasicHeader("dept_manager", "password")); Assert.assertEquals(HttpStatus.SC_OK, response5.getStatusCode()); @@ -443,7 +505,6 @@ public void testDlsWithMinDocCountZeroAggregations() throws Exception { Assert.assertTrue(response11.getBody(), response11.getBody().contains("\"termX\":\"D\"")); Assert.assertTrue(response11.getBody(), response11.getBody().contains("\"termX\":\"E\"")); - // Admin without setting "min_doc_count". Expected to have access to all buckets". HttpResponse response12 = rh.executePostRequest("logs*/_search", query6, encodeBasicHeader("admin", "admin")); @@ -456,7 +517,8 @@ public void testDlsWithMinDocCountZeroAggregations() throws Exception { // Date Histogram Aggregation is not impacted. // Non-admin user with setting "min_doc_count=0". Expected to only have access to buckets for dept_manager". - String query7 = "{\"size\":100,\"aggs\":{\"timestamp\":{\"date_histogram\":{\"field\":\"timestamp\",\"calendar_interval\":\"month\",\"min_doc_count\":0}}}}"; + String query7 = + "{\"size\":100,\"aggs\":{\"timestamp\":{\"date_histogram\":{\"field\":\"timestamp\",\"calendar_interval\":\"month\",\"min_doc_count\":0}}}}"; HttpResponse response13 = rh.executePostRequest("logs*/_search", query7, encodeBasicHeader("dept_manager", "password")); @@ -468,7 +530,8 @@ public void testDlsWithMinDocCountZeroAggregations() throws Exception { Assert.assertFalse(response13.getBody(), response13.getBody().contains("\"termX\":\"E\"")); // Non-admin user without setting "min_doc_count". Expected to only have access to buckets for dept_manager". - String query8 = "{\"size\":100,\"aggs\":{\"timestamp\":{\"date_histogram\":{\"field\":\"timestamp\",\"calendar_interval\":\"month\"}}}}"; + String query8 = + "{\"size\":100,\"aggs\":{\"timestamp\":{\"date_histogram\":{\"field\":\"timestamp\",\"calendar_interval\":\"month\"}}}}"; HttpResponse response14 = rh.executePostRequest("logs*/_search", query8, encodeBasicHeader("dept_manager", "password")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FieldMaskedTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FieldMaskedTest.java index 40542e76b7..2628bebbc0 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FieldMaskedTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FieldMaskedTest.java @@ -23,21 +23,37 @@ public class FieldMaskedTest extends AbstractDlsFlsTest { - protected void populateData(Client tc) { - tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust1\"}, \"ip_source\": \"100.100.1.1\",\"ip_dest\": \"123.123.1.1\",\"amount\": 10}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust2\"}, \"ip_source\": \"100.100.2.2\",\"ip_dest\": \"123.123.2.2\",\"amount\": 20}", XContentType.JSON)).actionGet(); - - - for (int i=0; i<30;i++) { - tc.index(new IndexRequest("deals").id("a"+i).setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust1\"}, \"ip_source\": \"200.100.1.1\",\"ip_dest\": \"123.123.1.1\",\"amount\": 10}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("deals").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust1\"}, \"ip_source\": \"100.100.1.1\",\"ip_dest\": \"123.123.1.1\",\"amount\": 10}", + XContentType.JSON + ) + ).actionGet(); + tc.index( + new IndexRequest("deals").id("2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust2\"}, \"ip_source\": \"100.100.2.2\",\"ip_dest\": \"123.123.2.2\",\"amount\": 20}", + XContentType.JSON + ) + ).actionGet(); + + for (int i = 0; i < 30; i++) { + tc.index( + new IndexRequest("deals").id("a" + i) + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust1\"}, \"ip_source\": \"200.100.1.1\",\"ip_dest\": \"123.123.1.1\",\"amount\": 10}", + XContentType.JSON + ) + ).actionGet(); } - } + } @Test public void testMaskedAggregations() throws Exception { @@ -46,61 +62,72 @@ public void testMaskedAggregations() throws Exception { String query; HttpResponse res; - query = "{"+ - "\"query\" : {"+ - "\"match_all\": {}"+ - "},"+ - "\"aggs\" : {"+ - "\"ips\" : { \"terms\" : { \"field\" : \"ip_source.keyword\" } }"+ - "}"+ - "}"; - - //Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); - //Assert.assertTrue(res.getBody().contains("100.100")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked", "password"))).getStatusCode()); + query = "{" + + "\"query\" : {" + + "\"match_all\": {}" + + "}," + + "\"aggs\" : {" + + "\"ips\" : { \"terms\" : { \"field\" : \"ip_source.keyword\" } }" + + "}" + + "}"; + + // Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, + // encodeBasicHeader("admin", "admin"))).getStatusCode()); + // Assert.assertTrue(res.getBody().contains("100.100")); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked", "password"))) + .getStatusCode() + ); Assert.assertFalse(res.getBody().contains("100.100")); - query = - "{" + - "\"query\" : {" + - "\"match_all\": {" + - "}" + - "}," + - "\"aggs\": {" + - "\"ips\" : {" + - "\"terms\" : {" + - "\"field\" : \"ip_source.keyword\"," + - "\"order\": {" + - "\"_term\" : \"asc\"" + - "}" + - "}" + - "}" + - "}" + - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked", "password"))).getStatusCode()); + query = "{" + + "\"query\" : {" + + "\"match_all\": {" + + "}" + + "}," + + "\"aggs\": {" + + "\"ips\" : {" + + "\"terms\" : {" + + "\"field\" : \"ip_source.keyword\"," + + "\"order\": {" + + "\"_term\" : \"asc\"" + + "}" + + "}" + + "}" + + "}" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked", "password"))) + .getStatusCode() + ); Assert.assertFalse(res.getBody().contains("100.100")); - query = - "{" + - "\"query\" : {" + - "\"match_all\": {" + - "}" + - "}," + - "\"aggs\": {" + - "\"ips\" : {" + - "\"terms\" : {" + - "\"field\" : \"ip_source.keyword\"," + - "\"order\": {" + - "\"_term\" : \"desc\"" + - "}" + - "}" + - "}" + - "}" + - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked", "password"))).getStatusCode()); + query = "{" + + "\"query\" : {" + + "\"match_all\": {" + + "}" + + "}," + + "\"aggs\": {" + + "\"ips\" : {" + + "\"terms\" : {" + + "\"field\" : \"ip_source.keyword\"," + + "\"order\": {" + + "\"_term\" : \"desc\"" + + "}" + + "}" + + "}" + + "}" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked", "password"))) + .getStatusCode() + ); Assert.assertFalse(res.getBody().contains("100.100")); } @@ -109,15 +136,17 @@ public void testMaskedAggregationsRace() throws Exception { setup(); - - String query = "{"+ - "\"aggs\" : {"+ - "\"ips\" : { \"terms\" : { \"field\" : \"ip_source.keyword\", \"size\": 1002, \"show_term_doc_count_error\": true } }"+ - "}"+ - "}"; + String query = "{" + + "\"aggs\" : {" + + "\"ips\" : { \"terms\" : { \"field\" : \"ip_source.keyword\", \"size\": 1002, \"show_term_doc_count_error\": true } }" + + "}" + + "}"; HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("100.100")); Assert.assertTrue(res.getBody().contains("200.100")); Assert.assertTrue(res.getBody().contains("\"doc_count\" : 30")); @@ -126,7 +155,11 @@ public void testMaskedAggregationsRace() throws Exception { Assert.assertFalse(res.getBody().contains("26a8671e57fefc13504f8c61ced67ac98338261ace1e5bf462038b2f2caae16e")); Assert.assertFalse(res.getBody().contains("87873bdb698e5f0f60e0b02b76dad1ec11b2787c628edbc95b7ff0e82274b140")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("user_masked", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"doc_count\" : 30")); Assert.assertTrue(res.getBody().contains("\"doc_count\" : 1")); Assert.assertFalse(res.getBody().contains("100.100")); @@ -135,8 +168,11 @@ public void testMaskedAggregationsRace() throws Exception { Assert.assertTrue(res.getBody().contains("26a8671e57fefc13504f8c61ced67ac98338261ace1e5bf462038b2f2caae16e")); Assert.assertTrue(res.getBody().contains("87873bdb698e5f0f60e0b02b76dad1ec11b2787c628edbc95b7ff0e82274b140")); - for(int i=0;i<10;i++) { - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + for (int i = 0; i < 10; i++) { + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty&size=0", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("100.100")); Assert.assertTrue(res.getBody().contains("200.100")); Assert.assertTrue(res.getBody().contains("\"doc_count\" : 30")); @@ -155,7 +191,10 @@ public void testMaskedSearch() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=100", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 32,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertTrue(res.getBody().contains("cust1")); @@ -164,8 +203,10 @@ public void testMaskedSearch() throws Exception { Assert.assertTrue(res.getBody().contains("100.100.2.2")); Assert.assertFalse(res.getBody().contains("87873bdb698e5f0f60e0b02b76dad1ec11b2787c628edbc95b7ff0e82274b140")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=100", encodeBasicHeader("user_masked", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=100", encodeBasicHeader("user_masked", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 32,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertTrue(res.getBody().contains("cust1")); @@ -183,7 +224,10 @@ public void testMaskedGet() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertTrue(res.getBody().contains("cust1")); Assert.assertFalse(res.getBody().contains("cust2")); @@ -191,8 +235,10 @@ public void testMaskedGet() throws Exception { Assert.assertFalse(res.getBody().contains("100.100.2.2")); Assert.assertFalse(res.getBody().contains("87873bdb698e5f0f60e0b02b76dad1ec11b2787c628edbc95b7ff0e82274b140")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("user_masked", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("user_masked", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertTrue(res.getBody().contains("cust1")); Assert.assertFalse(res.getBody().contains("cust2")); @@ -201,5 +247,4 @@ public void testMaskedGet() throws Exception { Assert.assertTrue(res.getBody().contains("87873bdb698e5f0f60e0b02b76dad1ec11b2787c628edbc95b7ff0e82274b140")); } - } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/Fls983Test.java b/src/test/java/org/opensearch/security/dlic/dlsfls/Fls983Test.java index 6f00dfd348..61bc9b53b3 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/Fls983Test.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/Fls983Test.java @@ -22,13 +22,11 @@ import org.opensearch.security.test.DynamicSecurityConfig; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class Fls983Test extends AbstractDlsFlsTest{ - +public class Fls983Test extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest(".kibana").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest(".kibana").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{}", XContentType.JSON)).actionGet(); } @Test @@ -38,11 +36,13 @@ public void test() throws Exception { HttpResponse res; - String doc = "{\"doc\" : {"+ - "\"x\" : \"y\""+ - "}}"; + String doc = "{\"doc\" : {" + "\"x\" : \"y\"" + "}}"; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/.kibana/_update/0?pretty", doc, encodeBasicHeader("human_resources_trainee", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/.kibana/_update/0?pretty", doc, encodeBasicHeader("human_resources_trainee", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("updated")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestAB.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestAB.java index 9cc5cc8b3b..aabe2e4add 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestAB.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestAB.java @@ -23,28 +23,48 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class FlsDlsTestAB extends AbstractDlsFlsTest{ - +public class FlsDlsTestAB extends AbstractDlsFlsTest { protected void populateData(Client tc) { - //aaa - tc.index(new IndexRequest("aaa").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"f1\": \"f1_a0\", \"f2\": \"f2_a0\", \"f3\": \"f3_a0\", \"f4\": \"f4_a0\",\"type\": \"a\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("aaa").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"f1\": \"f1_a1\", \"f2\": \"f2_a1\", \"f3\": \"f3_a1\", \"f4\": \"f4_a1\",\"type\": \"a\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("aaa").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"f1\": \"f1_a2\", \"f2\": \"f2_a2\", \"f3\": \"f3_a2\", \"f4\": \"f4_a2\",\"type\": \"x\"}", XContentType.JSON)).actionGet(); - - //bbb - tc.index(new IndexRequest("bbb").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"f1\": \"f1_b0\", \"f2\": \"f2_b0\", \"f3\": \"f3_b0\", \"f4\": \"f4_b0\",\"type\": \"b\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("bbb").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"f1\": \"f1_b1\", \"f2\": \"f2_b1\", \"f3\": \"f3_b1\", \"f4\": \"f4_b1\",\"type\": \"b\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("bbb").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"f1\": \"f1_b2\", \"f2\": \"f2_b2\", \"f3\": \"f3_b2\", \"f4\": \"f4_b2\",\"type\": \"x\"}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("aaa","bbb").alias("abalias"))).actionGet(); + // aaa + tc.index( + new IndexRequest("aaa").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"f1\": \"f1_a0\", \"f2\": \"f2_a0\", \"f3\": \"f3_a0\", \"f4\": \"f4_a0\",\"type\": \"a\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("aaa").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"f1\": \"f1_a1\", \"f2\": \"f2_a1\", \"f3\": \"f3_a1\", \"f4\": \"f4_a1\",\"type\": \"a\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("aaa").id("2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"f1\": \"f1_a2\", \"f2\": \"f2_a2\", \"f3\": \"f3_a2\", \"f4\": \"f4_a2\",\"type\": \"x\"}", XContentType.JSON) + ).actionGet(); + + // bbb + tc.index( + new IndexRequest("bbb").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"f1\": \"f1_b0\", \"f2\": \"f2_b0\", \"f3\": \"f3_b0\", \"f4\": \"f4_b0\",\"type\": \"b\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("bbb").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"f1\": \"f1_b1\", \"f2\": \"f2_b1\", \"f3\": \"f3_b1\", \"f4\": \"f4_b1\",\"type\": \"b\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("bbb").id("2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"f1\": \"f1_b2\", \"f2\": \"f2_b2\", \"f3\": \"f3_b2\", \"f4\": \"f4_b2\",\"type\": \"x\"}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("aaa", "bbb").alias("abalias"))) + .actionGet(); } @@ -55,7 +75,10 @@ public void testDlsFlsAB() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/aaa,bbb/_search?pretty", encodeBasicHeader("user_aaa", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/aaa,bbb/_search?pretty", encodeBasicHeader("user_aaa", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -69,8 +92,10 @@ public void testDlsFlsAB() throws Exception { Assert.assertTrue(res.getBody().contains("f3_b")); Assert.assertFalse(res.getBody().contains("f1_b")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/abalias/_search?pretty", encodeBasicHeader("user_aaa", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/abalias/_search?pretty", encodeBasicHeader("user_aaa", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -84,7 +109,10 @@ public void testDlsFlsAB() throws Exception { Assert.assertTrue(res.getBody().contains("f3_b")); Assert.assertFalse(res.getBody().contains("f1_b")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/aaa,bbb/_search?pretty", encodeBasicHeader("user_bbb", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/aaa,bbb/_search?pretty", encodeBasicHeader("user_bbb", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -98,8 +126,10 @@ public void testDlsFlsAB() throws Exception { Assert.assertFalse(res.getBody().contains("f3_b")); Assert.assertTrue(res.getBody().contains("f1_b")); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/abalias/_search?pretty", encodeBasicHeader("user_bbb", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/abalias/_search?pretty", encodeBasicHeader("user_bbb", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestForbiddenField.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestForbiddenField.java index 6df02c2e22..840f574a9f 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestForbiddenField.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestForbiddenField.java @@ -21,15 +21,23 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class FlsDlsTestForbiddenField extends AbstractDlsFlsTest{ - +public class FlsDlsTestForbiddenField extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust1\"}, \"zip\": \"12345\",\"secret\": \"tellnoone\",\"amount\": 10}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust2\", \"ctype\":\"industry\"}, \"amount\": 1500}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("deals").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust1\"}, \"zip\": \"12345\",\"secret\": \"tellnoone\",\"amount\": 10}", + XContentType.JSON + ) + ).actionGet(); + tc.index( + new IndexRequest("deals").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"customer\": {\"name\":\"cust2\", \"ctype\":\"industry\"}, \"amount\": 1500}", XContentType.JSON) + ).actionGet(); } @@ -38,23 +46,29 @@ public void testDlsAggregations() throws Exception { setup(); - - String query = "{"+ - "\"query\" : {"+ - "\"match_all\": {}"+ - "},"+ - "\"aggs\" : {"+ - "\"thesum\" : { \"sum\" : { \"field\" : \"amount\" } }"+ - "}"+ - "}"; + String query = "{" + + "\"query\" : {" + + "\"match_all\": {}" + + "}," + + "\"aggs\" : {" + + "\"thesum\" : { \"sum\" : { \"field\" : \"amount\" } }" + + "}" + + "}"; HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_fls_dls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_fls_dls", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 0,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"value\" : 0")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"value\" : 1510.0")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -66,58 +80,77 @@ public void testDls() throws Exception { setup(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("dept_manager_fls_dls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("dept_manager_fls_dls", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 0,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - String query = - "{"+ - "\"query\": {"+ - "\"range\" : {"+ - "\"amount\" : {"+ - "\"gte\" : 8,"+ - "\"lte\" : 20,"+ - "\"boost\" : 3.0"+ - "}"+ - "}"+ - "}"+ - "}"; - - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("dept_manager_fls_dls", "password"))).getStatusCode()); + "{" + + "\"query\": {" + + "\"range\" : {" + + "\"amount\" : {" + + "\"gte\" : 8," + + "\"lte\" : 20," + + "\"boost\" : 3.0" + + "}" + + "}" + + "}" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_fls_dls", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 0,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); query = - "{"+ - "\"query\": {"+ - "\"range\" : {"+ - "\"amount\" : {"+ - "\"gte\" : 100,"+ - "\"lte\" : 2000,"+ - "\"boost\" : 2.0"+ - "}"+ - "}"+ - "}"+ - "}"; - - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("dept_manager_fls_dls", "password"))).getStatusCode()); + "{" + + "\"query\": {" + + "\"range\" : {" + + "\"amount\" : {" + + "\"gte\" : 100," + + "\"lte\" : 2000," + + "\"boost\" : 2.0" + + "}" + + "}" + + "}" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_fls_dls", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 0,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?q=amount:10&pretty", encodeBasicHeader("dept_manager_fls_dls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?q=amount:10&pretty", encodeBasicHeader("dept_manager_fls_dls", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 0,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -133,11 +166,17 @@ public void testDls() throws Exception { res = rh.executeGetRequest("/deals/_doc/1?pretty", encodeBasicHeader("dept_manager_fls_dls", "password")); Assert.assertTrue(res.getBody().contains("\"found\" : false")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"count\" : 2,")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("dept_manager_fls_dls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("dept_manager_fls_dls", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"count\" : 0,")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); } @@ -149,7 +188,10 @@ public void testCombined() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("user_combined", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("user_combined", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestMulti.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestMulti.java index b177f1d346..e9d32f18ea 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestMulti.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsDlsTestMulti.java @@ -21,21 +21,33 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class FlsDlsTestMulti extends AbstractDlsFlsTest{ - +public class FlsDlsTestMulti extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust1\"}, \"zip\": \"12345\",\"secret\": \"tellnoone\",\"amount\": 10}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust2\", \"ctype\":\"industry\"}, \"amount\": 1500}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust3\", \"ctype\":\"industry\"}, \"amount\": 200}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("3").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust4\", \"ctype\":\"industry\"}, \"amount\": 20001}", XContentType.JSON)).actionGet(); - - + tc.index( + new IndexRequest("deals").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust1\"}, \"zip\": \"12345\",\"secret\": \"tellnoone\",\"amount\": 10}", + XContentType.JSON + ) + ).actionGet(); + tc.index( + new IndexRequest("deals").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"customer\": {\"name\":\"cust2\", \"ctype\":\"industry\"}, \"amount\": 1500}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("deals").id("2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"customer\": {\"name\":\"cust3\", \"ctype\":\"industry\"}, \"amount\": 200}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("deals").id("3") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"customer\": {\"name\":\"cust4\", \"ctype\":\"industry\"}, \"amount\": 20001}", XContentType.JSON) + ).actionGet(); } @@ -44,29 +56,34 @@ public void testDlsAggregations() throws Exception { setup(); - - String query = "{"+ - "\"query\" : {"+ - "\"match_all\": {}"+ - "},"+ - "\"aggs\" : {"+ - "\"thesum\" : { \"sum\" : { \"field\" : \"amount\" } }"+ - "}"+ - "}"; + String query = "{" + + "\"query\" : {" + + "\"match_all\": {}" + + "}," + + "\"aggs\" : {" + + "\"thesum\" : { \"sum\" : { \"field\" : \"amount\" } }" + + "}" + + "}"; HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_multi", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 3,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"value\" : 1710.0")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"value\" : 21711.0")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); } - @Test public void testDlsFls() throws Exception { @@ -74,63 +91,85 @@ public void testDlsFls() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("ctype")); Assert.assertFalse(res.getBody().contains("secret")); Assert.assertTrue(res.getBody().contains("zip")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("dept_manager_multi", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 3,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=0", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - String query = - "{"+ - "\"query\": {"+ - "\"range\" : {"+ - "\"amount\" : {"+ - "\"gte\" : 8,"+ - "\"lte\" : 20,"+ - "\"boost\" : 3.0"+ - "}"+ - "}"+ - "}"+ - "}"; - - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + "{" + + "\"query\": {" + + "\"range\" : {" + + "\"amount\" : {" + + "\"gte\" : 8," + + "\"lte\" : 20," + + "\"boost\" : 3.0" + + "}" + + "}" + + "}" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_multi", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); query = - "{"+ - "\"query\": {"+ - "\"range\" : {"+ - "\"amount\" : {"+ - "\"gte\" : 100,"+ - "\"lte\" : 2000,"+ - "\"boost\" : 2.0"+ - "}"+ - "}"+ - "}"+ - "}"; - - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + "{" + + "\"query\": {" + + "\"range\" : {" + + "\"amount\" : {" + + "\"gte\" : 100," + + "\"lte\" : 2000," + + "\"boost\" : 2.0" + + "}" + + "}" + + "}" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_multi", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query,encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?q=amount:10&pretty", encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?q=amount:10&pretty", encodeBasicHeader("dept_manager_multi", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -143,23 +182,34 @@ public void testDlsFls() throws Exception { res = rh.executeGetRequest("/deals/_doc/1?pretty", encodeBasicHeader("dept_manager_multi", "password")); Assert.assertTrue(res.getBody().contains("\"found\" : true")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"count\" : 4,")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_count?pretty", encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"count\" : 3,")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - //mget - //msearch - String msearchBody = - "{\"index\":\"deals\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - //"{\"index\":\".opendistro_security\", \"type\":\"_doc\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - //"{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + // mget + // msearch + String msearchBody = "{\"index\":\"deals\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); + // "{\"index\":\".opendistro_security\", \"type\":\"_doc\", \"ignore_unavailable\": true}"+System.lineSeparator()+ + // "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("dept_manager_multi", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody(), res.getBody().contains("\"value\" : 3,\n \"relation")); Assert.assertFalse(res.getBody().contains("_opendistro_security_dls_query")); Assert.assertFalse(res.getBody().contains("_opendistro_security_fls_fields")); @@ -169,29 +219,31 @@ public void testDlsFls() throws Exception { Assert.assertTrue(res.getBody().contains("\"amount\" : 20")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); - - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"deals\","+ - "\"_id\" : \"0\""+ - " },"+ - " {"+ - "\"_index\" : \"deals\","+ - " \"_id\" : \"1\""+ - "},"+ - " {"+ - "\"_index\" : \"deals\","+ - " \"_id\" : \"2\""+ - "},"+ - " {"+ - "\"_index\" : \"deals\","+ - " \"_id\" : \"3\""+ - "}"+ - "]"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"deals\"," + + "\"_id\" : \"0\"" + + " }," + + " {" + + "\"_index\" : \"deals\"," + + " \"_id\" : \"1\"" + + "}," + + " {" + + "\"_index\" : \"deals\"," + + " \"_id\" : \"2\"" + + "}," + + " {" + + "\"_index\" : \"deals\"," + + " \"_id\" : \"3\"" + + "}" + + "]" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("_opendistro_security_dls_query")); Assert.assertFalse(res.getBody().contains("_opendistro_security_fls_fields")); Assert.assertTrue(res.getBody().contains("\"amount\" : 1500")); @@ -209,30 +261,37 @@ public void testDlsSuggest() throws Exception { HttpResponse res; String query = - "{"+ - "\"query\": {"+ - "\"range\" : {"+ - "\"amount\" : {"+ - "\"gte\" : 11,"+ - "\"lte\" : 50000,"+ - "\"boost\" : 1.0"+ - "}"+ - "}"+ - "},"+ - "\"suggest\" : {\n" + - " \"thesuggestion\" : {\n" + - " \"text\" : \"cust\",\n" + - " \"term\" : {\n" + - " \"field\" : \"customer.name\"\n" + - " }\n" + - " }\n" + - " }"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + "{" + + "\"query\": {" + + "\"range\" : {" + + "\"amount\" : {" + + "\"gte\" : 11," + + "\"lte\" : 50000," + + "\"boost\" : 1.0" + + "}" + + "}" + + "}," + + "\"suggest\" : {\n" + + " \"thesuggestion\" : {\n" + + " \"text\" : \"cust\",\n" + + " \"term\" : {\n" + + " \"field\" : \"customer.name\"\n" + + " }\n" + + " }\n" + + " }" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("thesuggestion")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_multi", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("thesuggestion")); } @@ -244,21 +303,28 @@ public void testDlsSuggestOnly() throws Exception { HttpResponse res; String query = - "{"+ - "\"suggest\" : {\n" + - " \"thesuggestion\" : {\n" + - " \"text\" : \"cust\",\n" + - " \"term\" : {\n" + - " \"field\" : \"customer.name\"\n" + - " }\n" + - " }\n" + - " }"+ - "}"; - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + "{" + + "\"suggest\" : {\n" + + " \"thesuggestion\" : {\n" + + " \"text\" : \"cust\",\n" + + " \"term\" : {\n" + + " \"field\" : \"customer.name\"\n" + + " }\n" + + " }\n" + + " }" + + "}"; + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("thesuggestion")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_multi", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("dept_manager_multi", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("thesuggestion")); } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsExistsFieldsTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsExistsFieldsTest.java index 8f056c8244..32cc44efc0 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsExistsFieldsTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsExistsFieldsTest.java @@ -26,33 +26,49 @@ public class FlsExistsFieldsTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.admin().indices().create(new CreateIndexRequest("data") - .simpleMapping("@timestamp", "type=date", "host", "type=text,norms=false", "response", "type=text,norms=false", "non-existing", "type=text,norms=false")) - .actionGet(); + tc.admin() + .indices() + .create( + new CreateIndexRequest("data").simpleMapping( + "@timestamp", + "type=date", + "host", + "type=text,norms=false", + "response", + "type=text,norms=false", + "non-existing", + "type=text,norms=false" + ) + ) + .actionGet(); for (int i = 0; i < 1; i++) { - String doc = "{\"host\" : \"myhost"+i+"\",\n" + - " \"@timestamp\" : \"2018-01-18T09:03:25.877Z\",\n" + - " \"response\": \"404\"}"; - tc.index(new IndexRequest("data").id("a-normal-" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(doc, - XContentType.JSON)).actionGet(); + String doc = "{\"host\" : \"myhost" + + i + + "\",\n" + + " \"@timestamp\" : \"2018-01-18T09:03:25.877Z\",\n" + + " \"response\": \"404\"}"; + tc.index(new IndexRequest("data").id("a-normal-" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(doc, XContentType.JSON)) + .actionGet(); } for (int i = 0; i < 1; i++) { - String doc = "{" + - " \"@timestamp\" : \"2017-01-18T09:03:25.877Z\",\n" + - " \"response\": \"200\"}"; - tc.index(new IndexRequest("data").id("b-missing1-" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(doc, - XContentType.JSON)).actionGet(); + String doc = "{" + " \"@timestamp\" : \"2017-01-18T09:03:25.877Z\",\n" + " \"response\": \"200\"}"; + tc.index( + new IndexRequest("data").id("b-missing1-" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(doc, XContentType.JSON) + ).actionGet(); } for (int i = 0; i < 1; i++) { - String doc = "{\"host\" : \"myhost"+i+"\",\n" + - " \"@timestamp\" : \"2018-01-18T09:03:25.877Z\",\n" + - " \"non-existing\": \"xxx\","+ - " \"response\": \"403\"}"; - tc.index(new IndexRequest("data").id("c-missing2-" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(doc, - XContentType.JSON)).actionGet(); + String doc = "{\"host\" : \"myhost" + + i + + "\",\n" + + " \"@timestamp\" : \"2018-01-18T09:03:25.877Z\",\n" + + " \"non-existing\": \"xxx\"," + + " \"response\": \"403\"}"; + tc.index( + new IndexRequest("data").id("c-missing2-" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(doc, XContentType.JSON) + ).actionGet(); } } @@ -61,47 +77,50 @@ protected void populateData(Client tc) { public void testExistsField() throws Exception { setup(); - String query = "{\n" + - " \"query\": {\n" + - " \"bool\": {\n" + - - " \"must_not\": \n" + - " {\n" + - " \"exists\": {\n" + - " \"field\": \"non-existing\"\n" + - " \n" + - " }\n" + - " },\n" + - - " \"must\": [\n" + - " {\n" + - " \"exists\": {\n" + - " \"field\": \"@timestamp\"\n" + - " }\n" + - " },\n" + - " {\n" + - " \"exists\": {\n" + - " \"field\": \"host\"\n" + - " }\n" + - " }\n" + - " ]\n" + - " }\n" + - " }\n" + - "}"; + String query = "{\n" + " \"query\": {\n" + " \"bool\": {\n" + + + " \"must_not\": \n" + + " {\n" + + " \"exists\": {\n" + + " \"field\": \"non-existing\"\n" + + " \n" + + " }\n" + + " },\n" + + + + " \"must\": [\n" + + " {\n" + + " \"exists\": {\n" + + " \"field\": \"@timestamp\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"exists\": {\n" + + " \"field\": \"host\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + "}"; HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, - (res = rh.executePostRequest("/data/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/data/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("a-normal-0")); Assert.assertTrue(res.getBody().contains("response")); Assert.assertTrue(res.getBody().contains("404")); - //only see's - timestamp and host field - //therefore non-existing does not exist so we expect c-missing2-0 to be returned - Assert.assertEquals(HttpStatus.SC_OK, - (res = rh.executePostRequest("/data/_search?pretty", query, encodeBasicHeader("fls_exists", "password"))).getStatusCode()); + // only see's - timestamp and host field + // therefore non-existing does not exist so we expect c-missing2-0 to be returned + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/data/_search?pretty", query, encodeBasicHeader("fls_exists", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("a-normal-0")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsFieldsTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsFieldsTest.java index d4826222fa..a910cf5663 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsFieldsTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsFieldsTest.java @@ -25,19 +25,22 @@ import org.opensearch.security.test.helper.file.FileHelper; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class FlsFieldsTest extends AbstractDlsFlsTest{ - +public class FlsFieldsTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.admin().indices().create(new CreateIndexRequest("deals").simpleMapping("timestamp", "type=date", "@timestamp", "type=date")).actionGet(); + tc.admin() + .indices() + .create(new CreateIndexRequest("deals").simpleMapping("timestamp", "type=date", "@timestamp", "type=date")) + .actionGet(); try { String doc = FileHelper.loadFile("dlsfls/doc1.json"); for (int i = 0; i < 10; i++) { final String moddoc = doc.replace("", "cust" + i).replace("", "" + i).replace("", "1970-01-02"); - tc.index(new IndexRequest("deals").id("0" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(moddoc, XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("deals").id("0" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(moddoc, XContentType.JSON)) + .actionGet(); } } catch (IOException e) { @@ -46,7 +49,6 @@ protected void populateData(Client tc) { } - @Test public void testFields() throws Exception { setup(); @@ -54,13 +56,19 @@ public void testFields() throws Exception { String query = FileHelper.loadFile("dlsfls/flsquery.json"); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("secret")); Assert.assertTrue(res.getBody().contains("@timestamp")); Assert.assertTrue(res.getBody().contains("\"timestamp")); Assert.assertTrue(res.getBody().contains("numfield5")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("fls_fields", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("fls_fields", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("customer")); Assert.assertFalse(res.getBody().contains("secret")); Assert.assertFalse(res.getBody().contains("timestamp")); @@ -74,12 +82,18 @@ public void testFields2() throws Exception { String query = FileHelper.loadFile("dlsfls/flsquery2.json"); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty=true", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty=true", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("secret")); Assert.assertTrue(res.getBody().contains("@timestamp")); Assert.assertTrue(res.getBody().contains("\"timestamp")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty=true", query, encodeBasicHeader("fls_fields", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty=true", query, encodeBasicHeader("fls_fields", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("customer")); Assert.assertFalse(res.getBody().contains("secret")); Assert.assertFalse(res.getBody().contains("timestamp")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsFieldsWcTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsFieldsWcTest.java index 951e786891..f6cfd036fd 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsFieldsWcTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsFieldsWcTest.java @@ -25,19 +25,22 @@ import org.opensearch.security.test.helper.file.FileHelper; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class FlsFieldsWcTest extends AbstractDlsFlsTest{ - +public class FlsFieldsWcTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.admin().indices().create(new CreateIndexRequest("deals").simpleMapping("timestamp", "type=date", "@timestamp", "type=date")).actionGet(); + tc.admin() + .indices() + .create(new CreateIndexRequest("deals").simpleMapping("timestamp", "type=date", "@timestamp", "type=date")) + .actionGet(); try { String doc = FileHelper.loadFile("dlsfls/doc1.json"); for (int i = 0; i < 10; i++) { final String moddoc = doc.replace("", "cust" + i).replace("", "" + i).replace("", "1970-01-02"); - tc.index(new IndexRequest("deals").id("0" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(moddoc, XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("deals").id("0" + i).setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(moddoc, XContentType.JSON)) + .actionGet(); } } catch (IOException e) { @@ -46,7 +49,6 @@ protected void populateData(Client tc) { } - @Test public void testFields() throws Exception { setup(); @@ -54,12 +56,18 @@ public void testFields() throws Exception { String query = FileHelper.loadFile("dlsfls/flsquery.json"); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("secret")); Assert.assertTrue(res.getBody().contains("@timestamp")); Assert.assertTrue(res.getBody().contains("\"timestamp")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("fls_fields_wc", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("fls_fields_wc", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("customer")); Assert.assertFalse(res.getBody().contains("secret")); Assert.assertFalse(res.getBody().contains("timestamp")); @@ -73,12 +81,18 @@ public void testFields2() throws Exception { String query = FileHelper.loadFile("dlsfls/flsquery2.json"); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("secret")); Assert.assertTrue(res.getBody().contains("@timestamp")); Assert.assertTrue(res.getBody().contains("\"timestamp")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("fls_fields_wc", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_search?pretty", query, encodeBasicHeader("fls_fields_wc", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("customer")); Assert.assertFalse(res.getBody().contains("secret")); Assert.assertFalse(res.getBody().contains("timestamp")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsIndexingTests.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsIndexingTests.java index bbac74e6eb..2d7ed0efcf 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsIndexingTests.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsIndexingTests.java @@ -32,16 +32,24 @@ public class FlsIndexingTests extends AbstractDlsFlsTest { protected void populateData(final Client tc) { // Create several documents in different indices with shared field names, // different roles will have different levels of FLS restrictions - tc.index(new IndexRequest("yellow-pages").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"phone-all\":1001,\"phone-some\":1002,\"phone-one\":1003}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("green-pages").id("2").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"phone-all\":2001,\"phone-some\":2002,\"phone-one\":2003}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("blue-book").id("3").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"phone-all\":3001,\"phone-some\":3002,\"phone-one\":3003}", XContentType.JSON)).actionGet(); - - // Seperate index used to test aliasing - tc.index(new IndexRequest(".hidden").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("yellow-pages").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"phone-all\":1001,\"phone-some\":1002,\"phone-one\":1003}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("green-pages").id("2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"phone-all\":2001,\"phone-some\":2002,\"phone-one\":2003}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("blue-book").id("3") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"phone-all\":3001,\"phone-some\":3002,\"phone-one\":3003}", XContentType.JSON) + ).actionGet(); + + // Seperate index used to test aliasing + tc.index(new IndexRequest(".hidden").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{}", XContentType.JSON)).actionGet(); } private Header asPhoneOneUser = encodeBasicHeader("user_aaa", "password"); @@ -52,10 +60,10 @@ protected void populateData(final Client tc) { @Test public void testSingleIndexFlsApplied() throws Exception { - setup(new DynamicSecurityConfig() - .setSecurityRoles("roles_fls_indexing.yml") - .setSecurityRolesMapping("roles_mapping_fls_indexing.yml")); - + setup( + new DynamicSecurityConfig().setSecurityRoles("roles_fls_indexing.yml").setSecurityRolesMapping("roles_mapping_fls_indexing.yml") + ); + final HttpResponse phoneOneFilteredResponse = rh.executeGetRequest(searchQuery, asPhoneOneUser); assertThat(phoneOneFilteredResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat(phoneOneFilteredResponse.getBody(), not(containsString("1003"))); @@ -73,11 +81,14 @@ public void testSingleIndexFlsApplied() throws Exception { @Test public void testSingleIndexFlsAppliedForLimitedResults() throws Exception { - setup(new DynamicSecurityConfig() - .setSecurityRoles("roles_fls_indexing.yml") - .setSecurityRolesMapping("roles_mapping_fls_indexing.yml")); - - final HttpResponse phoneOneFilteredResponse = rh.executeGetRequest("/yellow-pages/_search?filter_path=hits.hits&pretty", asPhoneOneUser); + setup( + new DynamicSecurityConfig().setSecurityRoles("roles_fls_indexing.yml").setSecurityRolesMapping("roles_mapping_fls_indexing.yml") + ); + + final HttpResponse phoneOneFilteredResponse = rh.executeGetRequest( + "/yellow-pages/_search?filter_path=hits.hits&pretty", + asPhoneOneUser + ); assertThat(phoneOneFilteredResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat(phoneOneFilteredResponse.getBody(), not(containsString("1003"))); assertThat(phoneOneFilteredResponse.getBody(), containsString("1002")); @@ -94,9 +105,9 @@ public void testSingleIndexFlsAppliedForLimitedResults() throws Exception { @Test public void testSeveralIndexFlsApplied() throws Exception { - setup(new DynamicSecurityConfig() - .setSecurityRoles("roles_fls_indexing.yml") - .setSecurityRolesMapping("roles_mapping_fls_indexing.yml")); + setup( + new DynamicSecurityConfig().setSecurityRoles("roles_fls_indexing.yml").setSecurityRolesMapping("roles_mapping_fls_indexing.yml") + ); final HttpResponse phoneSomeFilteredResponse = rh.executeGetRequest(searchQuery, asPhoneSomeUser); assertThat(phoneSomeFilteredResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); @@ -115,9 +126,9 @@ public void testSeveralIndexFlsApplied() throws Exception { @Test public void testAllIndexFlsApplied() throws Exception { - setup(new DynamicSecurityConfig() - .setSecurityRoles("roles_fls_indexing.yml") - .setSecurityRolesMapping("roles_mapping_fls_indexing.yml")); + setup( + new DynamicSecurityConfig().setSecurityRoles("roles_fls_indexing.yml").setSecurityRolesMapping("roles_mapping_fls_indexing.yml") + ); final HttpResponse phoneAllFilteredResponse = rh.executeGetRequest(searchQuery, asPhoneAllUser); assertThat(phoneAllFilteredResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); @@ -136,11 +147,15 @@ public void testAllIndexFlsApplied() throws Exception { @Test public void testAllIndexFlsAppliedWithAlias() throws Exception { - setup(new DynamicSecurityConfig() - .setSecurityRoles("roles_fls_indexing.yml") - .setSecurityRolesMapping("roles_mapping_fls_indexing.yml")); - - final HttpResponse createAlias = rh.executePostRequest("_aliases", "{\"actions\":[{\"add\":{\"index\":\".hidden\",\"alias\":\"ducky\"}}]}", asPhoneAllUser); + setup( + new DynamicSecurityConfig().setSecurityRoles("roles_fls_indexing.yml").setSecurityRolesMapping("roles_mapping_fls_indexing.yml") + ); + + final HttpResponse createAlias = rh.executePostRequest( + "_aliases", + "{\"actions\":[{\"add\":{\"index\":\".hidden\",\"alias\":\"ducky\"}}]}", + asPhoneAllUser + ); assertThat(createAlias.getStatusCode(), equalTo(HttpStatus.SC_OK)); final HttpResponse phoneAllFilteredResponse = rh.executeGetRequest(searchQuery, asPhoneAllUser); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsKeywordTests.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsKeywordTests.java index 25069e48ef..1c51ec99b7 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsKeywordTests.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsKeywordTests.java @@ -32,20 +32,24 @@ public class FlsKeywordTests extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("movies").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"year\": 2013, \"title\": \"Rush\", \"actors\": [\"Daniel Br\u00FChl\", \"Chris Hemsworth\", \"Olivia Wilde\"]}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("movies").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"year\": 2013, \"title\": \"Rush\", \"actors\": [\"Daniel Br\u00FChl\", \"Chris Hemsworth\", \"Olivia Wilde\"]}", + XContentType.JSON + ) + ).actionGet(); } private Header movieUser = encodeBasicHeader("user_aaa", "password"); private Header movieNoActorUser = encodeBasicHeader("user_bbb", "password"); - private String[] actors = new String[] {"Daniel Br\u00FChl", "Chris Hemsworth", "Olivia Wilde"}; + private String[] actors = new String[] { "Daniel Br\u00FChl", "Chris Hemsworth", "Olivia Wilde" }; @Test public void testKeywordsAreAutomaticallyFiltered() throws Exception { - setup(new DynamicSecurityConfig() - .setSecurityRoles("roles_keyword.yml") - .setSecurityRolesMapping("roles_mappings_keyword.yml")); + setup(new DynamicSecurityConfig().setSecurityRoles("roles_keyword.yml").setSecurityRolesMapping("roles_mappings_keyword.yml")); final String searchQuery = "/movies/_search?filter_path=hits.hits._source"; final String aggQuery = "/movies/_search?filter_path=aggregations.actors.buckets.key"; @@ -73,14 +77,10 @@ public void testKeywordsAreAutomaticallyFiltered() throws Exception { } private void assertActorsPresent(final HttpResponse response) { - Arrays.stream(actors).forEach(actor -> { - assertThat(response.getBody(), containsString(actor)); - }); + Arrays.stream(actors).forEach(actor -> { assertThat(response.getBody(), containsString(actor)); }); } private void assertActorsNotPresent(final HttpResponse response) { - Arrays.stream(actors).forEach(actor -> { - assertThat(response.getBody(), not(containsString(actor))); - }); + Arrays.stream(actors).forEach(actor -> { assertThat(response.getBody(), not(containsString(actor))); }); } } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsPerfTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsPerfTest.java index 565dbdde9c..4fde195860 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsPerfTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsPerfTest.java @@ -30,30 +30,27 @@ import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; @Ignore -public class FlsPerfTest extends AbstractDlsFlsTest{ - +public class FlsPerfTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { Map indexSettings = new HashMap<>(3); - indexSettings.put("index.mapping.total_fields.limit",50000); + indexSettings.put("index.mapping.total_fields.limit", 50000); indexSettings.put("number_of_shards", 10); indexSettings.put("number_of_replicas", 0); - tc.admin().indices().create(new CreateIndexRequest("deals") - .settings(indexSettings)) - .actionGet(); + tc.admin().indices().create(new CreateIndexRequest("deals").settings(indexSettings)).actionGet(); try { - IndexRequest ir = new IndexRequest("deals").id("idx1"); + IndexRequest ir = new IndexRequest("deals").id("idx1"); XContentBuilder b = XContentBuilder.builder(JsonXContent.jsonXContent); b.startObject(); - b.field("amount",1000); + b.field("amount", 1000); b.startObject("xyz"); - b.field("abc","val"); + b.field("abc", "val"); b.endObject(); b.endObject(); @@ -61,13 +58,13 @@ protected void populateData(Client tc) { tc.index(ir).actionGet(); - for(int i=0; i<1500; i++) { + for (int i = 0; i < 1500; i++) { - ir = new IndexRequest("deals").id("id"+i); + ir = new IndexRequest("deals").id("id" + i); b = XContentBuilder.builder(JsonXContent.jsonXContent); b.startObject(); - for(int j=0; j<2000;j++) { - b.field("field"+j,"val"+j); + for (int j = 0; j < 2000; j++) { + b.field("field" + j, "val" + j); } b.endObject(); @@ -94,7 +91,10 @@ public void testFlsPerfNamed() throws Exception { StopWatch sw = new StopWatch("testFlsPerfNamed"); sw.start("non fls"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); Assert.assertTrue(res.getBody().contains("field2\"")); @@ -102,7 +102,11 @@ public void testFlsPerfNamed() throws Exception { Assert.assertTrue(res.getBody().contains("field997\"")); sw.start("with fls"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_only", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_only", "password"))) + .getStatusCode() + ); sw.stop(); Assert.assertFalse(res.getBody().contains("field1\"")); Assert.assertFalse(res.getBody().contains("field2\"")); @@ -111,7 +115,11 @@ public void testFlsPerfNamed() throws Exception { sw.start("with fls 2 after warmup"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_only", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_only", "password"))) + .getStatusCode() + ); sw.stop(); Assert.assertFalse(res.getBody().contains("field1\"")); @@ -121,7 +129,11 @@ public void testFlsPerfNamed() throws Exception { sw.start("with fls 3 after warmup"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_only", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_only", "password"))) + .getStatusCode() + ); sw.stop(); Assert.assertFalse(res.getBody().contains("field1\"")); @@ -141,7 +153,10 @@ public void testFlsPerfWcEx() throws Exception { StopWatch sw = new StopWatch("testFlsPerfWcEx"); sw.start("non fls"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); Assert.assertTrue(res.getBody().contains("field2\"")); @@ -149,7 +164,10 @@ public void testFlsPerfWcEx() throws Exception { Assert.assertTrue(res.getBody().contains("field997\"")); sw.start("with fls"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_ex", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_ex", "password"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); Assert.assertTrue(res.getBody().contains("field2\"")); @@ -158,7 +176,10 @@ public void testFlsPerfWcEx() throws Exception { sw.start("with fls 2 after warmup"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_ex", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_ex", "password"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); @@ -168,7 +189,10 @@ public void testFlsPerfWcEx() throws Exception { sw.start("with fls 3 after warmup"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_ex", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_ex", "password"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); @@ -188,7 +212,10 @@ public void testFlsPerfNamedEx() throws Exception { StopWatch sw = new StopWatch("testFlsPerfNamedEx"); sw.start("non fls"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); Assert.assertTrue(res.getBody().contains("field2\"")); @@ -196,7 +223,10 @@ public void testFlsPerfNamedEx() throws Exception { Assert.assertTrue(res.getBody().contains("field997\"")); sw.start("with fls"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_ex", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_ex", "password"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); Assert.assertTrue(res.getBody().contains("field2\"")); @@ -205,7 +235,10 @@ public void testFlsPerfNamedEx() throws Exception { sw.start("with fls 2 after warmup"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_ex", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_ex", "password"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); @@ -215,7 +248,10 @@ public void testFlsPerfNamedEx() throws Exception { sw.start("with fls 3 after warmup"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_ex", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_named_ex", "password"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); @@ -235,7 +271,10 @@ public void testFlsWcIn() throws Exception { StopWatch sw = new StopWatch("testFlsWcIn"); sw.start("non fls"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); sw.stop(); Assert.assertTrue(res.getBody().contains("field1\"")); Assert.assertTrue(res.getBody().contains("field2\"")); @@ -243,7 +282,10 @@ public void testFlsWcIn() throws Exception { Assert.assertTrue(res.getBody().contains("field997\"")); sw.start("with fls"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_in", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_in", "password"))).getStatusCode() + ); sw.stop(); Assert.assertFalse(res.getBody().contains("field0\"")); Assert.assertTrue(res.getBody().contains("field50\"")); @@ -251,7 +293,10 @@ public void testFlsWcIn() throws Exception { sw.start("with fls 2 after warmup"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_in", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_in", "password"))).getStatusCode() + ); sw.stop(); Assert.assertFalse(res.getBody().contains("field0\"")); @@ -260,7 +305,10 @@ public void testFlsWcIn() throws Exception { sw.start("with fls 3 after warmup"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_in", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty&size=1000", encodeBasicHeader("perf_wc_in", "password"))).getStatusCode() + ); sw.stop(); Assert.assertFalse(res.getBody().contains("field0\"")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsTest.java index c31650e734..180256efd9 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/FlsTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/FlsTest.java @@ -21,15 +21,23 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class FlsTest extends AbstractDlsFlsTest{ - +public class FlsTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust1\"}, \"zip\": \"12345\",\"secret\": \"tellnoone\",\"amount\": 10}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("deals").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust2\", \"ctype\":\"industry\"}, \"amount\": 1500}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("deals").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust1\"}, \"zip\": \"12345\",\"secret\": \"tellnoone\",\"amount\": 10}", + XContentType.JSON + ) + ).actionGet(); + tc.index( + new IndexRequest("deals").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"customer\": {\"name\":\"cust2\", \"ctype\":\"industry\"}, \"amount\": 1500}", XContentType.JSON) + ).actionGet(); } @Test @@ -39,8 +47,10 @@ public void testFieldCapabilities() throws Exception { HttpResponse res; - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_field_caps?fields=*&pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_field_caps?fields=*&pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("customer")); Assert.assertTrue(res.getBody().contains("customer.name")); Assert.assertTrue(res.getBody().contains("zip")); @@ -48,7 +58,11 @@ public void testFieldCapabilities() throws Exception { Assert.assertTrue(res.getBody().contains("amount")); Assert.assertTrue(res.getBody().contains("secret")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_field_caps?fields=*&pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_field_caps?fields=*&pretty", encodeBasicHeader("dept_manager_fls", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("customer")); Assert.assertTrue(res.getBody().contains("customer.name")); Assert.assertTrue(res.getBody().contains("zip")); @@ -56,7 +70,13 @@ public void testFieldCapabilities() throws Exception { Assert.assertFalse(res.getBody().contains("amount")); Assert.assertFalse(res.getBody().contains("secret")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_field_caps?fields=*&pretty", encodeBasicHeader("dept_manager_fls_reversed_fields", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "/deals/_field_caps?fields=*&pretty", + encodeBasicHeader("dept_manager_fls_reversed_fields", "password") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("customer")); Assert.assertFalse(res.getBody().contains("customer.name")); @@ -73,8 +93,10 @@ public void testMapping() throws Exception { HttpResponse res; - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_mapping?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_mapping?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("customer")); Assert.assertTrue(res.getBody().contains("name")); Assert.assertTrue(res.getBody().contains("zip")); @@ -82,7 +104,10 @@ public void testMapping() throws Exception { Assert.assertTrue(res.getBody().contains("amount")); Assert.assertTrue(res.getBody().contains("secret")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_mapping?pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_mapping?pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("customer")); Assert.assertTrue(res.getBody().contains("name")); Assert.assertTrue(res.getBody().contains("zip")); @@ -90,7 +115,11 @@ public void testMapping() throws Exception { Assert.assertFalse(res.getBody().contains("amount")); Assert.assertFalse(res.getBody().contains("secret")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_mapping?pretty", encodeBasicHeader("dept_manager_fls_reversed_fields", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_mapping?pretty", encodeBasicHeader("dept_manager_fls_reversed_fields", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("customer")); Assert.assertFalse(res.getBody().contains("name")); @@ -100,7 +129,6 @@ public void testMapping() throws Exception { Assert.assertTrue(res.getBody().contains("secret")); } - @Test public void testFlsSearch() throws Exception { @@ -108,7 +136,10 @@ public void testFlsSearch() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertTrue(res.getBody().contains("cust1")); @@ -118,7 +149,10 @@ public void testFlsSearch() throws Exception { Assert.assertTrue(res.getBody().contains("amount")); Assert.assertTrue(res.getBody().contains("secret")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertTrue(res.getBody().contains("cust1")); @@ -128,7 +162,11 @@ public void testFlsSearch() throws Exception { Assert.assertFalse(res.getBody().contains("amount")); Assert.assertFalse(res.getBody().contains("secret")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager_fls_reversed_fields", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_search?pretty", encodeBasicHeader("dept_manager_fls_reversed_fields", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertFalse(res.getBody().contains("cust1")); @@ -146,7 +184,10 @@ public void testFlsGet() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertTrue(res.getBody().contains("cust1")); Assert.assertFalse(res.getBody().contains("cust2")); @@ -154,7 +195,10 @@ public void testFlsGet() throws Exception { Assert.assertFalse(res.getBody().contains("ctype")); Assert.assertTrue(res.getBody().contains("amount")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_doc/0?pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertTrue(res.getBody().contains("cust1")); Assert.assertFalse(res.getBody().contains("cust2")); @@ -162,7 +206,11 @@ public void testFlsGet() throws Exception { Assert.assertFalse(res.getBody().contains("ctype")); Assert.assertFalse(res.getBody().contains("amount")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_doc/0?realtime=true&pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/deals/_doc/0?realtime=true&pretty", encodeBasicHeader("dept_manager_fls", "password"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertTrue(res.getBody().contains("cust1")); Assert.assertFalse(res.getBody().contains("cust2")); @@ -170,7 +218,13 @@ public void testFlsGet() throws Exception { Assert.assertFalse(res.getBody().contains("ctype")); Assert.assertFalse(res.getBody().contains("amount")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/deals/_doc/0?realtime=true&pretty", encodeBasicHeader("dept_manager_fls_reversed_fields", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "/deals/_doc/0?realtime=true&pretty", + encodeBasicHeader("dept_manager_fls_reversed_fields", "password") + )).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertFalse(res.getBody().contains("cust1")); Assert.assertFalse(res.getBody().contains("cust2")); @@ -187,11 +241,22 @@ public void testFlsUpdate() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("/deals/_update/0?pretty", "{\"doc\": {\"zip\": \"98765\"}}", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("/deals/_update/0?pretty", "{\"doc\": {\"zip\": \"98765\"}}", encodeBasicHeader("admin", "admin"))) + .getStatusCode() + ); Assert.assertTrue(res.getBody().contains("\"_version\" : 2")); Assert.assertFalse(res.getBody(), res.getBody().contains("\"successful\" : 0")); - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, (res = rh.executePostRequest("/deals/_update/0?pretty", "{\"doc\": {\"zip\": \"98765000\"}}", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + (res = rh.executePostRequest( + "/deals/_update/0?pretty", + "{\"doc\": {\"zip\": \"98765000\"}}", + encodeBasicHeader("dept_manager_fls", "password") + )).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("Update is not supported")); } @@ -202,7 +267,14 @@ public void testFlsUpdateIndex() throws Exception { HttpResponse res = null; - Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, (res = rh.executePostRequest("/deals/_update/0?pretty", "{\"doc\": {\"zip\": \"98765000\"}}", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + (res = rh.executePostRequest( + "/deals/_update/0?pretty", + "{\"doc\": {\"zip\": \"98765000\"}}", + encodeBasicHeader("dept_manager_fls", "password") + )).getStatusCode() + ); Assert.assertTrue(res.getBody().contains("Update is not supported")); } } diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/IndexPatternTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/IndexPatternTest.java index 7348b11341..9b075e0600 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/IndexPatternTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/IndexPatternTest.java @@ -21,20 +21,27 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class IndexPatternTest extends AbstractDlsFlsTest{ - +public class IndexPatternTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("logstash-2016").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"message\":\"mymsg1a\", \"ipaddr\": \"10.0.0.0\",\"msgid\": \"12\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-2016").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"message\":\"mymsg1b\", \"ipaddr\": \"10.0.0.1\",\"msgid\": \"14\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-2018").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"message\":\"mymsg1c\", \"ipaddr\": \"10.0.0.2\",\"msgid\": \"12\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("logstash-2018").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"message\":\"mymsg1d\", \"ipaddr\": \"10.0.0.3\",\"msgid\": \"14\"}", XContentType.JSON)).actionGet(); - } + tc.index( + new IndexRequest("logstash-2016").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"message\":\"mymsg1a\", \"ipaddr\": \"10.0.0.0\",\"msgid\": \"12\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("logstash-2016").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"message\":\"mymsg1b\", \"ipaddr\": \"10.0.0.1\",\"msgid\": \"14\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("logstash-2018").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"message\":\"mymsg1c\", \"ipaddr\": \"10.0.0.2\",\"msgid\": \"12\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("logstash-2018").setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"message\":\"mymsg1d\", \"ipaddr\": \"10.0.0.3\",\"msgid\": \"14\"}", XContentType.JSON) + ).actionGet(); + } @Test public void testSearch() throws Exception { @@ -43,7 +50,10 @@ public void testSearch() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-2016/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-2016/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -52,7 +62,11 @@ public void testSearch() throws Exception { Assert.assertTrue(res.getBody().contains("mymsg")); Assert.assertTrue(res.getBody().contains("msgid")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-2016/_search?pretty", encodeBasicHeader("opendistro_security_logstash", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-2016/_search?pretty", encodeBasicHeader("opendistro_security_logstash", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 1,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -69,13 +83,22 @@ public void testFieldCaps() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-2016/_field_caps?fields=*&pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-2016/_field_caps?fields=*&pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("ipaddr")); Assert.assertTrue(res.getBody().contains("message")); Assert.assertTrue(res.getBody().contains("msgid")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-2016/_field_caps?fields=*&pretty", encodeBasicHeader("opendistro_security_logstash", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + "/logstash-2016/_field_caps?fields=*&pretty", + encodeBasicHeader("opendistro_security_logstash", "password") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("ipaddr")); Assert.assertFalse(res.getBody().contains("message")); @@ -89,7 +112,10 @@ public void testSearchWc() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-20*/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-20*/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -98,7 +124,11 @@ public void testSearchWc() throws Exception { Assert.assertTrue(res.getBody().contains("mymsg")); Assert.assertTrue(res.getBody().contains("msgid")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-20*/_search?pretty", encodeBasicHeader("opendistro_security_logstash", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-20*/_search?pretty", encodeBasicHeader("opendistro_security_logstash", "password"))) + .getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -115,7 +145,10 @@ public void testSearchWcRegex() throws Exception { HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-20*/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-20*/_search?pretty", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 4,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); @@ -124,7 +157,10 @@ public void testSearchWcRegex() throws Exception { Assert.assertTrue(res.getBody().contains("mymsg")); Assert.assertTrue(res.getBody().contains("msgid")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("/logstash-20*/_search?pretty", encodeBasicHeader("regex", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("/logstash-20*/_search?pretty", encodeBasicHeader("regex", "password"))).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains("\"value\" : 2,\n \"relation")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); diff --git a/src/test/java/org/opensearch/security/dlic/dlsfls/MFlsTest.java b/src/test/java/org/opensearch/security/dlic/dlsfls/MFlsTest.java index b7305ee48c..81a2c50fc6 100644 --- a/src/test/java/org/opensearch/security/dlic/dlsfls/MFlsTest.java +++ b/src/test/java/org/opensearch/security/dlic/dlsfls/MFlsTest.java @@ -21,15 +21,26 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.security.test.helper.rest.RestHelper.HttpResponse; -public class MFlsTest extends AbstractDlsFlsTest{ - +public class MFlsTest extends AbstractDlsFlsTest { protected void populateData(Client tc) { - tc.index(new IndexRequest("deals").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"customer\": {\"name\":\"cust1\"}, \"zip\": \"12345\",\"secret\": \"tellnoone\",\"amount\": 10}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("finance").id("1").setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source("{\"finfield2\":\"fff\",\"xcustomer\": {\"name\":\"cust2\", \"ctype\":\"industry\"}, \"famount\": 1500}", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest("deals").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"customer\": {\"name\":\"cust1\"}, \"zip\": \"12345\",\"secret\": \"tellnoone\",\"amount\": 10}", + XContentType.JSON + ) + ).actionGet(); + tc.index( + new IndexRequest("finance").id("1") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source( + "{\"finfield2\":\"fff\",\"xcustomer\": {\"name\":\"cust2\", \"ctype\":\"industry\"}, \"famount\": 1500}", + XContentType.JSON + ) + ).actionGet(); } @Test @@ -40,7 +51,10 @@ public void testFlsMGetSearch() throws Exception { HttpResponse res; System.out.println("### normal search"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("deals,finance/_search?pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("deals,finance/_search?pretty", encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("_opendistro_security_")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertFalse(res.getBody().contains("xception")); @@ -50,16 +64,22 @@ public void testFlsMGetSearch() throws Exception { Assert.assertFalse(res.getBody().contains("amount")); Assert.assertFalse(res.getBody().contains("secret")); - //mget - //msearch - String msearchBody = - "{\"index\":\"deals\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"finance\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); + // mget + // msearch + String msearchBody = "{\"index\":\"deals\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"finance\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); System.out.println("### msearch"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("_opendistro_security_")); Assert.assertTrue(res.getBody().contains("\"failed\" : 0")); Assert.assertFalse(res.getBody().contains("xception")); @@ -69,22 +89,24 @@ public void testFlsMGetSearch() throws Exception { Assert.assertFalse(res.getBody().contains("amount")); Assert.assertFalse(res.getBody().contains("secret")); - - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"deals\","+ - "\"_id\" : \"0\""+ - " },"+ - " {"+ - "\"_index\" : \"finance\","+ - " \"_id\" : \"1\""+ - "}"+ - "]"+ - "}"; + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"deals\"," + + "\"_id\" : \"0\"" + + " }," + + " {" + + "\"_index\" : \"finance\"," + + " \"_id\" : \"1\"" + + "}" + + "]" + + "}"; System.out.println("### mget"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("dept_manager_fls", "password"))).getStatusCode() + ); Assert.assertFalse(res.getBody().contains("_opendistro_security_")); Assert.assertTrue(res.getBody().contains("\"found\" : true")); Assert.assertFalse(res.getBody().contains("\"found\" : false")); diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/AbstractRestApiUnitTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/AbstractRestApiUnitTest.java index 7b590f1d46..e7752c21d1 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/AbstractRestApiUnitTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/AbstractRestApiUnitTest.java @@ -44,8 +44,8 @@ public abstract class AbstractRestApiUnitTest extends SingleClusterTest { - protected RestHelper rh = null; - protected boolean init = true; + protected RestHelper rh = null; + protected boolean init = true; @Override protected String getResourceFolder() { @@ -53,247 +53,259 @@ protected String getResourceFolder() { } @Override - protected final void setup() throws Exception { - Settings.Builder builder = Settings.builder(); + protected final void setup() throws Exception { + Settings.Builder builder = Settings.builder(); - builder.put("plugins.security.ssl.http.enabled", true) - .put(SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH, PasswordValidator.ScoreStrength.FAIR.name()) - .put("plugins.security.ssl.http.keystore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks")); + builder.put("plugins.security.ssl.http.enabled", true) + .put(SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH, PasswordValidator.ScoreStrength.FAIR.name()) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks")); - setup(Settings.EMPTY, new DynamicSecurityConfig(), builder.build(), init); - rh = restHelper(); - rh.keystore = "restapi/kirk-keystore.jks"; - } + setup(Settings.EMPTY, new DynamicSecurityConfig(), builder.build(), init); + rh = restHelper(); + rh.keystore = "restapi/kirk-keystore.jks"; + } @Override - protected final void setup(Settings nodeOverride) throws Exception { - Settings.Builder builder = Settings.builder(); + protected final void setup(Settings nodeOverride) throws Exception { + Settings.Builder builder = Settings.builder(); - builder.put("plugins.security.ssl.http.enabled", true) - .put("plugins.security.ssl.http.keystore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks")) - .put(nodeOverride); + builder.put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks")) + .put(nodeOverride); - System.out.println(builder.toString()); + System.out.println(builder.toString()); - setup(Settings.EMPTY, new DynamicSecurityConfig(), builder.build(), init); - rh = restHelper(); - rh.keystore = "restapi/kirk-keystore.jks"; - } + setup(Settings.EMPTY, new DynamicSecurityConfig(), builder.build(), init); + rh = restHelper(); + rh.keystore = "restapi/kirk-keystore.jks"; + } - protected final void setupWithRestRoles() throws Exception { + protected final void setupWithRestRoles() throws Exception { setupWithRestRoles(null); } - protected final void setupWithRestRoles(Settings nodeOverride) throws Exception { - Settings.Builder builder = Settings.builder(); - - builder.put("plugins.security.ssl.http.enabled", true) - .put(SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH, PasswordValidator.ScoreStrength.FAIR.name()) - .put("plugins.security.ssl.http.keystore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks")); - - builder.put(rolesSettings()); - - if (null != nodeOverride) { - builder.put(nodeOverride); - } - - setup(Settings.EMPTY, new DynamicSecurityConfig(), builder.build(), init); - rh = restHelper(); - rh.keystore = "restapi/kirk-keystore.jks"; - - AuditTestUtils.updateAuditConfig(rh, nodeOverride != null ? nodeOverride : Settings.EMPTY); - } - - protected Settings rolesSettings() { - return Settings.builder() - .put("plugins.security.restapi.roles_enabled.0", "opendistro_security_role_klingons") - .put("plugins.security.restapi.roles_enabled.1", "opendistro_security_role_vulcans") - .put("plugins.security.restapi.roles_enabled.2", "opendistro_security_test") - .put("plugins.security.restapi.endpoints_disabled.global.CACHE.0", "*") - .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_klingons.conFiGuration.0", "*") - .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_klingons.wRongType.0", "WRONGType") - .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_klingons.ROLESMAPPING.0", "PUT") - .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_klingons.ROLESMAPPING.1", "DELETE") - .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_vulcans.CONFIG.0", "*") - .build(); - } - - protected void deleteUser(String username) throws Exception { - boolean sendAdminCertificate = rh.sendAdminCertificate; - rh.sendAdminCertificate = true; - HttpResponse response = rh.executeDeleteRequest("/_opendistro/_security/api/internalusers/" + username, new Header[0]); - Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - rh.sendAdminCertificate = sendAdminCertificate; - } - - protected void addUserWithPassword(String username, String password, int status) throws Exception { - addUserWithPassword(username, password, status, null); - } - - protected void addUserWithPassword(String username, String password, int status, String message) throws Exception { - boolean sendAdminCertificate = rh.sendAdminCertificate; - rh.sendAdminCertificate = true; - HttpResponse response = rh.executePutRequest("/_opendistro/_security/api/internalusers/" + username, - "{\"password\": \"" + password + "\"}", new Header[0]); - Assert.assertEquals(status, response.getStatusCode()); - rh.sendAdminCertificate = sendAdminCertificate; - if (Objects.nonNull(message)) { - Assert.assertTrue(response.getBody().contains(message)); - } - } - - protected void addUserWithPassword(String username, String password, String[] roles, int status) throws Exception { - boolean sendAdminCertificate = rh.sendAdminCertificate; - rh.sendAdminCertificate = true; - String payload = "{" + "\"password\": \"" + password + "\"," + "\"backend_roles\": ["; - for (int i = 0; i < roles.length; i++) { - payload += "\"" + roles[i] + "\""; - if (i + 1 < roles.length) { - payload += ","; - } - } - payload += "]}"; - HttpResponse response = rh.executePutRequest("/_opendistro/_security/api/internalusers/" + username, payload, new Header[0]); - Assert.assertEquals(status, response.getStatusCode()); - rh.sendAdminCertificate = sendAdminCertificate; - } - - protected void addUserWithoutPasswordOrHash(String username, String[] roles, int status) throws Exception { - boolean sendAdminCertificate = rh.sendAdminCertificate; - rh.sendAdminCertificate = true; - String payload = "{ \"backend_roles\": ["; - for (int i = 0; i < roles.length; i++) { - payload += "\" " + roles[i] + " \""; - if (i + 1 < roles.length) { - payload += ","; - } - } - payload += "]}"; - HttpResponse response = rh.executePutRequest("/_opendistro/_security/api/internalusers/" + username, payload, new Header[0]); - Assert.assertEquals(status, response.getStatusCode()); - rh.sendAdminCertificate = sendAdminCertificate; - } - - protected void addUserWithHash(String username, String hash) throws Exception { - addUserWithHash(username, hash, HttpStatus.SC_OK); - } - - protected void addUserWithHash(String username, String hash, int status) throws Exception { - boolean sendAdminCertificate = rh.sendAdminCertificate; - rh.sendAdminCertificate = true; - HttpResponse response = rh.executePutRequest("/_opendistro/_security/api/internalusers/" + username, "{\"hash\": \"" + hash + "\"}", - new Header[0]); - Assert.assertEquals(status, response.getStatusCode()); - rh.sendAdminCertificate = sendAdminCertificate; - } - - protected void addUserWithPasswordAndHash(String username, String password, String hash, int status) throws Exception { - boolean sendAdminCertificate = rh.sendAdminCertificate; - rh.sendAdminCertificate = true; - HttpResponse response = rh.executePutRequest("/_opendistro/_security/api/internalusers/" + username, "{\"hash\": \"" + hash + "\", \"password\": \"" + password + "\"}", - new Header[0]); - Assert.assertEquals(status, response.getStatusCode()); - rh.sendAdminCertificate = sendAdminCertificate; - } - - protected void checkGeneralAccess(int status, String username, String password) throws Exception { - boolean sendAdminCertificate = rh.sendAdminCertificate; - rh.sendAdminCertificate = false; - Assert.assertEquals(status, - rh.executeGetRequest("", - encodeBasicHeader(username, password)) - .getStatusCode()); - rh.sendAdminCertificate = sendAdminCertificate; - } - - protected String checkReadAccess(int status, String username, String password, String indexName, String actionType, - int id) throws Exception { - rh.sendAdminCertificate = false; - String action = indexName + "/" + actionType + "/" + id; - HttpResponse response = rh.executeGetRequest(action, encodeBasicHeader(username, password)); - int returnedStatus = response.getStatusCode(); - Assert.assertEquals(status, returnedStatus); - return response.getBody(); - - } - - protected String checkWriteAccess(int status, String username, String password, String indexName, String actionType, - int id) throws Exception { - rh.sendAdminCertificate = false; - String action = indexName + "/" + actionType + "/" + id; - String payload = "{\"value\" : \"true\"}"; - HttpResponse response = rh.executePutRequest(action, payload, encodeBasicHeader(username, password)); - int returnedStatus = response.getStatusCode(); - Assert.assertEquals(response.getBody(), status, returnedStatus); - return response.getBody(); - } - - protected void setupStarfleetIndex() throws Exception { - boolean sendAdminCertificate = rh.sendAdminCertificate; - rh.sendAdminCertificate = true; - rh.executePutRequest("sf", null, new Header[0]); - rh.executePutRequest("sf/_doc/0", "{\"number\" : \"NCC-1701-D\"}", new Header[0]); - rh.executePutRequest("sf/_doc/0", "{\"some\" : \"value\"}", new Header[0]); - rh.sendAdminCertificate = sendAdminCertificate; - } - - protected void assertHealthy() throws Exception { - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_opendistro/_security/health?pretty").getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("admin", "admin")).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("admin", "admin")).getStatusCode()); - } - - protected Settings defaultNodeSettings(boolean enableRestSSL) { - Settings.Builder builder = Settings.builder(); - - if (enableRestSSL) { - builder.put("plugins.security.ssl.http.enabled", true) - .put("plugins.security.ssl.http.keystore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", - FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks")); - } - return builder.build(); - } - - protected Map jsonStringToMap(String json) throws JsonParseException, JsonMappingException, IOException { - TypeReference> typeRef = new TypeReference>() {}; - return DefaultObjectMapper.objectMapper.readValue(json, typeRef); - } - - protected static Collection> asCollection(Class... plugins) { - return Arrays.asList(plugins); - } - - String createRestAdminPermissionsPayload(String... additionPerms) throws JsonProcessingException { - final ObjectNode rootNode = (ObjectNode) DefaultObjectMapper.objectMapper.createObjectNode(); - rootNode.set("cluster_permissions", clusterPermissionsForRestAdmin(additionPerms)); - return DefaultObjectMapper.objectMapper.writeValueAsString(rootNode); - } - - ArrayNode clusterPermissionsForRestAdmin(String... additionPerms) { - final ArrayNode permissionsArray = (ArrayNode) DefaultObjectMapper.objectMapper.createArrayNode(); - for (final Map.Entry entry : RestApiAdminPrivilegesEvaluator.ENDPOINTS_WITH_PERMISSIONS.entrySet()) { - if (entry.getKey() == Endpoint.SSL) { - permissionsArray - .add(entry.getValue().build("certs")) - .add(entry.getValue().build("reloadcerts")); - } else { - permissionsArray.add(entry.getValue().build()); - } - } - if (additionPerms.length != 0) { - Stream.of(additionPerms).forEach(permissionsArray::add); - } - return permissionsArray; - } + protected final void setupWithRestRoles(Settings nodeOverride) throws Exception { + Settings.Builder builder = Settings.builder(); + + builder.put("plugins.security.ssl.http.enabled", true) + .put(SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH, PasswordValidator.ScoreStrength.FAIR.name()) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks")); + + builder.put(rolesSettings()); + + if (null != nodeOverride) { + builder.put(nodeOverride); + } + + setup(Settings.EMPTY, new DynamicSecurityConfig(), builder.build(), init); + rh = restHelper(); + rh.keystore = "restapi/kirk-keystore.jks"; + + AuditTestUtils.updateAuditConfig(rh, nodeOverride != null ? nodeOverride : Settings.EMPTY); + } + + protected Settings rolesSettings() { + return Settings.builder() + .put("plugins.security.restapi.roles_enabled.0", "opendistro_security_role_klingons") + .put("plugins.security.restapi.roles_enabled.1", "opendistro_security_role_vulcans") + .put("plugins.security.restapi.roles_enabled.2", "opendistro_security_test") + .put("plugins.security.restapi.endpoints_disabled.global.CACHE.0", "*") + .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_klingons.conFiGuration.0", "*") + .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_klingons.wRongType.0", "WRONGType") + .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_klingons.ROLESMAPPING.0", "PUT") + .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_klingons.ROLESMAPPING.1", "DELETE") + .put("plugins.security.restapi.endpoints_disabled.opendistro_security_role_vulcans.CONFIG.0", "*") + .build(); + } + + protected void deleteUser(String username) throws Exception { + boolean sendAdminCertificate = rh.sendAdminCertificate; + rh.sendAdminCertificate = true; + HttpResponse response = rh.executeDeleteRequest("/_opendistro/_security/api/internalusers/" + username, new Header[0]); + Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); + rh.sendAdminCertificate = sendAdminCertificate; + } + + protected void addUserWithPassword(String username, String password, int status) throws Exception { + addUserWithPassword(username, password, status, null); + } + + protected void addUserWithPassword(String username, String password, int status, String message) throws Exception { + boolean sendAdminCertificate = rh.sendAdminCertificate; + rh.sendAdminCertificate = true; + HttpResponse response = rh.executePutRequest( + "/_opendistro/_security/api/internalusers/" + username, + "{\"password\": \"" + password + "\"}", + new Header[0] + ); + Assert.assertEquals(status, response.getStatusCode()); + rh.sendAdminCertificate = sendAdminCertificate; + if (Objects.nonNull(message)) { + Assert.assertTrue(response.getBody().contains(message)); + } + } + + protected void addUserWithPassword(String username, String password, String[] roles, int status) throws Exception { + boolean sendAdminCertificate = rh.sendAdminCertificate; + rh.sendAdminCertificate = true; + String payload = "{" + "\"password\": \"" + password + "\"," + "\"backend_roles\": ["; + for (int i = 0; i < roles.length; i++) { + payload += "\"" + roles[i] + "\""; + if (i + 1 < roles.length) { + payload += ","; + } + } + payload += "]}"; + HttpResponse response = rh.executePutRequest("/_opendistro/_security/api/internalusers/" + username, payload, new Header[0]); + Assert.assertEquals(status, response.getStatusCode()); + rh.sendAdminCertificate = sendAdminCertificate; + } + + protected void addUserWithoutPasswordOrHash(String username, String[] roles, int status) throws Exception { + boolean sendAdminCertificate = rh.sendAdminCertificate; + rh.sendAdminCertificate = true; + String payload = "{ \"backend_roles\": ["; + for (int i = 0; i < roles.length; i++) { + payload += "\" " + roles[i] + " \""; + if (i + 1 < roles.length) { + payload += ","; + } + } + payload += "]}"; + HttpResponse response = rh.executePutRequest("/_opendistro/_security/api/internalusers/" + username, payload, new Header[0]); + Assert.assertEquals(status, response.getStatusCode()); + rh.sendAdminCertificate = sendAdminCertificate; + } + + protected void addUserWithHash(String username, String hash) throws Exception { + addUserWithHash(username, hash, HttpStatus.SC_OK); + } + + protected void addUserWithHash(String username, String hash, int status) throws Exception { + boolean sendAdminCertificate = rh.sendAdminCertificate; + rh.sendAdminCertificate = true; + HttpResponse response = rh.executePutRequest( + "/_opendistro/_security/api/internalusers/" + username, + "{\"hash\": \"" + hash + "\"}", + new Header[0] + ); + Assert.assertEquals(status, response.getStatusCode()); + rh.sendAdminCertificate = sendAdminCertificate; + } + + protected void addUserWithPasswordAndHash(String username, String password, String hash, int status) throws Exception { + boolean sendAdminCertificate = rh.sendAdminCertificate; + rh.sendAdminCertificate = true; + HttpResponse response = rh.executePutRequest( + "/_opendistro/_security/api/internalusers/" + username, + "{\"hash\": \"" + hash + "\", \"password\": \"" + password + "\"}", + new Header[0] + ); + Assert.assertEquals(status, response.getStatusCode()); + rh.sendAdminCertificate = sendAdminCertificate; + } + + protected void checkGeneralAccess(int status, String username, String password) throws Exception { + boolean sendAdminCertificate = rh.sendAdminCertificate; + rh.sendAdminCertificate = false; + Assert.assertEquals(status, rh.executeGetRequest("", encodeBasicHeader(username, password)).getStatusCode()); + rh.sendAdminCertificate = sendAdminCertificate; + } + + protected String checkReadAccess(int status, String username, String password, String indexName, String actionType, int id) + throws Exception { + rh.sendAdminCertificate = false; + String action = indexName + "/" + actionType + "/" + id; + HttpResponse response = rh.executeGetRequest(action, encodeBasicHeader(username, password)); + int returnedStatus = response.getStatusCode(); + Assert.assertEquals(status, returnedStatus); + return response.getBody(); + + } + + protected String checkWriteAccess(int status, String username, String password, String indexName, String actionType, int id) + throws Exception { + rh.sendAdminCertificate = false; + String action = indexName + "/" + actionType + "/" + id; + String payload = "{\"value\" : \"true\"}"; + HttpResponse response = rh.executePutRequest(action, payload, encodeBasicHeader(username, password)); + int returnedStatus = response.getStatusCode(); + Assert.assertEquals(response.getBody(), status, returnedStatus); + return response.getBody(); + } + + protected void setupStarfleetIndex() throws Exception { + boolean sendAdminCertificate = rh.sendAdminCertificate; + rh.sendAdminCertificate = true; + rh.executePutRequest("sf", null, new Header[0]); + rh.executePutRequest("sf/_doc/0", "{\"number\" : \"NCC-1701-D\"}", new Header[0]); + rh.executePutRequest("sf/_doc/0", "{\"some\" : \"value\"}", new Header[0]); + rh.sendAdminCertificate = sendAdminCertificate; + } + + protected void assertHealthy() throws Exception { + Assert.assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_opendistro/_security/health?pretty").getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_opendistro/_security/authinfo?pretty", encodeBasicHeader("admin", "admin")).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("admin", "admin")).getStatusCode() + ); + } + + protected Settings defaultNodeSettings(boolean enableRestSSL) { + Settings.Builder builder = Settings.builder(); + + if (enableRestSSL) { + builder.put("plugins.security.ssl.http.enabled", true) + .put( + "plugins.security.ssl.http.keystore_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("restapi/node-0-keystore.jks") + ) + .put( + "plugins.security.ssl.http.truststore_filepath", + FileHelper.getAbsoluteFilePathFromClassPath("restapi/truststore.jks") + ); + } + return builder.build(); + } + + protected Map jsonStringToMap(String json) throws JsonParseException, JsonMappingException, IOException { + TypeReference> typeRef = new TypeReference>() { + }; + return DefaultObjectMapper.objectMapper.readValue(json, typeRef); + } + + protected static Collection> asCollection(Class... plugins) { + return Arrays.asList(plugins); + } + + String createRestAdminPermissionsPayload(String... additionPerms) throws JsonProcessingException { + final ObjectNode rootNode = (ObjectNode) DefaultObjectMapper.objectMapper.createObjectNode(); + rootNode.set("cluster_permissions", clusterPermissionsForRestAdmin(additionPerms)); + return DefaultObjectMapper.objectMapper.writeValueAsString(rootNode); + } + + ArrayNode clusterPermissionsForRestAdmin(String... additionPerms) { + final ArrayNode permissionsArray = (ArrayNode) DefaultObjectMapper.objectMapper.createArrayNode(); + for (final Map.Entry< + Endpoint, + RestApiAdminPrivilegesEvaluator.PermissionBuilder> entry : RestApiAdminPrivilegesEvaluator.ENDPOINTS_WITH_PERMISSIONS + .entrySet()) { + if (entry.getKey() == Endpoint.SSL) { + permissionsArray.add(entry.getValue().build("certs")).add(entry.getValue().build("reloadcerts")); + } else { + permissionsArray.add(entry.getValue().build()); + } + } + if (additionPerms.length != 0) { + Stream.of(additionPerms).forEach(permissionsArray::add); + } + return permissionsArray; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/AccountApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/AccountApiTest.java index 9f6bcb65c9..c07b0f1333 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/AccountApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/AccountApiTest.java @@ -29,13 +29,14 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class AccountApiTest extends AbstractRestApiUnitTest { - private final String BASE_ENDPOINT; - private final String ENDPOINT; + private final String BASE_ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public AccountApiTest(){ + public AccountApiTest() { BASE_ENDPOINT = getEndpointPrefix() + "/api/"; ENDPOINT = getEndpointPrefix() + "/api/account"; } @@ -189,14 +190,16 @@ public void testPutAccountRetainsAccountInformation() throws Exception { final String testUsername = "test"; final String testPassword = "test-password"; final String newPassword = "new-password"; - final String createInternalUserPayload = "{\n" + - " \"password\": \"" + testPassword + "\",\n" + - " \"backend_roles\": [\"test-backend-role-1\"],\n" + - " \"opendistro_security_roles\": [\"opendistro_security_all_access\"],\n" + - " \"attributes\": {\n" + - " \"attribute1\": \"value1\"\n" + - " }\n" + - "}"; + final String createInternalUserPayload = "{\n" + + " \"password\": \"" + + testPassword + + "\",\n" + + " \"backend_roles\": [\"test-backend-role-1\"],\n" + + " \"opendistro_security_roles\": [\"opendistro_security_all_access\"],\n" + + " \"attributes\": {\n" + + " \"attribute1\": \"value1\"\n" + + " }\n" + + "}"; final String changePasswordPayload = "{\"password\":\"" + newPassword + "\", \"current_password\":\"" + testPassword + "\"}"; final String internalUserEndpoint = BASE_ENDPOINT + "internalusers/" + testUsername; @@ -215,9 +218,9 @@ public void testPutAccountRetainsAccountInformation() throws Exception { response = rh.executeGetRequest(internalUserEndpoint); assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Settings responseBody = Settings.builder() - .loadFromSource(response.getBody(), XContentType.JSON) - .build() - .getAsSettings(testUsername); + .loadFromSource(response.getBody(), XContentType.JSON) + .build() + .getAsSettings(testUsername); assertTrue(responseBody.getAsList("backend_roles").contains("test-backend-role-1")); assertTrue(responseBody.getAsList("opendistro_security_roles").contains("opendistro_security_all_access")); assertEquals(responseBody.getAsSettings("attributes").get("attribute1"), "value1"); diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/ActionGroupsApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/ActionGroupsApiTest.java index 926ee23f28..c87698155f 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/ActionGroupsApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/ActionGroupsApiTest.java @@ -32,12 +32,13 @@ import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_ADMIN_ENABLED; public class ActionGroupsApiTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public ActionGroupsApiTest(){ + public ActionGroupsApiTest() { ENDPOINT = getEndpointPrefix() + "/api/actiongroups"; } @@ -69,7 +70,7 @@ public void testActionGroupsApi() throws Exception { void verifyGetForSuperAdmin(final Header[] header) throws Exception { // --- GET_UT // GET_UT, actiongroup exists - HttpResponse response = rh.executeGetRequest(ENDPOINT+"/CRUD_UT", header); + HttpResponse response = rh.executeGetRequest(ENDPOINT + "/CRUD_UT", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); List permissions = settings.getAsList("CRUD_UT.allowed_actions"); @@ -79,7 +80,7 @@ void verifyGetForSuperAdmin(final Header[] header) throws Exception { Assert.assertTrue(permissions.contains("OPENDISTRO_SECURITY_WRITE")); // GET_UT, actiongroup does not exist - response = rh.executeGetRequest(ENDPOINT+"/nothinghthere", header); + response = rh.executeGetRequest(ENDPOINT + "/nothinghthere", header); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // GET_UT, old endpoint @@ -112,13 +113,13 @@ void verifyDeleteForSuperAdmin(final Header[] header, final boolean userAdminCer // Non-existing role rh.sendAdminCertificate = userAdminCert; - HttpResponse response = rh.executeDeleteRequest(ENDPOINT+"/idonotexist", header); + HttpResponse response = rh.executeDeleteRequest(ENDPOINT + "/idonotexist", header); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // remove action group READ_UT, read access not possible since // opendistro_security_role_starfleet // uses this action group. - response = rh.executeDeleteRequest(ENDPOINT+"/READ_UT", header); + response = rh.executeDeleteRequest(ENDPOINT + "/READ_UT", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); rh.sendAdminCertificate = false; @@ -133,7 +134,7 @@ void verifyDeleteForSuperAdmin(final Header[] header, final boolean userAdminCer // now remove also CRUD_UT groups, write also not possible anymore rh.sendAdminCertificate = true; - response = rh.executeDeleteRequest(ENDPOINT+"/CRUD_UT", new Header[0]); + response = rh.executeDeleteRequest(ENDPOINT + "/CRUD_UT", new Header[0]); rh.sendAdminCertificate = false; checkWriteAccess(HttpStatus.SC_FORBIDDEN, "picard", "picardpicardpicard", "sf", "_doc", 0); checkReadAccess(HttpStatus.SC_FORBIDDEN, "picard", "picardpicardpicard", "sf", "_doc", 0); @@ -143,19 +144,18 @@ void verifyPutForSuperAdmin(final Header[] header, final boolean userAdminCert) // -- PUT // put with empty payload, must fail rh.sendAdminCertificate = userAdminCert; - HttpResponse response = rh.executePutRequest(ENDPOINT+"/SOMEGROUP", "", header); + HttpResponse response = rh.executePutRequest(ENDPOINT + "/SOMEGROUP", "", header); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.PAYLOAD_MANDATORY.getMessage(), settings.get("reason")); // put new configuration with invalid payload, must fail - response = rh.executePutRequest(ENDPOINT+"/SOMEGROUP", FileHelper.loadFile("restapi/actiongroup_not_parseable.json"), - header); + response = rh.executePutRequest(ENDPOINT + "/SOMEGROUP", FileHelper.loadFile("restapi/actiongroup_not_parseable.json"), header); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.BODY_NOT_PARSEABLE.getMessage(), settings.get("reason")); - response = rh.executePutRequest(ENDPOINT+"/CRUD_UT", FileHelper.loadFile("restapi/actiongroup_crud.json"), header); + response = rh.executePutRequest(ENDPOINT + "/CRUD_UT", FileHelper.loadFile("restapi/actiongroup_crud.json"), header); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); rh.sendAdminCertificate = false; @@ -166,7 +166,7 @@ void verifyPutForSuperAdmin(final Header[] header, final boolean userAdminCert) // restore READ_UT action groups rh.sendAdminCertificate = userAdminCert; - response = rh.executePutRequest(ENDPOINT+"/READ_UT", FileHelper.loadFile("restapi/actiongroup_read.json"), header); + response = rh.executePutRequest(ENDPOINT + "/READ_UT", FileHelper.loadFile("restapi/actiongroup_read.json"), header); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); rh.sendAdminCertificate = false; @@ -176,49 +176,51 @@ void verifyPutForSuperAdmin(final Header[] header, final boolean userAdminCert) // -- PUT, new JSON format including readonly flag, disallowed in REST API rh.sendAdminCertificate = userAdminCert; - response = rh.executePutRequest(ENDPOINT+"/CRUD_UT", FileHelper.loadFile("restapi/actiongroup_readonly.json"), header); + response = rh.executePutRequest(ENDPOINT + "/CRUD_UT", FileHelper.loadFile("restapi/actiongroup_readonly.json"), header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // -- DELETE read only resource, must be forbidden // superAdmin can delete read only resource rh.sendAdminCertificate = userAdminCert; - response = rh.executeDeleteRequest(ENDPOINT+"/GET_UT", header); + response = rh.executeDeleteRequest(ENDPOINT + "/GET_UT", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // -- PUT read only resource, must be forbidden // superAdmin can add/update read only resource rh.sendAdminCertificate = userAdminCert; - response = rh.executePutRequest(ENDPOINT+"/GET_UT", FileHelper.loadFile("restapi/actiongroup_read.json"), header); + response = rh.executePutRequest(ENDPOINT + "/GET_UT", FileHelper.loadFile("restapi/actiongroup_read.json"), header); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); Assert.assertFalse(response.getBody().contains("Resource 'GET_UT' is read-only.")); // PUT with role name rh.sendAdminCertificate = userAdminCert; - response = rh.executePutRequest(ENDPOINT+"/kibana_user", FileHelper.loadFile("restapi/actiongroup_read.json"), header); + response = rh.executePutRequest(ENDPOINT + "/kibana_user", FileHelper.loadFile("restapi/actiongroup_read.json"), header); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - Assert.assertTrue(response.getBody().contains("kibana_user is an existing role. A action group cannot be named with an existing role name.")); + Assert.assertTrue( + response.getBody().contains("kibana_user is an existing role. A action group cannot be named with an existing role name.") + ); // PUT with self-referencing action groups rh.sendAdminCertificate = userAdminCert; - response = rh.executePutRequest(ENDPOINT+"/reference_itself", "{\"allowed_actions\": [\"reference_itself\"]}", header); + response = rh.executePutRequest(ENDPOINT + "/reference_itself", "{\"allowed_actions\": [\"reference_itself\"]}", header); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("reference_itself cannot be an allowed_action of itself")); // -- GET_UT hidden resource, must be 404 but super admin can find it rh.sendAdminCertificate = userAdminCert; - response = rh.executeGetRequest(ENDPOINT+"/INTERNAL", header); + response = rh.executeGetRequest(ENDPOINT + "/INTERNAL", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("\"hidden\":true")); // -- DELETE hidden resource, must be 404 rh.sendAdminCertificate = userAdminCert; - response = rh.executeDeleteRequest(ENDPOINT+"/INTERNAL", header); + response = rh.executeDeleteRequest(ENDPOINT + "/INTERNAL", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("'INTERNAL' deleted.")); // -- PUT hidden resource, must be forbidden rh.sendAdminCertificate = userAdminCert; - response = rh.executePutRequest(ENDPOINT+"/INTERNAL", FileHelper.loadFile("restapi/actiongroup_read.json"), header); + response = rh.executePutRequest(ENDPOINT + "/INTERNAL", FileHelper.loadFile("restapi/actiongroup_read.json"), header); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); } @@ -226,52 +228,79 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean userAdminCert // -- PATCH // PATCH on non-existing resource rh.sendAdminCertificate = userAdminCert; - HttpResponse response = rh.executePatchRequest(ENDPOINT+"/imnothere", - "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", header); + HttpResponse response = rh.executePatchRequest( + ENDPOINT + "/imnothere", + "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // PATCH read only resource, must be forbidden // SuperAdmin can patch read only resource rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT+"/GET_UT", "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/GET_UT", + "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // PATCH with self-referencing action groups rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT+"/GET_UT", "[{ \"op\": \"add\", \"path\": \"/allowed_actions/-\", \"value\": \"GET_UT\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/GET_UT", + "[{ \"op\": \"add\", \"path\": \"/allowed_actions/-\", \"value\": \"GET_UT\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("GET_UT cannot be an allowed_action of itself")); // bulk PATCH with self-referencing action groups - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"add\", \"path\": \"/BULKNEW1\", \"value\": {\"allowed_actions\": [\"BULKNEW1\"] } }," + - "{ \"op\": \"add\", \"path\": \"/BULKNEW2\", \"value\": {\"allowed_actions\": [\"READ_UT\"] } }]", header); + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"add\", \"path\": \"/BULKNEW1\", \"value\": {\"allowed_actions\": [\"BULKNEW1\"] } }," + + "{ \"op\": \"add\", \"path\": \"/BULKNEW2\", \"value\": {\"allowed_actions\": [\"READ_UT\"] } }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("BULKNEW1 cannot be an allowed_action of itself")); // PATCH hidden resource, must be not found, can be found by superadmin, but fails with no path exist error rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT+"/INTERNAL", - "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/INTERNAL", + "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH value of hidden flag, must fail with validation error rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT+"/CRUD_UT", "[{ \"op\": \"add\", \"path\": \"/hidden\", \"value\": true }]", header); + response = rh.executePatchRequest(ENDPOINT + "/CRUD_UT", "[{ \"op\": \"add\", \"path\": \"/hidden\", \"value\": true }]", header); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - Assert.assertTrue(response.getBody(), response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*")); + Assert.assertTrue( + response.getBody(), + response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*") + ); // PATCH with relative JSON pointer, must fail rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT+"/CRUD_UT", "[{ \"op\": \"add\", \"path\": \"1/INTERNAL/allowed_actions/-\", " + - "\"value\": \"OPENDISTRO_SECURITY_DELETE\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/CRUD_UT", + "[{ \"op\": \"add\", \"path\": \"1/INTERNAL/allowed_actions/-\", " + "\"value\": \"OPENDISTRO_SECURITY_DELETE\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH new format rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT+"/CRUD_UT", "[{ \"op\": \"add\", \"path\": \"/allowed_actions/-\", " + - "\"value\": \"OPENDISTRO_SECURITY_DELETE\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/CRUD_UT", + "[{ \"op\": \"add\", \"path\": \"/allowed_actions/-\", " + "\"value\": \"OPENDISTRO_SECURITY_DELETE\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executeGetRequest(ENDPOINT+"/CRUD_UT", header); + response = rh.executeGetRequest(ENDPOINT + "/CRUD_UT", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); List permissions = settings.getAsList("CRUD_UT.allowed_actions"); @@ -281,12 +310,15 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean userAdminCert Assert.assertTrue(permissions.contains("OPENDISTRO_SECURITY_WRITE")); Assert.assertTrue(permissions.contains("OPENDISTRO_SECURITY_DELETE")); - // -- PATCH on whole config resource // PATCH read only resource, must be forbidden // SuperAdmin can patch read only resource rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"add\", \"path\": \"/GET_UT/a\", \"value\": [ \"foo\", \"bar\" ] }]", header); + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"add\", \"path\": \"/GET_UT/a\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); rh.sendAdminCertificate = userAdminCert; @@ -295,7 +327,11 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean userAdminCert // PATCH hidden resource, must be bad request rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"add\", \"path\": \"/INTERNAL/a\", \"value\": [ \"foo\", \"bar\" ] }]", header); + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"add\", \"path\": \"/INTERNAL/a\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH delete read only resource, must be forbidden @@ -310,7 +346,6 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean userAdminCert Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("\"message\":\"Resource updated.")); - // PATCH value of hidden flag, must fail with validation error rh.sendAdminCertificate = userAdminCert; response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"add\", \"path\": \"/CRUD_UT/hidden\", \"value\": true }]", header); @@ -319,16 +354,24 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean userAdminCert // add new resource with hidden flag, must fail with validation error rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT, - "[{ \"op\": \"add\", \"path\": \"/NEWNEWNEW\", \"value\": {\"allowed_actions\": [\"indices:data/write*\"], \"hidden\":true }}]", header); + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"add\", \"path\": \"/NEWNEWNEW\", \"value\": {\"allowed_actions\": [\"indices:data/write*\"], \"hidden\":true }}]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*")); // add new valid resources rh.sendAdminCertificate = userAdminCert; - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"add\", \"path\": \"/BULKNEW1\", \"value\": {\"allowed_actions\": [\"indices:data/*\", \"cluster:monitor/*\"] } }," + "{ \"op\": \"add\", \"path\": \"/BULKNEW2\", \"value\": {\"allowed_actions\": [\"READ_UT\"] } }]", header); + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"add\", \"path\": \"/BULKNEW1\", \"value\": {\"allowed_actions\": [\"indices:data/*\", \"cluster:monitor/*\"] } }," + + "{ \"op\": \"add\", \"path\": \"/BULKNEW2\", \"value\": {\"allowed_actions\": [\"READ_UT\"] } }]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executeGetRequest(ENDPOINT+"/BULKNEW1", header); + response = rh.executeGetRequest(ENDPOINT + "/BULKNEW1", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); permissions = settings.getAsList("BULKNEW1.allowed_actions"); @@ -337,7 +380,7 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean userAdminCert Assert.assertTrue(permissions.contains("indices:data/*")); Assert.assertTrue(permissions.contains("cluster:monitor/*")); - response = rh.executeGetRequest(ENDPOINT+"/BULKNEW2", header); + response = rh.executeGetRequest(ENDPOINT + "/BULKNEW2", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); permissions = settings.getAsList("BULKNEW2.allowed_actions"); @@ -348,11 +391,11 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean userAdminCert // delete resource response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"remove\", \"path\": \"/BULKNEW1\" }]", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executeGetRequest(ENDPOINT+"/BULKNEW1", header); + response = rh.executeGetRequest(ENDPOINT + "/BULKNEW1", header); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // assert other resource is still there - response = rh.executeGetRequest(ENDPOINT+"/BULKNEW2", header); + response = rh.executeGetRequest(ENDPOINT + "/BULKNEW2", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); permissions = settings.getAsList("BULKNEW2.allowed_actions"); @@ -373,10 +416,10 @@ public void testActionGroupsApiForRestAdmin() throws Exception { addUserWithPassword("picard", "picardpicardpicard", new String[] { "starfleet" }, HttpStatus.SC_CREATED); checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicard", "sf", "_doc", 0); checkWriteAccess(HttpStatus.SC_FORBIDDEN, "picard", "picardpicardpicard", "sf", "_doc", 0); - verifyGetForSuperAdmin(new Header[] {restApiAdminHeader}); - verifyDeleteForSuperAdmin(new Header[]{restApiAdminHeader}, false); - verifyPutForSuperAdmin(new Header[]{restApiAdminHeader}, false); - verifyPatchForSuperAdmin(new Header[]{restApiAdminHeader}, false); + verifyGetForSuperAdmin(new Header[] { restApiAdminHeader }); + verifyDeleteForSuperAdmin(new Header[] { restApiAdminHeader }, false); + verifyPutForSuperAdmin(new Header[] { restApiAdminHeader }, false); + verifyPatchForSuperAdmin(new Header[] { restApiAdminHeader }, false); } @Test @@ -391,10 +434,10 @@ public void testActionGroupsApiForActionGroupsRestApiAdmin() throws Exception { addUserWithPassword("picard", "picardpicardpicard", new String[] { "starfleet" }, HttpStatus.SC_CREATED); checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicard", "sf", "_doc", 0); checkWriteAccess(HttpStatus.SC_FORBIDDEN, "picard", "picardpicardpicard", "sf", "_doc", 0); - verifyGetForSuperAdmin(new Header[] {restApiAdminActionGroupsHeader}); - verifyDeleteForSuperAdmin(new Header[]{restApiAdminActionGroupsHeader}, false); - verifyPutForSuperAdmin(new Header[]{restApiAdminActionGroupsHeader}, false); - verifyPatchForSuperAdmin(new Header[]{restApiAdminActionGroupsHeader}, false); + verifyGetForSuperAdmin(new Header[] { restApiAdminActionGroupsHeader }); + verifyDeleteForSuperAdmin(new Header[] { restApiAdminActionGroupsHeader }, false); + verifyPutForSuperAdmin(new Header[] { restApiAdminActionGroupsHeader }, false); + verifyPatchForSuperAdmin(new Header[] { restApiAdminActionGroupsHeader }, false); } @Test @@ -405,8 +448,7 @@ public void testCreateActionGroupWithRestAdminPermissionsForbidden() throws Exce final Header restApiAdminActionGroupsHeader = encodeBasicHeader("rest_api_admin_actiongroups", "rest_api_admin_actiongroups"); final Header restApiHeader = encodeBasicHeader("test", "test"); - HttpResponse response = rh.executePutRequest(ENDPOINT + "/rest_api_admin_group", restAdminAllowedActions(), - restApiAdminHeader); + HttpResponse response = rh.executePutRequest(ENDPOINT + "/rest_api_admin_group", restAdminAllowedActions(), restApiAdminHeader); Assert.assertEquals(response.getBody(), HttpStatus.SC_FORBIDDEN, response.getStatusCode()); response = rh.executePutRequest(ENDPOINT + "/rest_api_admin_group", restAdminAllowedActions(), restApiAdminActionGroupsHeader); Assert.assertEquals(response.getBody(), HttpStatus.SC_FORBIDDEN, response.getStatusCode()); @@ -432,10 +474,7 @@ String restAdminPatchBody() throws JsonProcessingException { final ObjectNode opAddRootNode = DefaultObjectMapper.objectMapper.createObjectNode(); final ObjectNode allowedActionsNode = DefaultObjectMapper.objectMapper.createObjectNode(); allowedActionsNode.set("allowed_actions", clusterPermissionsForRestAdmin("cluster/*")); - opAddRootNode - .put("op", "add") - .put("path", "/rest_api_admin_group") - .set("value", allowedActionsNode); + opAddRootNode.put("op", "add").put("path", "/rest_api_admin_group").set("value", allowedActionsNode); rootNode.add(opAddRootNode); return DefaultObjectMapper.objectMapper.writeValueAsString(rootNode); } @@ -452,44 +491,60 @@ public void testActionGroupsApiForNonSuperAdmin() throws Exception { HttpResponse response; // Delete read only actiongroups - response = rh.executeDeleteRequest(ENDPOINT+"/create_index" , new Header[0]); + response = rh.executeDeleteRequest(ENDPOINT + "/create_index", new Header[0]); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Put read only actiongroups - response = rh.executePutRequest(ENDPOINT+"/create_index", FileHelper.loadFile("restapi/actiongroup_crud.json"), new Header[0]); + response = rh.executePutRequest(ENDPOINT + "/create_index", FileHelper.loadFile("restapi/actiongroup_crud.json"), new Header[0]); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch single read only actiongroups - response = rh.executePatchRequest(ENDPOINT+"/create_index", "[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/create_index", + "[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch multiple read only actiongroups - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"replace\", \"path\": \"/create_index/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"replace\", \"path\": \"/create_index/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - response = rh.executeGetRequest(ENDPOINT+"/INTERNAL" , new Header[0]); + response = rh.executeGetRequest(ENDPOINT + "/INTERNAL", new Header[0]); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Delete hidden actiongroups - response = rh.executeDeleteRequest(ENDPOINT+"/INTERNAL" , new Header[0]); + response = rh.executeDeleteRequest(ENDPOINT + "/INTERNAL", new Header[0]); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Put hidden actiongroups - response = rh.executePutRequest(ENDPOINT+"/INTERNAL", FileHelper.loadFile("restapi/actiongroup_crud.json"), new Header[0]); + response = rh.executePutRequest(ENDPOINT + "/INTERNAL", FileHelper.loadFile("restapi/actiongroup_crud.json"), new Header[0]); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Patch hidden actiongroups - response = rh.executePatchRequest(ENDPOINT+"/INTERNAL", "[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/INTERNAL", + "[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Patch multiple hidden actiongroups - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"replace\", \"path\": \"/INTERNAL/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"replace\", \"path\": \"/INTERNAL/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); } @Test - public void checkNullElementsInArray() throws Exception{ + public void checkNullElementsInArray() throws Exception { setup(); rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/AllowlistApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/AllowlistApiTest.java index 50090fcfcc..79ce591723 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/AllowlistApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/AllowlistApiTest.java @@ -11,7 +11,6 @@ package org.opensearch.security.dlic.rest.api; - import java.util.Map; import java.util.stream.Collectors; @@ -60,24 +59,32 @@ public class AllowlistApiTest extends AbstractRestApiUnitTest { * * @throws Exception */ - private void checkGetAndPutAllowlistPermissions(final int expectedStatus, final boolean sendAdminCertificate, final Header... headers) throws Exception { + private void checkGetAndPutAllowlistPermissions(final int expectedStatus, final boolean sendAdminCertificate, final Header... headers) + throws Exception { final boolean prevSendAdminCertificate = rh.sendAdminCertificate; rh.sendAdminCertificate = sendAdminCertificate; - //CHECK GET REQUEST + // CHECK GET REQUEST response = rh.executeGetRequest(ENDPOINT, headers); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); if (expectedStatus == HttpStatus.SC_OK) { - //Note: the response has no whitespaces, so the .json file does not have whitespaces - Assert.assertEquals(FileHelper.loadFile("restapi/whitelist_response_success.json"), FileHelper.loadFile("restapi/whitelist_response_success.json")); + // Note: the response has no whitespaces, so the .json file does not have whitespaces + Assert.assertEquals( + FileHelper.loadFile("restapi/whitelist_response_success.json"), + FileHelper.loadFile("restapi/whitelist_response_success.json") + ); } - //FORBIDDEN FOR NON SUPER ADMIN + // FORBIDDEN FOR NON SUPER ADMIN if (expectedStatus == HttpStatus.SC_FORBIDDEN) { assertTrue(response.getBody().contains("API allowed only for super admin.")); } - //CHECK PUT REQUEST - response = rh.executePutRequest(ENDPOINT, "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", headers); + // CHECK PUT REQUEST + response = rh.executePutRequest( + ENDPOINT, + "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", + headers + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); rh.sendAdminCertificate = prevSendAdminCertificate; @@ -100,7 +107,10 @@ public void testPutUnknownKey() throws Exception { setup(); rh.sendAdminCertificate = true; - RestHelper.HttpResponse response = rh.executePutRequest(ENDPOINT, "{ \"unknownkey\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}"); + RestHelper.HttpResponse response = rh.executePutRequest( + ENDPOINT, + "{ \"unknownkey\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}" + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); assertTrue(response.getBody().contains("invalid_keys")); assertHealthy(); @@ -111,7 +121,10 @@ public void testPutInvalidJson() throws Exception { setup(); rh.sendAdminCertificate = true; - RestHelper.HttpResponse response = rh.executePutRequest(ENDPOINT, "{ \"invalid\"::{{ [\"*\"], \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}"); + RestHelper.HttpResponse response = rh.executePutRequest( + ENDPOINT, + "{ \"invalid\"::{{ [\"*\"], \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}" + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); assertHealthy(); } @@ -147,7 +160,7 @@ public void testAllowlistApi() throws Exception { // No creds, no admin certificate - UNAUTHORIZED checkGetAndPutAllowlistPermissions(HttpStatus.SC_UNAUTHORIZED, false); - //non admin creds, no admin certificate - FORBIDDEN + // non admin creds, no admin certificate - FORBIDDEN checkGetAndPutAllowlistPermissions(HttpStatus.SC_FORBIDDEN, false, nonAdminCredsHeader); // admin creds, no admin certificate - FORBIDDEN @@ -183,37 +196,45 @@ public void testAllowlistApiWithAllowListPermissions() throws Exception { @Test public void testAllowlistAuditComplianceLogging() throws Exception { Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setupWithRestRoles(settings); TestAuditlogImpl.clear(); // any creds, admin certificate - OK checkGetAndPutAllowlistPermissions(HttpStatus.SC_OK, true, nonAdminCredsHeader); - //TESTS THAT 1 READ AND 1 WRITE HAPPENS IN testGetAndPut() + // TESTS THAT 1 READ AND 1 WRITE HAPPENS IN testGetAndPut() final Map expectedCategoryCounts = ImmutableMap.of( - AuditCategory.COMPLIANCE_INTERNAL_CONFIG_READ, 1L, - AuditCategory.COMPLIANCE_INTERNAL_CONFIG_WRITE, 1L); - Map actualCategoryCounts = TestAuditlogImpl.messages.stream().collect(Collectors.groupingBy(AuditMessage::getCategory, Collectors.counting())); + AuditCategory.COMPLIANCE_INTERNAL_CONFIG_READ, + 1L, + AuditCategory.COMPLIANCE_INTERNAL_CONFIG_WRITE, + 1L + ); + Map actualCategoryCounts = TestAuditlogImpl.messages.stream() + .collect(Collectors.groupingBy(AuditMessage::getCategory, Collectors.counting())); assertThat(actualCategoryCounts, equalTo(expectedCategoryCounts)); } @Test - public void testAllowlistInvalidHttpRequestMethod() throws Exception{ + public void testAllowlistInvalidHttpRequestMethod() throws Exception { setup(); rh.sendAdminCertificate = true; - response = rh.executePutRequest(ENDPOINT, "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GE\"],\"/_cat/indices\": [\"PUT\"] }}", adminCredsHeader); + response = rh.executePutRequest( + ENDPOINT, + "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GE\"],\"/_cat/indices\": [\"PUT\"] }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_INTERNAL_SERVER_ERROR)); assertTrue(response.getBody().contains("\\\"GE\\\": not one of the values accepted for Enum class")); } @@ -226,37 +247,53 @@ public void testAllowlistInvalidHttpRequestMethod() throws Exception{ * @throws Exception */ @Test - public void testPatchApi() throws Exception{ + public void testPatchApi() throws Exception { setup(); rh.sendAdminCertificate = true; - //PATCH entire config entry - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"replace\", \"path\": \"/config\", \"value\": {\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"PUT\"] }}}]", new Header[0]); + // PATCH entire config entry + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"replace\", \"path\": \"/config\", \"value\": {\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"PUT\"] }}}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); - assertEquals(response.getBody(),"{\"config\":{\"enabled\":true,\"requests\":{\"/_cat/nodes\":[\"GET\"],\"/_cat/indices\":[\"PUT\"]}}}"); - - //PATCH just requests - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"replace\", \"path\": \"/config/requests\", \"value\": {\"/_cat/nodes\": [\"GET\"]}}]", new Header[0]); + assertEquals( + response.getBody(), + "{\"config\":{\"enabled\":true,\"requests\":{\"/_cat/nodes\":[\"GET\"],\"/_cat/indices\":[\"PUT\"]}}}" + ); + + // PATCH just requests + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"replace\", \"path\": \"/config/requests\", \"value\": {\"/_cat/nodes\": [\"GET\"]}}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); assertTrue(response.getBody().contains("\"requests\":{\"/_cat/nodes\":[\"GET\"]}")); - //PATCH just allowlisted_enabled using "replace" operation - works when enabled is already true - response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"replace\", \"path\": \"/config/enabled\", \"value\": false}]", new Header[0]); + // PATCH just allowlisted_enabled using "replace" operation - works when enabled is already true + response = rh.executePatchRequest( + ENDPOINT, + "[{ \"op\": \"replace\", \"path\": \"/config/enabled\", \"value\": false}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); assertTrue(response.getBody().contains("\"enabled\":false")); - //PATCH just enabled using "add" operation when it is currently false - works correctly + // PATCH just enabled using "add" operation when it is currently false - works correctly response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"add\", \"path\": \"/config/enabled\", \"value\": true}]", new Header[0]); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); assertTrue(response.getBody().contains("\"enabled\":true")); - //PATCH just enabled using "add" operation when it is currently true - works correctly + // PATCH just enabled using "add" operation when it is currently true - works correctly response = rh.executePatchRequest(ENDPOINT, "[{ \"op\": \"add\", \"path\": \"/config/enabled\", \"value\": false}]", new Header[0]); - Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); + Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); + response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); assertTrue(response.getBody().contains("\"enabled\":false")); } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/AuditApiActionTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/AuditApiActionTest.java index 450a5de83b..3f97bae693 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/AuditApiActionTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/AuditApiActionTest.java @@ -51,13 +51,14 @@ public class AuditApiActionTest extends AbstractRestApiUnitTest { // non-admin final Header nonAdminCredsHeader = encodeBasicHeader("random", "random"); - private final String ENDPOINT; + private final String ENDPOINT; private final String CONFIG_ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public AuditApiActionTest(){ + public AuditApiActionTest() { ENDPOINT = getEndpointPrefix() + "/api/audit"; CONFIG_ENDPOINT = ENDPOINT + "/config"; } @@ -106,16 +107,18 @@ public void testDisabledCategoryOrder() throws Exception { setup(); final List testCategories = ImmutableList.of("SSL_EXCEPTION", "AUTHENTICATED", "BAD_HEADERS"); - final AuditConfig auditConfig = new AuditConfig(true, AuditConfig.Filter.from( - ImmutableMap.of("disabled_rest_categories", testCategories) - ), ComplianceConfig.DEFAULT); + final AuditConfig auditConfig = new AuditConfig( + true, + AuditConfig.Filter.from(ImmutableMap.of("disabled_rest_categories", testCategories)), + ComplianceConfig.DEFAULT + ); final ObjectNode json = DefaultObjectMapper.objectMapper.valueToTree(auditConfig); testPutRequest(json, HttpStatus.SC_OK, true); RestHelper.HttpResponse response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); List actual = Streams.stream(readTree(response.getBody()).at("/config/audit/disabled_rest_categories").iterator()) - .map(JsonNode::textValue) - .collect(Collectors.toList()); + .map(JsonNode::textValue) + .collect(Collectors.toList()); assertEquals(testCategories, actual); } @@ -125,36 +128,69 @@ public void testInvalidDisabledCategories() throws Exception { rh.sendAdminCertificate = true; // test bad request for REST disabled categories - AuditConfig auditConfig = new AuditConfig(true, AuditConfig.Filter.from( - ImmutableMap.of("disabled_rest_categories", ImmutableList.of("INDEX_EVENT", "COMPLIANCE_DOC_READ")) - ), ComplianceConfig.DEFAULT); + AuditConfig auditConfig = new AuditConfig( + true, + AuditConfig.Filter.from(ImmutableMap.of("disabled_rest_categories", ImmutableList.of("INDEX_EVENT", "COMPLIANCE_DOC_READ"))), + ComplianceConfig.DEFAULT + ); ObjectNode json = DefaultObjectMapper.objectMapper.valueToTree(auditConfig); RestHelper.HttpResponse response = rh.executePutRequest(CONFIG_ENDPOINT, writeValueAsString(json, false)); assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // test success for REST disabled categories - auditConfig = new AuditConfig(true, AuditConfig.Filter.from( - ImmutableMap.of("disabled_rest_categories", - ImmutableList.of("BAD_HEADERS", "SSL_EXCEPTION", "AUTHENTICATED", "FAILED_LOGIN", "GRANTED_PRIVILEGES", "MISSING_PRIVILEGES")) - ), ComplianceConfig.DEFAULT); + auditConfig = new AuditConfig( + true, + AuditConfig.Filter.from( + ImmutableMap.of( + "disabled_rest_categories", + ImmutableList.of( + "BAD_HEADERS", + "SSL_EXCEPTION", + "AUTHENTICATED", + "FAILED_LOGIN", + "GRANTED_PRIVILEGES", + "MISSING_PRIVILEGES" + ) + ) + ), + ComplianceConfig.DEFAULT + ); json = DefaultObjectMapper.objectMapper.valueToTree(auditConfig); response = rh.executePutRequest(CONFIG_ENDPOINT, writeValueAsString(json, false)); assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // test bad request for transport disabled categories - auditConfig = new AuditConfig(true, AuditConfig.Filter.from( - ImmutableMap.of("disabled_transport_categories", - ImmutableList.of("COMPLIANCE_DOC_READ", "COMPLIANCE_DOC_WRITE")) - ), ComplianceConfig.DEFAULT); + auditConfig = new AuditConfig( + true, + AuditConfig.Filter.from( + ImmutableMap.of("disabled_transport_categories", ImmutableList.of("COMPLIANCE_DOC_READ", "COMPLIANCE_DOC_WRITE")) + ), + ComplianceConfig.DEFAULT + ); json = DefaultObjectMapper.objectMapper.valueToTree(auditConfig); response = rh.executePutRequest(CONFIG_ENDPOINT, writeValueAsString(json, false)); assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // test success for transport disabled categories - auditConfig = new AuditConfig(true, AuditConfig.Filter.from( - ImmutableMap.of("disabled_transport_categories", - ImmutableList.of("BAD_HEADERS", "SSL_EXCEPTION", "AUTHENTICATED", "FAILED_LOGIN", "GRANTED_PRIVILEGES", "MISSING_PRIVILEGES", "INDEX_EVENT", "OPENDISTRO_SECURITY_INDEX_ATTEMPT")) - ), ComplianceConfig.DEFAULT); + auditConfig = new AuditConfig( + true, + AuditConfig.Filter.from( + ImmutableMap.of( + "disabled_transport_categories", + ImmutableList.of( + "BAD_HEADERS", + "SSL_EXCEPTION", + "AUTHENTICATED", + "FAILED_LOGIN", + "GRANTED_PRIVILEGES", + "MISSING_PRIVILEGES", + "INDEX_EVENT", + "OPENDISTRO_SECURITY_INDEX_ATTEMPT" + ) + ) + ), + ComplianceConfig.DEFAULT + ); json = DefaultObjectMapper.objectMapper.valueToTree(auditConfig); response = rh.executePutRequest(CONFIG_ENDPOINT, writeValueAsString(json, false)); assertEquals(HttpStatus.SC_OK, response.getStatusCode()); @@ -162,7 +198,12 @@ public void testInvalidDisabledCategories() throws Exception { @Test public void testReadonlyApi() throws Exception { - final List readonlyFields = ImmutableList.of("/audit/enable_rest", "/audit/disabled_rest_categories", "/audit/ignore_requests", "/compliance/read_watched_fields"); + final List readonlyFields = ImmutableList.of( + "/audit/enable_rest", + "/audit/disabled_rest_categories", + "/audit/ignore_requests", + "/compliance/read_watched_fields" + ); updateStaticResourceReadonly(readonlyFields); setupWithRestRoles(null); @@ -172,8 +213,8 @@ public void testReadonlyApi() throws Exception { RestHelper.HttpResponse response = rh.executeGetRequest(ENDPOINT, adminCredsHeader); assertEquals(HttpStatus.SC_OK, response.getStatusCode()); List actual = Streams.stream(readTree(response.getBody()).get("_readonly").iterator()) - .map(JsonNode::textValue) - .collect(Collectors.toList()); + .map(JsonNode::textValue) + .collect(Collectors.toList()); assertEquals(readonlyFields, actual); // test config @@ -209,13 +250,15 @@ public void testReadonlyApi() throws Exception { private void updateStaticResourceReadonly(List readonly) throws IOException { // create audit config - final Map result = ImmutableMap.of( - AuditApiAction.READONLY_FIELD, readonly + final Map result = ImmutableMap.of(AuditApiAction.READONLY_FIELD, readonly); + DefaultObjectMapper.YAML_MAPPER.writeValue( + FileHelper.getAbsoluteFilePathFromClassPath(AuditApiAction.STATIC_RESOURCE.substring(1)).toFile(), + result ); - DefaultObjectMapper.YAML_MAPPER.writeValue(FileHelper.getAbsoluteFilePathFromClassPath(AuditApiAction.STATIC_RESOURCE.substring(1)).toFile(), result); } - private void testPutRequest(final JsonNode json, final int expectedStatus, final boolean sendAdminCertificate, final Header... header) throws Exception { + private void testPutRequest(final JsonNode json, final int expectedStatus, final boolean sendAdminCertificate, final Header... header) + throws Exception { rh.sendAdminCertificate = sendAdminCertificate; RestHelper.HttpResponse response = rh.executePutRequest(CONFIG_ENDPOINT, writeValueAsString(json, false), header); assertEquals(expectedStatus, response.getStatusCode()); @@ -223,12 +266,12 @@ private void testPutRequest(final JsonNode json, final int expectedStatus, final private void testReadonlyBoolean(final ObjectNode json, final String config, final String resource) throws Exception { final String resourcePath = "/config" + config + "/" + resource; - ((ObjectNode)json.at(config)).put(resource, true); + ((ObjectNode) json.at(config)).put(resource, true); testPutRequest(json, HttpStatus.SC_OK, true); - ((ObjectNode)json.at(config)).put(resource, false); + ((ObjectNode) json.at(config)).put(resource, false); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testBooleanPatch(resourcePath, false, HttpStatus.SC_CONFLICT, adminCredsHeader); - ((ObjectNode)json.at(config)).put(resource, true); + ((ObjectNode) json.at(config)).put(resource, true); testPutRequest(json, HttpStatus.SC_OK, true); testBooleanPatch(resourcePath, true, HttpStatus.SC_OK, adminCredsHeader); testBooleanPatch(resourcePath, true, HttpStatus.SC_OK, adminCredsHeader); @@ -236,79 +279,96 @@ private void testReadonlyBoolean(final ObjectNode json, final String config, fin private void testReadonlyList(final ObjectNode json, final String config, final String resource) throws Exception { final String resourcePath = "/config" + config + "/" + resource; - ((ObjectNode)json.at(config)).putPOJO(resource, ImmutableList.of("test-resource-1", "test-resource-2")); + ((ObjectNode) json.at(config)).putPOJO(resource, ImmutableList.of("test-resource-1", "test-resource-2")); testPutRequest(json, HttpStatus.SC_OK, true); // change order List testList = ImmutableList.of("test-resource-2", "test-resource-1"); - ((ObjectNode)json.at(config)).putPOJO(resource, testList); + ((ObjectNode) json.at(config)).putPOJO(resource, testList); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testList(resourcePath, testList, HttpStatus.SC_CONFLICT, adminCredsHeader); // change values testList = ImmutableList.of("test-resource-3", "test-resource-4"); - ((ObjectNode)json.at(config)).putPOJO(resource, testList); + ((ObjectNode) json.at(config)).putPOJO(resource, testList); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testList(resourcePath, testList, HttpStatus.SC_CONFLICT, adminCredsHeader); // change values testList = Collections.emptyList(); - ((ObjectNode)json.at(config)).putPOJO(resource, testList); + ((ObjectNode) json.at(config)).putPOJO(resource, testList); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testList(resourcePath, testList, HttpStatus.SC_CONFLICT, adminCredsHeader); } private void testReadonlyMap(final ObjectNode json, final String config, final String resource) throws Exception { final String resourcePath = "/config" + config + "/" + resource; - ((ObjectNode)json.at(config)).putPOJO(resource, ImmutableMap.of("test-read-index-1", Collections.singletonList("test-field-1"), "test-read-index-2", Collections.singletonList("test-field-2"))); + ((ObjectNode) json.at(config)).putPOJO( + resource, + ImmutableMap.of( + "test-read-index-1", + Collections.singletonList("test-field-1"), + "test-read-index-2", + Collections.singletonList("test-field-2") + ) + ); testPutRequest(json, HttpStatus.SC_OK, true); // change values - Map> testMap = ImmutableMap.of("test-read-index-1", Collections.singletonList("test-field-1")); - ((ObjectNode)json.at(config)).putPOJO(resource, testMap); + Map> testMap = ImmutableMap.of("test-read-index-1", Collections.singletonList("test-field-1")); + ((ObjectNode) json.at(config)).putPOJO(resource, testMap); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testMap(resourcePath, testMap, HttpStatus.SC_CONFLICT, adminCredsHeader); // change values - testMap = ImmutableMap.of("test-read-index-1", ImmutableList.of("test-field-1", "test-field-2")); - ((ObjectNode)json.at(config)).putPOJO(resource, testMap); + testMap = ImmutableMap.of("test-read-index-1", ImmutableList.of("test-field-1", "test-field-2")); + ((ObjectNode) json.at(config)).putPOJO(resource, testMap); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testMap(resourcePath, testMap, HttpStatus.SC_CONFLICT, adminCredsHeader); // change values testMap = ImmutableMap.of("test-read-index", ImmutableList.of("test-field")); - ((ObjectNode)json.at(config)).putPOJO(resource, testMap); + ((ObjectNode) json.at(config)).putPOJO(resource, testMap); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testMap(resourcePath, testMap, HttpStatus.SC_CONFLICT, adminCredsHeader); // same object different order is valid - testMap = ImmutableMap.of("test-read-index-2", Collections.singletonList("test-field-2"), "test-read-index-1", Collections.singletonList("test-field-1")); - ((ObjectNode)json.at(config)).putPOJO(resource, testMap); + testMap = ImmutableMap.of( + "test-read-index-2", + Collections.singletonList("test-field-2"), + "test-read-index-1", + Collections.singletonList("test-field-1") + ); + ((ObjectNode) json.at(config)).putPOJO(resource, testMap); testPutRequest(json, HttpStatus.SC_OK, false, adminCredsHeader); - RestHelper.HttpResponse response = rh.executePatchRequest(ENDPOINT, "[{\"op\": \"add\",\"path\": \"" + resourcePath + "\",\"value\": " + writeValueAsString(testMap, false) + "}]", adminCredsHeader); + RestHelper.HttpResponse response = rh.executePatchRequest( + ENDPOINT, + "[{\"op\": \"add\",\"path\": \"" + resourcePath + "\",\"value\": " + writeValueAsString(testMap, false) + "}]", + adminCredsHeader + ); assertEquals(HttpStatus.SC_OK, response.getStatusCode()); } private void testReadonlyCategories(final ObjectNode json, final String config, final String resource) throws Exception { final String resourcePath = "/config" + config + "/" + resource; // change disabled_rest_categories readonly property - ((ObjectNode)json.at(config)).putPOJO(resource, ImmutableList.of("SSL_EXCEPTION", "AUTHENTICATED")); + ((ObjectNode) json.at(config)).putPOJO(resource, ImmutableList.of("SSL_EXCEPTION", "AUTHENTICATED")); testPutRequest(json, HttpStatus.SC_OK, true); // change order List testList = ImmutableList.of("AUTHENTICATED", "SSL_EXCEPTION"); - ((ObjectNode)json.at(config)).putPOJO(resource, testList); + ((ObjectNode) json.at(config)).putPOJO(resource, testList); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testList(resourcePath, testList, HttpStatus.SC_CONFLICT, adminCredsHeader); // change values testList = ImmutableList.of("AUTHENTICATED", "SSL_EXCEPTION", "FAILED_LOGIN"); - ((ObjectNode)json.at(config)).putPOJO(resource, testList); + ((ObjectNode) json.at(config)).putPOJO(resource, testList); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testList(resourcePath, testList, HttpStatus.SC_CONFLICT, adminCredsHeader); // change values testList = null; - ((ObjectNode)json.at(config)).putPOJO(resource, testList); + ((ObjectNode) json.at(config)).putPOJO(resource, testList); testPutRequest(json, HttpStatus.SC_CONFLICT, false, adminCredsHeader); testList(resourcePath, testList, HttpStatus.SC_CONFLICT, adminCredsHeader); } @@ -332,9 +392,15 @@ public void testBadRequest() throws Exception { // incorrect category final String jsonValue = DefaultObjectMapper.writeValueAsString(ImmutableList.of("RANDOM", "Test"), true); RestHelper.HttpResponse response; - response = rh.executePatchRequest(ENDPOINT, "[{\"op\": \"add\",\"path\": \"" + "/config/audit/disabled_rest_categories" + "\",\"value\": " + jsonValue + "}]"); + response = rh.executePatchRequest( + ENDPOINT, + "[{\"op\": \"add\",\"path\": \"" + "/config/audit/disabled_rest_categories" + "\",\"value\": " + jsonValue + "}]" + ); assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - response = rh.executePatchRequest(ENDPOINT, "[{\"op\": \"add\",\"path\": \"" + "/config/audit/disabled_transport_categories" + "\",\"value\": " + jsonValue + "}]"); + response = rh.executePatchRequest( + ENDPOINT, + "[{\"op\": \"add\",\"path\": \"" + "/config/audit/disabled_transport_categories" + "\",\"value\": " + jsonValue + "}]" + ); assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); } @@ -432,15 +498,25 @@ private void testPatchAction(final int expectedStatus, final Header... headers) testBoolean("/config/compliance/external_config", expectedStatus, headers); testBoolean("/config/compliance/read_metadata_only", expectedStatus, headers); testList("/config/compliance/read_ignore_users", ImmutableList.of("test-user-1"), expectedStatus, headers); - testMap("/config/compliance/read_watched_fields", ImmutableMap.of("test-index-1", Collections.singletonList("test-field")), expectedStatus, headers); + testMap( + "/config/compliance/read_watched_fields", + ImmutableMap.of("test-index-1", Collections.singletonList("test-field")), + expectedStatus, + headers + ); testBoolean("/config/compliance/write_metadata_only", expectedStatus, headers); testBoolean("/config/compliance/write_log_diffs", expectedStatus, headers); testList("/config/compliance/write_ignore_users", ImmutableList.of("test-user-1"), expectedStatus, headers); testList("/config/compliance/write_watched_indices", ImmutableList.of("test-index-1"), expectedStatus, headers); } - private void testBooleanPatch(final String patchResource, final boolean value, final int expected, final Header... headers) throws Exception { - RestHelper.HttpResponse response = rh.executePatchRequest(ENDPOINT, "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": " + value + "}]", headers); + private void testBooleanPatch(final String patchResource, final boolean value, final int expected, final Header... headers) + throws Exception { + RestHelper.HttpResponse response = rh.executePatchRequest( + ENDPOINT, + "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": " + value + "}]", + headers + ); assertEquals(expected, response.getStatusCode()); if (expected == HttpStatus.SC_OK) { assertEquals(value, readTree(rh.executeGetRequest(ENDPOINT, headers).getBody()).at(patchResource).asBoolean()); @@ -458,22 +534,35 @@ private void testBoolean(final String patchResource, final int expected, final H testBooleanPatch(patchResource, true, expected, headers); } - private void testList(final String patchResource, final List expectedList, final int expectedStatus, final Header... headers) throws Exception { + private void testList(final String patchResource, final List expectedList, final int expectedStatus, final Header... headers) + throws Exception { final String jsonValue = DefaultObjectMapper.writeValueAsString(expectedList, true); // make empty - RestHelper.HttpResponse response = rh.executePatchRequest(ENDPOINT, "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": []}]", headers); + RestHelper.HttpResponse response = rh.executePatchRequest( + ENDPOINT, + "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": []}]", + headers + ); assertEquals(expectedStatus, response.getStatusCode()); if (expectedStatus == HttpStatus.SC_OK) { assertEquals(0, readTree(rh.executeGetRequest(ENDPOINT, headers).getBody()).at(patchResource).size()); } // add value - response = rh.executePatchRequest(ENDPOINT, "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": " + jsonValue + "}]", headers); + response = rh.executePatchRequest( + ENDPOINT, + "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": " + jsonValue + "}]", + headers + ); assertEquals(expectedStatus, response.getStatusCode()); if (expectedStatus == HttpStatus.SC_OK) { final JsonNode responseJson = readTree(rh.executeGetRequest(ENDPOINT, headers).getBody()); - final List actualList = DefaultObjectMapper.readValue(responseJson.at(patchResource).toString(), new TypeReference>(){}); + final List actualList = DefaultObjectMapper.readValue( + responseJson.at(patchResource).toString(), + new TypeReference>() { + } + ); assertEquals(expectedList.size(), actualList.size()); assertTrue(actualList.containsAll(expectedList)); } @@ -486,22 +575,39 @@ private void testList(final String patchResource, final List expectedLis } } - private void testMap(final String patchResource, final Map> expectedMap, final int expectedStatus, final Header... headers) throws Exception { + private void testMap( + final String patchResource, + final Map> expectedMap, + final int expectedStatus, + final Header... headers + ) throws Exception { final String jsonValue = DefaultObjectMapper.writeValueAsString(expectedMap, true); // make empty - RestHelper.HttpResponse response = rh.executePatchRequest(ENDPOINT, "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": {}}]", headers); + RestHelper.HttpResponse response = rh.executePatchRequest( + ENDPOINT, + "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": {}}]", + headers + ); assertEquals(expectedStatus, response.getStatusCode()); if (expectedStatus == HttpStatus.SC_OK) { assertEquals(0, readTree(rh.executeGetRequest(ENDPOINT, headers).getBody()).at(patchResource).size()); } // add value - response = rh.executePatchRequest(ENDPOINT, "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": " + jsonValue + "}]", headers); + response = rh.executePatchRequest( + ENDPOINT, + "[{\"op\": \"add\",\"path\": \"" + patchResource + "\",\"value\": " + jsonValue + "}]", + headers + ); assertEquals(expectedStatus, response.getStatusCode()); if (expectedStatus == HttpStatus.SC_OK) { final JsonNode responseJson = readTree(rh.executeGetRequest(ENDPOINT, headers).getBody()); - final Map> actualMap = DefaultObjectMapper.readValue(responseJson.at(patchResource).toString(), new TypeReference>>(){}); + final Map> actualMap = DefaultObjectMapper.readValue( + responseJson.at(patchResource).toString(), + new TypeReference>>() { + } + ); assertEquals(actualMap, expectedMap); } @@ -520,32 +626,38 @@ public void testPatchRequest() throws Exception { rh.sendAdminCertificate = true; // update with non-default configuration - AuditConfig auditConfig = new AuditConfig(true, AuditConfig.Filter.from( + AuditConfig auditConfig = new AuditConfig( + true, + AuditConfig.Filter.from( ImmutableMap.builder() - .put("enable_rest", false) - .put("disabled_rest_categories", Collections.emptyList()) - .put("enable_transport", false) - .put("disabled_transport_categories", Collections.emptyList()) - .put("resolve_bulk_requests", false) - .put("resolve_indices", false) - .put("log_request_body", false) - .put("exclude_sensitive_headers", false) - .put("ignore_users", Collections.emptyList()) - .put("ignore_requests", Collections.emptyList()) - .build()) - , ComplianceConfig.from( + .put("enable_rest", false) + .put("disabled_rest_categories", Collections.emptyList()) + .put("enable_transport", false) + .put("disabled_transport_categories", Collections.emptyList()) + .put("resolve_bulk_requests", false) + .put("resolve_indices", false) + .put("log_request_body", false) + .put("exclude_sensitive_headers", false) + .put("ignore_users", Collections.emptyList()) + .put("ignore_requests", Collections.emptyList()) + .build() + ), + ComplianceConfig.from( ImmutableMap.builder() - .put("enabled", true) - .put("external_config", false) - .put("internal_config", false) - .put("read_metadata_only", false) - .put("read_watched_fields", Collections.emptyMap()) - .put("read_ignore_users", Collections.emptyList()) - .put("write_metadata_only", true) - .put("write_log_diffs", true) - .put("write_watched_indices", Collections.emptyList()) - .put("write_ignore_users", Collections.emptyList()) - .build(), Settings.EMPTY)); + .put("enabled", true) + .put("external_config", false) + .put("internal_config", false) + .put("read_metadata_only", false) + .put("read_watched_fields", Collections.emptyMap()) + .put("read_ignore_users", Collections.emptyList()) + .put("write_metadata_only", true) + .put("write_log_diffs", true) + .put("write_watched_indices", Collections.emptyList()) + .put("write_ignore_users", Collections.emptyList()) + .build(), + Settings.EMPTY + ) + ); final String payload = DefaultObjectMapper.writeValueAsString(auditConfig, false); // update config @@ -566,18 +678,18 @@ public void testPatchRequest() throws Exception { } private String getTestPayload() { - return "{" + - "\"enabled\":true," + - "\"audit\":{" + - "\"enable_rest\":true,\"disabled_rest_categories\":[\"AUTHENTICATED\"]," + - "\"enable_transport\":true,\"disabled_transport_categories\":[\"SSL_EXCEPTION\"]," + - "\"resolve_bulk_requests\":true,\"log_request_body\":true,\"resolve_indices\":true,\"exclude_sensitive_headers\":true," + - "\"ignore_users\":[\"test-user-1\"],\"ignore_requests\":[\"test-request\"]}," + - "\"compliance\":{" + - "\"enabled\":true," + - "\"internal_config\":true,\"external_config\":true," + - "\"read_metadata_only\":true,\"read_watched_fields\":{\"test-read-watch-field\":[]},\"read_ignore_users\":[\"test-user-2\"]," + - "\"write_metadata_only\":true,\"write_log_diffs\":true,\"write_watched_indices\":[\"test-write-watch-index\"],\"write_ignore_users\":[\"test-user-3\"]}" + - "}"; + return "{" + + "\"enabled\":true," + + "\"audit\":{" + + "\"enable_rest\":true,\"disabled_rest_categories\":[\"AUTHENTICATED\"]," + + "\"enable_transport\":true,\"disabled_transport_categories\":[\"SSL_EXCEPTION\"]," + + "\"resolve_bulk_requests\":true,\"log_request_body\":true,\"resolve_indices\":true,\"exclude_sensitive_headers\":true," + + "\"ignore_users\":[\"test-user-1\"],\"ignore_requests\":[\"test-request\"]}," + + "\"compliance\":{" + + "\"enabled\":true," + + "\"internal_config\":true,\"external_config\":true," + + "\"read_metadata_only\":true,\"read_watched_fields\":{\"test-read-watch-field\":[]},\"read_ignore_users\":[\"test-user-2\"]," + + "\"write_metadata_only\":true,\"write_log_diffs\":true,\"write_watched_indices\":[\"test-write-watch-index\"],\"write_ignore_users\":[\"test-user-3\"]}" + + "}"; } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/DashboardsInfoActionTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/DashboardsInfoActionTest.java index c17e997dc3..46128f5a71 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/DashboardsInfoActionTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/DashboardsInfoActionTest.java @@ -22,18 +22,21 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class DashboardsInfoActionTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpoint() { return PLUGINS_PREFIX + "/dashboardsinfo"; } - public DashboardsInfoActionTest(){ + public DashboardsInfoActionTest() { ENDPOINT = getEndpoint(); } @Test public void testDashboardsInfo() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build(); + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) + .build(); setup(settings); rh.keystore = "restapi/kirk-keystore.jks"; diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/FlushCacheApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/FlushCacheApiTest.java index c998bf5a19..120596f046 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/FlushCacheApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/FlushCacheApiTest.java @@ -23,11 +23,13 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class FlushCacheApiTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public FlushCacheApiTest(){ + + public FlushCacheApiTest() { ENDPOINT = getEndpointPrefix() + "/api/cache"; } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/GetConfigurationApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/GetConfigurationApiTest.java index ea5e96d37e..09c4a762b5 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/GetConfigurationApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/GetConfigurationApiTest.java @@ -24,12 +24,13 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class GetConfigurationApiTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public GetConfigurationApiTest(){ + public GetConfigurationApiTest() { ENDPOINT = getEndpointPrefix() + "/api"; } @@ -48,9 +49,7 @@ public void testGetConfiguration() throws Exception { response = rh.executeGetRequest(ENDPOINT + "/securityconfig"); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); - Assert.assertEquals( - settings.getAsBoolean("config.dynamic.authc.authentication_domain_basic_internal.http_enabled", false), - true); + Assert.assertEquals(settings.getAsBoolean("config.dynamic.authc.authentication_domain_basic_internal.http_enabled", false), true); Assert.assertNull(settings.get("_opendistro_security_meta.type")); // internalusers diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/IndexMissingTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/IndexMissingTest.java index c2313fe434..22035bba28 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/IndexMissingTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/IndexMissingTest.java @@ -24,12 +24,13 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class IndexMissingTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public IndexMissingTest(){ + public IndexMissingTest() { ENDPOINT = getEndpointPrefix() + "/api"; } @@ -81,7 +82,11 @@ protected void testHttpOperations() throws Exception { Assert.assertEquals("{\"status\":\"INTERNAL_SERVER_ERROR\",\"message\":\"Security index not initialized\"}", errorString); // PUT request - response = rh.executePutRequest(ENDPOINT + "/actiongroups/READ", FileHelper.loadFile("restapi/actiongroup_read.json"), new Header[0]); + response = rh.executePutRequest( + ENDPOINT + "/actiongroups/READ", + FileHelper.loadFile("restapi/actiongroup_read.json"), + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatusCode()); // DELETE request @@ -95,7 +100,10 @@ protected void testHttpOperations() throws Exception { response = rh.executeGetRequest(ENDPOINT + "/roles"); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); SecurityJsonNode securityJsonNode = new SecurityJsonNode(DefaultObjectMapper.readTree(response.getBody())); - Assert.assertEquals("OPENDISTRO_SECURITY_CLUSTER_ALL", securityJsonNode.get("opendistro_security_admin").get("cluster_permissions").get(0).asString()); + Assert.assertEquals( + "OPENDISTRO_SECURITY_CLUSTER_ALL", + securityJsonNode.get("opendistro_security_admin").get("cluster_permissions").get(0).asString() + ); } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/MultiTenancyConfigApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/MultiTenancyConfigApiTest.java index 24aa8737c6..7132dcc491 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/MultiTenancyConfigApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/MultiTenancyConfigApiTest.java @@ -31,27 +31,28 @@ private void verifyTenantUpdate(final Header... header) throws Exception { final HttpResponse getSettingResponse = rh.executeGetRequest("/_plugins/_security/api/tenancy/config", header); assertThat(getSettingResponse.getBody(), getSettingResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat( - getSettingResponse.getBody(), - getSettingResponse.findValueInJson("default_tenant"), - equalTo(ConfigConstants.TENANCY_GLOBAL_TENANT_DEFAULT_NAME) + getSettingResponse.getBody(), + getSettingResponse.findValueInJson("default_tenant"), + equalTo(ConfigConstants.TENANCY_GLOBAL_TENANT_DEFAULT_NAME) ); HttpResponse getDashboardsinfoResponse = rh.executeGetRequest("/_plugins/_security/dashboardsinfo", header); assertThat(getDashboardsinfoResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat( - getDashboardsinfoResponse.getBody(), - getDashboardsinfoResponse.findValueInJson("default_tenant"), - equalTo(ConfigConstants.TENANCY_GLOBAL_TENANT_DEFAULT_NAME) + getDashboardsinfoResponse.getBody(), + getDashboardsinfoResponse.findValueInJson("default_tenant"), + equalTo(ConfigConstants.TENANCY_GLOBAL_TENANT_DEFAULT_NAME) ); final HttpResponse setPrivateTenantAsDefaultResponse = rh.executePutRequest( - "/_plugins/_security/api/tenancy/config", - "{\"default_tenant\": \"Private\"}", header + "/_plugins/_security/api/tenancy/config", + "{\"default_tenant\": \"Private\"}", + header ); assertThat( - setPrivateTenantAsDefaultResponse.getBody(), - setPrivateTenantAsDefaultResponse.getStatusCode(), - equalTo(HttpStatus.SC_OK) + setPrivateTenantAsDefaultResponse.getBody(), + setPrivateTenantAsDefaultResponse.getStatusCode(), + equalTo(HttpStatus.SC_OK) ); getDashboardsinfoResponse = rh.executeGetRequest("/_plugins/_security/dashboardsinfo", ADMIN_FULL_ACCESS_USER); assertThat(getDashboardsinfoResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); @@ -73,67 +74,79 @@ public void testUpdateRestAPIAdmin() throws Exception { verifyTenantUpdate(ADMIN_FULL_ACCESS_USER); } - private void verifyTenantUpdateFailed(final Header... header) throws Exception { final HttpResponse disablePrivateTenantResponse = rh.executePutRequest( - "/_plugins/_security/api/tenancy/config", - "{\"private_tenant_enabled\":false}", header + "/_plugins/_security/api/tenancy/config", + "{\"private_tenant_enabled\":false}", + header ); assertThat(disablePrivateTenantResponse.getBody(), disablePrivateTenantResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); final HttpResponse setPrivateTenantAsDefaultFailResponse = rh.executePutRequest( - "/_plugins/_security/api/tenancy/config", - "{\"default_tenant\": \"Private\"}", header + "/_plugins/_security/api/tenancy/config", + "{\"default_tenant\": \"Private\"}", + header + ); + assertThat( + setPrivateTenantAsDefaultFailResponse.getBody(), + setPrivateTenantAsDefaultFailResponse.getStatusCode(), + equalTo(HttpStatus.SC_BAD_REQUEST) ); - assertThat(setPrivateTenantAsDefaultFailResponse.getBody(), setPrivateTenantAsDefaultFailResponse.getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST)); assertThat( - setPrivateTenantAsDefaultFailResponse.getBody(), - setPrivateTenantAsDefaultFailResponse.findValueInJson("error.reason"), - containsString("Private tenant can not be disabled if it is the default tenant.") + setPrivateTenantAsDefaultFailResponse.getBody(), + setPrivateTenantAsDefaultFailResponse.findValueInJson("error.reason"), + containsString("Private tenant can not be disabled if it is the default tenant.") ); final HttpResponse enablePrivateTenantResponse = rh.executePutRequest( - "/_plugins/_security/api/tenancy/config", - "{\"private_tenant_enabled\":true}", - header + "/_plugins/_security/api/tenancy/config", + "{\"private_tenant_enabled\":true}", + header ); assertThat(enablePrivateTenantResponse.getBody(), enablePrivateTenantResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); final HttpResponse setPrivateTenantAsDefaultResponse = rh.executePutRequest( - "/_plugins/_security/api/tenancy/config", - "{\"default_tenant\": \"Private\"}", - header + "/_plugins/_security/api/tenancy/config", + "{\"default_tenant\": \"Private\"}", + header + ); + assertThat( + setPrivateTenantAsDefaultResponse.getBody(), + setPrivateTenantAsDefaultResponse.getStatusCode(), + equalTo(HttpStatus.SC_OK) + ); + final HttpResponse updatePrivateSettingResponse = rh.executePutRequest( + "/_plugins/_security/api/tenancy/config", + "{\"private_tenant_enabled\":false}", + header ); - assertThat(setPrivateTenantAsDefaultResponse.getBody(), setPrivateTenantAsDefaultResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); - final HttpResponse updatePrivateSettingResponse = - rh.executePutRequest("/_plugins/_security/api/tenancy/config", "{\"private_tenant_enabled\":false}", header); assertThat(updatePrivateSettingResponse.getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST)); - assertThat(updatePrivateSettingResponse.findValueInJson("error.reason"), containsString("Private tenant can not be disabled if it is the default tenant.")); + assertThat( + updatePrivateSettingResponse.findValueInJson("error.reason"), + containsString("Private tenant can not be disabled if it is the default tenant.") + ); final HttpResponse getSettingResponseAfterUpdate = rh.executeGetRequest("/_plugins/_security/api/tenancy/config", header); assertThat(getSettingResponseAfterUpdate.getBody(), getSettingResponseAfterUpdate.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat( - getSettingResponseAfterUpdate.getBody(), - getSettingResponseAfterUpdate.findValueInJson("default_tenant"), - equalTo("Private") + getSettingResponseAfterUpdate.getBody(), + getSettingResponseAfterUpdate.findValueInJson("default_tenant"), + equalTo("Private") ); final HttpResponse getDashboardsinfoResponse = rh.executeGetRequest("/_plugins/_security/dashboardsinfo", header); - assertThat( - getDashboardsinfoResponse.getBody(), - getDashboardsinfoResponse.findValueInJson("default_tenant"), - equalTo("Private") - ); + assertThat(getDashboardsinfoResponse.getBody(), getDashboardsinfoResponse.findValueInJson("default_tenant"), equalTo("Private")); final HttpResponse setRandomStringAsDefaultTenant = rh.executePutRequest( - "/_plugins/_security/api/tenancy/config", - "{\"default_tenant\": \"NonExistentTenant\"}", - header + "/_plugins/_security/api/tenancy/config", + "{\"default_tenant\": \"NonExistentTenant\"}", + header ); assertThat(setRandomStringAsDefaultTenant.getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST)); - assertThat(setPrivateTenantAsDefaultFailResponse.getBody(), - setRandomStringAsDefaultTenant.findValueInJson("error.reason"), - containsString("Default tenant should be selected from one of the available tenants.") + assertThat( + setPrivateTenantAsDefaultFailResponse.getBody(), + setRandomStringAsDefaultTenant.findValueInJson("error.reason"), + containsString("Default tenant should be selected from one of the available tenants.") ); } @@ -160,11 +173,11 @@ public void testForbiddenAccess() throws Exception { HttpResponse getSettingResponse = rh.executeGetRequest("/_plugins/_security/api/tenancy/config", USER_NO_REST_API_ACCESS); assertThat(getSettingResponse.getBody(), getSettingResponse.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); HttpResponse updateSettingResponse = rh.executePutRequest( - "/_plugins/_security/api/tenancy/config", - "{\"default_tenant\": \"Private\"}", USER_NO_REST_API_ACCESS + "/_plugins/_security/api/tenancy/config", + "{\"default_tenant\": \"Private\"}", + USER_NO_REST_API_ACCESS ); assertThat(getSettingResponse.getBody(), updateSettingResponse.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); } - } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/NodesDnApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/NodesDnApiTest.java index ef1042682b..a549ad4dd9 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/NodesDnApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/NodesDnApiTest.java @@ -42,12 +42,13 @@ public class NodesDnApiTest extends AbstractRestApiUnitTest { private HttpResponse response; private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public NodesDnApiTest(){ + public NodesDnApiTest() { ENDPOINT = getEndpointPrefix() + "/api"; } @@ -55,7 +56,7 @@ private JsonNode asJsonNode(T t) throws Exception { return OBJECT_MAPPER.readTree(OBJECT_MAPPER.writeValueAsString(t)); } - private Map> nodesDnEntry(String...nodesDn) { + private Map> nodesDnEntry(String... nodesDn) { return ImmutableMap.of("nodes_dn", Arrays.asList(nodesDn)); } @@ -63,9 +64,14 @@ private void testCrudScenarios(final int expectedStatus, final Header... headers response = rh.executeGetRequest(ENDPOINT + "/nodesdn?show_all=true", headers); assertThat(response.getStatusCode(), equalTo(expectedStatus)); if (expectedStatus == HttpStatus.SC_OK) { - JsonNode expected = asJsonNode(ImmutableMap.of( - "cluster1", nodesDnEntry("cn=popeye"), - NodesDnApiAction.STATIC_OPENSEARCH_YML_NODES_DN, nodesDnEntry("CN=example.com"))); + JsonNode expected = asJsonNode( + ImmutableMap.of( + "cluster1", + nodesDnEntry("cn=popeye"), + NodesDnApiAction.STATIC_OPENSEARCH_YML_NODES_DN, + nodesDnEntry("CN=example.com") + ) + ); JsonNode node = OBJECT_MAPPER.readTree(response.getBody()); assertThat(node, equalTo(asJsonNode(expected))); @@ -98,7 +104,11 @@ private void testCrudScenarios(final int expectedStatus, final Header... headers response = rh.executePutRequest(ENDPOINT + "/nodesdn/cluster1", "{\"nodes_dn\": [\"cn=popeye\"]}", headers); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); - response = rh.executePatchRequest(ENDPOINT + "/nodesdn/cluster1", "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", headers); + response = rh.executePatchRequest( + ENDPOINT + "/nodesdn/cluster1", + "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", + headers + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); response = rh.executePatchRequest(ENDPOINT + "/nodesdn", "[{ \"op\": \"remove\", \"path\": \"/cluster1/nodes_dn/0\"}]", headers); @@ -108,7 +118,7 @@ private void testCrudScenarios(final int expectedStatus, final Header... headers assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); } - private void checkNullElementsInArray(final Header headers) throws Exception{ + private void checkNullElementsInArray(final Header headers) throws Exception { String body = FileHelper.loadFile("restapi/nodesdn_null_array_element.json"); HttpResponse response = rh.executePutRequest(ENDPOINT + "/nodesdn/cluster1", body, headers); @@ -128,7 +138,8 @@ public void testNodesDnApiWithDynamicConfigDisabled() throws Exception { @Test public void testNodesDnApi() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_NODES_DN_DYNAMIC_CONFIG_ENABLED, true) + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_NODES_DN_DYNAMIC_CONFIG_ENABLED, true) .putList(ConfigConstants.SECURITY_NODES_DN, "CN=example.com") .build(); setupWithRestRoles(settings); @@ -170,67 +181,70 @@ public void testNodesDnApi() throws Exception { final int expectedStatus = HttpStatus.SC_FORBIDDEN; - response = rh.executePutRequest(ENDPOINT + "/nodesdn/" + NodesDnApiAction.STATIC_OPENSEARCH_YML_NODES_DN, "{\"nodes_dn\": [\"cn=popeye\"]}", nonAdminCredsHeader); + response = rh.executePutRequest( + ENDPOINT + "/nodesdn/" + NodesDnApiAction.STATIC_OPENSEARCH_YML_NODES_DN, + "{\"nodes_dn\": [\"cn=popeye\"]}", + nonAdminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); - response = rh.executePatchRequest(ENDPOINT + "/nodesdn/" + NodesDnApiAction.STATIC_OPENSEARCH_YML_NODES_DN, - "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]" , nonAdminCredsHeader); + response = rh.executePatchRequest( + ENDPOINT + "/nodesdn/" + NodesDnApiAction.STATIC_OPENSEARCH_YML_NODES_DN, + "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", + nonAdminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); - response = rh.executeDeleteRequest(ENDPOINT + "/nodesdn/" + NodesDnApiAction.STATIC_OPENSEARCH_YML_NODES_DN, nonAdminCredsHeader); + response = rh.executeDeleteRequest( + ENDPOINT + "/nodesdn/" + NodesDnApiAction.STATIC_OPENSEARCH_YML_NODES_DN, + nonAdminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); } } - @Test public void testNodesDnApiWithPermissions() throws Exception { - Settings settings = - Settings.builder() - .put(ConfigConstants.SECURITY_NODES_DN_DYNAMIC_CONFIG_ENABLED, true) - .put(SECURITY_RESTAPI_ADMIN_ENABLED, true) - .build(); + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_NODES_DN_DYNAMIC_CONFIG_ENABLED, true) + .put(SECURITY_RESTAPI_ADMIN_ENABLED, true) + .build(); setupWithRestRoles(settings); final Header restApiAdminHeader = encodeBasicHeader("rest_api_admin_user", "rest_api_admin_user"); final Header restApiNodesDnHeader = encodeBasicHeader("rest_api_admin_nodesdn", "rest_api_admin_nodesdn"); final Header restApiUserHeader = encodeBasicHeader("test", "test"); - //full access admin + // full access admin { rh.sendAdminCertificate = false; - response = rh.executeGetRequest( - ENDPOINT + "/nodesdn", restApiAdminHeader); + response = rh.executeGetRequest(ENDPOINT + "/nodesdn", restApiAdminHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - response = rh.executePutRequest( - ENDPOINT + "/nodesdn/c1", "{\"nodes_dn\": [\"cn=popeye\"]}", - restApiAdminHeader); + response = rh.executePutRequest(ENDPOINT + "/nodesdn/c1", "{\"nodes_dn\": [\"cn=popeye\"]}", restApiAdminHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_CREATED)); response = rh.executePatchRequest( - ENDPOINT + "/nodesdn/c1", - "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", - restApiAdminHeader + ENDPOINT + "/nodesdn/c1", + "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", + restApiAdminHeader ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); response = rh.executeDeleteRequest(ENDPOINT + "/nodesdn/c1", restApiAdminHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); } - //NodesDN only + // NodesDN only { rh.sendAdminCertificate = false; response = rh.executeGetRequest(ENDPOINT + "/nodesdn", restApiNodesDnHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - response = rh.executePutRequest( - ENDPOINT + "/nodesdn/c1", "{\"nodes_dn\": [\"cn=popeye\"]}", - restApiNodesDnHeader); + response = rh.executePutRequest(ENDPOINT + "/nodesdn/c1", "{\"nodes_dn\": [\"cn=popeye\"]}", restApiNodesDnHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_CREATED)); response = rh.executePatchRequest( - ENDPOINT + "/nodesdn/c1", - "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", - restApiNodesDnHeader + ENDPOINT + "/nodesdn/c1", + "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", + restApiNodesDnHeader ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); @@ -240,21 +254,19 @@ public void testNodesDnApiWithPermissions() throws Exception { response = rh.executeGetRequest(ENDPOINT + "/actiongroups", restApiNodesDnHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); } - //rest api user + // rest api user { rh.sendAdminCertificate = false; response = rh.executeGetRequest(ENDPOINT + "/nodesdn", restApiUserHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - response = rh.executePutRequest( - ENDPOINT + "/nodesdn/c1", "{\"nodes_dn\": [\"cn=popeye\"]}", - restApiUserHeader); + response = rh.executePutRequest(ENDPOINT + "/nodesdn/c1", "{\"nodes_dn\": [\"cn=popeye\"]}", restApiUserHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); response = rh.executePatchRequest( - ENDPOINT + "/nodesdn/c1", - "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", - restApiUserHeader + ENDPOINT + "/nodesdn/c1", + "[{ \"op\": \"add\", \"path\": \"/nodes_dn/-\", \"value\": \"bluto\" }]", + restApiUserHeader ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); @@ -266,7 +278,8 @@ public void testNodesDnApiWithPermissions() throws Exception { @Test public void testNodesDnApiAuditComplianceLogging() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_NODES_DN_DYNAMIC_CONFIG_ENABLED, true) + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_NODES_DN_DYNAMIC_CONFIG_ENABLED, true) .putList(ConfigConstants.SECURITY_NODES_DN, "CN=example.com") .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) @@ -293,9 +306,13 @@ public void testNodesDnApiAuditComplianceLogging() throws Exception { System.out.println(TestAuditlogImpl.sb.toString()); final Map expectedCategoryCounts = ImmutableMap.of( - AuditCategory.COMPLIANCE_INTERNAL_CONFIG_READ, 4L, - AuditCategory.COMPLIANCE_INTERNAL_CONFIG_WRITE, 4L); - Map actualCategoryCounts = TestAuditlogImpl.messages.stream().collect(Collectors.groupingBy(AuditMessage::getCategory, Collectors.counting())); + AuditCategory.COMPLIANCE_INTERNAL_CONFIG_READ, + 4L, + AuditCategory.COMPLIANCE_INTERNAL_CONFIG_WRITE, + 4L + ); + Map actualCategoryCounts = TestAuditlogImpl.messages.stream() + .collect(Collectors.groupingBy(AuditMessage::getCategory, Collectors.counting())); assertThat(actualCategoryCounts, equalTo(expectedCategoryCounts)); } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/RestApiPrivilegesEvaluatorTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/RestApiPrivilegesEvaluatorTest.java index 6573082e5b..bbe1bf90f8 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/RestApiPrivilegesEvaluatorTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/RestApiPrivilegesEvaluatorTest.java @@ -34,12 +34,14 @@ public class RestApiPrivilegesEvaluatorTest { @Before public void setUp() { - this.privilegesEvaluator = new RestApiPrivilegesEvaluator(Settings.EMPTY, - mock(AdminDNs.class), - mock(PrivilegesEvaluator.class), - mock(PrincipalExtractor.class), - mock(Path.class), - mock(ThreadPool.class)); + this.privilegesEvaluator = new RestApiPrivilegesEvaluator( + Settings.EMPTY, + mock(AdminDNs.class), + mock(PrivilegesEvaluator.class), + mock(PrincipalExtractor.class), + mock(Path.class), + mock(ThreadPool.class) + ); } @Test diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/RoleBasedAccessTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/RoleBasedAccessTest.java index 5adac7ca78..fc5c59d36f 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/RoleBasedAccessTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/RoleBasedAccessTest.java @@ -25,12 +25,13 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class RoleBasedAccessTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public RoleBasedAccessTest(){ + public RoleBasedAccessTest() { ENDPOINT = getEndpointPrefix() + "/api"; } @@ -100,7 +101,6 @@ public void testActionGroupsApi() throws Exception { Assert.assertEquals("", settings.getAsList("opendistro_security_role_starfleet_library.backend_roles").get(0), "starfleet*"); Assert.assertEquals("", settings.getAsList("opendistro_security_zdummy_all.users").get(0), "bug108"); - // Deprecated get configuration API, acessible for sarek // response = rh.executeGetRequest("_opendistro/_security/api/configuration/internalusers", encodeBasicHeader("sarek", "sarek")); // settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); @@ -119,9 +119,9 @@ public void testActionGroupsApi() throws Exception { // Assert.assertEquals("", settings.getAsList("CRUD.permissions").get(0), "READ_UT"); // configuration API, not accessible for worf -// response = rh.executeGetRequest("_opendistro/_security/api/configuration/actiongroups", encodeBasicHeader("worf", "worf")); -// Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); -// Assert.assertTrue(response.getBody().contains("does not have any access to endpoint CONFIGURATION")); + // response = rh.executeGetRequest("_opendistro/_security/api/configuration/actiongroups", encodeBasicHeader("worf", "worf")); + // Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); + // Assert.assertTrue(response.getBody().contains("does not have any access to endpoint CONFIGURATION")); // cache API, not accessible for worf since it's disabled globally response = rh.executeDeleteRequest("_opendistro/_security/api/cache", encodeBasicHeader("worf", "worf")); @@ -173,10 +173,18 @@ public void testActionGroupsApi() throws Exception { // Worf, has access to roles API, get captains role response = rh.executeGetRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", encodeBasicHeader("worf", "worf")); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - Assert.assertEquals(new SecurityJsonNode(DefaultObjectMapper.readTree(response.getBody())).getDotted("opendistro_security_role_starfleet_captains.cluster_permissions").get(0).asString(), "cluster:monitor*"); + Assert.assertEquals( + new SecurityJsonNode(DefaultObjectMapper.readTree(response.getBody())).getDotted( + "opendistro_security_role_starfleet_captains.cluster_permissions" + ).get(0).asString(), + "cluster:monitor*" + ); // Worf, has access to roles API, able to delete - response = rh.executeDeleteRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", encodeBasicHeader("worf", "worf")); + response = rh.executeDeleteRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + encodeBasicHeader("worf", "worf") + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("'opendistro_security_role_starfleet_captains' deleted")); @@ -196,20 +204,31 @@ public void testActionGroupsApi() throws Exception { // --- PUT --- // admin, no access - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_captains_tenants.json"), encodeBasicHeader("admin", "admin")); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_captains_tenants.json"), + encodeBasicHeader("admin", "admin") + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // worf, restore role starfleet captains - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_captains_different_content.json"), encodeBasicHeader("worf", "worf")); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_captains_different_content.json"), + encodeBasicHeader("worf", "worf") + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); // starfleet role present again response = rh.executeGetRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", encodeBasicHeader("worf", "worf")); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - Assert.assertEquals(new SecurityJsonNode(DefaultObjectMapper.readTree(response.getBody())).getDotted("opendistro_security_role_starfleet_captains.index_permissions").get(0).get("allowed_actions").get(0).asString(), "blafasel"); + Assert.assertEquals( + new SecurityJsonNode(DefaultObjectMapper.readTree(response.getBody())).getDotted( + "opendistro_security_role_starfleet_captains.index_permissions" + ).get(0).get("allowed_actions").get(0).asString(), + "blafasel" + ); // Try the same, but now with admin certificate rh.sendAdminCertificate = true; @@ -245,8 +264,11 @@ public void testActionGroupsApi() throws Exception { Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // PUT roles - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_captains_different_content.json"), encodeBasicHeader("test", "test")); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_captains_different_content.json"), + encodeBasicHeader("test", "test") + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // GET captions role @@ -254,7 +276,10 @@ public void testActionGroupsApi() throws Exception { Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // Delete captions role - response = rh.executeDeleteRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", encodeBasicHeader("test", "test")); + response = rh.executeDeleteRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + encodeBasicHeader("test", "test") + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("'opendistro_security_role_starfleet_captains' deleted")); @@ -262,6 +287,5 @@ public void testActionGroupsApi() throws Exception { response = rh.executeGetRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", encodeBasicHeader("test", "test")); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); - } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/RolesApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/RolesApiTest.java index a85566dc91..bf703fea35 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/RolesApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/RolesApiTest.java @@ -81,7 +81,7 @@ public void testAllRolesForRestAdmin() throws Exception { setupWithRestRoles(Settings.builder().put(SECURITY_RESTAPI_ADMIN_ENABLED, true).build()); final Header restApiAdminHeader = encodeBasicHeader("rest_api_admin_user", "rest_api_admin_user"); rh.sendAdminCertificate = false; - checkSuperAdminRoles(new Header[]{restApiAdminHeader}); + checkSuperAdminRoles(new Header[] { restApiAdminHeader }); } @Test @@ -89,7 +89,7 @@ public void testAllRolesForRolesRestAdmin() throws Exception { setupWithRestRoles(Settings.builder().put(SECURITY_RESTAPI_ADMIN_ENABLED, true).build()); final Header restApiAdminRolesHeader = encodeBasicHeader("rest_api_admin_roles", "rest_api_admin_roles"); rh.sendAdminCertificate = false; - checkSuperAdminRoles(new Header[]{restApiAdminRolesHeader}); + checkSuperAdminRoles(new Header[] { restApiAdminRolesHeader }); } void checkSuperAdminRoles(final Header[] header) { @@ -108,12 +108,14 @@ public void testPutDuplicateKeys() throws Exception { rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - HttpResponse response = rh.executePutRequest(ENDPOINT + "/roles/dup", "{ \"cluster_permissions\": [\"*\"], \"cluster_permissions\": [\"*\"] }"); + HttpResponse response = rh.executePutRequest( + ENDPOINT + "/roles/dup", + "{ \"cluster_permissions\": [\"*\"], \"cluster_permissions\": [\"*\"] }" + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); assertHealthy(); } - @Test public void testPutUnknownKey() throws Exception { @@ -121,7 +123,10 @@ public void testPutUnknownKey() throws Exception { rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - HttpResponse response = rh.executePutRequest(ENDPOINT + "/roles/dup", "{ \"unknownkey\": [\"*\"], \"cluster_permissions\": [\"*\"] }"); + HttpResponse response = rh.executePutRequest( + ENDPOINT + "/roles/dup", + "{ \"unknownkey\": [\"*\"], \"cluster_permissions\": [\"*\"] }" + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("invalid_keys")); assertHealthy(); @@ -134,7 +139,10 @@ public void testPutInvalidJson() throws Exception { rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - HttpResponse response = rh.executePutRequest(ENDPOINT + "/roles/dup", "{ \"invalid\"::{{ [\"*\"], \"cluster_permissions\": [\"*\"] }"); + HttpResponse response = rh.executePutRequest( + ENDPOINT + "/roles/dup", + "{ \"invalid\"::{{ [\"*\"], \"cluster_permissions\": [\"*\"] }" + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); assertHealthy(); } @@ -151,7 +159,7 @@ public void testRolesApi() throws Exception { setupStarfleetIndex(); // add user picard, role starfleet, maps to opendistro_security_role_starfleet - addUserWithPassword("picard", "picardpicardpicardpicard", new String[]{"starfleet", "captains"}, HttpStatus.SC_CREATED); + addUserWithPassword("picard", "picardpicardpicardpicard", new String[] { "starfleet", "captains" }, HttpStatus.SC_CREATED); checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); checkWriteAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); @@ -242,25 +250,37 @@ void verifyPutForSuperAdmin(final Header[] header, final boolean sendAdminCert) Assert.assertEquals(AbstractConfigurationValidator.ErrorType.PAYLOAD_MANDATORY.getMessage(), settings.get("reason").asText()); // put new configuration with invalid payload, must fail - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet", - FileHelper.loadFile("restapi/roles_not_parseable.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet", + FileHelper.loadFile("restapi/roles_not_parseable.json"), + header + ); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.BODY_NOT_PARSEABLE.getMessage(), settings.get("reason").asText()); // put new configuration with invalid keys, must fail - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet", - FileHelper.loadFile("restapi/roles_invalid_keys.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet", + FileHelper.loadFile("restapi/roles_invalid_keys.json"), + header + ); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.INVALID_CONFIGURATION.getMessage(), settings.get("reason").asText()); - Assert.assertTrue(settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY).get("keys").asText().contains("indexx_permissions")); Assert.assertTrue( - settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY).get("keys").asText().contains("kluster_permissions")); + settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY).get("keys").asText().contains("indexx_permissions") + ); + Assert.assertTrue( + settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY).get("keys").asText().contains("kluster_permissions") + ); // put new configuration with wrong datatypes, must fail - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet", - FileHelper.loadFile("restapi/roles_wrong_datatype.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet", + FileHelper.loadFile("restapi/roles_wrong_datatype.json"), + header + ); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.WRONG_DATATYPE.getMessage(), settings.get("reason").asText()); @@ -268,18 +288,27 @@ void verifyPutForSuperAdmin(final Header[] header, final boolean sendAdminCert) // put read only role, must be forbidden // But SuperAdmin can still create it - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_transport_client", - FileHelper.loadFile("restapi/roles_captains.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_transport_client", + FileHelper.loadFile("restapi/roles_captains.json"), + header + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); // put hidden role, must be forbidden, but allowed for super admin - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_internal", - FileHelper.loadFile("restapi/roles_captains.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_internal", + FileHelper.loadFile("restapi/roles_captains.json"), + header + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); // restore starfleet role - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet", - FileHelper.loadFile("restapi/roles_starfleet.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet", + FileHelper.loadFile("restapi/roles_starfleet.json"), + header + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); rh.sendAdminCertificate = false; checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); @@ -287,53 +316,94 @@ void verifyPutForSuperAdmin(final Header[] header, final boolean sendAdminCert) // now picard is only in opendistro_security_role_starfleet, which has write access to // all indices. We collapse all document types in ODFE7 so this permission in the // starfleet role grants all permissions: - // _doc: - // - 'indices:*' + // _doc: + // - 'indices:*' checkWriteAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); rh.sendAdminCertificate = sendAdminCert; // restore captains role - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_captains.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_captains.json"), + header + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); rh.sendAdminCertificate = false; checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); checkWriteAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); rh.sendAdminCertificate = sendAdminCert; - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_complete_invalid.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_complete_invalid.json"), + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_multiple_2.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_multiple_2.json"), + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // check tenants rh.sendAdminCertificate = sendAdminCert; - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_captains_tenants.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_captains_tenants.json"), + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(2, settings.size()); Assert.assertEquals(settings.get("status").asText(), "OK"); - response = rh.executeGetRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); System.out.println(response.getBody()); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(1, settings.size()); - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(1).get("tenant_patterns").get(0).asString(), "tenant1"); - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(1).get("allowed_actions").get(0).asString(), "kibana_all_read"); + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(1) + .get("tenant_patterns") + .get(0) + .asString(), + "tenant1" + ); + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(1) + .get("allowed_actions") + .get(0) + .asString(), + "kibana_all_read" + ); + + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(0) + .get("tenant_patterns") + .get(0) + .asString(), + "tenant2" + ); + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(0) + .get("allowed_actions") + .get(0) + .asString(), + "kibana_all_write" + ); - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(0).get("tenant_patterns").get(0).asString(), "tenant2"); - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(0).get("allowed_actions").get(0).asString(), "kibana_all_write"); - - - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_captains_tenants2.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_captains_tenants2.json"), + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(2, settings.size()); @@ -344,18 +414,63 @@ void verifyPutForSuperAdmin(final Header[] header, final boolean sendAdminCert) settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(1, settings.size()); - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(0).get("tenant_patterns").get(0).asString(), "tenant2"); - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(0).get("tenant_patterns").get(1).asString(), "tenant4"); - - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(0).get("allowed_actions").get(0).asString(), "kibana_all_write"); - - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(1).get("tenant_patterns").get(0).asString(), "tenant1"); - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(1).get("tenant_patterns").get(1).asString(), "tenant3"); - Assert.assertEquals(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(1).get("allowed_actions").get(0).asString(), "kibana_all_read"); + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(0) + .get("tenant_patterns") + .get(0) + .asString(), + "tenant2" + ); + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(0) + .get("tenant_patterns") + .get(1) + .asString(), + "tenant4" + ); + + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(0) + .get("allowed_actions") + .get(0) + .asString(), + "kibana_all_write" + ); + + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(1) + .get("tenant_patterns") + .get(0) + .asString(), + "tenant1" + ); + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(1) + .get("tenant_patterns") + .get(1) + .asString(), + "tenant3" + ); + Assert.assertEquals( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions") + .get(1) + .get("allowed_actions") + .get(0) + .asString(), + "kibana_all_read" + ); // remove tenants from role - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_captains_no_tenants.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_captains_no_tenants.json"), + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(2, settings.size()); @@ -365,11 +480,18 @@ void verifyPutForSuperAdmin(final Header[] header, final boolean sendAdminCert) Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(1, settings.size()); - Assert.assertFalse(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.cluster_permissions").get(0).isNull()); - Assert.assertTrue(new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(0).isNull()); + Assert.assertFalse( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.cluster_permissions").get(0).isNull() + ); + Assert.assertTrue( + new SecurityJsonNode(settings).getDotted("opendistro_security_role_starfleet_captains.tenant_permissions").get(0).isNull() + ); - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/roles_captains_tenants_malformed.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/roles_captains_tenants_malformed.json"), + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); settings = DefaultObjectMapper.readTree(response.getBody()); Assert.assertEquals(settings.get("status").asText(), "error"); @@ -381,36 +503,43 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean sendAdminCert // PATCH on non-existing resource rh.sendAdminCertificate = sendAdminCert; HttpResponse response = rh.executePatchRequest( - ENDPOINT + "/roles/imnothere", - "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", - header); + ENDPOINT + "/roles/imnothere", + "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // PATCH read only resource, must be forbidden // SuperAdmin can patch it rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles/opendistro_security_transport_client", - "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", - header); + ENDPOINT + "/roles/opendistro_security_transport_client", + "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // PATCH hidden resource, must be not found, can be found for superadmin, but will fail with no path present exception rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles/opendistro_security_internal", - "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", - header); + ENDPOINT + "/roles/opendistro_security_internal", + "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH value of hidden flag, must fail with validation error rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles/opendistro_security_role_starfleet", - "[{ \"op\": \"add\", \"path\": \"/hidden\", \"value\": true }]", - header); + ENDPOINT + "/roles/opendistro_security_role_starfleet", + "[{ \"op\": \"add\", \"path\": \"/hidden\", \"value\": true }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - Assert.assertTrue(response.getBody(), response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*")); + Assert.assertTrue( + response.getBody(), + response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*") + ); List permissions = null; @@ -433,61 +562,69 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean sendAdminCert // PATCH on non-existing resource rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles", - "[{ \"op\": \"add\", \"path\": \"/imnothere/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", - header); + ENDPOINT + "/roles", + "[{ \"op\": \"add\", \"path\": \"/imnothere/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH read only resource, must be forbidden rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles", - "[{ \"op\": \"add\", \"path\": \"/opendistro_security_transport_client/a\", \"value\": [ \"foo\", \"bar\" ] }]", - header); + ENDPOINT + "/roles", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_transport_client/a\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH hidden resource, must be bad request rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles", - "[{ \"op\": \"add\", \"path\": \"/opendistro_security_internal/a\", \"value\": [ \"foo\", \"bar\" ] }]", - header); + ENDPOINT + "/roles", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_internal/a\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH delete read only resource, must be forbidden // SuperAdmin can delete read only user rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles", "[{ \"op\": \"remove\", \"path\": \"/opendistro_security_transport_client\" }]", - header); + ENDPOINT + "/roles", + "[{ \"op\": \"remove\", \"path\": \"/opendistro_security_transport_client\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // PATCH hidden resource, must be bad request, but allowed for superadmin rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles", - "[{ \"op\": \"remove\", \"path\": \"/opendistro_security_internal\"}]", - header); + ENDPOINT + "/roles", + "[{ \"op\": \"remove\", \"path\": \"/opendistro_security_internal\"}]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("\"message\":\"Resource updated.")); // PATCH value of hidden flag, must fail with validation error rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles", - "[{ \"op\": \"add\", \"path\": \"/newnewnew\", \"value\": { \"hidden\": true, \"index_permissions\" : " + - "[ {\"index_patterns\" : [ \"sf\" ],\"allowed_actions\" : [ \"OPENDISTRO_SECURITY_READ\" ]}] }}]", - header); + ENDPOINT + "/roles", + "[{ \"op\": \"add\", \"path\": \"/newnewnew\", \"value\": { \"hidden\": true, \"index_permissions\" : " + + "[ {\"index_patterns\" : [ \"sf\" ],\"allowed_actions\" : [ \"OPENDISTRO_SECURITY_READ\" ]}] }}]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*")); // PATCH rh.sendAdminCertificate = sendAdminCert; response = rh.executePatchRequest( - ENDPOINT + "/roles", - "[{ \"op\": \"add\", \"path\": \"/bulknew1\", \"value\": { \"index_permissions\" : " + - "[ {\"index_patterns\" : [ \"sf\" ],\"allowed_actions\" : [ \"OPENDISTRO_SECURITY_READ\" ]}] }}]", - header); + ENDPOINT + "/roles", + "[{ \"op\": \"add\", \"path\": \"/bulknew1\", \"value\": { \"index_permissions\" : " + + "[ {\"index_patterns\" : [ \"sf\" ],\"allowed_actions\" : [ \"OPENDISTRO_SECURITY_READ\" ]}] }}]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/roles/bulknew1", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); @@ -505,13 +642,19 @@ void verifyPatchForSuperAdmin(final Header[] header, final boolean sendAdminCert Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // put valid field masks - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_field_mask_valid", - FileHelper.loadFile("restapi/roles_field_masks_valid.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_field_mask_valid", + FileHelper.loadFile("restapi/roles_field_masks_valid.json"), + header + ); Assert.assertEquals(response.getBody(), HttpStatus.SC_CREATED, response.getStatusCode()); // put invalid field masks - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_field_mask_invalid", - FileHelper.loadFile("restapi/roles_field_masks_invalid.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_field_mask_invalid", + FileHelper.loadFile("restapi/roles_field_masks_invalid.json"), + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); } @@ -525,14 +668,14 @@ public void testRolesApiWithAllRestApiPermissions() throws Exception { setupStarfleetIndex(); // add user picard, role starfleet, maps to opendistro_security_role_starfleet - addUserWithPassword("picard", "picardpicardpicardpicard", new String[]{"starfleet", "captains"}, HttpStatus.SC_CREATED); + addUserWithPassword("picard", "picardpicardpicardpicard", new String[] { "starfleet", "captains" }, HttpStatus.SC_CREATED); checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); checkWriteAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); - verifyGetForSuperAdmin(new Header[]{restApiAdminHeader}); - verifyDeleteForSuperAdmin(new Header[]{restApiAdminHeader}, false); - verifyPutForSuperAdmin(new Header[]{restApiAdminHeader}, false); - verifyPatchForSuperAdmin(new Header[]{restApiAdminHeader}, false); + verifyGetForSuperAdmin(new Header[] { restApiAdminHeader }); + verifyDeleteForSuperAdmin(new Header[] { restApiAdminHeader }, false); + verifyPutForSuperAdmin(new Header[] { restApiAdminHeader }, false); + verifyPatchForSuperAdmin(new Header[] { restApiAdminHeader }, false); } @Test @@ -545,15 +688,14 @@ public void testRolesApiWithRestApiRolePermission() throws Exception { setupStarfleetIndex(); // add user picard, role starfleet, maps to opendistro_security_role_starfleet - addUserWithPassword("picard", "picardpicardpicardpicard", new String[]{"starfleet", "captains"}, HttpStatus.SC_CREATED); + addUserWithPassword("picard", "picardpicardpicardpicard", new String[] { "starfleet", "captains" }, HttpStatus.SC_CREATED); checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); checkWriteAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicard", "sf", "_doc", 0); - - verifyGetForSuperAdmin(new Header[]{restApiRolesHeader}); - verifyDeleteForSuperAdmin(new Header[]{restApiRolesHeader}, false); - verifyPutForSuperAdmin(new Header[]{restApiRolesHeader}, false); - verifyPatchForSuperAdmin(new Header[]{restApiRolesHeader}, false); + verifyGetForSuperAdmin(new Header[] { restApiRolesHeader }); + verifyDeleteForSuperAdmin(new Header[] { restApiRolesHeader }, false); + verifyPutForSuperAdmin(new Header[] { restApiRolesHeader }, false); + verifyPatchForSuperAdmin(new Header[] { restApiRolesHeader }, false); } @Test @@ -567,63 +709,45 @@ public void testCreateOrUpdateRestApiAdminRoleForbiddenForNonSuperAdmin() throws final String restAdminPermissionsPayload = createRestAdminPermissionsPayload("cluster/*"); HttpResponse response = rh.executePutRequest( - ENDPOINT + "/roles/new_rest_admin_role", restAdminPermissionsPayload, restApiAdminHeader); + ENDPOINT + "/roles/new_rest_admin_role", + restAdminPermissionsPayload, + restApiAdminHeader + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); - response = rh.executePutRequest( - ENDPOINT + "/roles/rest_admin_role_to_delete", restAdminPermissionsPayload, restApiAdminHeader); + response = rh.executePutRequest(ENDPOINT + "/roles/rest_admin_role_to_delete", restAdminPermissionsPayload, restApiAdminHeader); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); // attempt to create a new rest admin role by admin - response = rh.executePutRequest( - ENDPOINT + "/roles/some_rest_admin_role", - restAdminPermissionsPayload, - adminHeader); + response = rh.executePutRequest(ENDPOINT + "/roles/some_rest_admin_role", restAdminPermissionsPayload, adminHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // attempt to update exiting admin role - response = rh.executePutRequest( - ENDPOINT + "/roles/new_rest_admin_role", - restAdminPermissionsPayload, - adminHeader); + response = rh.executePutRequest(ENDPOINT + "/roles/new_rest_admin_role", restAdminPermissionsPayload, adminHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // attempt to patch exiting admin role response = rh.executePatchRequest( - ENDPOINT + "/roles/new_rest_admin_role", - createPatchRestAdminPermissionsPayload("replace"), - adminHeader); + ENDPOINT + "/roles/new_rest_admin_role", + createPatchRestAdminPermissionsPayload("replace"), + adminHeader + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // attempt to update exiting admin role - response = rh.executePutRequest( - ENDPOINT + "/roles/new_rest_admin_role", - restAdminPermissionsPayload, - restApiHeader); + response = rh.executePutRequest(ENDPOINT + "/roles/new_rest_admin_role", restAdminPermissionsPayload, restApiHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // attempt to create a new rest admin role by admin - response = rh.executePutRequest( - ENDPOINT + "/roles/some_rest_admin_role", - restAdminPermissionsPayload, - restApiHeader); + response = rh.executePutRequest(ENDPOINT + "/roles/some_rest_admin_role", restAdminPermissionsPayload, restApiHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // attempt to patch exiting admin role and crate a new one - response = rh.executePatchRequest( - ENDPOINT + "/roles", - createPatchRestAdminPermissionsPayload("replace"), - restApiHeader); + response = rh.executePatchRequest(ENDPOINT + "/roles", createPatchRestAdminPermissionsPayload("replace"), restApiHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - response = rh.executePatchRequest( - ENDPOINT + "/roles", - createPatchRestAdminPermissionsPayload("add"), - restApiHeader); + response = rh.executePatchRequest(ENDPOINT + "/roles", createPatchRestAdminPermissionsPayload("add"), restApiHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - response = rh.executePatchRequest( - ENDPOINT + "/roles", - createPatchRestAdminPermissionsPayload("remove"), - restApiHeader); + response = rh.executePatchRequest(ENDPOINT + "/roles", createPatchRestAdminPermissionsPayload("remove"), restApiHeader); System.out.println("RESPONSE: " + response.getBody()); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); } @@ -640,51 +764,42 @@ public void testDeleteRestApiAdminRoleForbiddenForNonSuperAdmin() throws Excepti final String allRestAdminPermissionsPayload = createRestAdminPermissionsPayload("cluster/*"); HttpResponse response = rh.executePutRequest( - ENDPOINT + "/roles/new_rest_admin_role", allRestAdminPermissionsPayload, restApiAdminHeader); + ENDPOINT + "/roles/new_rest_admin_role", + allRestAdminPermissionsPayload, + restApiAdminHeader + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); // attempt to update exiting admin role - response = rh.executeDeleteRequest( - ENDPOINT + "/roles/new_rest_admin_role", - adminHeader); + response = rh.executeDeleteRequest(ENDPOINT + "/roles/new_rest_admin_role", adminHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - //true to change - response = rh.executeDeleteRequest( - ENDPOINT + "/roles/new_rest_admin_role", - allRestAdminPermissionsPayload, - restApiHeader); + // true to change + response = rh.executeDeleteRequest(ENDPOINT + "/roles/new_rest_admin_role", allRestAdminPermissionsPayload, restApiHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); } - private String createPatchRestAdminPermissionsPayload(final String op) throws JsonProcessingException { final ArrayNode rootNode = (ArrayNode) DefaultObjectMapper.objectMapper.createArrayNode(); final ObjectNode opAddObjectNode = DefaultObjectMapper.objectMapper.createObjectNode(); final ObjectNode clusterPermissionsNode = DefaultObjectMapper.objectMapper.createObjectNode(); clusterPermissionsNode.set("cluster_permissions", clusterPermissionsForRestAdmin("cluster/*")); if ("add".equals(op)) { - opAddObjectNode - .put("op", "add") - .put("path", "/some_rest_admin_role") - .set("value", clusterPermissionsNode); + opAddObjectNode.put("op", "add").put("path", "/some_rest_admin_role").set("value", clusterPermissionsNode); rootNode.add(opAddObjectNode); } if ("remove".equals(op)) { final ObjectNode opRemoveObjectNode = DefaultObjectMapper.objectMapper.createObjectNode(); - opRemoveObjectNode - .put("op", "remove") - .put("path", "/rest_admin_role_to_delete"); + opRemoveObjectNode.put("op", "remove").put("path", "/rest_admin_role_to_delete"); rootNode.add(opRemoveObjectNode); } if ("replace".equals(op)) { final ObjectNode replaceRemoveObjectNode = DefaultObjectMapper.objectMapper.createObjectNode(); - replaceRemoveObjectNode - .put("op", "replace") - .put("path", "/new_rest_admin_role/cluster_permissions") - .set("value", clusterPermissionsForRestAdmin("*")); + replaceRemoveObjectNode.put("op", "replace") + .put("path", "/new_rest_admin_role/cluster_permissions") + .set("value", clusterPermissionsForRestAdmin("*")); rootNode.add(replaceRemoveObjectNode); } @@ -709,21 +824,27 @@ void checkNonSuperAdminRoles(final Header[] header) throws Exception { Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Put read only roles - response = rh.executePutRequest(ENDPOINT + "/roles/opendistro_security_transport_client", - FileHelper.loadFile("restapi/roles_captains.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/roles/opendistro_security_transport_client", + FileHelper.loadFile("restapi/roles_captains.json"), + header + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch single read only roles response = rh.executePatchRequest( - ENDPOINT + "/roles/opendistro_security_transport_client", - "[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"foo\" }]", - header); + ENDPOINT + "/roles/opendistro_security_transport_client", + "[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch multiple read only roles - response = rh.executePatchRequest(ENDPOINT + "/roles/", - "[{ \"op\": \"add\", \"path\": \"/opendistro_security_transport_client/description\", \"value\": \"foo\" }]", - header); + response = rh.executePatchRequest( + ENDPOINT + "/roles/", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_transport_client/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // get hidden role @@ -740,14 +861,19 @@ void checkNonSuperAdminRoles(final Header[] header) throws Exception { Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Patch single hidden roles - response = rh.executePatchRequest(ENDPOINT + "/roles/opendistro_security_internal", - "[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"foo\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/roles/opendistro_security_internal", + "[{ \"op\": \"replace\", \"path\": \"/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Patch multiple hidden roles - response = rh.executePatchRequest(ENDPOINT + "/roles/", - "[{ \"op\": \"add\", \"path\": \"/opendistro_security_internal/description\", \"value\": \"foo\" }]", - header); + response = rh.executePatchRequest( + ENDPOINT + "/roles/", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_internal/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/RolesMappingApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/RolesMappingApiTest.java index 3bc647bf12..42fb111281 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/RolesMappingApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/RolesMappingApiTest.java @@ -32,12 +32,13 @@ import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_ADMIN_ENABLED; public class RolesMappingApiTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public RolesMappingApiTest(){ + public RolesMappingApiTest() { ENDPOINT = getEndpointPrefix() + "/api"; } @@ -56,7 +57,7 @@ public void testRolesMappingApi() throws Exception { addUserWithPassword("picard", "picardpicardpicard", new String[] { "captains" }, HttpStatus.SC_CREATED); checkWriteAccess(HttpStatus.SC_CREATED, "picard", "picardpicardpicard", "sf", "_doc", 1); // TODO: only one doctype allowed for ES6 - //checkWriteAccess(HttpStatus.SC_CREATED, "picard", "picard", "sf", "_doc", 1); + // checkWriteAccess(HttpStatus.SC_CREATED, "picard", "picard", "sf", "_doc", 1); rh.sendAdminCertificate = true; verifyGetForSuperAdmin(new Header[0]); rh.sendAdminCertificate = true; @@ -65,35 +66,35 @@ public void testRolesMappingApi() throws Exception { verifyPutForSuperAdmin(new Header[0]); verifyPatchForSuperAdmin(new Header[0]); // mapping with several backend roles, one of the is captain - deleteAndPutNewMapping(new Header[0],"rolesmapping_backendroles_captains_list.json", true); + deleteAndPutNewMapping(new Header[0], "rolesmapping_backendroles_captains_list.json", true); checkAllSfAllowed(); // mapping with one backend role, captain - deleteAndPutNewMapping(new Header[0],"rolesmapping_backendroles_captains_single.json", true); + deleteAndPutNewMapping(new Header[0], "rolesmapping_backendroles_captains_single.json", true); checkAllSfAllowed(); // mapping with several users, one is picard - deleteAndPutNewMapping(new Header[0],"rolesmapping_users_picard_list.json", true); + deleteAndPutNewMapping(new Header[0], "rolesmapping_users_picard_list.json", true); checkAllSfAllowed(); // just user picard - deleteAndPutNewMapping(new Header[0],"rolesmapping_users_picard_single.json", true); + deleteAndPutNewMapping(new Header[0], "rolesmapping_users_picard_single.json", true); checkAllSfAllowed(); // hosts - deleteAndPutNewMapping(new Header[0],"rolesmapping_hosts_list.json", true); + deleteAndPutNewMapping(new Header[0], "rolesmapping_hosts_list.json", true); checkAllSfAllowed(); // hosts - deleteAndPutNewMapping(new Header[0],"rolesmapping_hosts_single.json", true); + deleteAndPutNewMapping(new Header[0], "rolesmapping_hosts_single.json", true); checkAllSfAllowed(); // full settings, access - deleteAndPutNewMapping(new Header[0],"rolesmapping_all_access.json", true); + deleteAndPutNewMapping(new Header[0], "rolesmapping_all_access.json", true); checkAllSfAllowed(); // full settings, no access - deleteAndPutNewMapping(new Header[0],"rolesmapping_all_noaccess.json", true); + deleteAndPutNewMapping(new Header[0], "rolesmapping_all_noaccess.json", true); checkAllSfForbidden(); } @@ -110,42 +111,42 @@ public void testRolesMappingApiWithFullPermissions() throws Exception { addUserWithPassword("picard", "picardpicardpicard", new String[] { "captains" }, HttpStatus.SC_CREATED); checkWriteAccess(HttpStatus.SC_CREATED, "picard", "picardpicardpicard", "sf", "_doc", 1); // TODO: only one doctype allowed for ES6 - //checkWriteAccess(HttpStatus.SC_CREATED, "picard", "picard", "sf", "_doc", 1); + // checkWriteAccess(HttpStatus.SC_CREATED, "picard", "picard", "sf", "_doc", 1); - verifyGetForSuperAdmin(new Header[]{restApiAdminHeader}); - verifyDeleteForSuperAdmin(new Header[]{restApiAdminHeader}, false); - verifyPutForSuperAdmin(new Header[]{restApiAdminHeader}); - verifyPatchForSuperAdmin(new Header[]{restApiAdminHeader}); + verifyGetForSuperAdmin(new Header[] { restApiAdminHeader }); + verifyDeleteForSuperAdmin(new Header[] { restApiAdminHeader }, false); + verifyPutForSuperAdmin(new Header[] { restApiAdminHeader }); + verifyPatchForSuperAdmin(new Header[] { restApiAdminHeader }); // mapping with several backend roles, one of the is captain - deleteAndPutNewMapping(new Header[]{restApiAdminHeader}, "rolesmapping_backendroles_captains_list.json", false); + deleteAndPutNewMapping(new Header[] { restApiAdminHeader }, "rolesmapping_backendroles_captains_list.json", false); checkAllSfAllowed(); // mapping with one backend role, captain - deleteAndPutNewMapping(new Header[]{restApiAdminHeader},"rolesmapping_backendroles_captains_single.json", true); + deleteAndPutNewMapping(new Header[] { restApiAdminHeader }, "rolesmapping_backendroles_captains_single.json", true); checkAllSfAllowed(); // mapping with several users, one is picard - deleteAndPutNewMapping(new Header[]{restApiAdminHeader},"rolesmapping_users_picard_list.json", true); + deleteAndPutNewMapping(new Header[] { restApiAdminHeader }, "rolesmapping_users_picard_list.json", true); checkAllSfAllowed(); // just user picard - deleteAndPutNewMapping(new Header[]{restApiAdminHeader},"rolesmapping_users_picard_single.json", true); + deleteAndPutNewMapping(new Header[] { restApiAdminHeader }, "rolesmapping_users_picard_single.json", true); checkAllSfAllowed(); // hosts - deleteAndPutNewMapping(new Header[]{restApiAdminHeader},"rolesmapping_hosts_list.json", true); + deleteAndPutNewMapping(new Header[] { restApiAdminHeader }, "rolesmapping_hosts_list.json", true); checkAllSfAllowed(); // hosts - deleteAndPutNewMapping(new Header[]{restApiAdminHeader},"rolesmapping_hosts_single.json", true); + deleteAndPutNewMapping(new Header[] { restApiAdminHeader }, "rolesmapping_hosts_single.json", true); checkAllSfAllowed(); // full settings, access - deleteAndPutNewMapping(new Header[]{restApiAdminHeader},"rolesmapping_all_access.json", true); + deleteAndPutNewMapping(new Header[] { restApiAdminHeader }, "rolesmapping_all_access.json", true); checkAllSfAllowed(); // full settings, no access - deleteAndPutNewMapping(new Header[]{restApiAdminHeader},"rolesmapping_all_noaccess.json", true); + deleteAndPutNewMapping(new Header[] { restApiAdminHeader }, "rolesmapping_all_noaccess.json", true); checkAllSfForbidden(); } @@ -166,7 +167,6 @@ void verifyGetForSuperAdmin(final Header[] header) throws Exception { // Superadmin should be able to see reserved rolesmapping Assert.assertTrue(response.getBody().contains("opendistro_security_reserved")); - // -- GET // GET opendistro_security_role_starfleet, exists response = rh.executeGetRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet", header); @@ -242,26 +242,34 @@ void verifyPutForSuperAdmin(final Header[] header) throws Exception { Assert.assertEquals(AbstractConfigurationValidator.ErrorType.PAYLOAD_MANDATORY.getMessage(), settings.get("reason")); // put new configuration with invalid payload, must fail - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/rolesmapping_not_parseable.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/rolesmapping_not_parseable.json"), + header + ); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.BODY_NOT_PARSEABLE.getMessage(), settings.get("reason")); // put new configuration with invalid keys, must fail - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/rolesmapping_invalid_keys.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/rolesmapping_invalid_keys.json"), + header + ); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.INVALID_CONFIGURATION.getMessage(), settings.get("reason")); Assert.assertTrue(settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY + ".keys").contains("theusers")); - Assert.assertTrue( - settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY + ".keys").contains("thebackendroles")); + Assert.assertTrue(settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY + ".keys").contains("thebackendroles")); Assert.assertTrue(settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY + ".keys").contains("thehosts")); // wrong datatypes - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/rolesmapping_backendroles_captains_single_wrong_datatype.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/rolesmapping_backendroles_captains_single_wrong_datatype.json"), + header + ); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.WRONG_DATATYPE.getMessage(), settings.get("reason")); @@ -269,8 +277,11 @@ void verifyPutForSuperAdmin(final Header[] header) throws Exception { Assert.assertTrue(settings.get("hosts") == null); Assert.assertTrue(settings.get("users") == null); - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/rolesmapping_hosts_single_wrong_datatype.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/rolesmapping_hosts_single_wrong_datatype.json"), + header + ); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.WRONG_DATATYPE.getMessage(), settings.get("reason")); @@ -278,8 +289,11 @@ void verifyPutForSuperAdmin(final Header[] header) throws Exception { Assert.assertTrue(settings.get("backend_roles") == null); Assert.assertTrue(settings.get("users") == null); - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/rolesmapping_users_picard_single_wrong_datatype.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/rolesmapping_users_picard_single_wrong_datatype.json"), + header + ); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.WRONG_DATATYPE.getMessage(), settings.get("reason")); @@ -289,46 +303,70 @@ void verifyPutForSuperAdmin(final Header[] header) throws Exception { // Read only role mapping // SuperAdmin can add read only roles - mappings - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", - FileHelper.loadFile("restapi/rolesmapping_all_access.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", + FileHelper.loadFile("restapi/rolesmapping_all_access.json"), + header + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); // hidden role, allowed for super admin - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_internal", - FileHelper.loadFile("restapi/rolesmapping_all_access.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_internal", + FileHelper.loadFile("restapi/rolesmapping_all_access.json"), + header + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/rolesmapping_all_access.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/rolesmapping_all_access.json"), + header + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); } void verifyPatchForSuperAdmin(final Header[] header) throws Exception { // PATCH on non-existing resource - HttpResponse response = rh.executePatchRequest(ENDPOINT + "/rolesmapping/imnothere", "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", header); + HttpResponse response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping/imnothere", + "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // PATCH read only resource, must be forbidden // SuperAdmin can patch read-only resource - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", - "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\"] }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", + "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\"] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH hidden resource, must be not found, can be found by super admin - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping/opendistro_security_internal", - "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ " + - "\"foo\", \"bar\" ] }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping/opendistro_security_internal", + "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ " + "\"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH value of hidden flag, must fail with validation error - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_vulcans", - "[{ \"op\": \"add\", \"path\": \"/hidden\", \"value\": true }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_vulcans", + "[{ \"op\": \"add\", \"path\": \"/hidden\", \"value\": true }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*")); // PATCH - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_vulcans", - "[{ \"op\": \"add\", \"path\": \"/backend_roles/-\", \"value\": \"spring\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_vulcans", + "[{ \"op\": \"add\", \"path\": \"/backend_roles/-\", \"value\": \"spring\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_vulcans", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); @@ -339,32 +377,48 @@ void verifyPatchForSuperAdmin(final Header[] header) throws Exception { // -- PATCH on whole config resource // PATCH on non-existing resource - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping", - "[{ \"op\": \"add\", \"path\": \"/imnothere/a\", \"value\": [ \"foo\", \"bar\" ] }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping", + "[{ \"op\": \"add\", \"path\": \"/imnothere/a\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH read only resource, must be forbidden // SuperAdmin can patch read only resource rh.sendAdminCertificate = true; - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping", - "[{ \"op\": \"add\", \"path\": \"/opendistro_security_role_starfleet_library/description\", \"value\": \"foo\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_role_starfleet_library/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // PATCH hidden resource, must be bad request rh.sendAdminCertificate = true; - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping", "[{ \"op\": \"add\", \"path\": \"/opendistro_security_internal/a\", \"value\": [ \"foo\", \"bar\" ] }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_internal/a\", \"value\": [ \"foo\", \"bar\" ] }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH value of hidden flag, must fail with validation error rh.sendAdminCertificate = true; - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping", - "[{ \"op\": \"add\", \"path\": \"/opendistro_security_role_vulcans/hidden\", \"value\": true }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_role_vulcans/hidden\", \"value\": true }]", + header + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*")); // PATCH - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping", - "[{ \"op\": \"add\", \"path\": \"/bulknew1\", \"value\": { \"backend_roles\":[\"vulcanadmin\"]} }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping", + "[{ \"op\": \"add\", \"path\": \"/bulknew1\", \"value\": { \"backend_roles\":[\"vulcanadmin\"]} }]", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/rolesmapping/bulknew1", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); @@ -394,11 +448,13 @@ private void checkAllSfForbidden() throws Exception { private HttpResponse deleteAndPutNewMapping(final Header[] header, final String fileName, final boolean useAdminCert) throws Exception { rh.sendAdminCertificate = useAdminCert; - HttpResponse response = rh.executeDeleteRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - header); + HttpResponse response = rh.executeDeleteRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - FileHelper.loadFile("restapi/"+fileName), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", + FileHelper.loadFile("restapi/" + fileName), + header + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); rh.sendAdminCertificate = false; return response; @@ -421,27 +477,38 @@ public void testRolesMappingApiForNonSuperAdminRestApiUser() throws Exception { setupWithRestRoles(); rh.sendAdminCertificate = false; final Header restApiHeader = encodeBasicHeader("test", "test"); - verifyNonSuperAdminUser(new Header[] {restApiHeader}); + verifyNonSuperAdminUser(new Header[] { restApiHeader }); } void verifyNonSuperAdminUser(final Header[] header) throws Exception { HttpResponse response; // Delete read only roles mapping - response = rh.executeDeleteRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library" , header); + response = rh.executeDeleteRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", header); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Put read only roles mapping - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", - FileHelper.loadFile("restapi/rolesmapping_all_access.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", + FileHelper.loadFile("restapi/rolesmapping_all_access.json"), + header + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch single read only roles mapping - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_library", + "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch multiple read only roles mapping - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping", "[{ \"op\": \"add\", \"path\": \"/opendistro_security_role_starfleet_library/description\", \"value\": \"foo\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_role_starfleet_library/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // GET, rolesmapping is hidden, allowed for super admin @@ -449,21 +516,33 @@ void verifyNonSuperAdminUser(final Header[] header) throws Exception { Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Delete hidden roles mapping - response = rh.executeDeleteRequest(ENDPOINT + "/rolesmapping/opendistro_security_internal" , header); + response = rh.executeDeleteRequest(ENDPOINT + "/rolesmapping/opendistro_security_internal", header); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Put hidden roles mapping - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_internal", - FileHelper.loadFile("restapi/rolesmapping_all_access.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_internal", + FileHelper.loadFile("restapi/rolesmapping_all_access.json"), + header + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Patch hidden roles mapping - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping/opendistro_security_internal", "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", header); + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping/opendistro_security_internal", + "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", + header + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Patch multiple hidden roles mapping - response = rh.executePatchRequest(ENDPOINT + "/rolesmapping", "[{ \"op\": \"add\", \"path\": \"/opendistro_security_internal/description\", \"value\": \"foo\" }]", header); - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); } + response = rh.executePatchRequest( + ENDPOINT + "/rolesmapping", + "[{ \"op\": \"add\", \"path\": \"/opendistro_security_internal/description\", \"value\": \"foo\" }]", + header + ); + Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); + } @Test public void testChangeRestApiAdminRoleMappingForbiddenForNonSuperAdmin() throws Exception { @@ -475,16 +554,22 @@ public void testChangeRestApiAdminRoleMappingForbiddenForNonSuperAdmin() throws final Header restApiHeader = encodeBasicHeader("test", "test"); HttpResponse response = rh.executePutRequest( - ENDPOINT + "/roles/new_rest_api_role", - createRestAdminPermissionsPayload(), restApiAdminHeader); + ENDPOINT + "/roles/new_rest_api_role", + createRestAdminPermissionsPayload(), + restApiAdminHeader + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); response = rh.executePutRequest( - ENDPOINT + "/roles/new_rest_api_role_without_mapping", - createRestAdminPermissionsPayload(), restApiAdminHeader); + ENDPOINT + "/roles/new_rest_api_role_without_mapping", + createRestAdminPermissionsPayload(), + restApiAdminHeader + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); response = rh.executePutRequest( - ENDPOINT + "/rolesmapping/new_rest_api_role", - createUsersPayload("a", "b", "c"), restApiAdminHeader); + ENDPOINT + "/rolesmapping/new_rest_api_role", + createUsersPayload("a", "b", "c"), + restApiAdminHeader + ); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); verifyRestApiPutAndDeleteForNonRestApiAdmin(adminHeader); @@ -497,11 +582,13 @@ public void testChangeRestApiAdminRoleMappingForbiddenForNonSuperAdmin() throws private void verifyRestApiPutAndDeleteForNonRestApiAdmin(final Header header) throws Exception { HttpResponse response = rh.executePutRequest( - ENDPOINT + "/rolesmapping/new_rest_api_role", createUsersPayload("a", "b", "c"), header); + ENDPOINT + "/rolesmapping/new_rest_api_role", + createUsersPayload("a", "b", "c"), + header + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - response = rh.executeDeleteRequest( - ENDPOINT + "/rolesmapping/new_rest_api_role", "", header); + response = rh.executeDeleteRequest(ENDPOINT + "/rolesmapping/new_rest_api_role", "", header); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); } @@ -552,28 +639,29 @@ private String createPathPayload(final String op) throws JsonProcessingException } @Test - public void checkNullElementsInArray() throws Exception{ + public void checkNullElementsInArray() throws Exception { setup(); rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; String body = FileHelper.loadFile("restapi/rolesmapping_null_array_element_users.json"); - HttpResponse response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - body, new Header[0]); + HttpResponse response = rh.executePutRequest( + ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", + body, + new Header[0] + ); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.NULL_ARRAY_ELEMENT.getMessage(), settings.get("reason")); body = FileHelper.loadFile("restapi/rolesmapping_null_array_element_backend_roles.json"); - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - body, new Header[0]); + response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", body, new Header[0]); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.NULL_ARRAY_ELEMENT.getMessage(), settings.get("reason")); body = FileHelper.loadFile("restapi/rolesmapping_null_array_element_hosts.json"); - response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", - body, new Header[0]); + response = rh.executePutRequest(ENDPOINT + "/rolesmapping/opendistro_security_role_starfleet_captains", body, new Header[0]); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.NULL_ARRAY_ELEMENT.getMessage(), settings.get("reason")); diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityApiAccessTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityApiAccessTest.java index 83630c036a..81fad7d4ff 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityApiAccessTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityApiAccessTest.java @@ -18,12 +18,13 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class SecurityApiAccessTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public SecurityApiAccessTest(){ + public SecurityApiAccessTest() { ENDPOINT = getEndpointPrefix() + "/api/internalusers"; } @@ -33,22 +34,14 @@ public void testRestApi() throws Exception { setup(); // test with no cert, must fail - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, - rh.executeGetRequest(ENDPOINT).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executeGetRequest(ENDPOINT, - encodeBasicHeader("admin", "admin")) - .getStatusCode()); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest(ENDPOINT).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest(ENDPOINT, encodeBasicHeader("admin", "admin")).getStatusCode()); // test with non-admin cert, must fail rh.keystore = "restapi/node-0-keystore.jks"; rh.sendAdminCertificate = true; - Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, - rh.executeGetRequest(ENDPOINT).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, - rh.executeGetRequest(ENDPOINT, - encodeBasicHeader("admin", "admin")) - .getStatusCode()); + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, rh.executeGetRequest(ENDPOINT).getStatusCode()); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, rh.executeGetRequest(ENDPOINT, encodeBasicHeader("admin", "admin")).getStatusCode()); } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityConfigApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityConfigApiTest.java index d717dcbf6c..8fc6ae1dd8 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityConfigApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityConfigApiTest.java @@ -25,12 +25,13 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class SecurityConfigApiTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public SecurityConfigApiTest(){ + public SecurityConfigApiTest() { ENDPOINT = getEndpointPrefix() + "/api"; } @@ -57,11 +58,13 @@ public void testSecurityConfigApiRead() throws Exception { response = rh.executeDeleteRequest(ENDPOINT + "/securityconfig", new Header[0]); Assert.assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, response.getStatusCode()); } - + @Test public void testSecurityConfigApiWrite() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build(); + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) + .build(); setup(settings); rh.keystore = "restapi/kirk-keystore.jks"; @@ -70,13 +73,25 @@ public void testSecurityConfigApiWrite() throws Exception { HttpResponse response = rh.executeGetRequest(ENDPOINT + "/securityconfig", new Header[0]); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executePutRequest(ENDPOINT + "/securityconfig/xxx", FileHelper.loadFile("restapi/securityconfig.json"), new Header[0]); + response = rh.executePutRequest( + ENDPOINT + "/securityconfig/xxx", + FileHelper.loadFile("restapi/securityconfig.json"), + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - response = rh.executePutRequest(ENDPOINT + "/securityconfig/config", FileHelper.loadFile("restapi/securityconfig.json"), new Header[0]); + response = rh.executePutRequest( + ENDPOINT + "/securityconfig/config", + FileHelper.loadFile("restapi/securityconfig.json"), + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executePutRequest(ENDPOINT + "/securityconfig/config", FileHelper.loadFile("restapi/invalid_config.json"), new Header[0]); + response = rh.executePutRequest( + ENDPOINT + "/securityconfig/config", + FileHelper.loadFile("restapi/invalid_config.json"), + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatusCode()); Assert.assertTrue(response.getContentType(), response.isJsonContentType()); Assert.assertTrue(response.getBody().contains("Unrecognized field")); @@ -87,7 +102,11 @@ public void testSecurityConfigApiWrite() throws Exception { response = rh.executePostRequest(ENDPOINT + "/securityconfig", "{\"xxx\": 1}", new Header[0]); Assert.assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, response.getStatusCode()); - response = rh.executePatchRequest(ENDPOINT + "/securityconfig", "[{\"op\": \"replace\",\"path\": \"/config/dynamic/hosts_resolver_mode\",\"value\": \"other\"}]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/securityconfig", + "[{\"op\": \"replace\",\"path\": \"/config/dynamic/hosts_resolver_mode\",\"value\": \"other\"}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeDeleteRequest(ENDPOINT + "/securityconfig", new Header[0]); @@ -98,30 +117,35 @@ public void testSecurityConfigApiWrite() throws Exception { @Test public void testSecurityConfigForHTTPPatch() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build(); + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) + .build(); setup(settings); rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - //non-default config + // non-default config String updatedConfig = FileHelper.loadFile("restapi/securityconfig_nondefault.json"); - //update config + // update config HttpResponse response = rh.executePutRequest(ENDPOINT + "/securityconfig/config", updatedConfig, new Header[0]); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - //make patch request - response = rh.executePatchRequest(ENDPOINT + "/securityconfig", "[{\"op\": \"add\",\"path\": \"/config/dynamic/do_not_fail_on_forbidden\",\"value\": \"false\"}]", new Header[0]); + // make patch request + response = rh.executePatchRequest( + ENDPOINT + "/securityconfig", + "[{\"op\": \"add\",\"path\": \"/config/dynamic/do_not_fail_on_forbidden\",\"value\": \"false\"}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - //get config + // get config response = rh.executeGetRequest(ENDPOINT + "/securityconfig", new Header[0]); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // verify configs are same Assert.assertEquals(DefaultObjectMapper.readTree(updatedConfig), DefaultObjectMapper.readTree(response.getBody()).get("config")); - } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityHealthActionTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityHealthActionTest.java index 13dc4ee885..d7a6edfea9 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityHealthActionTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityHealthActionTest.java @@ -22,18 +22,21 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class SecurityHealthActionTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public SecurityHealthActionTest(){ + public SecurityHealthActionTest() { ENDPOINT = getEndpointPrefix(); } @Test public void testSecurityHealthAPI() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build(); + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) + .build(); setup(settings); rh.keystore = "restapi/kirk-keystore.jks"; diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityInfoActionTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityInfoActionTest.java index 506ea3bdd2..db27be85ee 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/SecurityInfoActionTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/SecurityInfoActionTest.java @@ -22,18 +22,21 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class SecurityInfoActionTest extends AbstractRestApiUnitTest { - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public SecurityInfoActionTest(){ + public SecurityInfoActionTest() { ENDPOINT = getEndpointPrefix() + "/authinfo"; } @Test public void testSecurityInfoAPI() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build(); + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) + .build(); setup(settings); rh.keystore = "restapi/kirk-keystore.jks"; diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/SslCertsApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/SslCertsApiTest.java index 425c2dca50..8797d196f5 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/SslCertsApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/SslCertsApiTest.java @@ -36,32 +36,38 @@ public class SslCertsApiTest extends AbstractRestApiUnitTest { static final String TRANSPORT_CERTS = "transport"; - private final static List> EXPECTED_CERTIFICATES = - ImmutableList.of( - ImmutableMap.of( - "issuer_dn", "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", - "subject_dn", "CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE", - "san", "[[2, node-0.example.com], [2, localhost], [7, 127.0.0.1], [8, 1.2.3.4.5.5]]", - "not_before", "2018-05-05T14:37:09Z", - "not_after", "2028-05-02T14:37:09Z" - ), - ImmutableMap.of( - "issuer_dn", "CN=Example Com Inc. Root CA,OU=Example Com Inc. Root CA,O=Example Com Inc.,DC=example,DC=com", - "subject_dn", "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", - "san", "", - "not_before", "2018-05-05T14:37:08Z", - "not_after", "2028-05-04T14:37:08Z" - ) - ); + private final static List> EXPECTED_CERTIFICATES = ImmutableList.of( + ImmutableMap.of( + "issuer_dn", + "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", + "subject_dn", + "CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE", + "san", + "[[2, node-0.example.com], [2, localhost], [7, 127.0.0.1], [8, 1.2.3.4.5.5]]", + "not_before", + "2018-05-05T14:37:09Z", + "not_after", + "2028-05-02T14:37:09Z" + ), + ImmutableMap.of( + "issuer_dn", + "CN=Example Com Inc. Root CA,OU=Example Com Inc. Root CA,O=Example Com Inc.,DC=example,DC=com", + "subject_dn", + "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", + "san", + "", + "not_before", + "2018-05-05T14:37:08Z", + "not_after", + "2028-05-04T14:37:08Z" + ) + ); private final static String EXPECTED_CERTIFICATES_BY_TYPE; static { try { EXPECTED_CERTIFICATES_BY_TYPE = DefaultObjectMapper.objectMapper.writeValueAsString( - ImmutableMap.of( - "http_certificates_list", EXPECTED_CERTIFICATES, - "transport_certificates_list", EXPECTED_CERTIFICATES - ) + ImmutableMap.of("http_certificates_list", EXPECTED_CERTIFICATES, "transport_certificates_list", EXPECTED_CERTIFICATES) ); } catch (JsonProcessingException e) { throw new RuntimeException(e); @@ -71,11 +77,13 @@ public class SslCertsApiTest extends AbstractRestApiUnitTest { private final Header restApiAdminHeader = encodeBasicHeader("rest_api_admin_user", "rest_api_admin_user"); private final Header restApiCertsInfoAdminHeader = encodeBasicHeader("rest_api_admin_ssl_info", "rest_api_admin_ssl_info"); - private final Header restApiReloadCertsAdminHeader = encodeBasicHeader("rest_api_admin_ssl_reloadcerts", "rest_api_admin_ssl_reloadcerts"); + private final Header restApiReloadCertsAdminHeader = encodeBasicHeader( + "rest_api_admin_ssl_reloadcerts", + "rest_api_admin_ssl_reloadcerts" + ); private final Header restApiHeader = encodeBasicHeader("test", "test"); - public String certsInfoEndpoint() { return PLUGINS_PREFIX + "/api/ssl/certs"; } @@ -165,9 +173,7 @@ private void sendAdminCert() { } Settings reloadEnabled() { - return Settings.builder() - .put(ConfigConstants.SECURITY_SSL_CERT_RELOAD_ENABLED, true) - .build(); + return Settings.builder().put(ConfigConstants.SECURITY_SSL_CERT_RELOAD_ENABLED, true).build(); } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/TenantInfoActionTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/TenantInfoActionTest.java index ab7e807153..2c6a45faf7 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/TenantInfoActionTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/TenantInfoActionTest.java @@ -23,23 +23,26 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.PLUGINS_PREFIX; public class TenantInfoActionTest extends AbstractRestApiUnitTest { - private String payload = "{\"hosts\":[],\"users\":[\"sarek\"]," + - "\"backend_roles\":[\"starfleet*\",\"ambassador\"],\"and_backend_roles\":[],\"description\":\"Migrated " + - "from v6\"}"; + private String payload = "{\"hosts\":[],\"users\":[\"sarek\"]," + + "\"backend_roles\":[\"starfleet*\",\"ambassador\"],\"and_backend_roles\":[],\"description\":\"Migrated " + + "from v6\"}"; private final String BASE_ENDPOINT; - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public TenantInfoActionTest(){ + public TenantInfoActionTest() { BASE_ENDPOINT = getEndpointPrefix(); ENDPOINT = getEndpointPrefix() + "/tenantinfo"; } @Test public void testTenantInfoAPIAccess() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build(); + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) + .build(); setup(settings); rh.keystore = "restapi/kirk-keystore.jks"; @@ -58,16 +61,21 @@ public void testTenantInfoAPIAccess() throws Exception { @Test public void testTenantInfoAPIUpdate() throws Exception { - Settings settings = Settings.builder().put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true).build(); + Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_UNSUPPORTED_RESTAPI_ALLOW_SECURITYCONFIG_MODIFICATION, true) + .build(); setup(settings); - + rh.keystore = "restapi/kirk-keystore.jks"; rh.sendHTTPClientCredentials = true; rh.sendAdminCertificate = true; - //update security config - RestHelper.HttpResponse response = rh.executePatchRequest(BASE_ENDPOINT + "/api/securityconfig", "[{\"op\": \"add\",\"path\": \"/config/dynamic/kibana/opendistro_role\"," + - "\"value\": \"opendistro_security_internal\"}]", new Header[0]); + // update security config + RestHelper.HttpResponse response = rh.executePatchRequest( + BASE_ENDPOINT + "/api/securityconfig", + "[{\"op\": \"add\",\"path\": \"/config/dynamic/kibana/opendistro_role\"," + "\"value\": \"opendistro_security_internal\"}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executePutRequest(BASE_ENDPOINT + "/api/rolesmapping/opendistro_security_internal", payload, new Header[0]); diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/UserApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/UserApiTest.java index abcda9a69c..895f65bc81 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/UserApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/UserApiTest.java @@ -37,43 +37,42 @@ import static org.opensearch.security.dlic.rest.api.InternalUsersApiAction.RESTRICTED_FROM_USERNAME; import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_ADMIN_ENABLED; - public class UserApiTest extends AbstractRestApiUnitTest { private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - final int USER_SETTING_SIZE = 7 * 19; // Lines per account entry * number of accounts - private static final String ENABLED_SERVICE_ACCOUNT_BODY = "{" - + " \"attributes\": { \"service\": \"true\", " - + "\"enabled\": \"true\"}" - + " }\n"; + private static final String ENABLED_SERVICE_ACCOUNT_BODY = "{" + + " \"attributes\": { \"service\": \"true\", " + + "\"enabled\": \"true\"}" + + " }\n"; private static final String DISABLED_SERVICE_ACCOUNT_BODY = "{" - + " \"attributes\": { \"service\": \"true\", " - + "\"enabled\": \"false\"}" - + " }\n"; + + " \"attributes\": { \"service\": \"true\", " + + "\"enabled\": \"false\"}" + + " }\n"; private static final String ENABLED_NOT_SERVICE_ACCOUNT_BODY = "{" - + " \"attributes\": { \"service\": \"false\", " - + "\"enabled\": \"true\"}" - + " }\n"; + + " \"attributes\": { \"service\": \"false\", " + + "\"enabled\": \"true\"}" + + " }\n"; private static final String PASSWORD_SERVICE = "{ \"password\" : \"test\"," - + " \"attributes\": { \"service\": \"true\", " - + "\"enabled\": \"true\"}" - + " }\n"; + + " \"attributes\": { \"service\": \"true\", " + + "\"enabled\": \"true\"}" + + " }\n"; private static final String HASH_SERVICE = "{ \"owner\" : \"test_owner\"," - + " \"attributes\": { \"service\": \"true\", " - + "\"enabled\": \"true\"}" - + " }\n"; + + " \"attributes\": { \"service\": \"true\", " + + "\"enabled\": \"true\"}" + + " }\n"; private static final String PASSWORD_HASH_SERVICE = "{ \"password\" : \"test\", \"hash\" : \"123\"," - + " \"attributes\": { \"service\": \"true\", " - + "\"enabled\": \"true\"}" - + " }\n"; + + " \"attributes\": { \"service\": \"true\", " + + "\"enabled\": \"true\"}" + + " }\n"; - public UserApiTest(){ + public UserApiTest() { ENDPOINT = getEndpointPrefix() + "/api"; } @@ -86,17 +85,16 @@ public void testSecurityRoles() throws Exception { rh.sendAdminCertificate = true; // initial configuration, 6 users - HttpResponse response = rh - .executeGetRequest(ENDPOINT + "/" + CType.INTERNALUSERS.toLCString()); + HttpResponse response = rh.executeGetRequest(ENDPOINT + "/" + CType.INTERNALUSERS.toLCString()); Assert.assertEquals(response.getBody(), HttpStatus.SC_OK, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(133, settings.size()); response = rh.executePatchRequest( - ENDPOINT + "/internalusers", - "[{ \"op\": \"add\", \"path\": \"/newuser\", " + - "\"value\": {\"password\": \"fair password for the user\", " + - "\"opendistro_security_roles\": [\"opendistro_security_all_access\"] } }]", - new Header[0] + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/newuser\", " + + "\"value\": {\"password\": \"fair password for the user\", " + + "\"opendistro_security_roles\": [\"opendistro_security_all_access\"] } }]", + new Header[0] ); Assert.assertEquals(response.getBody(), HttpStatus.SC_OK, response.getStatusCode()); @@ -116,8 +114,11 @@ public void testParallelPutRequests() throws Exception { rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - HttpResponse[] responses = rh.executeMultipleAsyncPutRequest(10, - ENDPOINT + "/internalusers/test1", "{\"password\":\"test1test1test1test1test1test1\"}"); + HttpResponse[] responses = rh.executeMultipleAsyncPutRequest( + 10, + ENDPOINT + "/internalusers/test1", + "{\"password\":\"test1test1test1test1test1test1\"}" + ); boolean created = false; for (HttpResponse response : responses) { int sc = response.getStatusCode(); @@ -188,8 +189,7 @@ private void verifyPut(final Header... header) throws Exception { Assert.assertEquals(HttpStatus.SC_METHOD_NOT_ALLOWED, response.getStatusCode()); // Faulty JSON payload - response = rh.executePutRequest(ENDPOINT + "/internalusers/nagilum", "{some: \"thing\" asd other: \"thing\"}", - header); + response = rh.executePutRequest(ENDPOINT + "/internalusers/nagilum", "{some: \"thing\" asd other: \"thing\"}", header); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(settings.get("reason"), AbstractConfigurationValidator.ErrorType.BODY_NOT_PARSEABLE.getMessage()); @@ -198,37 +198,44 @@ private void verifyPut(final Header... header) throws Exception { response = rh.executePutRequest(ENDPOINT + "/internalusers/nagilum", "{some: \"thing\", other: \"thing\"}", header); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); - //JK: this should be "Could not parse content of request." because JSON is truly invalid - //Assert.assertEquals(settings.get("reason"), AbstractConfigurationValidator.ErrorType.INVALID_CONFIGURATION.getMessage()); - //Assert.assertTrue(settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY + ".keys").contains("some")); - //Assert.assertTrue(settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY + ".keys").contains("other")); + // JK: this should be "Could not parse content of request." because JSON is truly invalid + // Assert.assertEquals(settings.get("reason"), AbstractConfigurationValidator.ErrorType.INVALID_CONFIGURATION.getMessage()); + // Assert.assertTrue(settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY + ".keys").contains("some")); + // Assert.assertTrue(settings.get(AbstractConfigurationValidator.INVALID_KEYS_KEY + ".keys").contains("other")); // Get hidden role - response = rh.executeGetRequest(ENDPOINT + "/internalusers/hide" , header); + response = rh.executeGetRequest(ENDPOINT + "/internalusers/hide", header); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("\"hidden\":true")); // Associating with hidden role is allowed (for superadmin) - response = rh.executePutRequest(ENDPOINT + "/internalusers/test", "{ \"opendistro_security_roles\": " + - "[\"opendistro_security_hidden\"]}", header); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/test", + "{ \"opendistro_security_roles\": " + "[\"opendistro_security_hidden\"]}", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // Associating with reserved role is allowed (for superadmin) - response = rh.executePutRequest(ENDPOINT + "/internalusers/test", "{ \"opendistro_security_roles\": [\"opendistro_security_reserved\"], " + - "\"hash\": \"123\"}", - header); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/test", + "{ \"opendistro_security_roles\": [\"opendistro_security_reserved\"], " + "\"hash\": \"123\"}", + header + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // Associating with non-existent role is not allowed - response = rh.executePutRequest(ENDPOINT + "/internalusers/nagilum", "{ \"opendistro_security_roles\": [\"non_existent\"]}", - header); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/nagilum", + "{ \"opendistro_security_roles\": [\"non_existent\"]}", + header + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(settings.get("message"), "Role 'non_existent' is not available for role-mapping."); // Wrong config keys - response = rh.executePutRequest(ENDPOINT + "/internalusers/nagilum", "{\"some\": \"thing\", \"other\": \"thing\"}", - header); + response = rh.executePutRequest(ENDPOINT + "/internalusers/nagilum", "{\"some\": \"thing\", \"other\": \"thing\"}", header); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(settings.get("reason"), AbstractConfigurationValidator.ErrorType.INVALID_CONFIGURATION.getMessage()); @@ -241,29 +248,49 @@ private void verifyPatch(final boolean sendAdminCert, Header... restAdminHeader) // -- PATCH // PATCH on non-existing resource rh.sendAdminCertificate = sendAdminCert; - HttpResponse response = rh.executePatchRequest(ENDPOINT + "/internalusers/imnothere", "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", restAdminHeader); + HttpResponse response = rh.executePatchRequest( + ENDPOINT + "/internalusers/imnothere", + "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // PATCH read only resource, must be forbidden, // but SuperAdmin can PATCH read-only resource rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers/sarek", "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers/sarek", + "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); // PATCH hidden resource, must be not found, can be found for super admin rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers/q", "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers/q", + "[{ \"op\": \"add\", \"path\": \"/a/b/c\", \"value\": [ \"foo\", \"bar\" ] }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH value of hidden flag, must fail with validation error rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers/test", "[{ \"op\": \"add\", \"path\": \"/hidden\", \"value\": true }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers/test", + "[{ \"op\": \"add\", \"path\": \"/hidden\", \"value\": true }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*")); // PATCH password rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers/test", "[{ \"op\": \"add\", \"path\": \"/password\", \"value\": \"neu password 42\" }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers/test", + "[{ \"op\": \"add\", \"path\": \"/password\", \"value\": \"neu password 42\" }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/internalusers/test", restAdminHeader); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); @@ -274,34 +301,56 @@ private void verifyPatch(final boolean sendAdminCert, Header... restAdminHeader) // -- PATCH on whole config resource // PATCH on non-existing resource rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers", "[{ \"op\": \"add\", \"path\": \"/imnothere/a\", \"value\": [ \"foo\", \"bar\" ] }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/imnothere/a\", \"value\": [ \"foo\", \"bar\" ] }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH read only resource, must be forbidden, // but SuperAdmin can PATCH read only resouce rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers", "[{ \"op\": \"add\", \"path\": \"/sarek/description\", \"value\": \"foo\" }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/sarek/description\", \"value\": \"foo\" }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); rh.sendAdminCertificate = false; - response = rh.executePatchRequest(ENDPOINT + "/internalusers", "[{ \"op\": \"add\", \"path\": \"/sarek/a\", \"value\": [ \"foo\", \"bar\" ] }]"); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/sarek/a\", \"value\": [ \"foo\", \"bar\" ] }]" + ); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getStatusCode()); // PATCH hidden resource, must be bad request rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers", "[{ \"op\": \"add\", \"path\": \"/q/a\", \"value\": [ \"foo\", \"bar\" ] }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/q/a\", \"value\": [ \"foo\", \"bar\" ] }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // PATCH value of hidden flag, must fail with validation error rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers", "[{ \"op\": \"add\", \"path\": \"/test/hidden\", \"value\": true }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/test/hidden\", \"value\": true }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertTrue(response.getBody().matches(".*\"invalid_keys\"\\s*:\\s*\\{\\s*\"keys\"\\s*:\\s*\"hidden\"\\s*\\}.*")); // PATCH rh.sendAdminCertificate = sendAdminCert; - response = rh.executePatchRequest(ENDPOINT + "/internalusers", - "[{ \"op\": \"add\", \"path\": \"/bulknew1\", \"value\": {\"password\": \"bla bla bla password 42\", \"backend_roles\": [\"vulcan\"] } }]", restAdminHeader); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/bulknew1\", \"value\": {\"password\": \"bla bla bla password 42\", \"backend_roles\": [\"vulcan\"] } }]", + restAdminHeader + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/internalusers/bulknew1", restAdminHeader); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); @@ -320,46 +369,36 @@ private void verifyPatch(final boolean sendAdminCert, Header... restAdminHeader) // add/update user, user is read only, forbidden // SuperAdmin can add read only users rh.sendAdminCertificate = sendAdminCert; - addUserWithHash("sarek", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", - HttpStatus.SC_OK); + addUserWithHash("sarek", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", HttpStatus.SC_OK); // add/update user, user is hidden, forbidden, allowed for super admin rh.sendAdminCertificate = sendAdminCert; - addUserWithHash("q", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", - HttpStatus.SC_OK); + addUserWithHash("q", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", HttpStatus.SC_OK); // add users rh.sendAdminCertificate = sendAdminCert; - addUserWithHash("nagilum", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", - HttpStatus.SC_CREATED); + addUserWithHash("nagilum", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", HttpStatus.SC_CREATED); // Add enabled service account then get it - response = rh.executePutRequest(ENDPOINT + "/internalusers/happyServiceLive", - ENABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); + response = rh.executePutRequest(ENDPOINT + "/internalusers/happyServiceLive", ENABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); Assert.assertEquals(response.getBody(), HttpStatus.SC_CREATED, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/internalusers/happyServiceLive", restAdminHeader); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - // Add disabled service account - response = rh.executePutRequest(ENDPOINT + "/internalusers/happyServiceDead", - DISABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); + response = rh.executePutRequest(ENDPOINT + "/internalusers/happyServiceDead", DISABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); Assert.assertEquals(response.getBody(), HttpStatus.SC_CREATED, response.getStatusCode()); - // Add service account with password -- Should Fail - response = rh.executePutRequest(ENDPOINT + "/internalusers/passwordService", - PASSWORD_SERVICE, restAdminHeader); + response = rh.executePutRequest(ENDPOINT + "/internalusers/passwordService", PASSWORD_SERVICE, restAdminHeader); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - //Add service with hash -- should fail - response = rh.executePutRequest(ENDPOINT + "/internalusers/hashService", - HASH_SERVICE, restAdminHeader); + // Add service with hash -- should fail + response = rh.executePutRequest(ENDPOINT + "/internalusers/hashService", HASH_SERVICE, restAdminHeader); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // Add Service account with password & Hash -- should fail - response = rh.executePutRequest(ENDPOINT + "/internalusers/passwordHashService", - PASSWORD_HASH_SERVICE, restAdminHeader); + response = rh.executePutRequest(ENDPOINT + "/internalusers/passwordHashService", PASSWORD_HASH_SERVICE, restAdminHeader); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); // access must be allowed now @@ -403,12 +442,11 @@ private void verifyPatch(final boolean sendAdminCert, Header... restAdminHeader) rh.sendAdminCertificate = sendAdminCert; // new user, password or hash is mandatory - addUserWithoutPasswordOrHash("nagilum", new String[]{"starfleet"}, HttpStatus.SC_BAD_REQUEST); + addUserWithoutPasswordOrHash("nagilum", new String[] { "starfleet" }, HttpStatus.SC_BAD_REQUEST); // new user, add hash - addUserWithHash("nagilum", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", - HttpStatus.SC_CREATED); + addUserWithHash("nagilum", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", HttpStatus.SC_CREATED); // update user, do not specify hash or password, hash must remain the same - addUserWithoutPasswordOrHash("nagilum", new String[]{"starfleet"}, HttpStatus.SC_OK); + addUserWithoutPasswordOrHash("nagilum", new String[] { "starfleet" }, HttpStatus.SC_OK); // get user, check hash, must be untouched response = rh.executeGetRequest(ENDPOINT + "/internalusers/nagilum", restAdminHeader); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); @@ -421,42 +459,51 @@ private void verifyAuthToken(final boolean sendAdminCert, Header... restAdminHea // Add enabled service account then generate auth token rh.sendAdminCertificate = sendAdminCert; - HttpResponse response = rh.executePutRequest(ENDPOINT + "/internalusers/happyServiceLive", - ENABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); + HttpResponse response = rh.executePutRequest( + ENDPOINT + "/internalusers/happyServiceLive", + ENABLED_SERVICE_ACCOUNT_BODY, + restAdminHeader + ); Assert.assertEquals(response.getBody(), HttpStatus.SC_CREATED, response.getStatusCode()); rh.sendAdminCertificate = sendAdminCert; response = rh.executeGetRequest(ENDPOINT + "/internalusers/happyServiceLive", restAdminHeader); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executePostRequest(ENDPOINT + "/internalusers/happyServiceLive/authtoken", - ENABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); + response = rh.executePostRequest( + ENDPOINT + "/internalusers/happyServiceLive/authtoken", + ENABLED_SERVICE_ACCOUNT_BODY, + restAdminHeader + ); Assert.assertEquals(response.getBody(), HttpStatus.SC_CREATED, response.getStatusCode()); String tokenFromResponse = response.getBody(); byte[] decodedResponse = Base64.getUrlDecoder().decode(tokenFromResponse); String[] decodedResponseString = new String(decodedResponse).split(":", 2); String username = decodedResponseString[0]; String password = decodedResponseString[1]; - Assert.assertEquals("Username is: " + username,username, "happyServiceLive"); + Assert.assertEquals("Username is: " + username, username, "happyServiceLive"); // Add disabled service account then try to get its auth token rh.sendAdminCertificate = sendAdminCert; - response = rh.executePutRequest(ENDPOINT + "/internalusers/happyServiceDead", - DISABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); + response = rh.executePutRequest(ENDPOINT + "/internalusers/happyServiceDead", DISABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); Assert.assertEquals(response.getBody(), HttpStatus.SC_CREATED, response.getStatusCode()); - response = rh.executePostRequest(ENDPOINT + "/internalusers/happyServiceDead/authtoken", - ENABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); + response = rh.executePostRequest( + ENDPOINT + "/internalusers/happyServiceDead/authtoken", + ENABLED_SERVICE_ACCOUNT_BODY, + restAdminHeader + ); Assert.assertEquals(response.getBody(), HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - // Add enabled non-service account rh.sendAdminCertificate = sendAdminCert; - response = rh.executePutRequest(ENDPOINT + "/internalusers/user_is_owner_1", - ENABLED_NOT_SERVICE_ACCOUNT_BODY, restAdminHeader); + response = rh.executePutRequest(ENDPOINT + "/internalusers/user_is_owner_1", ENABLED_NOT_SERVICE_ACCOUNT_BODY, restAdminHeader); Assert.assertEquals(HttpStatus.SC_CREATED, response.getStatusCode()); - response = rh.executePostRequest(ENDPOINT + "/internalusers/user_is_owner_1/authtoken", - ENABLED_SERVICE_ACCOUNT_BODY, restAdminHeader); + response = rh.executePostRequest( + ENDPOINT + "/internalusers/user_is_owner_1/authtoken", + ENABLED_SERVICE_ACCOUNT_BODY, + restAdminHeader + ); Assert.assertEquals(response.getBody(), HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); } @@ -464,7 +511,11 @@ private void verifyAuthToken(final boolean sendAdminCert, Header... restAdminHea private void verifyRoles(final boolean sendAdminCert, Header... header) throws Exception { // wrong datatypes in roles file rh.sendAdminCertificate = sendAdminCert; - HttpResponse response = rh.executePutRequest(ENDPOINT + "/internalusers/picard", FileHelper.loadFile("restapi/users_wrong_datatypes.json"), header); + HttpResponse response = rh.executePutRequest( + ENDPOINT + "/internalusers/picard", + FileHelper.loadFile("restapi/users_wrong_datatypes.json"), + header + ); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.WRONG_DATATYPE.getMessage(), settings.get("reason")); @@ -472,7 +523,11 @@ private void verifyRoles(final boolean sendAdminCert, Header... header) throws E rh.sendAdminCertificate = false; rh.sendAdminCertificate = sendAdminCert; - response = rh.executePutRequest(ENDPOINT + "/internalusers/picard", FileHelper.loadFile("restapi/users_wrong_datatypes.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/picard", + FileHelper.loadFile("restapi/users_wrong_datatypes.json"), + header + ); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.WRONG_DATATYPE.getMessage(), settings.get("reason")); @@ -480,7 +535,11 @@ private void verifyRoles(final boolean sendAdminCert, Header... header) throws E rh.sendAdminCertificate = false; rh.sendAdminCertificate = sendAdminCert; - response = rh.executePutRequest(ENDPOINT + "/internalusers/picard", FileHelper.loadFile("restapi/users_wrong_datatypes2.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/picard", + FileHelper.loadFile("restapi/users_wrong_datatypes2.json"), + header + ); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.WRONG_DATATYPE.getMessage(), settings.get("reason")); @@ -489,7 +548,11 @@ private void verifyRoles(final boolean sendAdminCert, Header... header) throws E rh.sendAdminCertificate = false; rh.sendAdminCertificate = sendAdminCert; - response = rh.executePutRequest(ENDPOINT + "/internalusers/picard", FileHelper.loadFile("restapi/users_wrong_datatypes3.json"), header); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/picard", + FileHelper.loadFile("restapi/users_wrong_datatypes3.json"), + header + ); settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); Assert.assertEquals(AbstractConfigurationValidator.ErrorType.WRONG_DATATYPE.getMessage(), settings.get("reason")); @@ -507,14 +570,14 @@ private void verifyRoles(final boolean sendAdminCert, Header... header) throws E checkReadAccess(HttpStatus.SC_FORBIDDEN, "picard", "picardpicardpicardpicardpicard", "sf", "_doc", 0); // overwrite user picard, and give him role "starfleet". - addUserWithPassword("picard", "picardpicardpicardpicardpicard", new String[]{"starfleet"}, HttpStatus.SC_OK); + addUserWithPassword("picard", "picardpicardpicardpicardpicard", new String[] { "starfleet" }, HttpStatus.SC_OK); checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicardpicard", "sf", "_doc", 0); checkWriteAccess(HttpStatus.SC_FORBIDDEN, "picard", "picardpicardpicardpicardpicard", "sf", "_doc", 1); // overwrite user picard, and give him role "starfleet" plus "captains. Now // document can be created. - addUserWithPassword("picard", "picardpicardpicardpicardpicard", new String[]{"starfleet", "captains"}, HttpStatus.SC_OK); + addUserWithPassword("picard", "picardpicardpicardpicardpicard", new String[] { "starfleet", "captains" }, HttpStatus.SC_OK); checkReadAccess(HttpStatus.SC_OK, "picard", "picardpicardpicardpicardpicard", "sf", "_doc", 0); checkWriteAccess(HttpStatus.SC_CREATED, "picard", "picardpicardpicardpicardpicard", "sf", "_doc", 1); @@ -576,14 +639,11 @@ public void testUserApiWithRestInternalUsersAdminPermissions() throws Exception @Test public void testRegExpPasswordRules() throws Exception { - Settings nodeSettings = - Settings.builder() - .put(ConfigConstants.SECURITY_RESTAPI_PASSWORD_VALIDATION_ERROR_MESSAGE, "xxx") - .put(ConfigConstants.SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, - "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}") - .put(ConfigConstants.SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH, - PasswordValidator.ScoreStrength.FAIR.name()) - .build(); + Settings nodeSettings = Settings.builder() + .put(ConfigConstants.SECURITY_RESTAPI_PASSWORD_VALIDATION_ERROR_MESSAGE, "xxx") + .put(ConfigConstants.SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}") + .put(ConfigConstants.SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH, PasswordValidator.ScoreStrength.FAIR.name()) + .build(); setup(nodeSettings); @@ -591,8 +651,7 @@ public void testRegExpPasswordRules() throws Exception { rh.sendAdminCertificate = true; // initial configuration, 6 users - HttpResponse response = rh - .executeGetRequest("_plugins/_security/api/" + CType.INTERNALUSERS.toLCString()); + HttpResponse response = rh.executeGetRequest("_plugins/_security/api/" + CType.INTERNALUSERS.toLCString()); Assert.assertEquals(response.getBody(), HttpStatus.SC_OK, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(USER_SETTING_SIZE, settings.size()); @@ -611,7 +670,7 @@ public void testRegExpPasswordRules() throws Exception { private void verifyCouldNotCreatePasswords(final int expectedStatus) throws Exception { addUserWithPassword("tooshoort", "", expectedStatus); - addUserWithPassword("tooshoort", "123",expectedStatus); + addUserWithPassword("tooshoort", "123", expectedStatus); addUserWithPassword("tooshoort", "1234567", expectedStatus); addUserWithPassword("tooshoort", "1Aa%", expectedStatus); addUserWithPassword("no-nonnumeric", "123456789", expectedStatus); @@ -619,39 +678,65 @@ private void verifyCouldNotCreatePasswords(final int expectedStatus) throws Exce addUserWithPassword("no-lowercase", "A123456789", expectedStatus); addUserWithPassword("empty_password_no_hash", "", expectedStatus); HttpResponse response = rh.executePatchRequest( - PLUGINS_PREFIX + "/api/internalusers", - "[{ \"op\": \"add\", \"path\": \"/ok4\", \"value\": {\"password\": \"bla\", \"backend_roles\": [\"vulcan\"] } }]", - new Header[0] + PLUGINS_PREFIX + "/api/internalusers", + "[{ \"op\": \"add\", \"path\": \"/ok4\", \"value\": {\"password\": \"bla\", \"backend_roles\": [\"vulcan\"] } }]", + new Header[0] ); Assert.assertEquals(response.getBody(), expectedStatus, response.getStatusCode()); - response = rh.executePatchRequest(PLUGINS_PREFIX + "/api/internalusers", "[{ \"op\": \"replace\", \"path\": \"/ok4\", \"value\": {\"password\": \"bla\", \"backend_roles\": [\"vulcan\"] } }]", new Header[0]); + response = rh.executePatchRequest( + PLUGINS_PREFIX + "/api/internalusers", + "[{ \"op\": \"replace\", \"path\": \"/ok4\", \"value\": {\"password\": \"bla\", \"backend_roles\": [\"vulcan\"] } }]", + new Header[0] + ); Assert.assertEquals(response.getBody(), expectedStatus, response.getStatusCode()); addUserWithPassword("ok4", "123", expectedStatus); - //its not allowed to use the username as password (case insensitive) - response = rh.executePatchRequest(PLUGINS_PREFIX + "/api/internalusers", "[{ \"op\": \"add\", \"path\": \"/$1aAAAAAAAAB\", \"value\": {\"password\": \"$1aAAAAAAAAB\", \"backend_roles\": [\"vulcan\"] } }]", new Header[0]); + // its not allowed to use the username as password (case insensitive) + response = rh.executePatchRequest( + PLUGINS_PREFIX + "/api/internalusers", + "[{ \"op\": \"add\", \"path\": \"/$1aAAAAAAAAB\", \"value\": {\"password\": \"$1aAAAAAAAAB\", \"backend_roles\": [\"vulcan\"] } }]", + new Header[0] + ); Assert.assertEquals(response.getBody(), expectedStatus, response.getStatusCode()); addUserWithPassword("$1aAAAAAAAAC", "$1aAAAAAAAAC", expectedStatus); addUserWithPassword("$1aAAAAAAAac", "$1aAAAAAAAAC", expectedStatus); addUserWithPassword(URLEncoder.encode("$1aAAAAAAAac%", "UTF-8"), "$1aAAAAAAAAC%", expectedStatus); - addUserWithPassword(URLEncoder.encode("$1aAAAAAAAac%!=\"/\\;:test&~@^", "UTF-8").replace("+", "%2B"), "$1aAAAAAAAac%!=\\\"/\\\\;:test&~@^", expectedStatus); - addUserWithPassword(URLEncoder.encode("$1aAAAAAAAac%!=\"/\\;: test&", "UTF-8"), "$1aAAAAAAAac%!=\\\"/\\\\;: test&123", expectedStatus); - String patchPayload = "[ " + - "{ \"op\": \"add\", \"path\": \"/testuser1\", \"value\": { \"password\": \"$aA123456789\", \"backend_roles\": [\"testrole1\"] } }," + - "{ \"op\": \"add\", \"path\": \"/testuser2\", \"value\": { \"password\": \"testpassword2\", \"backend_roles\": [\"testrole2\"] } }" + - "]"; - - response = rh.executePatchRequest(PLUGINS_PREFIX + "/api/internalusers", patchPayload, new BasicHeader("Content-Type", "application/json")); + addUserWithPassword( + URLEncoder.encode("$1aAAAAAAAac%!=\"/\\;:test&~@^", "UTF-8").replace("+", "%2B"), + "$1aAAAAAAAac%!=\\\"/\\\\;:test&~@^", + expectedStatus + ); + addUserWithPassword( + URLEncoder.encode("$1aAAAAAAAac%!=\"/\\;: test&", "UTF-8"), + "$1aAAAAAAAac%!=\\\"/\\\\;: test&123", + expectedStatus + ); + String patchPayload = "[ " + + "{ \"op\": \"add\", \"path\": \"/testuser1\", \"value\": { \"password\": \"$aA123456789\", \"backend_roles\": [\"testrole1\"] } }," + + "{ \"op\": \"add\", \"path\": \"/testuser2\", \"value\": { \"password\": \"testpassword2\", \"backend_roles\": [\"testrole2\"] } }" + + "]"; + + response = rh.executePatchRequest( + PLUGINS_PREFIX + "/api/internalusers", + patchPayload, + new BasicHeader("Content-Type", "application/json") + ); Assert.assertEquals(expectedStatus, response.getStatusCode()); Assert.assertTrue(response.getBody().contains("error")); Assert.assertTrue(response.getBody().contains("xxx")); - response = rh.executePutRequest(PLUGINS_PREFIX + "/api/internalusers/ok1", "{\"backend_roles\":[\"my-backend-role\"],\"attributes\":{},\"password\":\"\"}", new Header[0]); + response = rh.executePutRequest( + PLUGINS_PREFIX + "/api/internalusers/ok1", + "{\"backend_roles\":[\"my-backend-role\"],\"attributes\":{},\"password\":\"\"}", + new Header[0] + ); Assert.assertEquals(expectedStatus, response.getStatusCode()); - response = rh.executePutRequest(PLUGINS_PREFIX + "/api/internalusers/ok1", - "{\"backend_roles\":[\"my-backend-role\"],\"attributes\":{},\"password\":\"bla\"}", - new Header[0]); + response = rh.executePutRequest( + PLUGINS_PREFIX + "/api/internalusers/ok1", + "{\"backend_roles\":[\"my-backend-role\"],\"attributes\":{},\"password\":\"bla\"}", + new Header[0] + ); Assert.assertEquals(expectedStatus, response.getStatusCode()); } @@ -662,35 +747,35 @@ private void verifyCanCreatePasswords() throws Exception { addUserWithPassword("ok4", "$1aAAAAAAAAA", HttpStatus.SC_CREATED); addUserWithPassword("ok4", "$1aAAAAAAAAC", HttpStatus.SC_OK); HttpResponse response = rh.executePatchRequest( - PLUGINS_PREFIX + "/api/internalusers", - "[{ \"op\": \"add\", \"path\": \"/ok4\", \"value\": {\"password\": \"$1aAAAAAAAAB\", \"backend_roles\": [\"vulcan\"] } }]", - new Header[0] + PLUGINS_PREFIX + "/api/internalusers", + "[{ \"op\": \"add\", \"path\": \"/ok4\", \"value\": {\"password\": \"$1aAAAAAAAAB\", \"backend_roles\": [\"vulcan\"] } }]", + new Header[0] ); Assert.assertEquals(response.getBody(), HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executePutRequest(PLUGINS_PREFIX + "/api/internalusers/ok1", "{\"backend_roles\":[\"my-backend-role\"],\"attributes\":{},\"password\":\"Admin_123\"}", new Header[0]); + response = rh.executePutRequest( + PLUGINS_PREFIX + "/api/internalusers/ok1", + "{\"backend_roles\":[\"my-backend-role\"],\"attributes\":{},\"password\":\"Admin_123\"}", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - response = rh.executePutRequest(PLUGINS_PREFIX + "/api/internalusers/ok1", "{\"backend_roles\":[\"my-backend-role\"],\"attributes\":{}}", new Header[0]); + response = rh.executePutRequest( + PLUGINS_PREFIX + "/api/internalusers/ok1", + "{\"backend_roles\":[\"my-backend-role\"],\"attributes\":{}}", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); } - private void verifySimilarity(final String expectedMessage) throws Exception { - addUserWithPassword( - "some_user_name", "H3235,cc,some_User_Name", - HttpStatus.SC_BAD_REQUEST, - expectedMessage - ); + addUserWithPassword("some_user_name", "H3235,cc,some_User_Name", HttpStatus.SC_BAD_REQUEST, expectedMessage); } @Test public void testScoreBasedPasswordRules() throws Exception { - Settings nodeSettings = - Settings.builder() - .put(ConfigConstants.SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, 9) - .build(); + Settings nodeSettings = Settings.builder().put(ConfigConstants.SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, 9).build(); setup(nodeSettings); @@ -698,28 +783,25 @@ public void testScoreBasedPasswordRules() throws Exception { rh.sendAdminCertificate = true; // initial configuration, 6 users - HttpResponse response = rh - .executeGetRequest("_plugins/_security/api/" + CType.INTERNALUSERS.toLCString()); + HttpResponse response = rh.executeGetRequest("_plugins/_security/api/" + CType.INTERNALUSERS.toLCString()); Assert.assertEquals(response.getBody(), HttpStatus.SC_OK, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(133, settings.size()); addUserWithPassword( - "admin", "password89", - HttpStatus.SC_BAD_REQUEST, - AbstractConfigurationValidator.ErrorType.WEAK_PASSWORD.getMessage() + "admin", + "password89", + HttpStatus.SC_BAD_REQUEST, + AbstractConfigurationValidator.ErrorType.WEAK_PASSWORD.getMessage() ); addUserWithPassword( - "admin", "A123456789", - HttpStatus.SC_BAD_REQUEST, - AbstractConfigurationValidator.ErrorType.WEAK_PASSWORD.getMessage() + "admin", + "A123456789", + HttpStatus.SC_BAD_REQUEST, + AbstractConfigurationValidator.ErrorType.WEAK_PASSWORD.getMessage() ); - addUserWithPassword( - "admin", "pas", - HttpStatus.SC_BAD_REQUEST, - "Password does not match minimum criteria" - ); + addUserWithPassword("admin", "pas", HttpStatus.SC_BAD_REQUEST, "Password does not match minimum criteria"); verifySimilarity(AbstractConfigurationValidator.ErrorType.SIMILAR_PASSWORD.getMessage()); @@ -735,23 +817,18 @@ public void testUserApiWithDots() throws Exception { rh.sendAdminCertificate = true; // initial configuration, 6 users - HttpResponse response = rh - .executeGetRequest(ENDPOINT + "/" + CType.INTERNALUSERS.toLCString()); + HttpResponse response = rh.executeGetRequest(ENDPOINT + "/" + CType.INTERNALUSERS.toLCString()); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(USER_SETTING_SIZE, settings.size()); - addUserWithPassword(".my.dotuser0", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", - HttpStatus.SC_CREATED); + addUserWithPassword(".my.dotuser0", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", HttpStatus.SC_CREATED); - addUserWithPassword(".my.dot.user0", "12345678Sd", - HttpStatus.SC_CREATED); + addUserWithPassword(".my.dot.user0", "12345678Sd", HttpStatus.SC_CREATED); - addUserWithHash(".my.dotuser1", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", - HttpStatus.SC_CREATED); + addUserWithHash(".my.dotuser1", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", HttpStatus.SC_CREATED); - addUserWithPassword(".my.dot.user2", "12345678Sd", - HttpStatus.SC_CREATED); + addUserWithPassword(".my.dot.user2", "12345678Sd", HttpStatus.SC_CREATED); } @@ -766,25 +843,32 @@ public void testUserApiNoPasswordChange() throws Exception { // initial configuration, 5 users HttpResponse response; - addUserWithHash("user1", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", - HttpStatus.SC_CREATED); + addUserWithHash("user1", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", HttpStatus.SC_CREATED); - response = rh.executePutRequest(ENDPOINT + "/internalusers/user1", "{\"hash\":\"$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m\",\"password\":\"\",\"backend_roles\":[\"admin\",\"rolea\"]}"); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/user1", + "{\"hash\":\"$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m\",\"password\":\"\",\"backend_roles\":[\"admin\",\"rolea\"]}" + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - response = rh.executePutRequest(ENDPOINT + "/internalusers/user1", "{\"hash\":\"$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m\",\"password\":\"Admin_123345Yq\",\"backend_roles\":[\"admin\",\"rolea\"]}"); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/user1", + "{\"hash\":\"$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m\",\"password\":\"Admin_123345Yq\",\"backend_roles\":[\"admin\",\"rolea\"]}" + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/internalusers/user1"); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - addUserWithHash("user2", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", - HttpStatus.SC_CREATED); + addUserWithHash("user2", "$2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m", HttpStatus.SC_CREATED); response = rh.executePutRequest(ENDPOINT + "/internalusers/user2", "{\"password\":\"\",\"backend_roles\":[\"admin\",\"rolex\"]}"); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); - response = rh.executePutRequest(ENDPOINT + "/internalusers/user2", "{\"password\":\"Admin_123Qerty\",\"backend_roles\":[\"admin\",\"rolex\"]}"); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/user2", + "{\"password\":\"Admin_123Qerty\",\"backend_roles\":[\"admin\",\"rolex\"]}" + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/internalusers/user2"); @@ -803,54 +887,89 @@ public void testUserApiForNonSuperAdmin() throws Exception { HttpResponse response; // Delete read only user - response = rh.executeDeleteRequest(ENDPOINT + "/internalusers/sarek" , new Header[0]); + response = rh.executeDeleteRequest(ENDPOINT + "/internalusers/sarek", new Header[0]); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch read only users - response = rh.executePatchRequest(ENDPOINT + "/internalusers/sarek", "[{ \"op\": \"add\", \"path\": \"/sarek/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers/sarek", + "[{ \"op\": \"add\", \"path\": \"/sarek/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Put read only users - response = rh.executePutRequest(ENDPOINT + "/internalusers/sarek", "{ \"opendistro_security_roles\": [\"opendistro_security_reserved\"]}", new Header[0]); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/sarek", + "{ \"opendistro_security_roles\": [\"opendistro_security_reserved\"]}", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch single read only user - response = rh.executePatchRequest(ENDPOINT + "/internalusers/sarek", "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers/sarek", + "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Patch multiple read only users - response = rh.executePatchRequest(ENDPOINT + "/internalusers", "[{ \"op\": \"add\", \"path\": \"/sarek/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/sarek/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); // Get hidden role - response = rh.executeGetRequest(ENDPOINT + "/internalusers/hide" , new Header[0]); + response = rh.executeGetRequest(ENDPOINT + "/internalusers/hide", new Header[0]); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Delete hidden user - response = rh.executeDeleteRequest(ENDPOINT + "/internalusers/hide" , new Header[0]); + response = rh.executeDeleteRequest(ENDPOINT + "/internalusers/hide", new Header[0]); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Patch hidden users - response = rh.executePatchRequest(ENDPOINT + "/internalusers/hide", "[{ \"op\": \"add\", \"path\": \"/sarek/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers/hide", + "[{ \"op\": \"add\", \"path\": \"/sarek/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Put hidden users - response = rh.executePutRequest(ENDPOINT + "/internalusers/hide", "{ \"opendistro_security_roles\": [\"opendistro_security_reserved\"]}", new Header[0]); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/hide", + "{ \"opendistro_security_roles\": [\"opendistro_security_reserved\"]}", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Put reserved role is forbidden for non-superadmin - response = rh.executePutRequest(ENDPOINT + "/internalusers/nagilum", "{ \"opendistro_security_roles\": [\"opendistro_security_reserved\"]}", - new Header[0]); + response = rh.executePutRequest( + ENDPOINT + "/internalusers/nagilum", + "{ \"opendistro_security_roles\": [\"opendistro_security_reserved\"]}", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); Settings settings = Settings.builder().loadFromSource(response.getBody(), XContentType.JSON).build(); Assert.assertEquals(settings.get("message"), "Resource 'opendistro_security_reserved' is read-only."); // Patch single hidden user - response = rh.executePatchRequest(ENDPOINT + "/internalusers/hide", "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers/hide", + "[{ \"op\": \"add\", \"path\": \"/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); // Patch multiple hidden users - response = rh.executePatchRequest(ENDPOINT + "/internalusers", "[{ \"op\": \"add\", \"path\": \"/hide/description\", \"value\": \"foo\" }]", new Header[0]); + response = rh.executePatchRequest( + ENDPOINT + "/internalusers", + "[{ \"op\": \"add\", \"path\": \"/hide/description\", \"value\": \"foo\" }]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); } @@ -873,7 +992,7 @@ public void restrictedUsernameContents() throws Exception { } @Test - public void checkNullElementsInArray() throws Exception{ + public void checkNullElementsInArray() throws Exception { setup(); rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/WhitelistApiTest.java b/src/test/java/org/opensearch/security/dlic/rest/api/WhitelistApiTest.java index e4fca1e99b..371341147e 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/WhitelistApiTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/WhitelistApiTest.java @@ -51,12 +51,13 @@ public class WhitelistApiTest extends AbstractRestApiUnitTest { */ private final Header adminCredsHeader = encodeBasicHeader("admin_all_access", "admin_all_access"); private final Header nonAdminCredsHeader = encodeBasicHeader("sarek", "sarek"); - private final String ENDPOINT; + private final String ENDPOINT; + protected String getEndpointPrefix() { return PLUGINS_PREFIX; } - public WhitelistApiTest(){ + public WhitelistApiTest() { ENDPOINT = getEndpointPrefix() + "/api"; } @@ -65,24 +66,32 @@ public WhitelistApiTest(){ * * @throws Exception */ - private void checkGetAndPutWhitelistPermissions(final int expectedStatus, final boolean sendAdminCertificate, final Header... headers) throws Exception { + private void checkGetAndPutWhitelistPermissions(final int expectedStatus, final boolean sendAdminCertificate, final Header... headers) + throws Exception { final boolean prevSendAdminCertificate = rh.sendAdminCertificate; rh.sendAdminCertificate = sendAdminCertificate; - //CHECK GET REQUEST + // CHECK GET REQUEST response = rh.executeGetRequest(ENDPOINT + "/whitelist", headers); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); if (expectedStatus == HttpStatus.SC_OK) { - //Note: the response has no whitespaces, so the .json file does not have whitespaces - Assert.assertEquals(FileHelper.loadFile("restapi/whitelist_response_success.json"), FileHelper.loadFile("restapi/whitelist_response_success.json")); + // Note: the response has no whitespaces, so the .json file does not have whitespaces + Assert.assertEquals( + FileHelper.loadFile("restapi/whitelist_response_success.json"), + FileHelper.loadFile("restapi/whitelist_response_success.json") + ); } - //FORBIDDEN FOR NON SUPER ADMIN + // FORBIDDEN FOR NON SUPER ADMIN if (expectedStatus == HttpStatus.SC_FORBIDDEN) { assertTrue(response.getBody().contains("API allowed only for super admin.")); } - //CHECK PUT REQUEST - response = rh.executePutRequest(ENDPOINT + "/whitelist", "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", headers); + // CHECK PUT REQUEST + response = rh.executePutRequest( + ENDPOINT + "/whitelist", + "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", + headers + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(expectedStatus)); rh.sendAdminCertificate = prevSendAdminCertificate; @@ -105,7 +114,10 @@ public void testPutUnknownKey() throws Exception { setup(); rh.sendAdminCertificate = true; - RestHelper.HttpResponse response = rh.executePutRequest(ENDPOINT + "/whitelist", "{ \"unknownkey\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}"); + RestHelper.HttpResponse response = rh.executePutRequest( + ENDPOINT + "/whitelist", + "{ \"unknownkey\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}" + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); assertTrue(response.getBody().contains("invalid_keys")); assertHealthy(); @@ -116,7 +128,10 @@ public void testPutInvalidJson() throws Exception { setup(); rh.sendAdminCertificate = true; - RestHelper.HttpResponse response = rh.executePutRequest(ENDPOINT + "/whitelist", "{ \"invalid\"::{{ [\"*\"], \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}"); + RestHelper.HttpResponse response = rh.executePutRequest( + ENDPOINT + "/whitelist", + "{ \"invalid\"::{{ [\"*\"], \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}" + ); Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusCode()); assertHealthy(); } @@ -152,7 +167,7 @@ public void testWhitelistApi() throws Exception { // No creds, no admin certificate - UNAUTHORIZED checkGetAndPutWhitelistPermissions(HttpStatus.SC_UNAUTHORIZED, false); - //non admin creds, no admin certificate - FORBIDDEN + // non admin creds, no admin certificate - FORBIDDEN checkGetAndPutWhitelistPermissions(HttpStatus.SC_FORBIDDEN, false, nonAdminCredsHeader); // admin creds, no admin certificate - FORBIDDEN @@ -165,37 +180,45 @@ public void testWhitelistApi() throws Exception { @Test public void testWhitelistAuditComplianceLogging() throws Exception { Settings settings = Settings.builder() - .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) - .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") - .build(); + .put("plugins.security.audit.type", TestAuditlogImpl.class.getName()) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_TRANSPORT, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_ENABLE_REST, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_RESOLVE_BULK_REQUESTS, false) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_WRITE_LOG_DIFFS, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_COMPLIANCE_HISTORY_EXTERNAL_CONFIG_ENABLED, false) + .put(ConfigConstants.SECURITY_COMPLIANCE_HISTORY_INTERNAL_CONFIG_ENABLED, true) + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_TRANSPORT_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .put(ConfigConstants.OPENDISTRO_SECURITY_AUDIT_CONFIG_DISABLED_REST_CATEGORIES, "authenticated,GRANTED_PRIVILEGES") + .build(); setupWithRestRoles(settings); TestAuditlogImpl.clear(); // any creds, admin certificate - OK checkGetAndPutWhitelistPermissions(HttpStatus.SC_OK, true, nonAdminCredsHeader); - //TESTS THAT 1 READ AND 1 WRITE HAPPENS IN testGetAndPut() + // TESTS THAT 1 READ AND 1 WRITE HAPPENS IN testGetAndPut() final Map expectedCategoryCounts = ImmutableMap.of( - AuditCategory.COMPLIANCE_INTERNAL_CONFIG_READ, 1L, - AuditCategory.COMPLIANCE_INTERNAL_CONFIG_WRITE, 1L); - Map actualCategoryCounts = TestAuditlogImpl.messages.stream().collect(Collectors.groupingBy(AuditMessage::getCategory, Collectors.counting())); + AuditCategory.COMPLIANCE_INTERNAL_CONFIG_READ, + 1L, + AuditCategory.COMPLIANCE_INTERNAL_CONFIG_WRITE, + 1L + ); + Map actualCategoryCounts = TestAuditlogImpl.messages.stream() + .collect(Collectors.groupingBy(AuditMessage::getCategory, Collectors.counting())); assertThat(actualCategoryCounts, equalTo(expectedCategoryCounts)); } @Test - public void testWhitelistInvalidHttpRequestMethod() throws Exception{ + public void testWhitelistInvalidHttpRequestMethod() throws Exception { setup(); rh.sendAdminCertificate = true; - response = rh.executePutRequest(ENDPOINT + "/whitelist", "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GE\"],\"/_cat/indices\": [\"PUT\"] }}", adminCredsHeader); + response = rh.executePutRequest( + ENDPOINT + "/whitelist", + "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GE\"],\"/_cat/indices\": [\"PUT\"] }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_INTERNAL_SERVER_ERROR)); assertTrue(response.getBody().contains("\\\"GE\\\": not one of the values accepted for Enum class")); } @@ -208,37 +231,61 @@ public void testWhitelistInvalidHttpRequestMethod() throws Exception{ * @throws Exception */ @Test - public void testPatchApi() throws Exception{ + public void testPatchApi() throws Exception { setup(); rh.sendAdminCertificate = true; - //PATCH entire config entry - response = rh.executePatchRequest(ENDPOINT + "/whitelist", "[{ \"op\": \"replace\", \"path\": \"/config\", \"value\": {\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"PUT\"] }}}]", new Header[0]); + // PATCH entire config entry + response = rh.executePatchRequest( + ENDPOINT + "/whitelist", + "[{ \"op\": \"replace\", \"path\": \"/config\", \"value\": {\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"PUT\"] }}}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/whitelist", adminCredsHeader); - assertEquals(response.getBody(),"{\"config\":{\"enabled\":true,\"requests\":{\"/_cat/nodes\":[\"GET\"],\"/_cat/indices\":[\"PUT\"]}}}"); - - //PATCH just requests - response = rh.executePatchRequest(ENDPOINT + "/whitelist", "[{ \"op\": \"replace\", \"path\": \"/config/requests\", \"value\": {\"/_cat/nodes\": [\"GET\"]}}]", new Header[0]); + assertEquals( + response.getBody(), + "{\"config\":{\"enabled\":true,\"requests\":{\"/_cat/nodes\":[\"GET\"],\"/_cat/indices\":[\"PUT\"]}}}" + ); + + // PATCH just requests + response = rh.executePatchRequest( + ENDPOINT + "/whitelist", + "[{ \"op\": \"replace\", \"path\": \"/config/requests\", \"value\": {\"/_cat/nodes\": [\"GET\"]}}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/whitelist", adminCredsHeader); assertTrue(response.getBody().contains("\"requests\":{\"/_cat/nodes\":[\"GET\"]}")); - //PATCH just whitelisted_enabled using "replace" operation - works when enabled is already true - response = rh.executePatchRequest(ENDPOINT + "/whitelist", "[{ \"op\": \"replace\", \"path\": \"/config/enabled\", \"value\": false}]", new Header[0]); + // PATCH just whitelisted_enabled using "replace" operation - works when enabled is already true + response = rh.executePatchRequest( + ENDPOINT + "/whitelist", + "[{ \"op\": \"replace\", \"path\": \"/config/enabled\", \"value\": false}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/whitelist", adminCredsHeader); assertTrue(response.getBody().contains("\"enabled\":false")); - //PATCH just enabled using "add" operation when it is currently false - works correctly - response = rh.executePatchRequest(ENDPOINT + "/whitelist", "[{ \"op\": \"add\", \"path\": \"/config/enabled\", \"value\": true}]", new Header[0]); + // PATCH just enabled using "add" operation when it is currently false - works correctly + response = rh.executePatchRequest( + ENDPOINT + "/whitelist", + "[{ \"op\": \"add\", \"path\": \"/config/enabled\", \"value\": true}]", + new Header[0] + ); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); response = rh.executeGetRequest(ENDPOINT + "/whitelist", adminCredsHeader); assertTrue(response.getBody().contains("\"enabled\":true")); - //PATCH just enabled using "add" operation when it is currently true - works correctly - response = rh.executePatchRequest(ENDPOINT + "/whitelist", "[{ \"op\": \"add\", \"path\": \"/config/enabled\", \"value\": false}]", new Header[0]); - Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());response = rh.executeGetRequest(ENDPOINT + "/whitelist", adminCredsHeader); + // PATCH just enabled using "add" operation when it is currently true - works correctly + response = rh.executePatchRequest( + ENDPOINT + "/whitelist", + "[{ \"op\": \"add\", \"path\": \"/config/enabled\", \"value\": false}]", + new Header[0] + ); + Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); + response = rh.executeGetRequest(ENDPOINT + "/whitelist", adminCredsHeader); response = rh.executeGetRequest(ENDPOINT + "/whitelist", adminCredsHeader); assertTrue(response.getBody().contains("\"enabled\":false")); } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyAccountApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyAccountApiTests.java index a48a7d2e3a..925d90ccba 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyAccountApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyAccountApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyAccountApiTests extends AccountApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyActionGroupsApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyActionGroupsApiTests.java index 9aa4b70c77..e92f046f65 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyActionGroupsApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyActionGroupsApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyActionGroupsApiTests extends ActionGroupsApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyAuditApiActionTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyAuditApiActionTests.java index 4d97da8bbb..fbde68e911 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyAuditApiActionTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyAuditApiActionTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyAuditApiActionTests extends AuditApiActionTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyDashboardsInfoActionTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyDashboardsInfoActionTests.java index a9baec37bd..ee39f93ee0 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyDashboardsInfoActionTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyDashboardsInfoActionTests.java @@ -16,7 +16,7 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyDashboardsInfoActionTests extends DashboardsInfoActionTest { - @Override + @Override protected String getEndpoint() { return LEGACY_OPENDISTRO_PREFIX + "/kibanainfo"; } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyFlushCacheApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyFlushCacheApiTests.java index ab09a6e2f2..df9cc3d59d 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyFlushCacheApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyFlushCacheApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyFlushCacheApiTests extends FlushCacheApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyGetConfigurationApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyGetConfigurationApiTests.java index cca6739733..07983bad0d 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyGetConfigurationApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyGetConfigurationApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyGetConfigurationApiTests extends GetConfigurationApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyIndexMissingTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyIndexMissingTests.java index 0680aa2c2e..fef436f4d7 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyIndexMissingTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyIndexMissingTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyIndexMissingTests extends IndexMissingTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyNodesDnApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyNodesDnApiTests.java index 22237ece3f..a316785f02 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyNodesDnApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyNodesDnApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyNodesDnApiTests extends NodesDnApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRoleBasedAccessTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRoleBasedAccessTests.java index c9f421058c..329404dfe7 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRoleBasedAccessTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRoleBasedAccessTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyRoleBasedAccessTests extends RoleBasedAccessTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRolesApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRolesApiTests.java index b4ec33a2d5..118f8e1ebe 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRolesApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRolesApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyRolesApiTests extends RolesApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRolesMappingApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRolesMappingApiTests.java index c659fb57bc..dd29b524c1 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRolesMappingApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyRolesMappingApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyRolesMappingApiTests extends RolesMappingApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityApiAccessTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityApiAccessTests.java index 72b6086c1e..85428d645d 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityApiAccessTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityApiAccessTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacySecurityApiAccessTests extends SecurityApiAccessTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityConfigApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityConfigApiTests.java index fd03e7248a..6175809b4a 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityConfigApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityConfigApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacySecurityConfigApiTests extends SecurityConfigApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityHealthActionTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityHealthActionTests.java index 470db0a526..99fa4a99ae 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityHealthActionTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityHealthActionTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacySecurityHealthActionTests extends SecurityHealthActionTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityInfoActionTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityInfoActionTests.java index 8480787423..75c5238f7f 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityInfoActionTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacySecurityInfoActionTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacySecurityInfoActionTests extends SecurityInfoActionTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyTenantInfoActionTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyTenantInfoActionTests.java index 1f2ac9a77d..49963d7d55 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyTenantInfoActionTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyTenantInfoActionTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyTenantInfoActionTests extends TenantInfoActionTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyUserApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyUserApiTests.java index 5753688097..449bce270d 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyUserApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyUserApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyUserApiTests extends UserApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyWhitelistApiTests.java b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyWhitelistApiTests.java index 3ae501f9a4..689981aa2a 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyWhitelistApiTests.java +++ b/src/test/java/org/opensearch/security/dlic/rest/api/legacy/LegacyWhitelistApiTests.java @@ -16,8 +16,8 @@ import static org.opensearch.security.OpenSearchSecurityPlugin.LEGACY_OPENDISTRO_PREFIX; public class LegacyWhitelistApiTests extends WhitelistApiTest { - @Override - protected String getEndpointPrefix() { - return LEGACY_OPENDISTRO_PREFIX; - } + @Override + protected String getEndpointPrefix() { + return LEGACY_OPENDISTRO_PREFIX; + } } diff --git a/src/test/java/org/opensearch/security/dlic/rest/validation/PasswordValidatorTest.java b/src/test/java/org/opensearch/security/dlic/rest/validation/PasswordValidatorTest.java index b5d27827b8..7ea6f23898 100644 --- a/src/test/java/org/opensearch/security/dlic/rest/validation/PasswordValidatorTest.java +++ b/src/test/java/org/opensearch/security/dlic/rest/validation/PasswordValidatorTest.java @@ -25,126 +25,120 @@ public class PasswordValidatorTest { - static final List WEAK_PASSWORDS = ImmutableList.of( - "q", "5", "&", "admin", "123456", "password" - ); + static final List WEAK_PASSWORDS = ImmutableList.of("q", "5", "&", "admin", "123456", "password"); static final List FAIR_PASSWORDS = ImmutableList.of( - "p@$$word@dmin", "qwertyuiop@[", - "zxcvbnm,./_", "asdfghjkl;:]", "20300101", - "pandapandapandapandapandapandapandapandapandaa", - "appleappleappleappleappleappleappleappleapplea", - "aelppaaelppaaelppaaelppaaelppaaelppaaelppaaelppa" + "p@$$word@dmin", + "qwertyuiop@[", + "zxcvbnm,./_", + "asdfghjkl;:]", + "20300101", + "pandapandapandapandapandapandapandapandapandaa", + "appleappleappleappleappleappleappleappleapplea", + "aelppaaelppaaelppaaelppaaelppaaelppaaelppaaelppa" ); static final List GOOD_PASSWORDS = ImmutableList.of( - "xsw234rfvb", "yaq123edc", "cde345tgbn", "yaqwedcvb", - "Tr0ub4dour&3", "qwER43@!" + "xsw234rfvb", + "yaq123edc", + "cde345tgbn", + "yaqwedcvb", + "Tr0ub4dour&3", + "qwER43@!" ); - static final List STRONG_PASSWORDS = ImmutableList.of( - "YWert,H90", "Admincc,H90", "Hadmin,120" - ); + static final List STRONG_PASSWORDS = ImmutableList.of("YWert,H90", "Admincc,H90", "Hadmin,120"); static final List VERY_STRONG_PASSWORDS = ImmutableList.of( - "AeTq($%u-44c_j9NJB45a#2#JP7sH", "IB7~EOw!51gug+7s#+%A9P1O/w8f", - "1v_f%7JvS8w!_t398+ON-CObI#v0", "8lFmfc0!w)&iU9DM6~4_w)D)Y44J" + "AeTq($%u-44c_j9NJB45a#2#JP7sH", + "IB7~EOw!51gug+7s#+%A9P1O/w8f", + "1v_f%7JvS8w!_t398+ON-CObI#v0", + "8lFmfc0!w)&iU9DM6~4_w)D)Y44J" ); static final List SIMILAR_PASSWORDS = ImmutableList.of( - "some_user_name,H2344cc", "H3235,Some_User_Name,cc", - "H3235,cc,some_User_Name", "H3235,SOME_User_Name,cc", - "H3235,eman_resu_emos,cc" + "some_user_name,H2344cc", + "H3235,Some_User_Name,cc", + "H3235,cc,some_User_Name", + "H3235,SOME_User_Name,cc", + "H3235,eman_resu_emos,cc" ); - public void verifyWeakPasswords(final PasswordValidator passwordValidator, - final AbstractConfigurationValidator.ErrorType expectedValidationResult) { + public void verifyWeakPasswords( + final PasswordValidator passwordValidator, + final AbstractConfigurationValidator.ErrorType expectedValidationResult + ) { for (final String password : WEAK_PASSWORDS) - assertEquals( - password, - expectedValidationResult, - passwordValidator.validate("some_user_name", password) - ); + assertEquals(password, expectedValidationResult, passwordValidator.validate("some_user_name", password)); } - public void verifyFairPasswords(final PasswordValidator passwordValidator, - final AbstractConfigurationValidator.ErrorType expectedValidationResult) { + public void verifyFairPasswords( + final PasswordValidator passwordValidator, + final AbstractConfigurationValidator.ErrorType expectedValidationResult + ) { for (final String password : FAIR_PASSWORDS) - assertEquals( - password, - expectedValidationResult, - passwordValidator.validate("some_user_name", password) - ); + assertEquals(password, expectedValidationResult, passwordValidator.validate("some_user_name", password)); } - public void verifyGoodPasswords(final PasswordValidator passwordValidator, - final AbstractConfigurationValidator.ErrorType expectedValidationResult) { + public void verifyGoodPasswords( + final PasswordValidator passwordValidator, + final AbstractConfigurationValidator.ErrorType expectedValidationResult + ) { for (final String password : GOOD_PASSWORDS) - assertEquals( - password, - expectedValidationResult, - passwordValidator.validate("some_user_name", password) - ); + assertEquals(password, expectedValidationResult, passwordValidator.validate("some_user_name", password)); } - public void verifyStrongPasswords(final PasswordValidator passwordValidator, - final AbstractConfigurationValidator.ErrorType expectedValidationResult) { + public void verifyStrongPasswords( + final PasswordValidator passwordValidator, + final AbstractConfigurationValidator.ErrorType expectedValidationResult + ) { for (final String password : STRONG_PASSWORDS) - assertEquals( - password, - expectedValidationResult, - passwordValidator.validate("some_user_name", password) - ); + assertEquals(password, expectedValidationResult, passwordValidator.validate("some_user_name", password)); } - public void verifyVeryStrongPasswords(final PasswordValidator passwordValidator, - final AbstractConfigurationValidator.ErrorType expectedValidationResult) { + public void verifyVeryStrongPasswords( + final PasswordValidator passwordValidator, + final AbstractConfigurationValidator.ErrorType expectedValidationResult + ) { for (final String password : VERY_STRONG_PASSWORDS) - assertEquals( - password, - expectedValidationResult, - passwordValidator.validate("some_user_name", password) - ); + assertEquals(password, expectedValidationResult, passwordValidator.validate("some_user_name", password)); } public void verifySimilarPasswords(final PasswordValidator passwordValidator) { for (final String password : SIMILAR_PASSWORDS) assertEquals( - password, - AbstractConfigurationValidator.ErrorType.SIMILAR_PASSWORD, - passwordValidator.validate("some_user_name", password) + password, + AbstractConfigurationValidator.ErrorType.SIMILAR_PASSWORD, + passwordValidator.validate("some_user_name", password) ); } @Test public void testRegExpBasedValidation() { - final PasswordValidator passwordValidator = - PasswordValidator.of( - Settings.builder() - .put( - SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, - "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}") - .build() - ); + final PasswordValidator passwordValidator = PasswordValidator.of( + Settings.builder() + .put(SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}") + .build() + ); verifyWeakPasswords(passwordValidator, AbstractConfigurationValidator.ErrorType.INVALID_PASSWORD); verifyFairPasswords(passwordValidator, AbstractConfigurationValidator.ErrorType.INVALID_PASSWORD); for (final String password : GOOD_PASSWORDS.subList(0, GOOD_PASSWORDS.size() - 2)) assertEquals( - password, - AbstractConfigurationValidator.ErrorType.INVALID_PASSWORD, - passwordValidator.validate("some_user_name", password) + password, + AbstractConfigurationValidator.ErrorType.INVALID_PASSWORD, + passwordValidator.validate("some_user_name", password) ); - for (final String password: GOOD_PASSWORDS.subList(GOOD_PASSWORDS.size() - 2, GOOD_PASSWORDS.size())) + for (final String password : GOOD_PASSWORDS.subList(GOOD_PASSWORDS.size() - 2, GOOD_PASSWORDS.size())) assertEquals( - password, - AbstractConfigurationValidator.ErrorType.WEAK_PASSWORD, - passwordValidator.validate("some_user_name", password) + password, + AbstractConfigurationValidator.ErrorType.WEAK_PASSWORD, + passwordValidator.validate("some_user_name", password) ); verifyStrongPasswords(passwordValidator, AbstractConfigurationValidator.ErrorType.NONE); verifyVeryStrongPasswords(passwordValidator, AbstractConfigurationValidator.ErrorType.NONE); @@ -153,17 +147,11 @@ public void testRegExpBasedValidation() { @Test public void testMinLength() { - final PasswordValidator passwordValidator = - PasswordValidator.of( - Settings.builder() - .put(SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, 15) - .build() - ); - for (final String password: STRONG_PASSWORDS) { - assertEquals( - AbstractConfigurationValidator.ErrorType.INVALID_PASSWORD, - passwordValidator.validate(password, "some_user_name") - ); + final PasswordValidator passwordValidator = PasswordValidator.of( + Settings.builder().put(SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, 15).build() + ); + for (final String password : STRONG_PASSWORDS) { + assertEquals(AbstractConfigurationValidator.ErrorType.INVALID_PASSWORD, passwordValidator.validate(password, "some_user_name")); } } @@ -178,13 +166,11 @@ public void testScoreBasedValidation() { verifyVeryStrongPasswords(passwordValidator, AbstractConfigurationValidator.ErrorType.NONE); verifySimilarPasswords(passwordValidator); - passwordValidator = - PasswordValidator.of( - Settings.builder() - .put( - SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH, - PasswordValidator.ScoreStrength.FAIR.name() - ).build()); + passwordValidator = PasswordValidator.of( + Settings.builder() + .put(SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH, PasswordValidator.ScoreStrength.FAIR.name()) + .build() + ); verifyWeakPasswords(passwordValidator, AbstractConfigurationValidator.ErrorType.WEAK_PASSWORD); verifyFairPasswords(passwordValidator, AbstractConfigurationValidator.ErrorType.NONE); diff --git a/src/test/java/org/opensearch/security/filter/SecurityFilterTest.java b/src/test/java/org/opensearch/security/filter/SecurityFilterTest.java index 9430450875..3e9cfe4b5e 100644 --- a/src/test/java/org/opensearch/security/filter/SecurityFilterTest.java +++ b/src/test/java/org/opensearch/security/filter/SecurityFilterTest.java @@ -59,32 +59,33 @@ public SecurityFilterTest(Settings settings, WildcardMatcher expected) { @Parameterized.Parameters public static Collection data() { - return Arrays.asList(new Object[][]{ - {Settings.EMPTY, WildcardMatcher.NONE}, - {Settings.builder() - .putList(ConfigConstants.SECURITY_COMPLIANCE_IMMUTABLE_INDICES, "immutable1", "immutable2") - .build(), - WildcardMatcher.from(ImmutableSet.of("immutable1", "immutable2"))}, - {Settings.builder() + return Arrays.asList( + new Object[][] { + { Settings.EMPTY, WildcardMatcher.NONE }, + { + Settings.builder().putList(ConfigConstants.SECURITY_COMPLIANCE_IMMUTABLE_INDICES, "immutable1", "immutable2").build(), + WildcardMatcher.from(ImmutableSet.of("immutable1", "immutable2")) }, + { + Settings.builder() .putList(ConfigConstants.SECURITY_COMPLIANCE_IMMUTABLE_INDICES, "immutable1", "immutable2", "immutable2") .build(), - WildcardMatcher.from(ImmutableSet.of("immutable1", "immutable2"))}, - }); + WildcardMatcher.from(ImmutableSet.of("immutable1", "immutable2")) }, } + ); } @Test public void testImmutableIndicesWildcardMatcher() { final SecurityFilter filter = new SecurityFilter( - settings, - mock(PrivilegesEvaluator.class), - mock(AdminDNs.class), - mock(DlsFlsRequestValve.class), - mock(AuditLog.class), - mock(ThreadPool.class), - mock(ClusterService.class), - mock(CompatConfig.class), - mock(IndexResolverReplacer.class), - mock(XFFResolver.class) + settings, + mock(PrivilegesEvaluator.class), + mock(AdminDNs.class), + mock(DlsFlsRequestValve.class), + mock(AuditLog.class), + mock(ThreadPool.class), + mock(ClusterService.class), + mock(CompatConfig.class), + mock(IndexResolverReplacer.class), + mock(XFFResolver.class) ); assertThat(expected, equalTo(filter.getImmutableIndicesMatcher())); } @@ -103,7 +104,7 @@ public void testUnexepectedCausesAreNotSendToCallers() { mock(AdminDNs.class), mock(DlsFlsRequestValve.class), auditLog, - new ThreadPool(Settings.builder().put("node.name", "mock").build()), + new ThreadPool(Settings.builder().put("node.name", "mock").build()), mock(ClusterService.class), mock(CompatConfig.class), mock(IndexResolverReplacer.class), @@ -119,8 +120,12 @@ public void testUnexepectedCausesAreNotSendToCallers() { final ArgumentCaptor cap = ArgumentCaptor.forClass(OpenSearchSecurityException.class); verify(listener).onFailure(cap.capture()); - assertThat("The cause should never be included as it will leak to callers", cap.getValue().getCause(), nullValue()); - assertThat("Make sure the cause exception wasn't toStringed in the method", cap.getValue().getMessage(), not(containsString("ABC!"))); + assertThat("The cause should never be included as it will leak to callers", cap.getValue().getCause(), nullValue()); + assertThat( + "Make sure the cause exception wasn't toStringed in the method", + cap.getValue().getMessage(), + not(containsString("ABC!")) + ); verifyNoMoreInteractions(auditLog, listener); } diff --git a/src/test/java/org/opensearch/security/filter/SecurityRestFilterTest.java b/src/test/java/org/opensearch/security/filter/SecurityRestFilterTest.java index 1a087887d8..692a950fb1 100644 --- a/src/test/java/org/opensearch/security/filter/SecurityRestFilterTest.java +++ b/src/test/java/org/opensearch/security/filter/SecurityRestFilterTest.java @@ -48,25 +48,29 @@ public void checkWhitelistedApisAreAccessible() throws Exception { setup(); - //ADD SOME WHITELISTED APIs + // ADD SOME WHITELISTED APIs rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_opendistro/_security/api/whitelist", "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", adminCredsHeader); + response = rh.executePutRequest( + "_opendistro/_security/api/whitelist", + "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", + adminCredsHeader + ); log.warn("the response is:" + rh.executeGetRequest("_opendistro/_security/api/whitelist", adminCredsHeader)); - //NON ADMIN TRIES ACCESSING A WHITELISTED API - OK + // NON ADMIN TRIES ACCESSING A WHITELISTED API - OK rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/nodes", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //ADMIN TRIES ACCESSING A WHITELISTED API - OK + // ADMIN TRIES ACCESSING A WHITELISTED API - OK rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/nodes", adminCredsHeader); log.warn("the second response is:{}", response); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //SUPERADMIN TRIES ACCESSING A WHITELISTED API - OK + // SUPERADMIN TRIES ACCESSING A WHITELISTED API - OK rh.sendAdminCertificate = true; response = rh.executeGetRequest("_cat/nodes", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); @@ -82,25 +86,29 @@ public void checkAllowlistedApisAreAccessible() throws Exception { setup(); - //ADD SOME ALLOWLISTED APIs + // ADD SOME ALLOWLISTED APIs rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_plugins/_security/api/allowlist", "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", adminCredsHeader); + response = rh.executePutRequest( + "_plugins/_security/api/allowlist", + "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", + adminCredsHeader + ); log.warn("the response is:" + rh.executeGetRequest("_plugins/_security/api/allowlist", adminCredsHeader)); - //NON ADMIN TRIES ACCESSING A ALLOWLISTED API - OK + // NON ADMIN TRIES ACCESSING A ALLOWLISTED API - OK rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/nodes", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //ADMIN TRIES ACCESSING A ALLOWLISTED API - OK + // ADMIN TRIES ACCESSING A ALLOWLISTED API - OK rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/nodes", adminCredsHeader); log.warn("the second response is:{}", response); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //SUPERADMIN TRIES ACCESSING A ALLOWLISTED API - OK + // SUPERADMIN TRIES ACCESSING A ALLOWLISTED API - OK rh.sendAdminCertificate = true; response = rh.executeGetRequest("_cat/nodes", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); @@ -115,22 +123,26 @@ public void checkAllowlistedApisAreAccessible() throws Exception { public void checkNonWhitelistedApisAccessibleOnlyBySuperAdmin() throws Exception { setup(); - //ADD SOME WHITELISTED APIs - /_cat/nodes and /_cat/indices + // ADD SOME WHITELISTED APIs - /_cat/nodes and /_cat/indices rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_opendistro/_security/api/whitelist", "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_opendistro/_security/api/whitelist", + "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", + nonAdminCredsHeader + ); - //NON ADMIN TRIES ACCESSING A NON-WHITELISTED API - FORBIDDEN + // NON ADMIN TRIES ACCESSING A NON-WHITELISTED API - FORBIDDEN rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/plugins", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //ADMIN TRIES ACCESSING A NON-WHITELISTED API - FORBIDDEN + // ADMIN TRIES ACCESSING A NON-WHITELISTED API - FORBIDDEN rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/plugins", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //SUPERADMIN TRIES ACCESSING A NON-WHITELISTED API - OK + // SUPERADMIN TRIES ACCESSING A NON-WHITELISTED API - OK rh.sendAdminCertificate = true; response = rh.executeGetRequest("_cat/plugins", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); @@ -145,22 +157,26 @@ public void checkNonWhitelistedApisAccessibleOnlyBySuperAdmin() throws Exception public void checkNonAllowlistedApisAccessibleOnlyBySuperAdmin() throws Exception { setup(); - //ADD SOME ALLOWLISTED APIs - /_cat/nodes and /_cat/indices + // ADD SOME ALLOWLISTED APIs - /_cat/nodes and /_cat/indices rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_plugins/_security/api/allowlist", "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_plugins/_security/api/allowlist", + "{\"enabled\": true, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", + nonAdminCredsHeader + ); - //NON ADMIN TRIES ACCESSING A NON-ALLOWLISTED API - FORBIDDEN + // NON ADMIN TRIES ACCESSING A NON-ALLOWLISTED API - FORBIDDEN rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/plugins", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //ADMIN TRIES ACCESSING A NON-ALLOWLISTED API - FORBIDDEN + // ADMIN TRIES ACCESSING A NON-ALLOWLISTED API - FORBIDDEN rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/plugins", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //SUPERADMIN TRIES ACCESSING A NON-ALLOWLISTED API - OK + // SUPERADMIN TRIES ACCESSING A NON-ALLOWLISTED API - OK rh.sendAdminCertificate = true; response = rh.executeGetRequest("_cat/plugins", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); @@ -173,26 +189,30 @@ public void checkNonAllowlistedApisAccessibleOnlyBySuperAdmin() throws Exception public void checkAllApisWhenWhitelistingNotEnabled() throws Exception { setup(); - //DISABLE WHITELISTING BUT ADD SOME WHITELISTED APIs - /_cat/nodes and /_cat/plugins + // DISABLE WHITELISTING BUT ADD SOME WHITELISTED APIs - /_cat/nodes and /_cat/plugins rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_opendistro/_security/api/whitelist", "{\"enabled\": false, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_opendistro/_security/api/whitelist", + "{\"enabled\": false, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", + nonAdminCredsHeader + ); - //NON-ADMIN TRIES ACCESSING 2 APIs: One in the list and one outside - OK for both (Because whitelisting is off) + // NON-ADMIN TRIES ACCESSING 2 APIs: One in the list and one outside - OK for both (Because whitelisting is off) rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/plugins", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); response = rh.executeGetRequest("_cat/nodes", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //ADMIN USER TRIES ACCESSING 2 APIs: One in the list and one outside - OK for both (Because whitelisting is off) + // ADMIN USER TRIES ACCESSING 2 APIs: One in the list and one outside - OK for both (Because whitelisting is off) rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/plugins", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); response = rh.executeGetRequest("_cat/nodes", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //SUPERADMIN TRIES ACCESSING 2 APIS - OK (would work even if whitelisting was on) + // SUPERADMIN TRIES ACCESSING 2 APIS - OK (would work even if whitelisting was on) rh.sendAdminCertificate = true; response = rh.executeGetRequest("_cat/plugins", adminCredsHeader); @@ -208,26 +228,30 @@ public void checkAllApisWhenWhitelistingNotEnabled() throws Exception { public void checkAllApisWhenAllowlistingNotEnabled() throws Exception { setup(); - //DISABLE ALLOWLISTED BUT ADD SOME ALLOWLISTED APIs - /_cat/nodes and /_cat/plugins + // DISABLE ALLOWLISTED BUT ADD SOME ALLOWLISTED APIs - /_cat/nodes and /_cat/plugins rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_plugins/_security/api/allowlist", "{\"enabled\": false, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_plugins/_security/api/allowlist", + "{\"enabled\": false, \"requests\": {\"/_cat/nodes\": [\"GET\"],\"/_cat/indices\": [\"GET\"] }}", + nonAdminCredsHeader + ); - //NON-ADMIN TRIES ACCESSING 2 APIs: One in the list and one outside - OK for both (Because allowlisting is off) + // NON-ADMIN TRIES ACCESSING 2 APIs: One in the list and one outside - OK for both (Because allowlisting is off) rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/plugins", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); response = rh.executeGetRequest("_cat/nodes", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //ADMIN USER TRIES ACCESSING 2 APIs: One in the list and one outside - OK for both (Because allowlisting is off) + // ADMIN USER TRIES ACCESSING 2 APIs: One in the list and one outside - OK for both (Because allowlisting is off) rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cat/plugins", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); response = rh.executeGetRequest("_cat/nodes", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //SUPERADMIN TRIES ACCESSING 2 APIS - OK (would work even if allowlisting was on) + // SUPERADMIN TRIES ACCESSING 2 APIS - OK (would work even if allowlisting was on) rh.sendAdminCertificate = true; response = rh.executeGetRequest("_cat/plugins", adminCredsHeader); @@ -245,34 +269,50 @@ public void checkAllApisWhenAllowlistingNotEnabled() throws Exception { * */ @Test - public void checkSpecificRequestMethodWhitelisting() throws Exception{ + public void checkSpecificRequestMethodWhitelisting() throws Exception { setup(); - //WHITELIST GET /_cluster/settings + // WHITELIST GET /_cluster/settings rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_opendistro/_security/api/whitelist", "{\"enabled\": true, \"requests\": {\"/_cluster/settings\": [\"GET\"]}}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_opendistro/_security/api/whitelist", + "{\"enabled\": true, \"requests\": {\"/_cluster/settings\": [\"GET\"]}}", + nonAdminCredsHeader + ); - //NON-ADMIN TRIES ACCESSING GET - OK, PUT - FORBIDDEN + // NON-ADMIN TRIES ACCESSING GET - OK, PUT - FORBIDDEN rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cluster/settings", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + nonAdminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //ADMIN USER TRIES ACCESSING GET - OK, PUT - FORBIDDEN + // ADMIN USER TRIES ACCESSING GET - OK, PUT - FORBIDDEN rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cluster/settings", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //SUPERADMIN TRIES ACCESSING GET - OK, PUT - OK + // SUPERADMIN TRIES ACCESSING GET - OK, PUT - OK rh.sendAdminCertificate = true; response = rh.executeGetRequest("_cluster/settings", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); } @@ -285,38 +325,53 @@ public void checkSpecificRequestMethodWhitelisting() throws Exception{ * */ @Test - public void checkSpecificRequestMethodAllowlisting() throws Exception{ + public void checkSpecificRequestMethodAllowlisting() throws Exception { setup(); - //WHITELIST GET /_cluster/settings + // WHITELIST GET /_cluster/settings rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_plugins/_security/api/allowlist", "{\"enabled\": true, \"requests\": {\"/_cluster/settings\": [\"GET\"]}}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_plugins/_security/api/allowlist", + "{\"enabled\": true, \"requests\": {\"/_cluster/settings\": [\"GET\"]}}", + nonAdminCredsHeader + ); - //NON-ADMIN TRIES ACCESSING GET - OK, PUT - FORBIDDEN + // NON-ADMIN TRIES ACCESSING GET - OK, PUT - FORBIDDEN rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cluster/settings", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + nonAdminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //ADMIN USER TRIES ACCESSING GET - OK, PUT - FORBIDDEN + // ADMIN USER TRIES ACCESSING GET - OK, PUT - FORBIDDEN rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cluster/settings", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //SUPERADMIN TRIES ACCESSING GET - OK, PUT - OK + // SUPERADMIN TRIES ACCESSING GET - OK, PUT - OK rh.sendAdminCertificate = true; response = rh.executeGetRequest("_cluster/settings", adminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); } - /** * Tests that a whitelisted API with an extra '/' does not cause an issue * i.e if only GET /_cluster/settings/ is whitelisted, then: @@ -327,29 +382,41 @@ public void checkSpecificRequestMethodAllowlisting() throws Exception{ * @throws Exception */ @Test - public void testWhitelistedApiWithExtraSlash() throws Exception{ + public void testWhitelistedApiWithExtraSlash() throws Exception { setup(); - //WHITELIST GET /_cluster/settings/ - extra / in the request + // WHITELIST GET /_cluster/settings/ - extra / in the request rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_opendistro/_security/api/whitelist", "{\"enabled\": true, \"requests\": {\"/_cluster/settings/\": [\"GET\"]}}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_opendistro/_security/api/whitelist", + "{\"enabled\": true, \"requests\": {\"/_cluster/settings/\": [\"GET\"]}}", + nonAdminCredsHeader + ); - //NON ADMIN ACCESS GET /_cluster/settings/ - OK + // NON ADMIN ACCESS GET /_cluster/settings/ - OK rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cluster/settings/", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //NON ADMIN ACCESS GET /_cluster/settings - OK + // NON ADMIN ACCESS GET /_cluster/settings - OK response = rh.executeGetRequest("_cluster/settings", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //NON ADMIN ACCESS PUT /_cluster/settings/ - FORBIDDEN - response = rh.executePutRequest("_cluster/settings/","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + // NON ADMIN ACCESS PUT /_cluster/settings/ - FORBIDDEN + response = rh.executePutRequest( + "_cluster/settings/", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //NON ADMIN ACCESS PUT /_cluster/settings - FORBIDDEN - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + // NON ADMIN ACCESS PUT /_cluster/settings - FORBIDDEN + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); } @@ -364,29 +431,41 @@ public void testWhitelistedApiWithExtraSlash() throws Exception{ * @throws Exception */ @Test - public void testAllowlistedApiWithExtraSlash() throws Exception{ + public void testAllowlistedApiWithExtraSlash() throws Exception { setup(); - //WHITELIST GET /_cluster/settings/ - extra / in the request + // WHITELIST GET /_cluster/settings/ - extra / in the request rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_plugins/_security/api/allowlist", "{\"enabled\": true, \"requests\": {\"/_cluster/settings/\": [\"GET\"]}}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_plugins/_security/api/allowlist", + "{\"enabled\": true, \"requests\": {\"/_cluster/settings/\": [\"GET\"]}}", + nonAdminCredsHeader + ); - //NON ADMIN ACCESS GET /_cluster/settings/ - OK + // NON ADMIN ACCESS GET /_cluster/settings/ - OK rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cluster/settings/", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //NON ADMIN ACCESS GET /_cluster/settings - OK + // NON ADMIN ACCESS GET /_cluster/settings - OK response = rh.executeGetRequest("_cluster/settings", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //NON ADMIN ACCESS PUT /_cluster/settings/ - FORBIDDEN - response = rh.executePutRequest("_cluster/settings/","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + // NON ADMIN ACCESS PUT /_cluster/settings/ - FORBIDDEN + response = rh.executePutRequest( + "_cluster/settings/", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //NON ADMIN ACCESS PUT /_cluster/settings - FORBIDDEN - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + // NON ADMIN ACCESS PUT /_cluster/settings - FORBIDDEN + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); } @@ -401,29 +480,41 @@ public void testAllowlistedApiWithExtraSlash() throws Exception{ * @throws Exception */ @Test - public void testWhitelistedApiWithoutExtraSlash() throws Exception{ + public void testWhitelistedApiWithoutExtraSlash() throws Exception { setup(); - //WHITELIST GET /_cluster/settings (no extra / in request) + // WHITELIST GET /_cluster/settings (no extra / in request) rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_opendistro/_security/api/whitelist", "{\"enabled\": true, \"requests\": {\"/_cluster/settings\": [\"GET\"]}}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_opendistro/_security/api/whitelist", + "{\"enabled\": true, \"requests\": {\"/_cluster/settings\": [\"GET\"]}}", + nonAdminCredsHeader + ); - //NON ADMIN ACCESS GET /_cluster/settings/ - OK + // NON ADMIN ACCESS GET /_cluster/settings/ - OK rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cluster/settings/", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //NON ADMIN ACCESS GET /_cluster/settings - OK + // NON ADMIN ACCESS GET /_cluster/settings - OK response = rh.executeGetRequest("_cluster/settings", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //NON ADMIN ACCESS PUT /_cluster/settings/ - FORBIDDEN - response = rh.executePutRequest("_cluster/settings/","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + // NON ADMIN ACCESS PUT /_cluster/settings/ - FORBIDDEN + response = rh.executePutRequest( + "_cluster/settings/", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //NON ADMIN ACCESS PUT /_cluster/settings - FORBIDDEN - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + // NON ADMIN ACCESS PUT /_cluster/settings - FORBIDDEN + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); } @@ -437,29 +528,41 @@ public void testWhitelistedApiWithoutExtraSlash() throws Exception{ * @throws Exception */ @Test - public void testAllowlistedApiWithoutExtraSlash() throws Exception{ + public void testAllowlistedApiWithoutExtraSlash() throws Exception { setup(); - //WHITELIST GET /_cluster/settings (no extra / in request) + // WHITELIST GET /_cluster/settings (no extra / in request) rh.keystore = "restapi/kirk-keystore.jks"; rh.sendAdminCertificate = true; - response = rh.executePutRequest("_plugins/_security/api/allowlist", "{\"enabled\": true, \"requests\": {\"/_cluster/settings\": [\"GET\"]}}", nonAdminCredsHeader); + response = rh.executePutRequest( + "_plugins/_security/api/allowlist", + "{\"enabled\": true, \"requests\": {\"/_cluster/settings\": [\"GET\"]}}", + nonAdminCredsHeader + ); - //NON ADMIN ACCESS GET /_cluster/settings/ - OK + // NON ADMIN ACCESS GET /_cluster/settings/ - OK rh.sendAdminCertificate = false; response = rh.executeGetRequest("_cluster/settings/", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //NON ADMIN ACCESS GET /_cluster/settings - OK + // NON ADMIN ACCESS GET /_cluster/settings - OK response = rh.executeGetRequest("_cluster/settings", nonAdminCredsHeader); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_OK)); - //NON ADMIN ACCESS PUT /_cluster/settings/ - FORBIDDEN - response = rh.executePutRequest("_cluster/settings/","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + // NON ADMIN ACCESS PUT /_cluster/settings/ - FORBIDDEN + response = rh.executePutRequest( + "_cluster/settings/", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - //NON ADMIN ACCESS PUT /_cluster/settings - FORBIDDEN - response = rh.executePutRequest("_cluster/settings","{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", adminCredsHeader); + // NON ADMIN ACCESS PUT /_cluster/settings - FORBIDDEN + response = rh.executePutRequest( + "_cluster/settings", + "{\"persistent\": { }, \"transient\": {\"indices.recovery.max_bytes_per_sec\": \"15mb\" }}", + adminCredsHeader + ); assertThat(response.getBody(), response.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); } } diff --git a/src/test/java/org/opensearch/security/http/HTTPOnBehalfOfJwtAuthenticatorTest.java b/src/test/java/org/opensearch/security/http/HTTPOnBehalfOfJwtAuthenticatorTest.java index 5a6c5ec41c..06f19a888a 100644 --- a/src/test/java/org/opensearch/security/http/HTTPOnBehalfOfJwtAuthenticatorTest.java +++ b/src/test/java/org/opensearch/security/http/HTTPOnBehalfOfJwtAuthenticatorTest.java @@ -53,10 +53,11 @@ public class HTTPOnBehalfOfJwtAuthenticatorTest { public void testNoKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - null, - claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy"), - false); + null, + claimsEncryptionKey, + Jwts.builder().setSubject("Leonard McCoy"), + false + ); Assert.assertNull(credentials); } @@ -65,10 +66,11 @@ public void testNoKey() throws Exception { public void testEmptyKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - "", - claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy"), - false); + "", + claimsEncryptionKey, + Jwts.builder().setSubject("Leonard McCoy"), + false + ); Assert.assertNull(credentials); } @@ -77,10 +79,11 @@ public void testEmptyKey() throws Exception { public void testBadKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - BaseEncoding.base64().encode(new byte[]{1,3,3,4,3,6,7,8,3,10}), - claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy"), - false); + BaseEncoding.base64().encode(new byte[] { 1, 3, 3, 4, 3, 6, 7, 8, 3, 10 }), + claimsEncryptionKey, + Jwts.builder().setSubject("Leonard McCoy"), + false + ); Assert.assertNull(credentials); } @@ -88,7 +91,10 @@ public void testBadKey() throws Exception { @Test public void testTokenMissing() throws Exception { - HTTPOnBehalfOfJwtAuthenticator jwtAuth = new HTTPOnBehalfOfJwtAuthenticator(BaseEncoding.base64().encode(secretKeyBytes),claimsEncryptionKey); + HTTPOnBehalfOfJwtAuthenticator jwtAuth = new HTTPOnBehalfOfJwtAuthenticator( + BaseEncoding.base64().encode(secretKeyBytes), + claimsEncryptionKey + ); Map headers = new HashMap(); AuthCredentials credentials = jwtAuth.extractCredentials(new FakeRestRequest(headers, new HashMap()), null); @@ -101,9 +107,12 @@ public void testInvalid() throws Exception { String jwsToken = "123invalidtoken.."; - HTTPOnBehalfOfJwtAuthenticator jwtAuth = new HTTPOnBehalfOfJwtAuthenticator(BaseEncoding.base64().encode(secretKeyBytes), claimsEncryptionKey); + HTTPOnBehalfOfJwtAuthenticator jwtAuth = new HTTPOnBehalfOfJwtAuthenticator( + BaseEncoding.base64().encode(secretKeyBytes), + claimsEncryptionKey + ); Map headers = new HashMap(); - headers.put("Authorization", "Bearer "+jwsToken); + headers.put("Authorization", "Bearer " + jwsToken); AuthCredentials credentials = jwtAuth.extractCredentials(new FakeRestRequest(headers, new HashMap()), null); Assert.assertNull(credentials); @@ -112,11 +121,18 @@ public void testInvalid() throws Exception { @Test public void testBearer() throws Exception { - String jwsToken = Jwts.builder().setSubject("Leonard McCoy").setAudience("ext_0").signWith(secretKey, SignatureAlgorithm.HS512).compact(); + String jwsToken = Jwts.builder() + .setSubject("Leonard McCoy") + .setAudience("ext_0") + .signWith(secretKey, SignatureAlgorithm.HS512) + .compact(); - HTTPOnBehalfOfJwtAuthenticator jwtAuth = new HTTPOnBehalfOfJwtAuthenticator(BaseEncoding.base64().encode(secretKeyBytes), claimsEncryptionKey); + HTTPOnBehalfOfJwtAuthenticator jwtAuth = new HTTPOnBehalfOfJwtAuthenticator( + BaseEncoding.base64().encode(secretKeyBytes), + claimsEncryptionKey + ); Map headers = new HashMap(); - headers.put("Authorization", "Bearer "+jwsToken); + headers.put("Authorization", "Bearer " + jwsToken); AuthCredentials credentials = jwtAuth.extractCredentials(new FakeRestRequest(headers, new HashMap()), null); @@ -142,7 +158,6 @@ public void testBearerWrongPosition() throws Exception { Assert.assertNull(credentials); } - @Test public void testBasicAuthHeader() throws Exception { Settings settings = Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKeyBytes)).build(); @@ -160,10 +175,11 @@ public void testRoles() throws Exception { List roles = List.of("IT", "HR"); final AuthCredentials credentials = extractCredentialsFromJwtHeader( - signingKey, - claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy").claim("dr", "role1,role2"), - true); + signingKey, + claimsEncryptionKey, + Jwts.builder().setSubject("Leonard McCoy").claim("dr", "role1,role2"), + true + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); @@ -174,10 +190,11 @@ public void testRoles() throws Exception { public void testNullClaim() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - signingKey, - claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy").claim("dr", null), - false); + signingKey, + claimsEncryptionKey, + Jwts.builder().setSubject("Leonard McCoy").claim("dr", null), + false + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); @@ -188,25 +205,27 @@ public void testNullClaim() throws Exception { public void testNonStringClaim() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - signingKey, - claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy").claim("dr", 123L), - true); + signingKey, + claimsEncryptionKey, + Jwts.builder().setSubject("Leonard McCoy").claim("dr", 123L), + true + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); Assert.assertEquals(1, credentials.getBackendRoles().size()); - Assert.assertTrue( credentials.getBackendRoles().contains("123")); + Assert.assertTrue(credentials.getBackendRoles().contains("123")); } @Test public void testRolesMissing() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - signingKey, - claimsEncryptionKey, - Jwts.builder().setSubject("Leonard McCoy"), - false); + signingKey, + claimsEncryptionKey, + Jwts.builder().setSubject("Leonard McCoy"), + false + ); Assert.assertNotNull(credentials); Assert.assertEquals("Leonard McCoy", credentials.getUsername()); @@ -217,10 +236,11 @@ public void testRolesMissing() throws Exception { public void testWrongSubjectKey() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - signingKey, - claimsEncryptionKey, - Jwts.builder().claim("roles", "role1,role2").claim("asub", "Dr. Who"), - false); + signingKey, + claimsEncryptionKey, + Jwts.builder().claim("roles", "role1,role2").claim("asub", "Dr. Who"), + false + ); Assert.assertNull(credentials); } @@ -229,10 +249,11 @@ public void testWrongSubjectKey() throws Exception { public void testExp() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - signingKey, - claimsEncryptionKey, - Jwts.builder().setSubject("Expired").setExpiration(new Date(100)), - false); + signingKey, + claimsEncryptionKey, + Jwts.builder().setSubject("Expired").setExpiration(new Date(100)), + false + ); Assert.assertNull(credentials); } @@ -241,10 +262,11 @@ public void testExp() throws Exception { public void testNbf() throws Exception { final AuthCredentials credentials = extractCredentialsFromJwtHeader( - signingKey, - claimsEncryptionKey, - Jwts.builder().setSubject("Expired").setNotBefore(new Date(System.currentTimeMillis()+(1000*36000))), - false); + signingKey, + claimsEncryptionKey, + Jwts.builder().setSubject("Expired").setNotBefore(new Date(System.currentTimeMillis() + (1000 * 36000))), + false + ); Assert.assertNull(credentials); } @@ -253,17 +275,9 @@ public void testNbf() throws Exception { public void testRolesArray() throws Exception { JwtBuilder builder = Jwts.builder() - .setPayload("{"+ - "\"sub\": \"Cluster_0\","+ - "\"aud\": \"ext_0\","+ - "\"dr\": \"a,b,3rd\""+ - "}"); + .setPayload("{" + "\"sub\": \"Cluster_0\"," + "\"aud\": \"ext_0\"," + "\"dr\": \"a,b,3rd\"" + "}"); - final AuthCredentials credentials = extractCredentialsFromJwtHeader( - signingKey, - claimsEncryptionKey, - builder, - true); + final AuthCredentials credentials = extractCredentialsFromJwtHeader(signingKey, claimsEncryptionKey, builder, true); Assert.assertNotNull(credentials); Assert.assertEquals("Cluster_0", credentials.getUsername()); @@ -275,10 +289,11 @@ public void testRolesArray() throws Exception { /** extracts a default user credential from a request header */ private AuthCredentials extractCredentialsFromJwtHeader( - final String signingKey, - final String encryptionKey, - final JwtBuilder jwtBuilder, - final Boolean bwcPluginCompatibilityMode) { + final String signingKey, + final String encryptionKey, + final JwtBuilder jwtBuilder, + final Boolean bwcPluginCompatibilityMode + ) { final String jwsToken = jwtBuilder.signWith(secretKey, SignatureAlgorithm.HS512).compact(); final HTTPOnBehalfOfJwtAuthenticator jwtAuth = new HTTPOnBehalfOfJwtAuthenticator(signingKey, encryptionKey); final Map headers = Map.of("Authorization", "Bearer " + jwsToken); diff --git a/src/test/java/org/opensearch/security/http/proxy/HTTPExtendedProxyAuthenticatorTest.java b/src/test/java/org/opensearch/security/http/proxy/HTTPExtendedProxyAuthenticatorTest.java index 111a07bf40..47d779cd12 100644 --- a/src/test/java/org/opensearch/security/http/proxy/HTTPExtendedProxyAuthenticatorTest.java +++ b/src/test/java/org/opensearch/security/http/proxy/HTTPExtendedProxyAuthenticatorTest.java @@ -65,9 +65,7 @@ public class HTTPExtendedProxyAuthenticatorTest { @Before public void setup() { context.putTransient(ConfigConstants.OPENDISTRO_SECURITY_XFF_DONE, Boolean.TRUE); - settings = Settings.builder() - .put("user_header","user") - .build(); + settings = Settings.builder().put("user_header", "user").build(); authenticator = new HTTPExtendedProxyAuthenticator(settings, null); } @@ -79,7 +77,7 @@ public void testGetType() { @Test(expected = OpenSearchSecurityException.class) public void testThrowsExceptionWhenMissingXFFDone() { authenticator = new HTTPExtendedProxyAuthenticator(Settings.EMPTY, null); - authenticator.extractCredentials(new TestRestRequest(), new ThreadContext(Settings.EMPTY)); + authenticator.extractCredentials(new TestRestRequest(), new ThreadContext(Settings.EMPTY)); } @Test @@ -90,11 +88,12 @@ public void testReturnsNullWhenUserHeaderIsUnconfigured() { @Test public void testReturnsNullWhenUserHeaderIsMissing() { - + assertNull(authenticator.extractCredentials(new TestRestRequest(), context)); } + @Test - + public void testReturnsCredentials() { headers.put("user", new ArrayList<>()); headers.put("proxy_uid", new ArrayList<>()); @@ -103,9 +102,9 @@ public void testReturnsCredentials() { headers.get("proxy_uid").add("123"); headers.get("proxy_uid").add("456"); headers.get("proxy_other").add("someothervalue"); - - settings = Settings.builder().put(settings).put("attr_header_prefix","proxy_").build(); - authenticator = new HTTPExtendedProxyAuthenticator(settings,null); + + settings = Settings.builder().put(settings).put("attr_header_prefix", "proxy_").build(); + authenticator = new HTTPExtendedProxyAuthenticator(settings, null); AuthCredentials creds = authenticator.extractCredentials(new TestRestRequest(headers), context); assertNotNull(creds); assertEquals("aValidUser", creds.getUsername()); @@ -113,19 +112,16 @@ public void testReturnsCredentials() { assertEquals("someothervalue", creds.getAttributes().get("attr.proxy.other")); assertTrue(creds.isComplete()); } - + @Test public void testTrimOnRoles() { - headers.put("user", new ArrayList<>()); + headers.put("user", new ArrayList<>()); headers.put("roles", new ArrayList<>()); headers.get("user").add("aValidUser"); headers.get("roles").add("role1, role2,\t"); - - settings = Settings.builder().put(settings) - .put("roles_header","roles") - .put("roles_separator", ",") - .build(); - authenticator = new HTTPExtendedProxyAuthenticator(settings,null); + + settings = Settings.builder().put(settings).put("roles_header", "roles").put("roles_separator", ",").build(); + authenticator = new HTTPExtendedProxyAuthenticator(settings, null); AuthCredentials creds = authenticator.extractCredentials(new TestRestRequest(headers), context); assertNotNull(creds); assertEquals("aValidUser", creds.getUsername()); @@ -134,16 +130,22 @@ public void testTrimOnRoles() { } static class TestRestRequest extends RestRequest { - + public TestRestRequest() { - super(NamedXContentRegistry.EMPTY, new HashMap<>(), "", new HashMap<>(),new HttpRequestImpl(),new HttpChannelImpl()); + super(NamedXContentRegistry.EMPTY, new HashMap<>(), "", new HashMap<>(), new HttpRequestImpl(), new HttpChannelImpl()); } + public TestRestRequest(Map> headers) { - super(NamedXContentRegistry.EMPTY, new HashMap<>(), "", headers, new HttpRequestImpl(),new HttpChannelImpl()); + super(NamedXContentRegistry.EMPTY, new HashMap<>(), "", headers, new HttpRequestImpl(), new HttpChannelImpl()); } - public TestRestRequest(NamedXContentRegistry xContentRegistry, Map params, String path, - Map> headers) { - super(xContentRegistry, params, path, headers, new HttpRequestImpl(),new HttpChannelImpl()); + + public TestRestRequest( + NamedXContentRegistry xContentRegistry, + Map params, + String path, + Map> headers + ) { + super(xContentRegistry, params, path, headers, new HttpRequestImpl(), new HttpChannelImpl()); } @Override @@ -162,7 +164,7 @@ public boolean hasContent() { } } - + static class HttpRequestImpl implements HttpRequest { @Override @@ -228,19 +230,19 @@ public Exception getInboundException() { return null; } } - + static class HttpChannelImpl implements HttpChannel { @Override public void close() { // TODO Auto-generated method stub - + } @Override public void addCloseListener(ActionListener listener) { // TODO Auto-generated method stub - + } @Override @@ -252,7 +254,7 @@ public boolean isOpen() { @Override public void sendResponse(HttpResponse response, ActionListener listener) { // TODO Auto-generated method stub - + } @Override @@ -266,6 +268,6 @@ public InetSocketAddress getRemoteAddress() { // TODO Auto-generated method stub return null; } - + } } diff --git a/src/test/java/org/opensearch/security/httpclient/HttpClientTest.java b/src/test/java/org/opensearch/security/httpclient/HttpClientTest.java index 96d41b6735..3da6ad3d7f 100644 --- a/src/test/java/org/opensearch/security/httpclient/HttpClientTest.java +++ b/src/test/java/org/opensearch/security/httpclient/HttpClientTest.java @@ -30,38 +30,44 @@ protected String getResourceFolder() { @Test public void testPlainConnection() throws Exception { - final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled", false) - .build(); + final Settings settings = Settings.builder().put("plugins.security.ssl.http.enabled", false).build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings); Thread.sleep(1000); - try(final HttpClient httpClient = HttpClient.builder(clusterInfo.httpHost+":"+clusterInfo.httpPort) - .setBasicCredentials("admin", "admin").build()) { + try ( + final HttpClient httpClient = HttpClient.builder(clusterInfo.httpHost + ":" + clusterInfo.httpPort) + .setBasicCredentials("admin", "admin") + .build() + ) { Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", false)); Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", true)); Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", true)); } - try(final HttpClient httpClient = HttpClient.builder("unknownhost:6654") - .setBasicCredentials("admin", "admin").build()) { + try (final HttpClient httpClient = HttpClient.builder("unknownhost:6654").setBasicCredentials("admin", "admin").build()) { Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", false)); Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", true)); Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", true)); } - try(final HttpClient httpClient = HttpClient.builder("unknownhost:6654", clusterInfo.httpHost+":"+clusterInfo.httpPort) - .enableSsl(FileHelper.getKeystoreFromClassPath("auditlog/truststore.jks","changeit"), false) - .setBasicCredentials("admin", "admin").build()) { + try ( + final HttpClient httpClient = HttpClient.builder("unknownhost:6654", clusterInfo.httpHost + ":" + clusterInfo.httpPort) + .enableSsl(FileHelper.getKeystoreFromClassPath("auditlog/truststore.jks", "changeit"), false) + .setBasicCredentials("admin", "admin") + .build() + ) { Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", false)); Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", true)); Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", true)); } - try(final HttpClient httpClient = HttpClient.builder("unknownhost:6654", clusterInfo.httpHost+":"+clusterInfo.httpPort) - .setBasicCredentials("admin", "admin").build()) { + try ( + final HttpClient httpClient = HttpClient.builder("unknownhost:6654", clusterInfo.httpHost + ":" + clusterInfo.httpPort) + .setBasicCredentials("admin", "admin") + .build() + ) { Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", false)); Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", true)); Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", true)); @@ -73,27 +79,33 @@ public void testPlainConnection() throws Exception { public void testSslConnection() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled", true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, false) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, false) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings); Thread.sleep(1000); - try(final HttpClient httpClient = HttpClient.builder(clusterInfo.httpHost+":"+clusterInfo.httpPort) - .enableSsl(FileHelper.getKeystoreFromClassPath("auditlog/truststore.jks","changeit"), false) - .setBasicCredentials("admin", "admin").build()) { + try ( + final HttpClient httpClient = HttpClient.builder(clusterInfo.httpHost + ":" + clusterInfo.httpPort) + .enableSsl(FileHelper.getKeystoreFromClassPath("auditlog/truststore.jks", "changeit"), false) + .setBasicCredentials("admin", "admin") + .build() + ) { Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", false)); Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", true)); Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", true)); } - try(final HttpClient httpClient = HttpClient.builder(clusterInfo.httpHost+":"+clusterInfo.httpPort) - .setBasicCredentials("admin", "admin").build()) { + try ( + final HttpClient httpClient = HttpClient.builder(clusterInfo.httpHost + ":" + clusterInfo.httpPort) + .setBasicCredentials("admin", "admin") + .build() + ) { Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", false)); Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", true)); Assert.assertFalse(httpClient.index("{\"a\":5}", "index", "type", true)); @@ -105,22 +117,28 @@ public void testSslConnection() throws Exception { public void testSslConnectionPKIAuth() throws Exception { final Settings settings = Settings.builder() - .put("plugins.security.ssl.http.enabled", true) - .put("plugins.security.ssl.http.clientauth_mode", "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, false) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) - .build(); + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.clientauth_mode", "REQUIRE") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, false) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("auditlog/truststore.jks")) + .build(); setup(Settings.EMPTY, new DynamicSecurityConfig(), settings); Thread.sleep(1000); - try(final HttpClient httpClient = HttpClient.builder(clusterInfo.httpHost+":"+clusterInfo.httpPort) - .enableSsl(FileHelper.getKeystoreFromClassPath("auditlog/truststore.jks","changeit"), false) - .setPkiCredentials(FileHelper.getKeystoreFromClassPath("auditlog/spock-keystore.jks", "changeit"), "changeit".toCharArray(), null) - .build()) { + try ( + final HttpClient httpClient = HttpClient.builder(clusterInfo.httpHost + ":" + clusterInfo.httpPort) + .enableSsl(FileHelper.getKeystoreFromClassPath("auditlog/truststore.jks", "changeit"), false) + .setPkiCredentials( + FileHelper.getKeystoreFromClassPath("auditlog/spock-keystore.jks", "changeit"), + "changeit".toCharArray(), + null + ) + .build() + ) { Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", false)); Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", true)); Assert.assertTrue(httpClient.index("{\"a\":5}", "index", "type", true)); diff --git a/src/test/java/org/opensearch/security/multitenancy/test/MultitenancyTests.java b/src/test/java/org/opensearch/security/multitenancy/test/MultitenancyTests.java index 5177dbae10..648f5df4a0 100644 --- a/src/test/java/org/opensearch/security/multitenancy/test/MultitenancyTests.java +++ b/src/test/java/org/opensearch/security/multitenancy/test/MultitenancyTests.java @@ -50,210 +50,321 @@ protected String getResourceFolder() { @Test public void testNoDnfof() throws Exception { - final Settings settings = Settings.builder() - .put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH") - .build(); + final Settings settings = Settings.builder().put(ConfigConstants.SECURITY_ROLES_MAPPING_RESOLUTION, "BOTH").build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_nodnfof.yml"), settings); final RestHelper rh = nonSslRestHelper(); - try (Client tc = getClient()) { - tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); - - tc.index(new IndexRequest("indexa").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":\"indexa\"}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("indexb").id("0").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":\"indexb\"}", XContentType.JSON)).actionGet(); - - - tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - tc.index(new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)).actionGet(); - - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("starfleet","starfleet_academy","starfleet_library").alias("sf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire","vulcangov").alias("nonsf"))).actionGet(); - tc.admin().indices().aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))).actionGet(); - - } - - HttpResponse resc; - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_b", "user_b"))).getStatusCode()); - System.out.println(resc.getBody()); - - String msearchBody = - "{\"index\":\"indexa\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"indexb\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - System.out.println("#### msearch a"); - resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_a", "user_a")); - Assert.assertEquals(200, resc.getStatusCode()); - System.out.println(resc.getBody()); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexa")); - Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexb")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); - - System.out.println("#### msearch b"); - resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_b", "user_b")); - Assert.assertEquals(200, resc.getStatusCode()); - System.out.println(resc.getBody()); - Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexa")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexb")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); - - msearchBody = - "{\"index\":\"indexc\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator()+ - "{\"index\":\"indexd\", \"ignore_unavailable\": true}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - - System.out.println("#### msearch b2"); - resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_b", "user_b")); - System.out.println(resc.getBody()); - Assert.assertEquals(200, resc.getStatusCode()); - Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexc")); - Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexd")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); - int count = resc.getBody().split("\"status\" : 403").length; - Assert.assertEquals(3, count); - - String mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"indexa\","+ - "\"_id\" : \"0\""+ - " },"+ - " {"+ - "\"_index\" : \"indexb\","+ - " \"_id\" : \"0\""+ - "}"+ - "]"+ - "}"; - - resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); - Assert.assertEquals(200, resc.getStatusCode()); - Assert.assertFalse(resc.getBody(), resc.getBody().contains("\"content\" : \"indexa\"")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexb")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); - - mgetBody = "{"+ - "\"docs\" : ["+ - "{"+ - "\"_index\" : \"indexx\","+ - "\"_id\" : \"0\""+ - " },"+ - " {"+ - "\"_index\" : \"indexy\","+ - " \"_id\" : \"0\""+ - "}"+ - "]"+ - "}"; - - resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); - Assert.assertEquals(200, resc.getStatusCode()); - Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); - count = resc.getBody().split("root_cause").length; - Assert.assertEquals(3, count); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("index*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - - - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("indexa/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("_all/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("notexists/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_NOT_FOUND, (resc=rh.executeGetRequest("indexanbh,indexabb*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (resc=rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode()); - System.out.println(resc.getBody()); - - Assert.assertEquals(HttpStatus.SC_OK, (resc=rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode()); - System.out.println(resc.getBody()); + try (Client tc = getClient()) { + tc.admin().indices().create(new CreateIndexRequest("copysf")).actionGet(); + + tc.index( + new IndexRequest("indexa").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":\"indexa\"}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("indexb").id("0") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source("{\"content\":\"indexb\"}", XContentType.JSON) + ).actionGet(); + + tc.index(new IndexRequest("vulcangov").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("starfleet").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("starfleet_academy").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("starfleet_library").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index( + new IndexRequest("klingonempire").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + tc.index(new IndexRequest("public").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + + tc.index(new IndexRequest("spock").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index(new IndexRequest("kirk").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest("role01_role02").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"content\":1}", XContentType.JSON) + ).actionGet(); + + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction( + AliasActions.add().indices("starfleet", "starfleet_academy", "starfleet_library").alias("sf") + ) + ) + .actionGet(); + tc.admin() + .indices() + .aliases( + new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("klingonempire", "vulcangov").alias("nonsf")) + ) + .actionGet(); + tc.admin() + .indices() + .aliases(new IndicesAliasesRequest().addAliasAction(AliasActions.add().indices("public").alias("unrestricted"))) + .actionGet(); + + } + + HttpResponse resc; + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("indexa,indexb/_search?pretty", encodeBasicHeader("user_b", "user_b"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + String msearchBody = "{\"index\":\"indexa\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"indexb\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); + System.out.println("#### msearch a"); + resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_a", "user_a")); + Assert.assertEquals(200, resc.getStatusCode()); + System.out.println(resc.getBody()); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexa")); + Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexb")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); + + System.out.println("#### msearch b"); + resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_b", "user_b")); + Assert.assertEquals(200, resc.getStatusCode()); + System.out.println(resc.getBody()); + Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexa")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexb")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); + + msearchBody = "{\"index\":\"indexc\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator() + + "{\"index\":\"indexd\", \"ignore_unavailable\": true}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); + + System.out.println("#### msearch b2"); + resc = rh.executePostRequest("_msearch?pretty", msearchBody, encodeBasicHeader("user_b", "user_b")); + System.out.println(resc.getBody()); + Assert.assertEquals(200, resc.getStatusCode()); + Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexc")); + Assert.assertFalse(resc.getBody(), resc.getBody().contains("indexd")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); + int count = resc.getBody().split("\"status\" : 403").length; + Assert.assertEquals(3, count); + + String mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"indexa\"," + + "\"_id\" : \"0\"" + + " }," + + " {" + + "\"_index\" : \"indexb\"," + + " \"_id\" : \"0\"" + + "}" + + "]" + + "}"; + + resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); + Assert.assertEquals(200, resc.getStatusCode()); + Assert.assertFalse(resc.getBody(), resc.getBody().contains("\"content\" : \"indexa\"")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("indexb")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("permission")); + + mgetBody = "{" + + "\"docs\" : [" + + "{" + + "\"_index\" : \"indexx\"," + + "\"_id\" : \"0\"" + + " }," + + " {" + + "\"_index\" : \"indexy\"," + + " \"_id\" : \"0\"" + + "}" + + "]" + + "}"; + + resc = rh.executePostRequest("_mget?pretty", mgetBody, encodeBasicHeader("user_b", "user_b")); + Assert.assertEquals(200, resc.getStatusCode()); + Assert.assertTrue(resc.getBody(), resc.getBody().contains("exception")); + count = resc.getBody().split("root_cause").length; + Assert.assertEquals(3, count); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("index*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("indexa/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("indexb/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("_all/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("notexists/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + Assert.assertEquals( + HttpStatus.SC_NOT_FOUND, + (resc = rh.executeGetRequest("indexanbh,indexabb*/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (resc = rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("user_a", "user_a"))).getStatusCode() + ); + System.out.println(resc.getBody()); + + Assert.assertEquals( + HttpStatus.SC_OK, + (resc = rh.executeGetRequest("starfleet/_search?pretty", encodeBasicHeader("worf", "worf"))).getStatusCode() + ); + System.out.println(resc.getBody()); } @Test public void testMt() throws Exception { - final Settings settings = Settings.builder() - .build(); + final Settings settings = Settings.builder().build(); setup(settings); final RestHelper rh = nonSslRestHelper(); HttpResponse res; String body = "{\"buildNum\": 15460, \"defaultIndex\": \"humanresources\", \"tenant\": \"human_resources\"}"; - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executePutRequest(".kibana/_doc/5.6.0?pretty",body, new BasicHeader("securitytenant", "blafasel"), encodeBasicHeader("hr_employee", "hr_employee"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePutRequest( + ".kibana/_doc/5.6.0?pretty", + body, + new BasicHeader("securitytenant", "blafasel"), + encodeBasicHeader("hr_employee", "hr_employee") + )).getStatusCode() + ); body = "{\"buildNum\": 15460, \"defaultIndex\": \"humanresources\", \"tenant\": \"human_resources\"}"; - Assert.assertEquals(HttpStatus.SC_FORBIDDEN, (res = rh.executePutRequest(".kibana/_doc/5.6.0?pretty",body, new BasicHeader("securitytenant", "business_intelligence"), encodeBasicHeader("hr_employee", "hr_employee"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_FORBIDDEN, + (res = rh.executePutRequest( + ".kibana/_doc/5.6.0?pretty", + body, + new BasicHeader("securitytenant", "business_intelligence"), + encodeBasicHeader("hr_employee", "hr_employee") + )).getStatusCode() + ); body = "{\"buildNum\": 15460, \"defaultIndex\": \"humanresources\", \"tenant\": \"human_resources\"}"; - Assert.assertEquals(HttpStatus.SC_CREATED, (res = rh.executePutRequest(".kibana/_doc/5.6.0?pretty",body, new BasicHeader("securitytenant", "human_resources"), encodeBasicHeader("hr_employee", "hr_employee"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_CREATED, + (res = rh.executePutRequest( + ".kibana/_doc/5.6.0?pretty", + body, + new BasicHeader("securitytenant", "human_resources"), + encodeBasicHeader("hr_employee", "hr_employee") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertEquals(".kibana_1592542611_humanresources_1", DefaultObjectMapper.readTree(res.getBody()).get("_index").asText()); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest(".kibana/_doc/5.6.0?pretty",new BasicHeader("securitytenant", "human_resources"), encodeBasicHeader("hr_employee", "hr_employee"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + ".kibana/_doc/5.6.0?pretty", + new BasicHeader("securitytenant", "human_resources"), + encodeBasicHeader("hr_employee", "hr_employee") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(WildcardMatcher.from("*human_resources*").test(res.getBody())); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest(".kibana_1592542611_humanresources_1/_alias", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest(".kibana_1592542611_humanresources_1/_alias", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); System.out.println(res.getBody()); - Assert.assertNotNull(DefaultObjectMapper.readTree(res.getBody()).get(".kibana_1592542611_humanresources_1").get("aliases").get(".kibana_1592542611_humanresources")); + Assert.assertNotNull( + DefaultObjectMapper.readTree(res.getBody()) + .get(".kibana_1592542611_humanresources_1") + .get("aliases") + .get(".kibana_1592542611_humanresources") + ); } - @Test public void testMtMulti() throws Exception { - final Settings settings = Settings.builder() - .build(); + final Settings settings = Settings.builder().build(); setup(settings); final String dashboardsIndex = ".kibana_92668751_admin_1"; try (Client tc = getClient()) { - String body = "{"+ - "\"type\" : \"index-pattern\","+ - "\"updated_at\" : \"2018-09-29T08:56:59.066Z\","+ - "\"index-pattern\" : {"+ - "\"title\" : \"humanresources\""+ - "}}"; + String body = "{" + + "\"type\" : \"index-pattern\"," + + "\"updated_at\" : \"2018-09-29T08:56:59.066Z\"," + + "\"index-pattern\" : {" + + "\"title\" : \"humanresources\"" + + "}}"; Map indexSettings = new HashMap(); indexSettings.put("number_of_shards", 1); indexSettings.put("number_of_replicas", 0); - tc.admin().indices().create(new CreateIndexRequest(dashboardsIndex) - .settings(indexSettings) - .alias(new Alias(".kibana_92668751_admin"))) + tc.admin() + .indices() + .create(new CreateIndexRequest(dashboardsIndex).settings(indexSettings).alias(new Alias(".kibana_92668751_admin"))) .actionGet(); - tc.index(new IndexRequest(dashboardsIndex) - .id("index-pattern:9fbbd1a0-c3c5-11e8-a13f-71b8ea5a4f7b") + tc.index( + new IndexRequest(dashboardsIndex).id("index-pattern:9fbbd1a0-c3c5-11e8-a13f-71b8ea5a4f7b") .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(body, XContentType.JSON)).actionGet(); + .source(body, XContentType.JSON) + ).actionGet(); } final RestHelper rh = nonSslRestHelper(); @@ -261,28 +372,52 @@ public void testMtMulti() throws Exception { System.out.println("#### search"); HttpResponse res; String body = "{\"query\" : {\"term\" : { \"_id\" : \"index-pattern:9fbbd1a0-c3c5-11e8-a13f-71b8ea5a4f7b\"}}}"; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest(".kibana/_search/?pretty",body, new BasicHeader("securitytenant", "__user__"), encodeBasicHeader("admin", "admin"))).getStatusCode()); - //System.out.println(res.getBody()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + ".kibana/_search/?pretty", + body, + new BasicHeader("securitytenant", "__user__"), + encodeBasicHeader("admin", "admin") + )).getStatusCode() + ); + // System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("exception")); Assert.assertTrue(res.getBody().contains("humanresources")); Assert.assertTrue(res.getBody().contains("\"value\" : 1")); Assert.assertTrue(res.getBody().contains(dashboardsIndex)); System.out.println("#### msearch"); - body = - "{\"index\":\".kibana\", \"ignore_unavailable\": false}"+System.lineSeparator()+ - "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}"+System.lineSeparator(); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_msearch/?pretty",body, new BasicHeader("securitytenant", "__user__"), encodeBasicHeader("admin", "admin"))).getStatusCode()); - //System.out.println(res.getBody()); + body = "{\"index\":\".kibana\", \"ignore_unavailable\": false}" + + System.lineSeparator() + + "{\"size\":10, \"query\":{\"bool\":{\"must\":{\"match_all\":{}}}}}" + + System.lineSeparator(); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "_msearch/?pretty", + body, + new BasicHeader("securitytenant", "__user__"), + encodeBasicHeader("admin", "admin") + )).getStatusCode() + ); + // System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("exception")); Assert.assertTrue(res.getBody().contains("humanresources")); Assert.assertTrue(res.getBody().contains("\"value\" : 1")); Assert.assertTrue(res.getBody().contains(dashboardsIndex)); System.out.println("#### get"); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest(".kibana/_doc/index-pattern:9fbbd1a0-c3c5-11e8-a13f-71b8ea5a4f7b?pretty", new BasicHeader("securitytenant", "__user__"), encodeBasicHeader("admin", "admin"))).getStatusCode()); - //System.out.println(res.getBody()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + ".kibana/_doc/index-pattern:9fbbd1a0-c3c5-11e8-a13f-71b8ea5a4f7b?pretty", + new BasicHeader("securitytenant", "__user__"), + encodeBasicHeader("admin", "admin") + )).getStatusCode() + ); + // System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("exception")); Assert.assertTrue(res.getBody().contains("humanresources")); Assert.assertTrue(res.getBody().contains("\"found\" : true")); @@ -290,40 +425,70 @@ public void testMtMulti() throws Exception { System.out.println("#### mget"); body = "{\"docs\" : [{\"_index\" : \".kibana\",\"_id\" : \"index-pattern:9fbbd1a0-c3c5-11e8-a13f-71b8ea5a4f7b\"}]}"; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePostRequest("_mget/?pretty",body, new BasicHeader("securitytenant", "__user__"), encodeBasicHeader("admin", "admin"))).getStatusCode()); - //System.out.println(res.getBody()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePostRequest( + "_mget/?pretty", + body, + new BasicHeader("securitytenant", "__user__"), + encodeBasicHeader("admin", "admin") + )).getStatusCode() + ); + // System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("exception")); Assert.assertTrue(res.getBody().contains("humanresources")); Assert.assertTrue(res.getBody().contains(dashboardsIndex)); System.out.println("#### index"); - body = "{"+ - "\"type\" : \"index-pattern\","+ - "\"updated_at\" : \"2017-09-29T08:56:59.066Z\","+ - "\"index-pattern\" : {"+ - "\"title\" : \"xyz\""+ - "}}"; - Assert.assertEquals(HttpStatus.SC_CREATED, (res = rh.executePutRequest(".kibana/_doc/abc?pretty",body, new BasicHeader("securitytenant", "__user__"), encodeBasicHeader("admin", "admin"))).getStatusCode()); - //System.out.println(res.getBody()); + body = "{" + + "\"type\" : \"index-pattern\"," + + "\"updated_at\" : \"2017-09-29T08:56:59.066Z\"," + + "\"index-pattern\" : {" + + "\"title\" : \"xyz\"" + + "}}"; + Assert.assertEquals( + HttpStatus.SC_CREATED, + (res = rh.executePutRequest( + ".kibana/_doc/abc?pretty", + body, + new BasicHeader("securitytenant", "__user__"), + encodeBasicHeader("admin", "admin") + )).getStatusCode() + ); + // System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("exception")); Assert.assertTrue(res.getBody().contains("\"result\" : \"created\"")); Assert.assertTrue(res.getBody().contains(dashboardsIndex)); System.out.println("#### bulk"); - body = - "{ \"index\" : { \"_index\" : \".kibana\", \"_id\" : \"b1\" } }"+System.lineSeparator()+ - "{ \"field1\" : \"value1\" }" +System.lineSeparator()+ - "{ \"index\" : { \"_index\" : \".kibana\", \"_id\" : \"b2\" } }"+System.lineSeparator()+ - "{ \"field2\" : \"value2\" }"+System.lineSeparator(); - - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executePutRequest("_bulk?pretty",body, new BasicHeader("securitytenant", "__user__"), encodeBasicHeader("admin", "admin"))).getStatusCode()); - //System.out.println(res.getBody()); + body = "{ \"index\" : { \"_index\" : \".kibana\", \"_id\" : \"b1\" } }" + + System.lineSeparator() + + "{ \"field1\" : \"value1\" }" + + System.lineSeparator() + + "{ \"index\" : { \"_index\" : \".kibana\", \"_id\" : \"b2\" } }" + + System.lineSeparator() + + "{ \"field2\" : \"value2\" }" + + System.lineSeparator(); + + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executePutRequest( + "_bulk?pretty", + body, + new BasicHeader("securitytenant", "__user__"), + encodeBasicHeader("admin", "admin") + )).getStatusCode() + ); + // System.out.println(res.getBody()); Assert.assertFalse(res.getBody().contains("exception")); Assert.assertTrue(res.getBody().contains(dashboardsIndex)); Assert.assertTrue(res.getBody().contains("\"errors\" : false")); Assert.assertTrue(res.getBody().contains("\"result\" : \"created\"")); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest("_cat/indices", encodeBasicHeader("admin", "admin"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest("_cat/indices", encodeBasicHeader("admin", "admin"))).getStatusCode() + ); Assert.assertEquals(2, res.getBody().split(".kibana").length); Assert.assertTrue(res.getBody().contains(dashboardsIndex)); @@ -331,8 +496,7 @@ public void testMtMulti() throws Exception { @Test public void testDashboardsAlias() throws Exception { - final Settings settings = Settings.builder() - .build(); + final Settings settings = Settings.builder().build(); setup(settings); try (Client tc = getClient()) { @@ -340,19 +504,26 @@ public void testDashboardsAlias() throws Exception { Map indexSettings = new HashMap(); indexSettings.put("number_of_shards", 1); indexSettings.put("number_of_replicas", 0); - tc.admin().indices().create(new CreateIndexRequest(".kibana-6") - .alias(new Alias(".kibana")) - .settings(indexSettings)) + tc.admin() + .indices() + .create(new CreateIndexRequest(".kibana-6").alias(new Alias(".kibana")).settings(indexSettings)) .actionGet(); - tc.index(new IndexRequest(".kibana-6").id("6.2.2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(body, XContentType.JSON)).actionGet(); + tc.index(new IndexRequest(".kibana-6").id("6.2.2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(body, XContentType.JSON)) + .actionGet(); } final RestHelper rh = nonSslRestHelper(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest(".kibana-6/_doc/6.2.2?pretty", encodeBasicHeader("kibanaro", "kibanaro"))).getStatusCode()); - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest(".kibana/_doc/6.2.2?pretty", encodeBasicHeader("kibanaro", "kibanaro"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest(".kibana-6/_doc/6.2.2?pretty", encodeBasicHeader("kibanaro", "kibanaro"))).getStatusCode() + ); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest(".kibana/_doc/6.2.2?pretty", encodeBasicHeader("kibanaro", "kibanaro"))).getStatusCode() + ); System.out.println(res.getBody()); @@ -360,8 +531,7 @@ public void testDashboardsAlias() throws Exception { @Test public void testDashboardsAlias65() throws Exception { - final Settings settings = Settings.builder() - .build(); + final Settings settings = Settings.builder().build(); setup(settings); try (Client tc = getClient()) { @@ -369,29 +539,39 @@ public void testDashboardsAlias65() throws Exception { Map indexSettings = new HashMap(); indexSettings.put("number_of_shards", 1); indexSettings.put("number_of_replicas", 0); - tc.admin().indices().create(new CreateIndexRequest(".kibana_1") - .alias(new Alias(".kibana")) - .settings(indexSettings)) + tc.admin() + .indices() + .create(new CreateIndexRequest(".kibana_1").alias(new Alias(".kibana")).settings(indexSettings)) .actionGet(); - tc.index(new IndexRequest(".kibana_1").id("6.2.2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(body, XContentType.JSON)).actionGet(); - tc.index(new IndexRequest(".kibana_-900636979_kibanaro").id("6.2.2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(body, XContentType.JSON)).actionGet(); + tc.index(new IndexRequest(".kibana_1").id("6.2.2").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source(body, XContentType.JSON)) + .actionGet(); + tc.index( + new IndexRequest(".kibana_-900636979_kibanaro").id("6.2.2") + .setRefreshPolicy(RefreshPolicy.IMMEDIATE) + .source(body, XContentType.JSON) + ).actionGet(); } final RestHelper rh = nonSslRestHelper(); HttpResponse res; - Assert.assertEquals(HttpStatus.SC_OK, (res = rh.executeGetRequest(".kibana/_doc/6.2.2?pretty", new BasicHeader("securitytenant", "__user__"), encodeBasicHeader("kibanaro", "kibanaro"))).getStatusCode()); + Assert.assertEquals( + HttpStatus.SC_OK, + (res = rh.executeGetRequest( + ".kibana/_doc/6.2.2?pretty", + new BasicHeader("securitytenant", "__user__"), + encodeBasicHeader("kibanaro", "kibanaro") + )).getStatusCode() + ); System.out.println(res.getBody()); Assert.assertTrue(res.getBody().contains(".kibana_-900636979_kibanaro")); } - @Test public void testTenantParametersSubstitution() throws Exception { - final Settings settings = Settings.builder() - .build(); + final Settings settings = Settings.builder().build(); setup(settings); final RestHelper rh = nonSslRestHelper(); @@ -419,9 +599,10 @@ public void testTenantParametersSubstitution() throws Exception { assertThat(res.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat(res.findValueInJson("_source.tenant"), equalTo(tenantName)); - final String tenantNameAppended = "tenant_parameters_substitution_1"; - final String createTenantAppendedBody = "{\"buildNum\": 15460, \"defaultIndex\": \"plop\", \"tenant\": \"" + tenantNameAppended + "\"}"; + final String createTenantAppendedBody = "{\"buildNum\": 15460, \"defaultIndex\": \"plop\", \"tenant\": \"" + + tenantNameAppended + + "\"}"; final Header userTenantAppended = new BasicHeader("securitytenant", tenantNameAppended); res = rh.executeGetRequest(url, asNoAccessUser, userTenantAppended); @@ -440,8 +621,7 @@ public void testTenantParametersSubstitution() throws Exception { @Test public void testMultitenancyAnonymousUser() throws Exception { - final Settings settings = Settings.builder() - .build(); + final Settings settings = Settings.builder().build(); setup(Settings.EMPTY, new DynamicSecurityConfig().setConfig("config_anonymous.yml"), settings); final RestHelper rh = nonSslRestHelper(); diff --git a/src/test/java/org/opensearch/security/multitenancy/test/TenancyMultitenancyEnabledTests.java b/src/test/java/org/opensearch/security/multitenancy/test/TenancyMultitenancyEnabledTests.java index bd9664a84c..b25a50d934 100644 --- a/src/test/java/org/opensearch/security/multitenancy/test/TenancyMultitenancyEnabledTests.java +++ b/src/test/java/org/opensearch/security/multitenancy/test/TenancyMultitenancyEnabledTests.java @@ -29,15 +29,17 @@ public class TenancyMultitenancyEnabledTests extends SingleClusterTest { private static final Header AS_REST_API_USER = encodeBasicHeader("user_rest_api_access", "user_rest_api_access"); private static final Header AS_USER = encodeBasicHeader("admin", "admin"); private static final Header ON_USER_TENANT = new BasicHeader("securitytenant", "__user__"); - + private static String createIndexPatternDoc(final String title) { - return "{"+ - "\"type\" : \"index-pattern\","+ - "\"updated_at\" : \"2018-09-29T08:56:59.066Z\","+ - "\"index-pattern\" : {"+ - "\"title\" : \"" + title + "\""+ - "}}"; - } + return "{" + + "\"type\" : \"index-pattern\"," + + "\"updated_at\" : \"2018-09-29T08:56:59.066Z\"," + + "\"index-pattern\" : {" + + "\"title\" : \"" + + title + + "\"" + + "}}"; + } @Override protected String getResourceFolder() { @@ -46,37 +48,69 @@ protected String getResourceFolder() { @Test public void testMultitenancyDisabled_endToEndTest() throws Exception { - setup(Settings.EMPTY, - new DynamicSecurityConfig(), - Settings.builder().put("plugins.security.restapi.roles_enabled.0", "security_rest_api_access").build(), - true); - - final HttpResponse getSettingResponse = nonSslRestHelper().executeGetRequest("/_plugins/_security/api/tenancy/config", AS_REST_API_USER); + setup( + Settings.EMPTY, + new DynamicSecurityConfig(), + Settings.builder().put("plugins.security.restapi.roles_enabled.0", "security_rest_api_access").build(), + true + ); + + final HttpResponse getSettingResponse = nonSslRestHelper().executeGetRequest( + "/_plugins/_security/api/tenancy/config", + AS_REST_API_USER + ); assertThat(getSettingResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat(getSettingResponse.findValueInJson("multitenancy_enabled"), equalTo("true")); HttpResponse getDashboardsinfoResponse = nonSslRestHelper().executeGetRequest("/_plugins/_security/dashboardsinfo", AS_USER); - assertThat(getDashboardsinfoResponse.findValueInJson("multitenancy_enabled"),equalTo("true")); + assertThat(getDashboardsinfoResponse.findValueInJson("multitenancy_enabled"), equalTo("true")); - final HttpResponse createDocInGlobalTenantResponse = nonSslRestHelper().executePostRequest(".kibana/_doc?refresh=true", createIndexPatternDoc("globalIndex"), AS_USER); + final HttpResponse createDocInGlobalTenantResponse = nonSslRestHelper().executePostRequest( + ".kibana/_doc?refresh=true", + createIndexPatternDoc("globalIndex"), + AS_USER + ); assertThat(createDocInGlobalTenantResponse.getStatusCode(), equalTo(HttpStatus.SC_CREATED)); - final HttpResponse createDocInUserTenantResponse = nonSslRestHelper().executePostRequest(".kibana/_doc?refresh=true", createIndexPatternDoc("userIndex"), ON_USER_TENANT, AS_USER); + final HttpResponse createDocInUserTenantResponse = nonSslRestHelper().executePostRequest( + ".kibana/_doc?refresh=true", + createIndexPatternDoc("userIndex"), + ON_USER_TENANT, + AS_USER + ); assertThat(createDocInUserTenantResponse.getStatusCode(), equalTo(HttpStatus.SC_CREATED)); - final HttpResponse searchInUserTenantWithMutlitenancyEnabled = nonSslRestHelper().executeGetRequest(".kibana/_search", ON_USER_TENANT, AS_USER); + final HttpResponse searchInUserTenantWithMutlitenancyEnabled = nonSslRestHelper().executeGetRequest( + ".kibana/_search", + ON_USER_TENANT, + AS_USER + ); assertThat(searchInUserTenantWithMutlitenancyEnabled.getStatusCode(), equalTo(HttpStatus.SC_OK)); - assertThat(searchInUserTenantWithMutlitenancyEnabled.findValueInJson("hits.hits[0]._source.index-pattern.title"), equalTo("userIndex")); - - final HttpResponse updateMutlitenancyToDisabled = nonSslRestHelper().executePutRequest("/_plugins/_security/api/tenancy/config", "{\"multitenancy_enabled\": \"false\"}", AS_REST_API_USER); + assertThat( + searchInUserTenantWithMutlitenancyEnabled.findValueInJson("hits.hits[0]._source.index-pattern.title"), + equalTo("userIndex") + ); + + final HttpResponse updateMutlitenancyToDisabled = nonSslRestHelper().executePutRequest( + "/_plugins/_security/api/tenancy/config", + "{\"multitenancy_enabled\": \"false\"}", + AS_REST_API_USER + ); assertThat(updateMutlitenancyToDisabled.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat(updateMutlitenancyToDisabled.findValueInJson("multitenancy_enabled"), equalTo("false")); getDashboardsinfoResponse = nonSslRestHelper().executeGetRequest("/_plugins/_security/dashboardsinfo", AS_USER); - assertThat(getDashboardsinfoResponse.findValueInJson("multitenancy_enabled"),equalTo("false")); + assertThat(getDashboardsinfoResponse.findValueInJson("multitenancy_enabled"), equalTo("false")); - final HttpResponse searchInUserTenantWithMutlitenancyDisabled = nonSslRestHelper().executeGetRequest(".kibana/_search", ON_USER_TENANT, AS_USER); + final HttpResponse searchInUserTenantWithMutlitenancyDisabled = nonSslRestHelper().executeGetRequest( + ".kibana/_search", + ON_USER_TENANT, + AS_USER + ); assertThat(searchInUserTenantWithMutlitenancyDisabled.getStatusCode(), equalTo(HttpStatus.SC_OK)); - assertThat(searchInUserTenantWithMutlitenancyDisabled.findValueInJson("hits.hits[0]._source.index-pattern.title"), equalTo("globalIndex")); + assertThat( + searchInUserTenantWithMutlitenancyDisabled.findValueInJson("hits.hits[0]._source.index-pattern.title"), + equalTo("globalIndex") + ); } } diff --git a/src/test/java/org/opensearch/security/multitenancy/test/TenancyPrivateTenantEnabledTests.java b/src/test/java/org/opensearch/security/multitenancy/test/TenancyPrivateTenantEnabledTests.java index 599586239c..1af102802f 100644 --- a/src/test/java/org/opensearch/security/multitenancy/test/TenancyPrivateTenantEnabledTests.java +++ b/src/test/java/org/opensearch/security/multitenancy/test/TenancyPrivateTenantEnabledTests.java @@ -32,12 +32,14 @@ public class TenancyPrivateTenantEnabledTests extends SingleClusterTest { private static final Header ON_USER_TENANT = new BasicHeader("securitytenant", "__user__"); private static String createIndexPatternDoc(final String title) { - return "{"+ - "\"type\" : \"index-pattern\","+ - "\"updated_at\" : \"2018-09-29T08:56:59.066Z\","+ - "\"index-pattern\" : {"+ - "\"title\" : \"" + title + "\""+ - "}}"; + return "{" + + "\"type\" : \"index-pattern\"," + + "\"updated_at\" : \"2018-09-29T08:56:59.066Z\"," + + "\"index-pattern\" : {" + + "\"title\" : \"" + + title + + "\"" + + "}}"; } @Override @@ -47,37 +49,69 @@ protected String getResourceFolder() { @Test public void testPrivateTenantDisabled_Update_EndToEnd() throws Exception { - setup(Settings.EMPTY, - new DynamicSecurityConfig(), - Settings.builder().put("plugins.security.restapi.roles_enabled.0", "security_rest_api_access").build(), - true); - - final HttpResponse getSettingResponse = nonSslRestHelper().executeGetRequest("/_plugins/_security/api/tenancy/config", AS_REST_API_USER); + setup( + Settings.EMPTY, + new DynamicSecurityConfig(), + Settings.builder().put("plugins.security.restapi.roles_enabled.0", "security_rest_api_access").build(), + true + ); + + final HttpResponse getSettingResponse = nonSslRestHelper().executeGetRequest( + "/_plugins/_security/api/tenancy/config", + AS_REST_API_USER + ); assertThat(getSettingResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat(getSettingResponse.findValueInJson("private_tenant_enabled"), equalTo("true")); HttpResponse getDashboardsinfoResponse = nonSslRestHelper().executeGetRequest("/_plugins/_security/dashboardsinfo", AS_ADMIN_USER); assertThat(getDashboardsinfoResponse.findValueInJson("private_tenant_enabled"), equalTo("true")); - final HttpResponse createDocInGlobalTenantResponse = nonSslRestHelper().executePostRequest(".kibana/_doc?refresh=true", createIndexPatternDoc("globalIndex"), AS_ADMIN_USER); + final HttpResponse createDocInGlobalTenantResponse = nonSslRestHelper().executePostRequest( + ".kibana/_doc?refresh=true", + createIndexPatternDoc("globalIndex"), + AS_ADMIN_USER + ); assertThat(createDocInGlobalTenantResponse.getStatusCode(), equalTo(HttpStatus.SC_CREATED)); - final HttpResponse createDocInUserTenantResponse = nonSslRestHelper().executePostRequest(".kibana/_doc?refresh=true", createIndexPatternDoc("userIndex"), ON_USER_TENANT, AS_USER); + final HttpResponse createDocInUserTenantResponse = nonSslRestHelper().executePostRequest( + ".kibana/_doc?refresh=true", + createIndexPatternDoc("userIndex"), + ON_USER_TENANT, + AS_USER + ); assertThat(createDocInUserTenantResponse.getStatusCode(), equalTo(HttpStatus.SC_CREATED)); - final HttpResponse searchInUserTenantWithPrivateTenantEnabled = nonSslRestHelper().executeGetRequest(".kibana/_search", ON_USER_TENANT, AS_USER); + final HttpResponse searchInUserTenantWithPrivateTenantEnabled = nonSslRestHelper().executeGetRequest( + ".kibana/_search", + ON_USER_TENANT, + AS_USER + ); assertThat(searchInUserTenantWithPrivateTenantEnabled.getStatusCode(), equalTo(HttpStatus.SC_OK)); - assertThat(searchInUserTenantWithPrivateTenantEnabled.findValueInJson("hits.hits[0]._source.index-pattern.title"), equalTo("userIndex")); - - final HttpResponse disablePrivateTenantResponse = nonSslRestHelper().executePutRequest("/_plugins/_security/api/tenancy/config", "{\"private_tenant_enabled\": \"false\"}", AS_REST_API_USER); + assertThat( + searchInUserTenantWithPrivateTenantEnabled.findValueInJson("hits.hits[0]._source.index-pattern.title"), + equalTo("userIndex") + ); + + final HttpResponse disablePrivateTenantResponse = nonSslRestHelper().executePutRequest( + "/_plugins/_security/api/tenancy/config", + "{\"private_tenant_enabled\": \"false\"}", + AS_REST_API_USER + ); assertThat(disablePrivateTenantResponse.getStatusCode(), equalTo(HttpStatus.SC_OK)); assertThat(disablePrivateTenantResponse.findValueInJson("private_tenant_enabled"), equalTo("false")); getDashboardsinfoResponse = nonSslRestHelper().executeGetRequest("/_plugins/_security/dashboardsinfo", AS_ADMIN_USER); - assertThat(getDashboardsinfoResponse.findValueInJson("private_tenant_enabled"),equalTo("false")); + assertThat(getDashboardsinfoResponse.findValueInJson("private_tenant_enabled"), equalTo("false")); - final HttpResponse searchInUserTenantWithPrivateTenantDisabled = nonSslRestHelper().executeGetRequest(".kibana/_search", ON_USER_TENANT, AS_USER); + final HttpResponse searchInUserTenantWithPrivateTenantDisabled = nonSslRestHelper().executeGetRequest( + ".kibana/_search", + ON_USER_TENANT, + AS_USER + ); assertThat(searchInUserTenantWithPrivateTenantDisabled.getStatusCode(), equalTo(HttpStatus.SC_FORBIDDEN)); - assertThat(searchInUserTenantWithPrivateTenantDisabled.findValueInJson("error.reason"), containsString("no permissions for [indices:data/read/search] and User")); + assertThat( + searchInUserTenantWithPrivateTenantDisabled.findValueInJson("error.reason"), + containsString("no permissions for [indices:data/read/search] and User") + ); } diff --git a/src/test/java/org/opensearch/security/privileges/PrivilegesEvaluatorTest.java b/src/test/java/org/opensearch/security/privileges/PrivilegesEvaluatorTest.java index ba265bcf2e..b953ac8ddb 100644 --- a/src/test/java/org/opensearch/security/privileges/PrivilegesEvaluatorTest.java +++ b/src/test/java/org/opensearch/security/privileges/PrivilegesEvaluatorTest.java @@ -26,15 +26,15 @@ public class PrivilegesEvaluatorTest extends SingleClusterTest { private static final Header NegatedRegexUserHeader = encodeBasicHeader("negated_regex_user", "negated_regex_user"); public void setupSettingsIndexPattern() throws Exception { - Settings settings = Settings.builder() - .build(); - setup(Settings.EMPTY, - new DynamicSecurityConfig() - .setSecurityRoles("roles_index_patterns.yml") - .setSecurityInternalUsers("internal_users_index_patterns.yml") - .setSecurityRolesMapping("roles_mapping_index_patterns.yml"), - settings, - true); + Settings settings = Settings.builder().build(); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setSecurityRoles("roles_index_patterns.yml") + .setSecurityInternalUsers("internal_users_index_patterns.yml") + .setSecurityRolesMapping("roles_mapping_index_patterns.yml"), + settings, + true + ); } @Test @@ -42,9 +42,9 @@ public void testNegativeLookaheadPattern() throws Exception { setupSettingsIndexPattern(); RestHelper rh = nonSslRestHelper(); - RestHelper.HttpResponse response = rh.executeGetRequest( "*/_search", NegativeLookaheadUserHeader); + RestHelper.HttpResponse response = rh.executeGetRequest("*/_search", NegativeLookaheadUserHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - response = rh.executeGetRequest( "r*/_search", NegativeLookaheadUserHeader); + response = rh.executeGetRequest("r*/_search", NegativeLookaheadUserHeader); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); } @@ -53,9 +53,9 @@ public void testRegexPattern() throws Exception { setupSettingsIndexPattern(); RestHelper rh = nonSslRestHelper(); - RestHelper.HttpResponse response = rh.executeGetRequest( "*/_search", NegatedRegexUserHeader); + RestHelper.HttpResponse response = rh.executeGetRequest("*/_search", NegatedRegexUserHeader); Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode()); - response = rh.executeGetRequest( "r*/_search", NegatedRegexUserHeader); + response = rh.executeGetRequest("r*/_search", NegatedRegexUserHeader); Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode()); } } diff --git a/src/test/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluatorTest.java b/src/test/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluatorTest.java index 6d81c3b1da..14c5eabb73 100644 --- a/src/test/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluatorTest.java +++ b/src/test/java/org/opensearch/security/privileges/SecurityIndexAccessEvaluatorTest.java @@ -55,11 +55,10 @@ public class SecurityIndexAccessEvaluatorTest { @Mock private Logger log; - private SecurityIndexAccessEvaluator evaluator; - private static final String UNPROTECTED_ACTION = "indices:data/read"; - private static final String PROTECTED_ACTION = "indices:data/write"; + private static final String UNPROTECTED_ACTION = "indices:data/read"; + private static final String PROTECTED_ACTION = "indices:data/write"; @Before public void before() { @@ -69,7 +68,8 @@ public void before() { .put("plugins.security.system_indices.enabled", true) .build(), auditLog, - irr); + irr + ); evaluator.log = log; when(log.isDebugEnabled()).thenReturn(true); @@ -79,7 +79,7 @@ public void before() { public void after() { verifyNoMoreInteractions(auditLog, irr, request, task, presponse, log); } - + @Test public void actionIsNotProtected_noSystemIndexInvolved() { final Resolved resolved = createResolved(".test"); @@ -140,13 +140,16 @@ public void protectedActionSystemIndex() { verify(presponse).markComplete(); verify(log).isDebugEnabled(); - verify(log).warn( - "{} for '{}' index is not allowed for a regular user", - "indices:data/write", - ".opendistro_security, .test"); + verify(log).warn("{} for '{}' index is not allowed for a regular user", "indices:data/write", ".opendistro_security, .test"); } private Resolved createResolved(final String... indexes) { - return new Resolved(ImmutableSet.of(), ImmutableSet.copyOf(indexes), ImmutableSet.copyOf(indexes), ImmutableSet.of(), IndicesOptions.STRICT_EXPAND_OPEN); + return new Resolved( + ImmutableSet.of(), + ImmutableSet.copyOf(indexes), + ImmutableSet.copyOf(indexes), + ImmutableSet.of(), + IndicesOptions.STRICT_EXPAND_OPEN + ); } } diff --git a/src/test/java/org/opensearch/security/protected_indices/ProtectedIndicesTests.java b/src/test/java/org/opensearch/security/protected_indices/ProtectedIndicesTests.java index 52f66f3462..0ff7d64de9 100644 --- a/src/test/java/org/opensearch/security/protected_indices/ProtectedIndicesTests.java +++ b/src/test/java/org/opensearch/security/protected_indices/ProtectedIndicesTests.java @@ -66,7 +66,10 @@ public class ProtectedIndicesTests extends SingleClusterTest { // This user is mapped to all_access, but is not mapped to any protectedIndexRoles private static final String indexAccessNoRoleUser = "indexAccessNoRoleUser"; private static final Header indexAccessNoRoleUserHeader = encodeBasicHeader(indexAccessNoRoleUser, indexAccessNoRoleUser); - private static final String generalErrorMessage = String.format("no permissions for [] and User [name=%s, backend_roles=[], requestedTenant=null]", indexAccessNoRoleUser); + private static final String generalErrorMessage = String.format( + "no permissions for [] and User [name=%s, backend_roles=[], requestedTenant=null]", + indexAccessNoRoleUser + ); // This user is mapped to all_access and protected_index_role1 private static final String protectedIndexUser = "protectedIndexUser"; private static final Header protectedIndexUserHeader = encodeBasicHeader(protectedIndexUser, protectedIndexUser); @@ -81,35 +84,37 @@ public class ProtectedIndicesTests extends SingleClusterTest { public void setupSettingsEnabled() throws Exception { // Setup settings Settings protectedIndexSettings = Settings.builder() - .put(ConfigConstants.SECURITY_PROTECTED_INDICES_ENABLED_KEY, true) - .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_KEY, listOfIndexesToTest) - .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_ROLES_KEY, protectedIndexRoles) - .build(); - setup(Settings.EMPTY, - new DynamicSecurityConfig() - .setConfig("config_protected_indices.yml") - .setSecurityRoles("roles_protected_indices.yml") - .setSecurityInternalUsers("internal_users_protected_indices.yml") - .setSecurityRolesMapping("roles_mapping_protected_indices.yml"), - protectedIndexSettings, - true); + .put(ConfigConstants.SECURITY_PROTECTED_INDICES_ENABLED_KEY, true) + .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_KEY, listOfIndexesToTest) + .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_ROLES_KEY, protectedIndexRoles) + .build(); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setConfig("config_protected_indices.yml") + .setSecurityRoles("roles_protected_indices.yml") + .setSecurityInternalUsers("internal_users_protected_indices.yml") + .setSecurityRolesMapping("roles_mapping_protected_indices.yml"), + protectedIndexSettings, + true + ); } public void setupSettingsIndexPatterns() throws Exception { // Setup settings Settings protectedIndexSettings = Settings.builder() - .put(ConfigConstants.SECURITY_PROTECTED_INDICES_ENABLED_KEY, true) - .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_KEY, listOfIndexPatternsToTest) - .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_ROLES_KEY, protectedIndexRoles) - .build(); - setup(Settings.EMPTY, - new DynamicSecurityConfig() - .setConfig("config_protected_indices.yml") - .setSecurityRoles("roles_protected_indices.yml") - .setSecurityInternalUsers("internal_users_protected_indices.yml") - .setSecurityRolesMapping("roles_mapping_protected_indices.yml"), - protectedIndexSettings, - true); + .put(ConfigConstants.SECURITY_PROTECTED_INDICES_ENABLED_KEY, true) + .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_KEY, listOfIndexPatternsToTest) + .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_ROLES_KEY, protectedIndexRoles) + .build(); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setConfig("config_protected_indices.yml") + .setSecurityRoles("roles_protected_indices.yml") + .setSecurityInternalUsers("internal_users_protected_indices.yml") + .setSecurityRolesMapping("roles_mapping_protected_indices.yml"), + protectedIndexSettings, + true + ); } /** @@ -122,35 +127,38 @@ public void setupSettingsIndexPatterns() throws Exception { public void setupSettingsDisabled() throws Exception { // Setup settings Settings protectedIndexSettings = Settings.builder() - .put(ConfigConstants.SECURITY_PROTECTED_INDICES_ENABLED_KEY, false) - .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_KEY, listOfIndexesToTest) - .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_ROLES_KEY, protectedIndexRoles) - .build(); - setup(Settings.EMPTY, - new DynamicSecurityConfig() - .setConfig("config_protected_indices.yml") - .setSecurityRoles("roles_protected_indices.yml") - .setSecurityInternalUsers("internal_users_protected_indices.yml") - .setSecurityRolesMapping("roles_mapping_protected_indices.yml"), - protectedIndexSettings, - true); + .put(ConfigConstants.SECURITY_PROTECTED_INDICES_ENABLED_KEY, false) + .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_KEY, listOfIndexesToTest) + .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_ROLES_KEY, protectedIndexRoles) + .build(); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setConfig("config_protected_indices.yml") + .setSecurityRoles("roles_protected_indices.yml") + .setSecurityInternalUsers("internal_users_protected_indices.yml") + .setSecurityRolesMapping("roles_mapping_protected_indices.yml"), + protectedIndexSettings, + true + ); } public void setupSettingsEnabledSnapshot() throws Exception { final Settings settings = Settings.builder() - .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .put(ConfigConstants.SECURITY_PROTECTED_INDICES_ENABLED_KEY, true) - .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_KEY, listOfIndexesToTest) - .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_ROLES_KEY, protectedIndexRoles) - .build(); - - setup(Settings.EMPTY, new DynamicSecurityConfig() - .setConfig("config_protected_indices.yml") + .putList("path.repo", repositoryPath.getRoot().getAbsolutePath()) + .put(ConfigConstants.SECURITY_PROTECTED_INDICES_ENABLED_KEY, true) + .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_KEY, listOfIndexesToTest) + .putList(ConfigConstants.SECURITY_PROTECTED_INDICES_ROLES_KEY, protectedIndexRoles) + .build(); + + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setConfig("config_protected_indices.yml") .setSecurityRoles("roles_protected_indices.yml") .setSecurityInternalUsers("internal_users_protected_indices.yml") .setSecurityRolesMapping("roles_mapping_protected_indices.yml"), - settings, - true); + settings, + true + ); } /** @@ -162,7 +170,11 @@ public void createTestIndicesAndDocs() { try (Client tc = getClient()) { for (String index : listOfIndexesToTest) { tc.admin().indices().create(new CreateIndexRequest(index)).actionGet(); - tc.index(new IndexRequest(index).setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).id("document1").source("{ \"foo\": \"bar\" }", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest(index).setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .id("document1") + .source("{ \"foo\": \"bar\" }", XContentType.JSON) + ).actionGet(); } } } @@ -170,8 +182,19 @@ public void createTestIndicesAndDocs() { public void createSnapshots() { try (Client tc = getClient()) { for (String index : listOfIndexesToTest) { - tc.admin().cluster().putRepository(new PutRepositoryRequest(index).type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/" + index))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest(index, index + "_1").indices(index).includeGlobalState(true).waitForCompletion(true)).actionGet(); + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest(index).type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/" + index)) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest(index, index + "_1").indices(index).includeGlobalState(true).waitForCompletion(true) + ) + .actionGet(); } } } @@ -192,7 +215,8 @@ public void testNoSearchResults() throws Exception { // Test direct index query. for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = rh.executePostRequest(index + "/_search", matchAllQuery, indexAccessNoRoleUserHeader); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); // confirm good response. assertTrue(searchResponse.status() == RestStatus.OK); @@ -207,7 +231,8 @@ public void testNoSearchResults() throws Exception { // Test index pattern for (String indexPattern : listOfIndexPatternsToTest) { RestHelper.HttpResponse response = rh.executePostRequest(indexPattern + "/_search", matchAllQuery, indexAccessNoRoleUserHeader); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); // confirm good response. assertTrue(searchResponse.status() == RestStatus.OK); @@ -231,7 +256,8 @@ public void testSearchWithSettingDisabled() throws Exception { // Test direct index query. for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = rh.executePostRequest(index + "/_search", matchAllQuery, protectedIndexUserHeader); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); // confirm good response. assertTrue(searchResponse.status() == RestStatus.OK); @@ -246,7 +272,8 @@ public void testSearchWithSettingDisabled() throws Exception { // Test index pattern for (String indexPattern : listOfIndexPatternsToTest) { RestHelper.HttpResponse response = rh.executePostRequest(indexPattern + "/_search", matchAllQuery, protectedIndexUserHeader); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); // confirm good response. assertTrue(searchResponse.status() == RestStatus.OK); @@ -268,10 +295,9 @@ public void testNoResultsAlias() throws Exception { try (Client tc = getClient()) { for (String index : listOfIndexesToTest) { IndicesAliasesRequest request = new IndicesAliasesRequest(); - IndicesAliasesRequest.AliasActions aliasAction = - new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.ADD) - .index(index) - .alias("alias" + i); + IndicesAliasesRequest.AliasActions aliasAction = new IndicesAliasesRequest.AliasActions( + IndicesAliasesRequest.AliasActions.Type.ADD + ).index(index).alias("alias" + i); request.addAliasAction(aliasAction); tc.admin().indices().aliases(request).actionGet(); i++; @@ -282,8 +308,13 @@ public void testNoResultsAlias() throws Exception { RestHelper rh = nonSslRestHelper(); for (int aliasNumber = 0; aliasNumber < i; aliasNumber++) { - RestHelper.HttpResponse response = rh.executePostRequest("alias" + aliasNumber + "/_search", matchAllQuery, indexAccessNoRoleUserHeader); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + RestHelper.HttpResponse response = rh.executePostRequest( + "alias" + aliasNumber + "/_search", + matchAllQuery, + indexAccessNoRoleUserHeader + ); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); // confirm good response. assertTrue(searchResponse.status() == RestStatus.OK); @@ -303,14 +334,14 @@ public void testNoAccessCreateIndexDisabled() throws Exception { // Create rest client RestHelper rh = nonSslRestHelper(); - String indexSettings = "{\n" + - " \"settings\" : {\n" + - " \"index\" : {\n" + - " \"number_of_shards\" : 3, \n" + - " \"number_of_replicas\" : 2 \n" + - " }\n" + - " }\n" + - "}"; + String indexSettings = "{\n" + + " \"settings\" : {\n" + + " \"index\" : {\n" + + " \"number_of_shards\" : 3, \n" + + " \"number_of_replicas\" : 2 \n" + + " }\n" + + " }\n" + + "}"; for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = rh.executePutRequest(index, indexSettings, indexAccessNoRoleUserHeader); assertTrue(response.getStatusCode() == RestStatus.OK.getStatus()); @@ -446,10 +477,7 @@ public void testNonAccessUpdateMappings() throws Exception { setupSettingsEnabled(); createTestIndicesAndDocs(); - String newMappings = "{\"properties\": {" + - "\"user_name\": {" + - "\"type\": \"text\"" + - "}}}"; + String newMappings = "{\"properties\": {" + "\"user_name\": {" + "\"type\": \"text\"" + "}}}"; // Create rest client RestHelper rh = nonSslRestHelper(); @@ -467,10 +495,7 @@ public void testNonAccessUpdateMappingsDisabled() throws Exception { setupSettingsDisabled(); createTestIndicesAndDocs(); - String newMappings = "{\"properties\": {" + - "\"user_name\": {" + - "\"type\": \"text\"" + - "}}}"; + String newMappings = "{\"properties\": {" + "\"user_name\": {" + "\"type\": \"text\"" + "}}}"; // Create rest client RestHelper rh = nonSslRestHelper(); @@ -510,7 +535,11 @@ public void testNonAccessAliasOperations() throws Exception { String aliasTemplate = "{\"actions\" : [{ \"add\" : { \"index\" : \"%s\", \"alias\" : \"foobar\" } }]}"; for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse response = rh.executePostRequest("_aliases", String.format(aliasTemplate, index), indexAccessNoRoleUserHeader); + RestHelper.HttpResponse response = rh.executePostRequest( + "_aliases", + String.format(aliasTemplate, index), + indexAccessNoRoleUserHeader + ); assertTrue(response.getStatusCode() == RestStatus.FORBIDDEN.getStatus()); assertTrue(response.getBody().contains(generalErrorMessage)); } @@ -519,7 +548,11 @@ public void testNonAccessAliasOperations() throws Exception { aliasTemplate = "{\"actions\" : [{ \"remove\" : { \"index\" : \"%s\", \"alias\" : \"foobar\" } }]}"; for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse response = rh.executePostRequest("_aliases", String.format(aliasTemplate, index), indexAccessNoRoleUserHeader); + RestHelper.HttpResponse response = rh.executePostRequest( + "_aliases", + String.format(aliasTemplate, index), + indexAccessNoRoleUserHeader + ); assertTrue(response.getStatusCode() == RestStatus.FORBIDDEN.getStatus()); assertTrue(response.getBody().contains(generalErrorMessage)); } @@ -528,7 +561,11 @@ public void testNonAccessAliasOperations() throws Exception { aliasTemplate = "{\"actions\" : [{ \"remove_index\" : { \"index\" : \"%s\"} }]}"; for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse response = rh.executePostRequest("_aliases", String.format(aliasTemplate, index), indexAccessNoRoleUserHeader); + RestHelper.HttpResponse response = rh.executePostRequest( + "_aliases", + String.format(aliasTemplate, index), + indexAccessNoRoleUserHeader + ); assertTrue(response.getStatusCode() == RestStatus.FORBIDDEN.getStatus()); assertTrue(response.getBody().contains(generalErrorMessage)); } @@ -543,14 +580,14 @@ public void testNonAccessUpdateIndexSettings() throws Exception { // Create rest client RestHelper rh = nonSslRestHelper(); - String indexSettings = "{\n" + - " \"settings\" : {\n" + - " \"index\" : {\n" + - " \"number_of_shards\" : 30, \n" + - " \"number_of_replicas\" : 20 \n" + - " }\n" + - " }\n" + - "}"; + String indexSettings = "{\n" + + " \"settings\" : {\n" + + " \"index\" : {\n" + + " \"number_of_shards\" : 30, \n" + + " \"number_of_replicas\" : 20 \n" + + " }\n" + + " }\n" + + "}"; for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = rh.executePutRequest(index + "/_settings", indexSettings, indexAccessNoRoleUserHeader); @@ -575,7 +612,8 @@ public void testSearchResults() throws Exception { // Test direct index query. for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = rh.executePostRequest(index + "/_search", matchAllQuery, protectedIndexUserHeader); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); // confirm good response. assertTrue(searchResponse.status() == RestStatus.OK); @@ -590,7 +628,8 @@ public void testSearchResults() throws Exception { // Test index pattern for (String indexPattern : listOfIndexPatternsToTest) { RestHelper.HttpResponse response = rh.executePostRequest(indexPattern + "/_search", matchAllQuery, protectedIndexUserHeader); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); // confirm good response. assertTrue(searchResponse.status() == RestStatus.OK); @@ -612,10 +651,9 @@ public void testResultsAlias() throws Exception { try (Client tc = getClient()) { for (String index : listOfIndexesToTest) { IndicesAliasesRequest request = new IndicesAliasesRequest(); - IndicesAliasesRequest.AliasActions aliasAction = - new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.ADD) - .index(index) - .alias("alias" + i); + IndicesAliasesRequest.AliasActions aliasAction = new IndicesAliasesRequest.AliasActions( + IndicesAliasesRequest.AliasActions.Type.ADD + ).index(index).alias("alias" + i); request.addAliasAction(aliasAction); tc.admin().indices().aliases(request).actionGet(); i++; @@ -626,9 +664,14 @@ public void testResultsAlias() throws Exception { RestHelper rh = nonSslRestHelper(); for (int aliasNumber = 0; aliasNumber < i; aliasNumber++) { - RestHelper.HttpResponse response = rh.executePostRequest("alias" + aliasNumber + "/_search", matchAllQuery, protectedIndexUserHeader); - - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + RestHelper.HttpResponse response = rh.executePostRequest( + "alias" + aliasNumber + "/_search", + matchAllQuery, + protectedIndexUserHeader + ); + + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); // confirm good response. assertTrue(searchResponse.status() == RestStatus.OK); @@ -648,14 +691,14 @@ public void testCreateIndex() throws Exception { // Create rest client RestHelper rh = nonSslRestHelper(); - String indexSettings = "{\n" + - " \"settings\" : {\n" + - " \"index\" : {\n" + - " \"number_of_shards\" : 3, \n" + - " \"number_of_replicas\" : 2 \n" + - " }\n" + - " }\n" + - "}"; + String indexSettings = "{\n" + + " \"settings\" : {\n" + + " \"index\" : {\n" + + " \"number_of_shards\" : 3, \n" + + " \"number_of_replicas\" : 2 \n" + + " }\n" + + " }\n" + + "}"; for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = rh.executePutRequest(index, indexSettings, protectedIndexUserHeader); assertTrue(response.getStatusCode() == RestStatus.OK.getStatus()); @@ -716,10 +759,7 @@ public void testUpdateMappings() throws Exception { setupSettingsEnabled(); createTestIndicesAndDocs(); - String newMappings = "{\"properties\": {" + - "\"user_name\": {" + - "\"type\": \"text\"" + - "}}}"; + String newMappings = "{\"properties\": {" + "\"user_name\": {" + "\"type\": \"text\"" + "}}}"; // Create rest client RestHelper rh = nonSslRestHelper(); @@ -775,7 +815,11 @@ public void testAliasOperations() throws Exception { String aliasTemplate = "{\"actions\" : [{ \"add\" : { \"index\" : \"%s\", \"alias\" : \"foobar\" } }]}"; for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse response = rh.executePostRequest("_aliases", String.format(aliasTemplate, index), protectedIndexUserHeader); + RestHelper.HttpResponse response = rh.executePostRequest( + "_aliases", + String.format(aliasTemplate, index), + protectedIndexUserHeader + ); assertTrue(response.getStatusCode() == RestStatus.OK.getStatus()); } @@ -783,7 +827,11 @@ public void testAliasOperations() throws Exception { aliasTemplate = "{\"actions\" : [{ \"remove\" : { \"index\" : \"%s\", \"alias\" : \"foobar\" } }]}"; for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse response = rh.executePostRequest("_aliases", String.format(aliasTemplate, index), protectedIndexUserHeader); + RestHelper.HttpResponse response = rh.executePostRequest( + "_aliases", + String.format(aliasTemplate, index), + protectedIndexUserHeader + ); assertTrue(response.getStatusCode() == RestStatus.OK.getStatus()); } @@ -791,7 +839,11 @@ public void testAliasOperations() throws Exception { aliasTemplate = "{\"actions\" : [{ \"remove_index\" : { \"index\" : \"%s\"} }]}"; for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse response = rh.executePostRequest("_aliases", String.format(aliasTemplate, index), protectedIndexUserHeader); + RestHelper.HttpResponse response = rh.executePostRequest( + "_aliases", + String.format(aliasTemplate, index), + protectedIndexUserHeader + ); assertTrue(response.getStatusCode() == RestStatus.OK.getStatus()); } } @@ -805,11 +857,7 @@ public void testUpdateIndexSettings() throws Exception { // Create rest client RestHelper rh = nonSslRestHelper(); - String indexSettings = "{\n" + - " \"index\" : {\n" + - " \"refresh_interval\" : null\n" + - " }\n" + - "}"; + String indexSettings = "{\n" + " \"index\" : {\n" + " \"refresh_interval\" : null\n" + " }\n" + "}"; for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = rh.executePutRequest(index + "/_settings", indexSettings, protectedIndexUserHeader); @@ -833,21 +881,48 @@ public void testAccessSnapshot() throws Exception { } } - String putSnapshot = "{"+ - "\"indices\": \"%s\"," + - "\"ignore_unavailable\": false," + - "\"include_global_state\": false" + - "}"; + String putSnapshot = "{" + "\"indices\": \"%s\"," + "\"ignore_unavailable\": false," + "\"include_global_state\": false" + "}"; // Create rest client RestHelper rh = nonSslRestHelper(); for (String index : listOfIndexesToTest) { - assertEquals(HttpStatus.SC_OK, rh.executeGetRequest("_snapshot/" + index + "/" + index + "_1", protectedIndexUserHeader).getStatusCode()); - assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", protectedIndexUserHeader).getStatusCode()); - assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true", "", protectedIndexUserHeader).getStatusCode()); - assertEquals(HttpStatus.SC_OK, rh.executePostRequest("_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true","{ \"indices\": \"" + index + "\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"" + index + "_1\" }", protectedIndexUserHeader).getStatusCode()); - assertEquals(HttpStatus.SC_OK, rh.executePutRequest("_snapshot/" + index + "/" + index + "_2?wait_for_completion=true", String.format(putSnapshot, index), protectedIndexUserHeader).getStatusCode()); + assertEquals( + HttpStatus.SC_OK, + rh.executeGetRequest("_snapshot/" + index + "/" + index + "_1", protectedIndexUserHeader).getStatusCode() + ); + assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", + protectedIndexUserHeader + ).getStatusCode() + ); + assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true", + "", + protectedIndexUserHeader + ).getStatusCode() + ); + assertEquals( + HttpStatus.SC_OK, + rh.executePostRequest( + "_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true", + "{ \"indices\": \"" + index + "\", \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"" + index + "_1\" }", + protectedIndexUserHeader + ).getStatusCode() + ); + assertEquals( + HttpStatus.SC_OK, + rh.executePutRequest( + "_snapshot/" + index + "/" + index + "_2?wait_for_completion=true", + String.format(putSnapshot, index), + protectedIndexUserHeader + ).getStatusCode() + ); } } } diff --git a/src/test/java/org/opensearch/security/sanity/tests/SecurityRestTestCase.java b/src/test/java/org/opensearch/security/sanity/tests/SecurityRestTestCase.java index 51c4ddb984..b0d53deaa8 100644 --- a/src/test/java/org/opensearch/security/sanity/tests/SecurityRestTestCase.java +++ b/src/test/java/org/opensearch/security/sanity/tests/SecurityRestTestCase.java @@ -45,54 +45,52 @@ public class SecurityRestTestCase extends OpenSearchRestTestCase { private static final String CERT_FILE_DIRECTORY = "sanity-tests/"; + private boolean isHttps() { return System.getProperty("https").equals("true"); } + private boolean securityEnabled() { return System.getProperty("security.enabled").equals("true"); } @Override - protected Settings restAdminSettings(){ - return Settings - .builder() - .put("http.port", 9200) - .put(SECURITY_SSL_HTTP_ENABLED, isHttps()) - .put(SECURITY_SSL_HTTP_PEMCERT_FILEPATH, CERT_FILE_DIRECTORY + "opensearch-node.pem") - .put(SECURITY_SSL_HTTP_PEMKEY_FILEPATH, CERT_FILE_DIRECTORY + "opensearch-node-key.pem") - .put(SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, CERT_FILE_DIRECTORY + "root-ca.pem") - .put(SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, CERT_FILE_DIRECTORY + "test-kirk.jks") - .put(SECURITY_SSL_HTTP_KEYSTORE_PASSWORD.insecurePropertyName, "changeit") - .put(SECURITY_SSL_HTTP_KEYSTORE_KEYPASSWORD.insecurePropertyName, "changeit") - .build(); + protected Settings restAdminSettings() { + return Settings.builder() + .put("http.port", 9200) + .put(SECURITY_SSL_HTTP_ENABLED, isHttps()) + .put(SECURITY_SSL_HTTP_PEMCERT_FILEPATH, CERT_FILE_DIRECTORY + "opensearch-node.pem") + .put(SECURITY_SSL_HTTP_PEMKEY_FILEPATH, CERT_FILE_DIRECTORY + "opensearch-node-key.pem") + .put(SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, CERT_FILE_DIRECTORY + "root-ca.pem") + .put(SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, CERT_FILE_DIRECTORY + "test-kirk.jks") + .put(SECURITY_SSL_HTTP_KEYSTORE_PASSWORD.insecurePropertyName, "changeit") + .put(SECURITY_SSL_HTTP_KEYSTORE_KEYPASSWORD.insecurePropertyName, "changeit") + .build(); } @Override protected RestClient buildClient(Settings settings, HttpHost[] hosts) throws IOException { - if(securityEnabled()){ + if (securityEnabled()) { String keystore = settings.get(SECURITY_SSL_HTTP_KEYSTORE_FILEPATH); - if(keystore != null){ + if (keystore != null) { // create adminDN (super-admin) client File file = new File(getClass().getClassLoader().getResource(CERT_FILE_DIRECTORY).getFile()); Path configPath = PathUtils.get(file.toURI()).getParent().toAbsolutePath(); - return new SecureRestClientBuilder(settings, configPath) - .setSocketTimeout(60000) - .setConnectionRequestTimeout(180000) - .build(); + return new SecureRestClientBuilder(settings, configPath).setSocketTimeout(60000) + .setConnectionRequestTimeout(180000) + .build(); } // create client with passed user String userName = System.getProperty("user"); String password = System.getProperty("password"); - return new SecureRestClientBuilder(hosts, isHttps(), userName, password) - .setSocketTimeout(60000) - .setConnectionRequestTimeout(180000) - .build(); - } - else { + return new SecureRestClientBuilder(hosts, isHttps(), userName, password).setSocketTimeout(60000) + .setConnectionRequestTimeout(180000) + .build(); + } else { RestClientBuilder builder = RestClient.builder(hosts); configureClient(builder, settings); builder.setStrictDeprecationMode(true); diff --git a/src/test/java/org/opensearch/security/sanity/tests/SingleClusterSanityIT.java b/src/test/java/org/opensearch/security/sanity/tests/SingleClusterSanityIT.java index 55d4a6ea0b..8987744d58 100644 --- a/src/test/java/org/opensearch/security/sanity/tests/SingleClusterSanityIT.java +++ b/src/test/java/org/opensearch/security/sanity/tests/SingleClusterSanityIT.java @@ -24,7 +24,6 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; - @SuppressWarnings("unchecked") public class SingleClusterSanityIT extends SecurityRestTestCase { diff --git a/src/test/java/org/opensearch/security/securityconf/SecurityRolesPermissionsTest.java b/src/test/java/org/opensearch/security/securityconf/SecurityRolesPermissionsTest.java index 010b453b85..49a9be8a91 100644 --- a/src/test/java/org/opensearch/security/securityconf/SecurityRolesPermissionsTest.java +++ b/src/test/java/org/opensearch/security/securityconf/SecurityRolesPermissionsTest.java @@ -56,90 +56,62 @@ public class SecurityRolesPermissionsTest { - static final Map NO_REST_ADMIN_PERMISSIONS_ROLES = - ImmutableMap.builder() - .put( - "all_access", - role("*")) - .put( - "all_cluster_and_indices", - role("custer:*", "indices:*") - ).build(); - - static final Map REST_ADMIN_PERMISSIONS_FULL_ACCESS_ROLES = - ImmutableMap.builder() - .put( - "security_rest_api_full_access", - role(allRestApiPermissions())) - .put( - "security_rest_api_full_access_with_star", - role("restapi:admin/*")) - .build(); + static final Map NO_REST_ADMIN_PERMISSIONS_ROLES = ImmutableMap.builder() + .put("all_access", role("*")) + .put("all_cluster_and_indices", role("custer:*", "indices:*")) + .build(); + static final Map REST_ADMIN_PERMISSIONS_FULL_ACCESS_ROLES = ImmutableMap.builder() + .put("security_rest_api_full_access", role(allRestApiPermissions())) + .put("security_rest_api_full_access_with_star", role("restapi:admin/*")) + .build(); static String restAdminApiRoleName(final String endpoint) { return String.format("security_rest_api_%s_only", endpoint); } - static final Map REST_ADMIN_PERMISSIONS_ROLES = - ENDPOINTS_WITH_PERMISSIONS - .entrySet() - .stream() - .flatMap(e -> { - final String endpoint = e.getKey().name().toLowerCase(Locale.ROOT); - final PermissionBuilder pb = e.getValue(); - if (e.getKey() == Endpoint.SSL) { - return Stream.of( - new SimpleEntry<>( - restAdminApiRoleName(CERTS_INFO_ACTION), - role(pb.build(CERTS_INFO_ACTION)) - ), - new SimpleEntry<>( - restAdminApiRoleName(RELOAD_CERTS_ACTION), - role(pb.build(RELOAD_CERTS_ACTION)) - ) - ); - } else { - return Stream.of( - new SimpleEntry<>(restAdminApiRoleName(endpoint), role(pb.build())) - ); - } - }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + static final Map REST_ADMIN_PERMISSIONS_ROLES = ENDPOINTS_WITH_PERMISSIONS.entrySet().stream().flatMap(e -> { + final String endpoint = e.getKey().name().toLowerCase(Locale.ROOT); + final PermissionBuilder pb = e.getValue(); + if (e.getKey() == Endpoint.SSL) { + return Stream.of( + new SimpleEntry<>(restAdminApiRoleName(CERTS_INFO_ACTION), role(pb.build(CERTS_INFO_ACTION))), + new SimpleEntry<>(restAdminApiRoleName(RELOAD_CERTS_ACTION), role(pb.build(RELOAD_CERTS_ACTION))) + ); + } else { + return Stream.of(new SimpleEntry<>(restAdminApiRoleName(endpoint), role(pb.build()))); + } + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); static ObjectNode role(final String... clusterPermissions) { final ArrayNode clusterPermissionsArrayNode = DefaultObjectMapper.objectMapper.createArrayNode(); Arrays.stream(clusterPermissions).forEach(clusterPermissionsArrayNode::add); - return DefaultObjectMapper.objectMapper - .createObjectNode() - .put("reserved", true) - .set("cluster_permissions", clusterPermissionsArrayNode); + return DefaultObjectMapper.objectMapper.createObjectNode() + .put("reserved", true) + .set("cluster_permissions", clusterPermissionsArrayNode); } static String[] allRestApiPermissions() { - return ENDPOINTS_WITH_PERMISSIONS - .entrySet() - .stream() - .flatMap(entry -> { - if (entry.getKey() == Endpoint.SSL) { - return Stream.of(entry.getValue().build(CERTS_INFO_ACTION), entry.getValue().build(RELOAD_CERTS_ACTION)); - } else { - return Stream.of(entry.getValue().build()); - } - }).toArray(String[]::new); + return ENDPOINTS_WITH_PERMISSIONS.entrySet().stream().flatMap(entry -> { + if (entry.getKey() == Endpoint.SSL) { + return Stream.of(entry.getValue().build(CERTS_INFO_ACTION), entry.getValue().build(RELOAD_CERTS_ACTION)); + } else { + return Stream.of(entry.getValue().build()); + } + }).toArray(String[]::new); } final ConfigModel configModel; public SecurityRolesPermissionsTest() throws IOException { - this.configModel = - new ConfigModelV7( - createRolesConfig(), - createRoleMappingsConfig(), - createActionGroupsConfig(), - createTenantsConfig(), - Mockito.mock(DynamicConfigModel.class), - Settings.EMPTY - ); + this.configModel = new ConfigModelV7( + createRolesConfig(), + createRoleMappingsConfig(), + createActionGroupsConfig(), + createTenantsConfig(), + Mockito.mock(DynamicConfigModel.class), + Settings.EMPTY + ); } @Test @@ -151,17 +123,17 @@ public void hasNoExplicitClusterPermissionPermissionForRestAdmin() { final PermissionBuilder permissionBuilder = entry.getValue(); if (endpoint == Endpoint.SSL) { Assert.assertFalse( - endpoint.name(), - securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(CERTS_INFO_ACTION)) + endpoint.name(), + securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(CERTS_INFO_ACTION)) ); Assert.assertFalse( - endpoint.name(), - securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(RELOAD_CERTS_ACTION)) + endpoint.name(), + securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(RELOAD_CERTS_ACTION)) ); } else { Assert.assertFalse( - endpoint.name(), - securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build()) + endpoint.name(), + securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build()) ); } } @@ -176,10 +148,19 @@ public void hasExplicitClusterPermissionPermissionForRestAdminWitFullAccess() { final Endpoint endpoint = entry.getKey(); final PermissionBuilder permissionBuilder = entry.getValue(); if (endpoint == Endpoint.SSL) { - Assert.assertTrue(endpoint.name() + "/" + CERTS_INFO_ACTION, securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(CERTS_INFO_ACTION))); - Assert.assertTrue(endpoint.name() + "/" + CERTS_INFO_ACTION, securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(RELOAD_CERTS_ACTION))); + Assert.assertTrue( + endpoint.name() + "/" + CERTS_INFO_ACTION, + securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(CERTS_INFO_ACTION)) + ); + Assert.assertTrue( + endpoint.name() + "/" + CERTS_INFO_ACTION, + securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(RELOAD_CERTS_ACTION)) + ); } else { - Assert.assertTrue(endpoint.name(), securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build())); + Assert.assertTrue( + endpoint.name(), + securityRolesForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build()) + ); } } } @@ -188,60 +169,53 @@ public void hasExplicitClusterPermissionPermissionForRestAdminWitFullAccess() { @Test public void hasExplicitClusterPermissionPermissionForRestAdmin() { // verify all endpoint except SSL - final Collection noSslEndpoints = - ENDPOINTS_WITH_PERMISSIONS.keySet().stream() - .filter(e -> e != Endpoint.SSL).collect(Collectors.toList()); + final Collection noSslEndpoints = ENDPOINTS_WITH_PERMISSIONS.keySet() + .stream() + .filter(e -> e != Endpoint.SSL) + .collect(Collectors.toList()); for (final Endpoint endpoint : noSslEndpoints) { final String permission = ENDPOINTS_WITH_PERMISSIONS.get(endpoint).build(); - final SecurityRoles allowOnePermissionRole = - configModel.getSecurityRoles().filter( - ImmutableSet.of(restAdminApiRoleName(endpoint.name().toLowerCase(Locale.ROOT)))); + final SecurityRoles allowOnePermissionRole = configModel.getSecurityRoles() + .filter(ImmutableSet.of(restAdminApiRoleName(endpoint.name().toLowerCase(Locale.ROOT)))); Assert.assertTrue(endpoint.name(), allowOnePermissionRole.hasExplicitClusterPermissionPermission(permission)); - assertHasNoPermissionsForRestApiAdminOnePermissionRole( - endpoint, - allowOnePermissionRole - ); + assertHasNoPermissionsForRestApiAdminOnePermissionRole(endpoint, allowOnePermissionRole); } // verify SSL endpoint with 2 actions for (final String sslAction : ImmutableSet.of(CERTS_INFO_ACTION, RELOAD_CERTS_ACTION)) { - final SecurityRoles sslAllowRole = - configModel.getSecurityRoles().filter(ImmutableSet.of(restAdminApiRoleName(sslAction))); + final SecurityRoles sslAllowRole = configModel.getSecurityRoles().filter(ImmutableSet.of(restAdminApiRoleName(sslAction))); final PermissionBuilder permissionBuilder = ENDPOINTS_WITH_PERMISSIONS.get(Endpoint.SSL); Assert.assertTrue( - Endpoint.SSL + "/" + sslAction, - sslAllowRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(sslAction)) + Endpoint.SSL + "/" + sslAction, + sslAllowRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(sslAction)) ); assertHasNoPermissionsForRestApiAdminOnePermissionRole(Endpoint.SSL, sslAllowRole); } } void assertHasNoPermissionsForRestApiAdminOnePermissionRole(final Endpoint allowEndpoint, final SecurityRoles allowOnlyRoleForRole) { - final Collection noPermissionEndpoints = - ENDPOINTS_WITH_PERMISSIONS.keySet().stream() - .filter(e -> e != allowEndpoint) - .collect(Collectors.toList()); + final Collection noPermissionEndpoints = ENDPOINTS_WITH_PERMISSIONS.keySet() + .stream() + .filter(e -> e != allowEndpoint) + .collect(Collectors.toList()); for (final Endpoint endpoint : noPermissionEndpoints) { final PermissionBuilder permissionBuilder = ENDPOINTS_WITH_PERMISSIONS.get(endpoint); if (endpoint == Endpoint.SSL) { Assert.assertFalse( - endpoint.name(), - allowOnlyRoleForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(CERTS_INFO_ACTION))); + endpoint.name(), + allowOnlyRoleForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(CERTS_INFO_ACTION)) + ); Assert.assertFalse( - endpoint.name(), - allowOnlyRoleForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(RELOAD_CERTS_ACTION))); + endpoint.name(), + allowOnlyRoleForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build(RELOAD_CERTS_ACTION)) + ); } else { - Assert.assertFalse( - endpoint.name(), - allowOnlyRoleForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build())); + Assert.assertFalse(endpoint.name(), allowOnlyRoleForRole.hasExplicitClusterPermissionPermission(permissionBuilder.build())); } } } static ObjectNode meta(final String type) { - return DefaultObjectMapper.objectMapper - .createObjectNode() - .put("type", type) - .put("config_version", 2); + return DefaultObjectMapper.objectMapper.createObjectNode().put("type", type).put("config_version", 2); } static SecurityDynamicConfiguration createRolesConfig() throws IOException { diff --git a/src/test/java/org/opensearch/security/securityconf/impl/v7/IndexPatternTests.java b/src/test/java/org/opensearch/security/securityconf/impl/v7/IndexPatternTests.java index be7c2da7b0..2b95a6e84c 100644 --- a/src/test/java/org/opensearch/security/securityconf/impl/v7/IndexPatternTests.java +++ b/src/test/java/org/opensearch/security/securityconf/impl/v7/IndexPatternTests.java @@ -68,7 +68,7 @@ public void before() { @After public void after() { verifyNoMoreInteractions(user, resolver, clusterService); - } + } @Test public void testCtor() { @@ -78,7 +78,7 @@ public void testCtor() { /** Ensure that concreteIndexNames sends correct parameters are sent to getResolvedIndexPattern */ @Test public void testConcreteIndexNamesOverload() { - doReturn(ImmutableSet.of("darn")).when(ip).getResolvedIndexPattern(user, resolver, clusterService, false); + doReturn(ImmutableSet.of("darn")).when(ip).getResolvedIndexPattern(user, resolver, clusterService, false); final Set results = ip.concreteIndexNames(user, resolver, clusterService); @@ -93,7 +93,7 @@ public void testConcreteIndexNamesOverload() { @Test public void testAttemptResolveIndexNamesOverload() { doReturn(ImmutableSet.of("yarn")).when(ip).getResolvedIndexPattern(user, resolver, clusterService, true); - + final Set results = ip.attemptResolveIndexNames(user, resolver, clusterService); assertThat(results, contains("yarn")); @@ -108,7 +108,9 @@ public void testAttemptResolveIndexNamesOverload() { public void testExactNameWithNoMatches() { doReturn("index-17").when(ip).getUnresolvedIndexPattern(user); when(clusterService.state()).thenReturn(mock(ClusterState.class)); - when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-17"))).thenReturn(new String[]{}); + when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-17"))).thenReturn( + new String[] {} + ); final Set results = ip.concreteIndexNames(user, resolver, clusterService); @@ -124,7 +126,9 @@ public void testExactNameWithNoMatches() { public void testExactName() { doReturn("index-17").when(ip).getUnresolvedIndexPattern(user); when(clusterService.state()).thenReturn(mock(ClusterState.class)); - when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-17"))).thenReturn(new String[]{"resolved-index-17"}); + when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-17"))).thenReturn( + new String[] { "resolved-index-17" } + ); final Set results = ip.concreteIndexNames(user, resolver, clusterService); @@ -140,7 +144,9 @@ public void testExactName() { public void testMultipleConcreteIndices() { doReturn("index-1*").when(ip).getUnresolvedIndexPattern(user); doReturn(createClusterState()).when(clusterService).state(); - when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-1*"))).thenReturn(new String[]{"resolved-index-17", "resolved-index-18"}); + when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-1*"))).thenReturn( + new String[] { "resolved-index-17", "resolved-index-18" } + ); final Set results = ip.concreteIndexNames(user, resolver, clusterService); @@ -156,12 +162,18 @@ public void testMultipleConcreteIndices() { public void testMultipleConcreteIndicesWithOneAlias() { doReturn("index-1*").when(ip).getUnresolvedIndexPattern(user); - doReturn(createClusterState( - new IndexShorthand("index-100", Type.ALIAS), // Name and type match - new IndexShorthand("19", Type.ALIAS) // Type matches/wrong name - )).when(clusterService).state(); - when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-100"))).thenReturn(new String[]{"resolved-index-100"}); - when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-1*"))).thenReturn(new String[]{"resolved-index-17", "resolved-index-18"}); + doReturn( + createClusterState( + new IndexShorthand("index-100", Type.ALIAS), // Name and type match + new IndexShorthand("19", Type.ALIAS) // Type matches/wrong name + ) + ).when(clusterService).state(); + when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-100"))).thenReturn( + new String[] { "resolved-index-100" } + ); + when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-1*"))).thenReturn( + new String[] { "resolved-index-17", "resolved-index-18" } + ); final Set results = ip.concreteIndexNames(user, resolver, clusterService); @@ -172,18 +184,23 @@ public void testMultipleConcreteIndicesWithOneAlias() { verify(resolver).concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-100")); verify(resolver).concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-1*")); } - + /** Verify attemptResolveIndexNames with multiple aliases */ @Test public void testMultipleConcreteAliasedAndUnresolved() { doReturn("index-1*").when(ip).getUnresolvedIndexPattern(user); - doReturn(createClusterState( - new IndexShorthand("index-100", Type.ALIAS), // Name and type match - new IndexShorthand("index-101", Type.ALIAS), // Name and type match - new IndexShorthand("19", Type.ALIAS) // Type matches/wrong name - )).when(clusterService).state(); - when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-100"), eq("index-101"))).thenReturn(new String[]{"resolved-index-100", "resolved-index-101"}); - when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-1*"))).thenReturn(new String[]{"resolved-index-17", "resolved-index-18"}); + doReturn( + createClusterState( + new IndexShorthand("index-100", Type.ALIAS), // Name and type match + new IndexShorthand("index-101", Type.ALIAS), // Name and type match + new IndexShorthand("19", Type.ALIAS) // Type matches/wrong name + ) + ).when(clusterService).state(); + when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-100"), eq("index-101"))) + .thenReturn(new String[] { "resolved-index-100", "resolved-index-101" }); + when(resolver.concreteIndexNames(any(), eq(IndicesOptions.lenientExpandOpen()), eq(true), eq("index-1*"))).thenReturn( + new String[] { "resolved-index-17", "resolved-index-18" } + ); final Set results = ip.attemptResolveIndexNames(user, resolver, clusterService); @@ -200,7 +217,7 @@ private ClusterState createClusterState(final IndexShorthand... indices) { Arrays.stream(indices).forEach(indexShorthand -> { final IndexAbstraction indexAbstraction = mock(IndexAbstraction.class); when(indexAbstraction.getType()).thenReturn(indexShorthand.type); - indexMap.put(indexShorthand.name, indexAbstraction); + indexMap.put(indexShorthand.name, indexAbstraction); }); final Metadata mockMetadata = mock(Metadata.class, withSettings().strictness(Strictness.LENIENT)); @@ -215,6 +232,7 @@ private ClusterState createClusterState(final IndexShorthand... indices) { private class IndexShorthand { public final String name; public final Type type; + public IndexShorthand(final String name, final Type type) { this.name = name; this.type = type; diff --git a/src/test/java/org/opensearch/security/setting/DeprecatedSettingsTest.java b/src/test/java/org/opensearch/security/setting/DeprecatedSettingsTest.java index 72c1bc3741..143efe9b11 100644 --- a/src/test/java/org/opensearch/security/setting/DeprecatedSettingsTest.java +++ b/src/test/java/org/opensearch/security/setting/DeprecatedSettingsTest.java @@ -29,7 +29,7 @@ public class DeprecatedSettingsTest { @Mock private DeprecationLogger logger; - private DeprecationLogger original; + private DeprecationLogger original; @Before public void before() { diff --git a/src/test/java/org/opensearch/security/ssl/CertificateValidatorTest.java b/src/test/java/org/opensearch/security/ssl/CertificateValidatorTest.java index f1f7f9ea84..ce614a17ca 100644 --- a/src/test/java/org/opensearch/security/ssl/CertificateValidatorTest.java +++ b/src/test/java/org/opensearch/security/ssl/CertificateValidatorTest.java @@ -1,10 +1,10 @@ /* * Copyright 2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl; @@ -41,39 +41,39 @@ import org.opensearch.security.test.helper.file.FileHelper; public class CertificateValidatorTest { - + public static final Date CRL_DATE = new Date(1525546426000L); protected final Logger log = LogManager.getLogger(this.getClass()); - + @Test public void testStaticCRL() throws Exception { - + File staticCrl = FileHelper.getAbsoluteFilePathFromClassPath("ssl/crl/revoked.crl").toFile(); Collection crls = null; - try(FileInputStream crlin = new FileInputStream(staticCrl)) { + try (FileInputStream crlin = new FileInputStream(staticCrl)) { crls = CertificateFactory.getInstance("X.509").generateCRLs(crlin); } - + Assert.assertEquals(crls.size(), 1); - - //trust chain incl intermediate certificates (root + intermediates) + + // trust chain incl intermediate certificates (root + intermediates) Collection rootCas; final File trustedCas = FileHelper.getAbsoluteFilePathFromClassPath("ssl/chain-ca.pem").toFile(); - try(FileInputStream trin = new FileInputStream(trustedCas)) { - rootCas = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); + try (FileInputStream trin = new FileInputStream(trustedCas)) { + rootCas = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); } - + Assert.assertEquals(rootCas.size(), 2); - //certificate chain to validate (client cert + intermediates but without root) + // certificate chain to validate (client cert + intermediates but without root) Collection certsToValidate; final File certs = FileHelper.getAbsoluteFilePathFromClassPath("ssl/crl/revoked.crt.pem").toFile(); - try(FileInputStream trin = new FileInputStream(certs)) { - certsToValidate = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); + try (FileInputStream trin = new FileInputStream(certs)) { + certsToValidate = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); } - + Assert.assertEquals(certsToValidate.size(), 2); - + CertificateValidator validator = new CertificateValidator(rootCas.toArray(new X509Certificate[0]), crls); validator.setDate(CRL_DATE); try { @@ -83,36 +83,36 @@ public void testStaticCRL() throws Exception { Assert.assertTrue(ExceptionUtils.getRootCause(e) instanceof CertificateRevokedException); } } - + @Test public void testStaticCRLOk() throws Exception { - + File staticCrl = FileHelper.getAbsoluteFilePathFromClassPath("ssl/crl/revoked.crl").toFile(); Collection crls = null; - try(FileInputStream crlin = new FileInputStream(staticCrl)) { + try (FileInputStream crlin = new FileInputStream(staticCrl)) { crls = CertificateFactory.getInstance("X.509").generateCRLs(crlin); } - + Assert.assertEquals(crls.size(), 1); - - //trust chain incl intermediate certificates (root + intermediates) + + // trust chain incl intermediate certificates (root + intermediates) Collection rootCas; final File trustedCas = FileHelper.getAbsoluteFilePathFromClassPath("ssl/chain-ca.pem").toFile(); - try(FileInputStream trin = new FileInputStream(trustedCas)) { - rootCas = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); + try (FileInputStream trin = new FileInputStream(trustedCas)) { + rootCas = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); } - + Assert.assertEquals(rootCas.size(), 2); - //certificate chain to validate (client cert + intermediates but without root) + // certificate chain to validate (client cert + intermediates but without root) Collection certsToValidate; final File certs = FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem").toFile(); - try(FileInputStream trin = new FileInputStream(certs)) { - certsToValidate = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); + try (FileInputStream trin = new FileInputStream(certs)) { + certsToValidate = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); } - + Assert.assertEquals(certsToValidate.size(), 3); - + CertificateValidator validator = new CertificateValidator(rootCas.toArray(new X509Certificate[0]), crls); validator.setDate(CRL_DATE); try { @@ -121,26 +121,26 @@ public void testStaticCRLOk() throws Exception { Assert.fail(ExceptionsHelper.stackTrace(ExceptionUtils.getRootCause(e))); } } - + @Test public void testNoValidationPossible() throws Exception { - //trust chain incl intermediate certificates (root + intermediates) + // trust chain incl intermediate certificates (root + intermediates) Collection rootCas; final File trustedCas = FileHelper.getAbsoluteFilePathFromClassPath("ssl/chain-ca.pem").toFile(); - try(FileInputStream trin = new FileInputStream(trustedCas)) { - rootCas = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); + try (FileInputStream trin = new FileInputStream(trustedCas)) { + rootCas = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); } - + Assert.assertEquals(rootCas.size(), 2); - //certificate chain to validate (client cert + intermediates but without root) + // certificate chain to validate (client cert + intermediates but without root) Collection certsToValidate; final File certs = FileHelper.getAbsoluteFilePathFromClassPath("ssl/crl/revoked.crt.pem").toFile(); - try(FileInputStream trin = new FileInputStream(certs)) { - certsToValidate = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); + try (FileInputStream trin = new FileInputStream(certs)) { + certsToValidate = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); } - + Assert.assertEquals(certsToValidate.size(), 2); CertificateValidator validator = new CertificateValidator(rootCas.toArray(new X509Certificate[0]), Collections.emptyList()); @@ -153,29 +153,29 @@ public void testNoValidationPossible() throws Exception { Assert.assertTrue(e.getCause().getMessage().contains("unable to find valid certification path to requested target")); } } - + @Test public void testCRLDP() throws Exception { - //trust chain incl intermediate certificates (root + intermediates) + // trust chain incl intermediate certificates (root + intermediates) Collection rootCas; final File trustedCas = FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem").toFile(); - try(FileInputStream trin = new FileInputStream(trustedCas)) { - rootCas = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); + try (FileInputStream trin = new FileInputStream(trustedCas)) { + rootCas = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); } - + Assert.assertEquals(rootCas.size(), 1); - //certificate chain to validate (client cert + intermediates but without root) + // certificate chain to validate (client cert + intermediates but without root) Collection certsToValidate; final File certs = FileHelper.getAbsoluteFilePathFromClassPath("ssl/crl/revoked.crt.pem").toFile(); - //final File certs = getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem"); - try(FileInputStream trin = new FileInputStream(certs)) { - certsToValidate = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); + // final File certs = getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem"); + try (FileInputStream trin = new FileInputStream(certs)) { + certsToValidate = (Collection) CertificateFactory.getInstance("X.509").generateCertificates(trin); } - + Assert.assertEquals(certsToValidate.size(), 2); - + CertificateValidator validator = new CertificateValidator(rootCas.toArray(new X509Certificate[0]), Collections.emptyList()); validator.setEnableCRLDP(true); validator.setEnableOCSP(true); diff --git a/src/test/java/org/opensearch/security/ssl/OpenSSLTest.java b/src/test/java/org/opensearch/security/ssl/OpenSSLTest.java index 6d473c0160..f205f5fff9 100644 --- a/src/test/java/org/opensearch/security/ssl/OpenSSLTest.java +++ b/src/test/java/org/opensearch/security/ssl/OpenSSLTest.java @@ -1,10 +1,10 @@ /* * Copyright 2015-2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl; @@ -104,21 +104,20 @@ public void testHttpsV3Fail() throws Exception { super.testHttpsV3Fail(); } - @Override - @Test(timeout=40000) + @Test(timeout = 40000) public void testNodeClientSSL() throws Exception { Assume.assumeTrue(OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && OpenSsl.isAvailable()); super.testNodeClientSSL(); } - + @Override @Test public void testHttpsOptionalAuth() throws Exception { Assume.assumeTrue(OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && OpenSsl.isAvailable()); super.testHttpsOptionalAuth(); } - + @Test public void testAvailCiphersOpenSSL() throws Exception { Assume.assumeTrue(OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && OpenSsl.isAvailable()); @@ -139,7 +138,7 @@ public void testAvailCiphersOpenSSL() throws Exception { System.out.println("OpenSSL secure ciphers: " + openSSLSecureCiphers); Assert.assertTrue(openSSLSecureCiphers.size() > 0); } - + @Test public void testHttpsEnforceFail() throws Exception { Assume.assumeTrue(OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && OpenSsl.isAvailable()); @@ -157,55 +156,64 @@ public void testHttpsAndNodeSSLFailedCipher() throws Exception { Assume.assumeTrue(OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && OpenSsl.isAvailable()); super.testHttpsAndNodeSSLFailedCipher(); } - + @Test public void testHttpsAndNodeSSLPem() throws Exception { Assume.assumeTrue(OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && OpenSsl.isAvailable()); super.testHttpsAndNodeSSLPKCS8Pem(); } - + @Test public void testHttpsAndNodeSSLPemEnc() throws Exception { Assume.assumeTrue(OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && OpenSsl.isAvailable()); super.testHttpsAndNodeSSLPemEnc(); } - + @Test public void testNodeClientSSLwithOpenSslTLSv13() throws Exception { - + Assume.assumeTrue(OpenSearchSecuritySSLPlugin.OPENSSL_SUPPORTED && OpenSsl.isAvailable() && OpenSsl.version() > 0x10101009L); - final Settings settings = Settings.builder().put("plugins.security.ssl.transport.enabled", true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put("plugins.security.ssl.transport.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put("plugins.security.ssl.transport.enforce_hostname_verification", false) - .put("plugins.security.ssl.transport.resolve_hostname", false) - .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "TLSv1.3") - .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "TLS_CHACHA20_POLY1305_SHA256") - .put("node.max_local_storage_nodes",4) - .build(); + final Settings settings = Settings.builder() + .put("plugins.security.ssl.transport.enabled", true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put("plugins.security.ssl.transport.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put("plugins.security.ssl.transport.enforce_hostname_verification", false) + .put("plugins.security.ssl.transport.resolve_hostname", false) + .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "TLSv1.3") + .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "TLS_CHACHA20_POLY1305_SHA256") + .put("node.max_local_storage_nodes", 4) + .build(); setupSslOnlyMode(settings); - + RestHelper rh = nonSslRestHelper(); - final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put("cluster.name", clusterInfo.clustername).put("path.home", "/tmp") - .put("node.name", "client_node_" + new Random().nextInt()) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/ssl/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/ssl/logs") - .put("path.home", "./target") - .put("discovery.initial_state_timeout","8s") - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost+":"+clusterInfo.nodePort) - .put(settings)// ----- - .build(); + final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) + .put("cluster.name", clusterInfo.clustername) + .put("path.home", "/tmp") + .put("node.name", "client_node_" + new Random().nextInt()) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/ssl/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/ssl/logs") + .put("path.home", "./target") + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .put(settings)// ----- + .build(); try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class).start()) { - ClusterHealthResponse res = node.client().admin().cluster().health(new ClusterHealthRequest().waitForNodes("4").timeout(TimeValue.timeValueSeconds(5))).actionGet(); + ClusterHealthResponse res = node.client() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForNodes("4").timeout(TimeValue.timeValueSeconds(5))) + .actionGet(); Assert.assertFalse(res.isTimedOut()); Assert.assertEquals(4, res.getNumberOfNodes()); Assert.assertEquals(4, node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); diff --git a/src/test/java/org/opensearch/security/ssl/SSLTest.java b/src/test/java/org/opensearch/security/ssl/SSLTest.java index 65181d66b9..72ad6d5d16 100644 --- a/src/test/java/org/opensearch/security/ssl/SSLTest.java +++ b/src/test/java/org/opensearch/security/ssl/SSLTest.java @@ -70,7 +70,7 @@ import static org.opensearch.security.ssl.SecureSSLSettings.SSLSetting.SECURITY_SSL_TRANSPORT_PEMKEY_PASSWORD; import static org.opensearch.security.ssl.SecureSSLSettings.SSLSetting.SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD; -@SuppressWarnings({"resource", "unchecked"}) +@SuppressWarnings({ "resource", "unchecked" }) public class SSLTest extends SingleClusterTest { @Rule @@ -82,19 +82,25 @@ public class SSLTest extends SingleClusterTest { public void testHttps() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .putList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, "TLSv1.1", "TLSv1.2") - .putList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_CIPHERS, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256") - .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "TLSv1.1", "TLSv1.2") - .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .putList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, "TLSv1.1", "TLSv1.2") + .putList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_CIPHERS, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256") + .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "TLSv1.1", "TLSv1.2") + .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .build(); setupSslOnlyMode(settings); @@ -105,14 +111,18 @@ public void testHttps() throws Exception { rh.keystore = "node-untspec5-keystore.p12"; System.out.println(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=true")); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=true").contains("EMAILADDRESS=unt@tst.com")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=true").contains("EMAILADDRESS=unt@tst.com") + ); Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=true").contains("local_certificates_list")); - Assert.assertFalse(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=false").contains("local_certificates_list")); + Assert.assertFalse( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=false").contains("local_certificates_list") + ); Assert.assertFalse(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("local_certificates_list")); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); Assert.assertFalse(rh.executeSimpleRequest("_nodes/settings?pretty").contains("\"opendistro_security\"")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/settings?pretty").contains("keystore_filepath")); - //Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + // Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); } @@ -124,28 +134,35 @@ public void testCipherAndProtocols() throws Exception { System.out.println("allowOpenSSL: " + allowOpenSSL); Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0").put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - //WEAK and insecure cipher, do NOT use this, its here for unittesting only!!! - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_CIPHERS, "SSL_RSA_EXPORT_WITH_RC4_40_MD5") - //WEAK and insecure protocol, do NOT use this, its here for unittesting only!!! - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, "SSLv3") - .put("client.type", "node") - .put("path.home", ".") - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + // WEAK and insecure cipher, do NOT use this, its here for unittesting only!!! + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_CIPHERS, "SSL_RSA_EXPORT_WITH_RC4_40_MD5") + // WEAK and insecure protocol, do NOT use this, its here for unittesting only!!! + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, "SSLv3") + .put("client.type", "node") + .put("path.home", ".") + .build(); try { String[] enabledCiphers = new DefaultSecurityKeyStore(settings, Paths.get(".")).createHTTPSSLEngine().getEnabledCipherSuites(); String[] enabledProtocols = new DefaultSecurityKeyStore(settings, Paths.get(".")).createHTTPSSLEngine().getEnabledProtocols(); if (allowOpenSSL) { - Assert.assertEquals(2, enabledProtocols.length); //SSLv2Hello is always enabled when using openssl + Assert.assertEquals(2, enabledProtocols.length); // SSLv2Hello is always enabled when using openssl Assert.assertTrue("Check SSLv3", "SSLv3".equals(enabledProtocols[0]) || "SSLv3".equals(enabledProtocols[1])); Assert.assertEquals(1, enabledCiphers.length); Assert.assertEquals("TLS_RSA_EXPORT_WITH_RC4_40_MD5", enabledCiphers[0]); @@ -157,25 +174,32 @@ public void testCipherAndProtocols() throws Exception { } settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - //WEAK and insecure cipher, do NOT use this, its here for unittesting only!!! - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "SSL_RSA_EXPORT_WITH_RC4_40_MD5") - //WEAK and insecure protocol, do NOT use this, its here for unittesting only!!! - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "SSLv3") - .put("client.type", "node") - .put("path.home", ".") - .build(); - - enabledCiphers = new DefaultSecurityKeyStore(settings, Paths.get(".")).createServerTransportSSLEngine().getEnabledCipherSuites(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + // WEAK and insecure cipher, do NOT use this, its here for unittesting only!!! + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "SSL_RSA_EXPORT_WITH_RC4_40_MD5") + // WEAK and insecure protocol, do NOT use this, its here for unittesting only!!! + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "SSLv3") + .put("client.type", "node") + .put("path.home", ".") + .build(); + + enabledCiphers = new DefaultSecurityKeyStore(settings, Paths.get(".")).createServerTransportSSLEngine() + .getEnabledCipherSuites(); enabledProtocols = new DefaultSecurityKeyStore(settings, Paths.get(".")).createServerTransportSSLEngine().getEnabledProtocols(); if (allowOpenSSL) { - Assert.assertEquals(2, enabledProtocols.length); //SSLv2Hello is always enabled when using openssl + Assert.assertEquals(2, enabledProtocols.length); // SSLv2Hello is always enabled when using openssl Assert.assertTrue("Check SSLv3", "SSLv3".equals(enabledProtocols[0]) || "SSLv3".equals(enabledProtocols[1])); Assert.assertEquals(1, enabledCiphers.length); Assert.assertEquals("TLS_RSA_EXPORT_WITH_RC4_40_MD5", enabledCiphers[0]); @@ -185,11 +209,13 @@ public void testCipherAndProtocols() throws Exception { Assert.assertEquals(1, enabledCiphers.length); Assert.assertEquals("SSL_RSA_EXPORT_WITH_RC4_40_MD5", enabledCiphers[0]); } - enabledCiphers = new DefaultSecurityKeyStore(settings, Paths.get(".")).createClientTransportSSLEngine(null, -1).getEnabledCipherSuites(); - enabledProtocols = new DefaultSecurityKeyStore(settings, Paths.get(".")).createClientTransportSSLEngine(null, -1).getEnabledProtocols(); + enabledCiphers = new DefaultSecurityKeyStore(settings, Paths.get(".")).createClientTransportSSLEngine(null, -1) + .getEnabledCipherSuites(); + enabledProtocols = new DefaultSecurityKeyStore(settings, Paths.get(".")).createClientTransportSSLEngine(null, -1) + .getEnabledProtocols(); if (allowOpenSSL) { - Assert.assertEquals(2, enabledProtocols.length); //SSLv2Hello is always enabled when using openssl + Assert.assertEquals(2, enabledProtocols.length); // SSLv2Hello is always enabled when using openssl Assert.assertTrue("Check SSLv3", "SSLv3".equals(enabledProtocols[0]) || "SSLv3".equals(enabledProtocols[1])); Assert.assertEquals(1, enabledCiphers.length); Assert.assertEquals("TLS_RSA_EXPORT_WITH_RC4_40_MD5", enabledCiphers[0]); @@ -200,9 +226,18 @@ public void testCipherAndProtocols() throws Exception { Assert.assertEquals("SSL_RSA_EXPORT_WITH_RC4_40_MD5", enabledCiphers[0]); } } catch (OpenSearchSecurityException e) { - System.out.println("EXPECTED " + e.getClass().getSimpleName() + " for " + System.getProperty("java.specification.version") + ": " + e.toString()); + System.out.println( + "EXPECTED " + + e.getClass().getSimpleName() + + " for " + + System.getProperty("java.specification.version") + + ": " + + e.toString() + ); e.printStackTrace(); - Assert.assertTrue("Check if error contains 'no valid cipher suites' -> " + e.toString(), e.toString().contains("no valid cipher suites") + Assert.assertTrue( + "Check if error contains 'no valid cipher suites' -> " + e.toString(), + e.toString().contains("no valid cipher suites") || e.toString().contains("failed to set cipher suite") || e.toString().contains("Unable to configure permitted SSL ciphers") || e.toString().contains("OPENSSL_internal:NO_CIPHER_MATCH") @@ -215,13 +250,21 @@ public void testCipherAndProtocols() throws Exception { public void testHttpsOptionalAuth() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0").put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")).build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .build(); setupSslOnlyMode(settings); @@ -234,29 +277,44 @@ public void testHttpsOptionalAuth() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("TLS")); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); Assert.assertFalse(rh.executeSimpleRequest("_nodes/settings?pretty").contains("\"opendistro_security\"")); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); } @Test public void testHttpsAndNodeSSL() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true).put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + + .build(); setupSslOnlyMode(settings); @@ -269,7 +327,9 @@ public void testHttpsAndNodeSSL() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("TLS")); Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"tx_size_in_bytes\" : 0")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"rx_count\" : 0")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"rx_size_in_bytes\" : 0")); @@ -281,22 +341,34 @@ public void testHttpsAndNodeSSL() throws Exception { public void testHttpsAndNodeSSLPKCS8Pem() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem")) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .build(); setupSslOnlyMode(settings); @@ -309,30 +381,47 @@ public void testHttpsAndNodeSSLPKCS8Pem() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("TLS")); Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - //Assert.assertTrue(!executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("null")); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + // Assert.assertTrue(!executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("null")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); } @Test public void testHttpsAndNodeSSLPKCS1Pem() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-pkcs1.key.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-pkcs1.key.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-pkcs1.key.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-pkcs1.key.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .build(); setupSslOnlyMode(settings); @@ -344,7 +433,9 @@ public void testHttpsAndNodeSSLPKCS1Pem() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("TLS")); Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); } @Test @@ -354,23 +445,38 @@ public void testHttpsAndNodeSSLPemEnc() throws Exception { mockSecureSettings.setString(SECURITY_SSL_TRANSPORT_PEMKEY_PASSWORD.propertyName, "changeit"); final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.key")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.key")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .setSecureSettings(mockSecureSettings) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.crt.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.key") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.crt.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.key")) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .setSecureSettings(mockSecureSettings) + .build(); setupSslOnlyMode(settings); @@ -383,32 +489,49 @@ public void testHttpsAndNodeSSLPemEnc() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("TLS")); Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - //Assert.assertTrue(!executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("null")); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + // Assert.assertTrue(!executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("null")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); } @Test public void testSSLPemEncWithInsecureSettings() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.key")) - // legacy insecure passwords - .put(SECURITY_SSL_TRANSPORT_PEMKEY_PASSWORD.insecurePropertyName, "changeit") - .put(SECURITY_SSL_HTTP_PEMKEY_PASSWORD.insecurePropertyName, "changeit") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.key")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.crt.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.key") + ) + // legacy insecure passwords + .put(SECURITY_SSL_TRANSPORT_PEMKEY_PASSWORD.insecurePropertyName, "changeit") + .put(SECURITY_SSL_HTTP_PEMKEY_PASSWORD.insecurePropertyName, "changeit") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.crt.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/pem/node-4.key")) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .build(); setupSslOnlyMode(settings); @@ -417,33 +540,46 @@ public void testSSLPemEncWithInsecureSettings() throws Exception { rh.trustHTTPServerCertificate = true; rh.sendAdminCertificate = true; - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); } - @Test public void testHttpsAndNodeSSLFailedCipher() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_CIPHERS, "INVALID_CIPHER") - - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_CIPHERS, "INVALID_CIPHER") + + .build(); try { setupSslOnlyMode(settings); @@ -461,18 +597,25 @@ public void testHttpPlainFail() throws Exception { thrown.expect(NoHttpResponseException.class); final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0").put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "OPTIONAL") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")).build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "OPTIONAL") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .build(); setupSslOnlyMode(settings); - RestHelper rh = restHelper(); rh.enableHTTPClientSSL = false; rh.trustHTTPServerCertificate = true; @@ -480,21 +623,31 @@ public void testHttpPlainFail() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); } @Test public void testHttpsNoEnforce() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0").put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "NONE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")).build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "NONE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .build(); setupSslOnlyMode(settings); @@ -505,21 +658,31 @@ public void testHttpsNoEnforce() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - Assert.assertFalse(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertFalse( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); } @Test public void testHttpsEnforceFail() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0").put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")).build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .build(); setupSslOnlyMode(settings); @@ -532,7 +695,7 @@ public void testHttpsEnforceFail() throws Exception { rh.executeSimpleRequest(""); Assert.fail(); } catch (SocketException | SSLException e) { - //expected + // expected System.out.println("Expected SSLHandshakeException " + e.toString()); } catch (Exception e) { e.printStackTrace(); @@ -545,14 +708,22 @@ public void testHttpsV3Fail() throws Exception { thrown.expect(SSLHandshakeException.class); final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0").put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "NONE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")).build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "NONE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .build(); setupSslOnlyMode(settings); @@ -570,34 +741,45 @@ public void testHttpsV3Fail() throws Exception { public void testNodeClientSSL() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + .build(); setupSslOnlyMode(settings); RestHelper rh = nonSslRestHelper(); final Settings tcSettings = AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), false, false) - .put("cluster.name", clusterInfo.clustername).put("path.home", ".") - .put("node.name", "client_node_" + new Random().nextInt()) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/ssl/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/ssl/logs") - .put("path.home", "./target") - .put("discovery.initial_state_timeout", "8s") - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) - .put(settings)// ----- - .build(); + .put("cluster.name", clusterInfo.clustername) + .put("path.home", ".") + .put("node.name", "client_node_" + new Random().nextInt()) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/ssl/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/ssl/logs") + .put("path.home", "./target") + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .put(settings)// ----- + .build(); try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class).start()) { - ClusterHealthResponse res = node.client().admin().cluster().health(new ClusterHealthRequest().waitForNodes("4").timeout(TimeValue.timeValueSeconds(15))).actionGet(); + ClusterHealthResponse res = node.client() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForNodes("4").timeout(TimeValue.timeValueSeconds(15))) + .actionGet(); Assert.assertFalse(res.isTimedOut()); Assert.assertEquals(4, res.getNumberOfNodes()); Assert.assertEquals(4, node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); @@ -635,7 +817,7 @@ public void testUnmodifieableCipherProtocolConfig() throws Exception { SSLConfigConstants.getSecureSSLCiphers(Settings.EMPTY, false).set(0, "bogus"); Assert.fail(); } catch (UnsupportedOperationException e) { - //expected + // expected } } @@ -643,20 +825,33 @@ public void testUnmodifieableCipherProtocolConfig() throws Exception { public void testCustomPrincipalExtractor() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PRINCIPAL_EXTRACTOR_CLASS, "org.opensearch.security.ssl.TestPrincipalExtractor") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")).build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PRINCIPAL_EXTRACTOR_CLASS, "org.opensearch.security.ssl.TestPrincipalExtractor") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .build(); setupSslOnlyMode(settings); @@ -667,7 +862,11 @@ public void testCustomPrincipalExtractor() throws Exception { log.debug("OpenSearch started"); - final Settings tcSettings = Settings.builder().put("cluster.name", clusterInfo.clustername).put("path.home", ".").put(settings).build(); + final Settings tcSettings = Settings.builder() + .put("cluster.name", clusterInfo.clustername) + .put("path.home", ".") + .put(settings) + .build(); try (Client tc = getClient()) { @@ -676,7 +875,12 @@ public void testCustomPrincipalExtractor() throws Exception { Assert.assertEquals(3, tc.admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); log.debug("Client connected"); TestPrincipalExtractor.reset(); - Assert.assertEquals("test", tc.index(new IndexRequest("test").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"a\":5}", XContentType.JSON)).actionGet().getIndex()); + Assert.assertEquals( + "test", + tc.index(new IndexRequest("test").setRefreshPolicy(RefreshPolicy.IMMEDIATE).source("{\"a\":5}", XContentType.JSON)) + .actionGet() + .getIndex() + ); log.debug("Index created"); Assert.assertEquals(1L, tc.search(new SearchRequest("test")).actionGet().getHits().getTotalHits().value); log.debug("Search done"); @@ -688,8 +892,8 @@ public void testCustomPrincipalExtractor() throws Exception { rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty"); - //we need to test this in SG itself because in the SSL only plugin the info is not longer propagated - //Assert.assertTrue(TestPrincipalExtractor.getTransportCount() > 0); + // we need to test this in SG itself because in the SSL only plugin the info is not longer propagated + // Assert.assertTrue(TestPrincipalExtractor.getTransportCount() > 0); Assert.assertTrue(TestPrincipalExtractor.getHttpCount() > 0); } @@ -697,24 +901,36 @@ public void testCustomPrincipalExtractor() throws Exception { public void testCRLPem() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/chain-ca.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATE, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATION_DATE, CertificateValidatorTest.CRL_DATE.getTime()) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem")) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/chain-ca.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATE, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATION_DATE, CertificateValidatorTest.CRL_DATE.getTime()) + .build(); setupSslOnlyMode(settings); @@ -730,19 +946,25 @@ public void testCRLPem() throws Exception { public void testCRL() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATE, true) - .put(SSLConfigConstants.SSECURITY_SSL_HTTP_CRL_FILE, FileHelper.getAbsoluteFilePathFromClassPath("ssl/crl/revoked.crl")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATION_DATE, CertificateValidatorTest.CRL_DATE.getTime()) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, false) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATE, true) + .put(SSLConfigConstants.SSECURITY_SSL_HTTP_CRL_FILE, FileHelper.getAbsoluteFilePathFromClassPath("ssl/crl/revoked.crl")) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CRL_VALIDATION_DATE, CertificateValidatorTest.CRL_DATE.getTime()) + .build(); setupSslOnlyMode(settings); @@ -758,40 +980,50 @@ public void testCRL() throws Exception { @Test public void testNodeClientSSLwithJavaTLSv13() throws Exception { - //Java TLS 1.3 is available since Java 11 + // Java TLS 1.3 is available since Java 11 Assume.assumeTrue(!allowOpenSSL && PlatformDependent.javaVersion() >= 11); final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "TLSv1.3") - .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "TLS_AES_128_GCM_SHA256") - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, "TLSv1.3") + .putList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_CIPHERS, "TLS_AES_128_GCM_SHA256") + .build(); setupSslOnlyMode(settings); RestHelper rh = nonSslRestHelper(); final Settings tcSettings = Settings.builder() - .put("cluster.name", clusterInfo.clustername) - .put("path.data", "./target/data/" + clusterInfo.clustername + "/ssl/data") - .put("path.logs", "./target/data/" + clusterInfo.clustername + "/ssl/logs") - .put("path.home", "./target") - .put("node.name", "client_node_" + new Random().nextInt()) - .put("discovery.initial_state_timeout", "8s") - .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) - .put(settings)// ----- - .build(); + .put("cluster.name", clusterInfo.clustername) + .put("path.data", "./target/data/" + clusterInfo.clustername + "/ssl/data") + .put("path.logs", "./target/data/" + clusterInfo.clustername + "/ssl/logs") + .put("path.home", "./target") + .put("node.name", "client_node_" + new Random().nextInt()) + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.zen.ping.unicast.hosts", clusterInfo.nodeHost + ":" + clusterInfo.nodePort) + .put(settings)// ----- + .build(); try (Node node = new PluginAwareNode(false, tcSettings, Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class).start()) { - ClusterHealthResponse res = node.client().admin().cluster().health(new ClusterHealthRequest().waitForNodes("4").timeout(TimeValue.timeValueSeconds(5))).actionGet(); + ClusterHealthResponse res = node.client() + .admin() + .cluster() + .health(new ClusterHealthRequest().waitForNodes("4").timeout(TimeValue.timeValueSeconds(5))) + .actionGet(); Assert.assertFalse(res.isTimedOut()); Assert.assertEquals(4, res.getNumberOfNodes()); Assert.assertEquals(4, node.client().admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); @@ -807,20 +1039,32 @@ public void testNodeClientSSLwithJavaTLSv13() throws Exception { public void testTLSv12() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, "TLSv1.2") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, "TLSv1.2") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .build(); setupSslOnlyMode(settings); @@ -831,7 +1075,6 @@ public void testTLSv12() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"tx_size_in_bytes\"")); } - @Test public void testHttpsAndNodeSSLKeyPass() throws Exception { final MockSecureSettings mockSecureSettings = new MockSecureSettings(); @@ -839,24 +1082,36 @@ public void testHttpsAndNodeSSLKeyPass() throws Exception { mockSecureSettings.setString(SECURITY_SSL_TRANSPORT_KEYSTORE_KEYPASSWORD.propertyName, "changeit"); final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .setSecureSettings(mockSecureSettings) - - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .setSecureSettings(mockSecureSettings) + + .build(); setupSslOnlyMode(settings); @@ -869,7 +1124,9 @@ public void testHttpsAndNodeSSLKeyPass() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("TLS")); Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"tx_size_in_bytes\" : 0")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"rx_count\" : 0")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"rx_size_in_bytes\" : 0")); @@ -885,30 +1142,43 @@ public void testHttpsAndNodeSSLKeyStoreExtendedUsageEnabled() throws Exception { mockSecureSettings.setString(SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.propertyName, "changeit"); final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_EXTENDED_KEY_USAGE_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_KEYSTORE_ALIAS, "node-0-client") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_KEYSTORE_ALIAS, "node-0-server") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_TRUSTSTORE_ALIAS, "root-ca") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_TRUSTSTORE_ALIAS, "root-ca") - - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/truststore.jks")) - - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true).put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .setSecureSettings(mockSecureSettings) - - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_EXTENDED_KEY_USAGE_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_KEYSTORE_ALIAS, "node-0-client") + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_KEYSTORE_ALIAS, "node-0-server") + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_TRUSTSTORE_ALIAS, "root-ca") + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_TRUSTSTORE_ALIAS, "root-ca") + + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/truststore.jks") + ) + + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .setSecureSettings(mockSecureSettings) + + .build(); setupSslOnlyMode(settings); @@ -921,7 +1191,9 @@ public void testHttpsAndNodeSSLKeyStoreExtendedUsageEnabled() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("TLS")); Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"tx_size_in_bytes\" : 0")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"rx_count\" : 0")); Assert.assertFalse(rh.executeSimpleRequest("_nodes/stats?pretty").contains("\"rx_size_in_bytes\" : 0")); @@ -936,25 +1208,36 @@ public void testHttpsAndNodeSSLKeyPassFail() throws Exception { mockSecureSettings.setString(SECURITY_SSL_TRANSPORT_KEYSTORE_KEYPASSWORD.propertyName, "wrongpass"); final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks")) - .setSecureSettings(mockSecureSettings) - - - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_ALIAS, "node-0") + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore.jks") + ) + .setSecureSettings(mockSecureSettings) + + .build(); setupSslOnlyMode(settings); @@ -971,26 +1254,47 @@ public void testHttpsAndNodeSSLKeyPassFail() throws Exception { public void testHttpsAndNodeSSLPemExtendedUsageEnabled() throws Exception { final Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) - .put(ConfigConstants.SECURITY_SSL_ONLY, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_EXTENDED_KEY_USAGE_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-client.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-key-client.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/root-ca.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-server.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-key-server.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/root-ca.pem")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) - - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem")) - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem")) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED, true) + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_EXTENDED_KEY_USAGE_ENABLED, true) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-client.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-key-client.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_CLIENT_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/root-ca.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_PEMCERT_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-server.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_PEMKEY_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-key-server.pem") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_SERVER_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/root-ca.pem") + ) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) + + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_CLIENTAUTH_MODE, "REQUIRE") + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem")) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem")) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem") + ) + .build(); setupSslOnlyMode(settings); @@ -1003,6 +1307,8 @@ public void testHttpsAndNodeSSLPemExtendedUsageEnabled() throws Exception { Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("TLS")); Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").length() > 0); Assert.assertTrue(rh.executeSimpleRequest("_nodes/settings?pretty").contains(clusterInfo.clustername)); - Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + Assert.assertTrue( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE") + ); } } diff --git a/src/test/java/org/opensearch/security/ssl/SecureSSLSettingsTest.java b/src/test/java/org/opensearch/security/ssl/SecureSSLSettingsTest.java index d60c2cfcc5..beb170a31a 100644 --- a/src/test/java/org/opensearch/security/ssl/SecureSSLSettingsTest.java +++ b/src/test/java/org/opensearch/security/ssl/SecureSSLSettingsTest.java @@ -31,9 +31,7 @@ public void testGetSecureSetting() { @Test public void testGetInsecureSetting() { - final var settings = Settings.builder() - .put(SECURITY_SSL_HTTP_PEMKEY_PASSWORD.insecurePropertyName, "test-password") - .build(); + final var settings = Settings.builder().put(SECURITY_SSL_HTTP_PEMKEY_PASSWORD.insecurePropertyName, "test-password").build(); final var password = SECURITY_SSL_HTTP_PEMKEY_PASSWORD.getSetting(settings); Assert.assertEquals("test-password", password); } @@ -43,9 +41,9 @@ public void testShouldFavorSecureOverInsecureSetting() { final var mockSecureSettings = new MockSecureSettings(); mockSecureSettings.setString(SECURITY_SSL_HTTP_PEMKEY_PASSWORD.propertyName, "secure-password"); final var settings = Settings.builder() - .setSecureSettings(mockSecureSettings) - .put(SECURITY_SSL_HTTP_PEMKEY_PASSWORD.insecurePropertyName, "insecure-password") - .build(); + .setSecureSettings(mockSecureSettings) + .put(SECURITY_SSL_HTTP_PEMKEY_PASSWORD.insecurePropertyName, "insecure-password") + .build(); final var password = SECURITY_SSL_HTTP_PEMKEY_PASSWORD.getSetting(settings); Assert.assertEquals("secure-password", password); } diff --git a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java index e1c8ec7282..ee1cd585f7 100644 --- a/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java +++ b/src/test/java/org/opensearch/security/ssl/SecuritySSLReloadCertsActionTests.java @@ -50,20 +50,31 @@ public class SecuritySSLReloadCertsActionTests extends SingleClusterTest { private final List> NODE_CERT_DETAILS = ImmutableList.of( ImmutableMap.of( - "issuer_dn", "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", - "subject_dn", "CN=node-1.example.com,OU=SSL,O=Test,L=Test,C=DE", - "san", "[[8, 1.2.3.4.5.5], [0, [2.5.4.3, node-1.example.com]], [2, node-1.example.com], [2, localhost], [7, 127.0.0.1]]", - "not_before", "2023-04-14T13:22:53Z", - "not_after", "2033-04-11T13:22:53Z" - )); + "issuer_dn", + "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", + "subject_dn", + "CN=node-1.example.com,OU=SSL,O=Test,L=Test,C=DE", + "san", + "[[8, 1.2.3.4.5.5], [0, [2.5.4.3, node-1.example.com]], [2, node-1.example.com], [2, localhost], [7, 127.0.0.1]]", + "not_before", + "2023-04-14T13:22:53Z", + "not_after", + "2033-04-11T13:22:53Z" + ) + ); private final List> NEW_NODE_CERT_DETAILS = ImmutableList.of( ImmutableMap.of( - "issuer_dn", "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", - "subject_dn", "CN=node-1.example.com,OU=SSL,O=Test,L=Test,C=DE", - "san", "[[8, 1.2.3.4.5.5], [0, [2.5.4.3, node-1.example.com]], [2, node-1.example.com], [2, localhost], [7, 127.0.0.1]]", - "not_before", "2023-04-14T13:23:00Z", - "not_after", "2033-04-11T13:23:00Z" + "issuer_dn", + "CN=Example Com Inc. Signing CA,OU=Example Com Inc. Signing CA,O=Example Com Inc.,DC=example,DC=com", + "subject_dn", + "CN=node-1.example.com,OU=SSL,O=Test,L=Test,C=DE", + "san", + "[[8, 1.2.3.4.5.5], [0, [2.5.4.3, node-1.example.com]], [2, node-1.example.com], [2, localhost], [7, 127.0.0.1]]", + "not_before", + "2023-04-14T13:23:00Z", + "not_after", + "2033-04-11T13:23:00Z" ) ); @@ -71,7 +82,7 @@ public class SecuritySSLReloadCertsActionTests extends SingleClusterTest { private String pemKeyFilePath; private final String defaultCertFilePath = "ssl/reload/node.crt.pem"; private final String defaultKeyFilePath = "ssl/reload/node.key.pem"; - private final String newCertFilePath = "ssl/reload/node-new.crt.pem"; + private final String newCertFilePath = "ssl/reload/node-new.crt.pem"; private final String newKeyFilePath = "ssl/reload/node-new.key.pem"; @Before @@ -138,8 +149,11 @@ public void testSSLReloadFail_InvalidDNAndDate() throws Exception { RestHelper.HttpResponse reloadCertsResponse = rh.executePutRequest(RELOAD_TRANSPORT_CERTS_ENDPOINT, null); Assert.assertEquals(500, reloadCertsResponse.getStatusCode()); JSONObject expectedResponse = new JSONObject(); - expectedResponse.appendField("error", "OpenSearchSecurityException[Error while initializing transport SSL layer from PEM: java.lang.Exception: " + - "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];"); + expectedResponse.appendField( + "error", + "OpenSearchSecurityException[Error while initializing transport SSL layer from PEM: java.lang.Exception: " + + "New Certs do not have valid Issuer DN, Subject DN or SAN.]; nested: Exception[New Certs do not have valid Issuer DN, Subject DN or SAN.];" + ); Assert.assertEquals(expectedResponse.toString(), reloadCertsResponse.getBody()); } @@ -261,7 +275,13 @@ private void initClusterWithTestCerts() throws Exception { * @param httpPemKeyFilePath Absolute Path to transport pem key file * @param sslCertReload Sets the ssl cert reload flag */ - private void initTestCluster(final String transportPemCertFilePath, final String transportPemKeyFilePath, final String httpPemCertFilePath, final String httpPemKeyFilePath, final boolean sslCertReload) throws Exception { + private void initTestCluster( + final String transportPemCertFilePath, + final String transportPemKeyFilePath, + final String httpPemCertFilePath, + final String httpPemKeyFilePath, + final boolean sslCertReload + ) throws Exception { final Settings settings = Settings.builder() .putList(ConfigConstants.SECURITY_AUTHCZ_ADMIN_DN, "CN=kirk,OU=client,O=client,L=Test,C=DE") .putList(ConfigConstants.SECURITY_NODES_DN, "CN=node-1.example.com,OU=SSL,O=Test,L=Test,C=DE") @@ -271,19 +291,29 @@ private void initTestCluster(final String transportPemCertFilePath, final String .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION_RESOLVE_HOST_NAME, false) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH, transportPemCertFilePath) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH, transportPemKeyFilePath) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/root-ca.pem")) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/root-ca.pem") + ) .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMCERT_FILEPATH, httpPemCertFilePath) // "ssl/reload/node.crt.pem" .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMKEY_FILEPATH, httpPemKeyFilePath) // "ssl/reload/node.key.pem" - .put(SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/root-ca.pem")) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/root-ca.pem") + ) .put(ConfigConstants.SECURITY_SSL_CERT_RELOAD_ENABLED, sslCertReload) .build(); final Settings initTransportClientSettings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/truststore.jks")) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/truststore.jks") + ) .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENFORCE_HOSTNAME_VERIFICATION, false) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/kirk-keystore.jks")) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/reload/kirk-keystore.jks") + ) .build(); setup(initTransportClientSettings, new DynamicSecurityConfig(), settings, true, clusterConfiguration); diff --git a/src/test/java/org/opensearch/security/ssl/TestPrincipalExtractor.java b/src/test/java/org/opensearch/security/ssl/TestPrincipalExtractor.java index 6102327fe4..886df37b91 100644 --- a/src/test/java/org/opensearch/security/ssl/TestPrincipalExtractor.java +++ b/src/test/java/org/opensearch/security/ssl/TestPrincipalExtractor.java @@ -1,10 +1,10 @@ /* * Copyright 2017 floragunn GmbH - * + * * 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 @@ -12,7 +12,7 @@ * 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. - * + * */ package org.opensearch.security.ssl; @@ -25,20 +25,19 @@ public class TestPrincipalExtractor implements PrincipalExtractor { private static int transportCount = 0; private static int httpCount = 0; - - public TestPrincipalExtractor() { - } + + public TestPrincipalExtractor() {} @Override public String extractPrincipal(X509Certificate x509Certificate, Type type) { - if(type == Type.HTTP) { + if (type == Type.HTTP) { httpCount++; } - - if(type == Type.TRANSPORT) { + + if (type == Type.TRANSPORT) { transportCount++; } - + return "testdn"; } @@ -49,10 +48,10 @@ public static int getTransportCount() { public static int getHttpCount() { return httpCount; } - + public static void reset() { - httpCount = 0; - transportCount = 0; + httpCount = 0; + transportCount = 0; } } diff --git a/src/test/java/org/opensearch/security/ssl/transport/DualModeSSLHandlerTests.java b/src/test/java/org/opensearch/security/ssl/transport/DualModeSSLHandlerTests.java index 9016a8a3db..79d53f4d7b 100644 --- a/src/test/java/org/opensearch/security/ssl/transport/DualModeSSLHandlerTests.java +++ b/src/test/java/org/opensearch/security/ssl/transport/DualModeSSLHandlerTests.java @@ -76,10 +76,8 @@ public void testValidTLSMessage() throws Exception { handler.decode(ctx, buffer, null); // ensure ssl handler is added Mockito.verify(ctx, Mockito.times(1)).pipeline(); - Mockito.verify(pipeline, Mockito.times(1)) - .addAfter("port_unification_handler", "ssl_server", sslHandler); - Mockito.verify(pipeline, - Mockito.times(1)).remove(handler); + Mockito.verify(pipeline, Mockito.times(1)).addAfter("port_unification_handler", "ssl_server", sslHandler); + Mockito.verify(pipeline, Mockito.times(1)).remove(handler); } @Test @@ -95,10 +93,8 @@ public void testNonTLSMessage() throws Exception { handler.decode(ctx, buffer, null); // ensure ssl handler is added Mockito.verify(ctx, Mockito.times(1)).pipeline(); - Mockito.verify(pipeline, Mockito.times(0)) - .addAfter("port_unification_handler", "ssl_server", sslHandler); - Mockito.verify(pipeline, - Mockito.times(1)).remove(handler); + Mockito.verify(pipeline, Mockito.times(0)).addAfter("port_unification_handler", "ssl_server", sslHandler); + Mockito.verify(pipeline, Mockito.times(1)).remove(handler); } @Test diff --git a/src/test/java/org/opensearch/security/ssl/util/CertFromFileTests.java b/src/test/java/org/opensearch/security/ssl/util/CertFromFileTests.java index 383c60147c..097d65472c 100644 --- a/src/test/java/org/opensearch/security/ssl/util/CertFromFileTests.java +++ b/src/test/java/org/opensearch/security/ssl/util/CertFromFileTests.java @@ -22,60 +22,65 @@ public class CertFromFileTests { @Test public void testLoadSameCertForClientServerUsage() throws Exception { - CertFileProps certProps = new CertFileProps( - FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem").toString(), - FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem").toString(), - FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem").toString(), - null); - - CertFromFile cert = new CertFromFile(certProps); - - Assert.assertEquals(1, cert.getCerts().length); - Assert.assertNotNull(cert.getClientPemCert()); - Assert.assertNotNull(cert.getClientPemKey()); - Assert.assertNotNull(cert.getClientTrustedCas()); + CertFileProps certProps = new CertFileProps( + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem").toString(), + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem").toString(), + FileHelper.getAbsoluteFilePathFromClassPath("ssl/root-ca.pem").toString(), + null + ); + + CertFromFile cert = new CertFromFile(certProps); + + Assert.assertEquals(1, cert.getCerts().length); + Assert.assertNotNull(cert.getClientPemCert()); + Assert.assertNotNull(cert.getClientPemKey()); + Assert.assertNotNull(cert.getClientTrustedCas()); } - @Test - public void testLoadCertWithoutCA() throws Exception { + @Test + public void testLoadCertWithoutCA() throws Exception { CertFileProps certProps = new CertFileProps( FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.crt.pem").toString(), FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem").toString(), null, - null); + null + ); CertFromFile cert = new CertFromFile(certProps); Assert.assertNull(cert.getClientTrustedCas()); } - @Test(expected= FileNotFoundException.class) + @Test(expected = FileNotFoundException.class) public void testLoadCertWithMissingFiles() throws Exception { CertFileProps certProps = new CertFileProps( "missing.pem", FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0.key.pem").toString(), null, - null); + null + ); CertFromFile cert = new CertFromFile(certProps); } @Test public void testLoadDifferentCertsForClientServerUsage() throws Exception { - CertFileProps clientCertProps = new CertFileProps( - FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-client.pem").toString(), - FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-key-client.pem").toString(), - FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/root-ca.pem").toString(), - null); - CertFileProps servertCertProps = new CertFileProps( - FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-server.pem").toString(), - FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-key-server.pem").toString(), - FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/root-ca.pem").toString(), - null); - - CertFromFile cert = new CertFromFile(clientCertProps, servertCertProps); - - Assert.assertEquals(2, cert.getCerts().length); + CertFileProps clientCertProps = new CertFileProps( + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-client.pem").toString(), + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-key-client.pem").toString(), + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/root-ca.pem").toString(), + null + ); + CertFileProps servertCertProps = new CertFileProps( + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-server.pem").toString(), + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-key-server.pem").toString(), + FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/root-ca.pem").toString(), + null + ); + + CertFromFile cert = new CertFromFile(clientCertProps, servertCertProps); + + Assert.assertEquals(2, cert.getCerts().length); } } diff --git a/src/test/java/org/opensearch/security/ssl/util/CertFromKeystoreTests.java b/src/test/java/org/opensearch/security/ssl/util/CertFromKeystoreTests.java index 0a2cac18b5..fb97fdcfd1 100644 --- a/src/test/java/org/opensearch/security/ssl/util/CertFromKeystoreTests.java +++ b/src/test/java/org/opensearch/security/ssl/util/CertFromKeystoreTests.java @@ -25,7 +25,8 @@ public class CertFromKeystoreTests { @Test - public void testLoadSameCertForClientServerUsage() throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { + public void testLoadSameCertForClientServerUsage() throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, + KeyStoreException, IOException { KeystoreProps props = new KeystoreProps( FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks").toString(), "JKS", @@ -43,7 +44,8 @@ public void testLoadSameCertForClientServerUsage() throws UnrecoverableKeyExcept } @Test - public void testLoadSameCertWithoutAlias() throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { + public void testLoadSameCertWithoutAlias() throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, + KeyStoreException, IOException { KeystoreProps props = new KeystoreProps( FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks").toString(), "JKS", @@ -58,7 +60,8 @@ public void testLoadSameCertWithoutAlias() throws UnrecoverableKeyException, Cer } @Test - public void testLoadDifferentCertsForClientServerUsage() throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { + public void testLoadDifferentCertsForClientServerUsage() throws UnrecoverableKeyException, CertificateException, + NoSuchAlgorithmException, KeyStoreException, IOException { KeystoreProps props = new KeystoreProps( FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/node-0-keystore.jks").toString(), "JKS", diff --git a/src/test/java/org/opensearch/security/ssl/util/CertFromTruststoreTests.java b/src/test/java/org/opensearch/security/ssl/util/CertFromTruststoreTests.java index ed0f0ac252..e4ab860759 100644 --- a/src/test/java/org/opensearch/security/ssl/util/CertFromTruststoreTests.java +++ b/src/test/java/org/opensearch/security/ssl/util/CertFromTruststoreTests.java @@ -24,7 +24,8 @@ public class CertFromTruststoreTests { @Test - public void testLoadSameCertForClientServerUsage() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { + public void testLoadSameCertForClientServerUsage() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, + IOException { KeystoreProps props = new KeystoreProps( FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/truststore.jks").toString(), "JKS", @@ -50,7 +51,8 @@ public void testLoadSameCertWithoutAlias() throws CertificateException, NoSuchAl Assert.assertEquals(1, cert.getClientTrustedCerts().length); } - public void testLoadDifferentCertsForClientServerUsage() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { + public void testLoadDifferentCertsForClientServerUsage() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, + IOException { KeystoreProps props = new KeystoreProps( FileHelper.getAbsoluteFilePathFromClassPath("ssl/extended_key_usage/truststore.jks").toString(), "JKS", diff --git a/src/test/java/org/opensearch/security/ssl/util/SSLConnectionTestUtilTests.java b/src/test/java/org/opensearch/security/ssl/util/SSLConnectionTestUtilTests.java index 1400b0d401..98ee95a90b 100644 --- a/src/test/java/org/opensearch/security/ssl/util/SSLConnectionTestUtilTests.java +++ b/src/test/java/org/opensearch/security/ssl/util/SSLConnectionTestUtilTests.java @@ -43,16 +43,22 @@ public void setup() { public void testConnectionSSLAvailable() throws Exception { Mockito.doNothing().when(outputStreamWriter).write(Mockito.anyString()); Mockito.when(inputStreamReader.read()) - .thenReturn((int)'D') - .thenReturn((int)'U') - .thenReturn((int)'A') - .thenReturn((int)'L') - .thenReturn((int)'S') - .thenReturn((int)'M') + .thenReturn((int) 'D') + .thenReturn((int) 'U') + .thenReturn((int) 'A') + .thenReturn((int) 'L') + .thenReturn((int) 'S') + .thenReturn((int) 'M') .thenReturn(-1); Mockito.doNothing().when(socket).close(); - SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil("127.0.0.1", 443, socket, outputStreamWriter, inputStreamReader); + SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil( + "127.0.0.1", + 443, + socket, + outputStreamWriter, + inputStreamReader + ); SSLConnectionTestResult result = connectionTestUtil.testConnection(); verifyClientHelloSend(); @@ -66,7 +72,13 @@ public void testConnectionSSLNotAvailable() throws Exception { setupMocksForOpenSearchPingSuccess(); Mockito.doNothing().when(socket).close(); - SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil("127.0.0.1", 443, socket, outputStreamWriter, inputStreamReader); + SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil( + "127.0.0.1", + 443, + socket, + outputStreamWriter, + inputStreamReader + ); SSLConnectionTestResult result = connectionTestUtil.testConnection(); verifyClientHelloSend(); @@ -77,13 +89,17 @@ public void testConnectionSSLNotAvailable() throws Exception { @Test public void testConnectionSSLNotAvailableIOException() throws Exception { - Mockito.doThrow(new IOException("Error while writing bytes to output stream")) - .when(outputStreamWriter) - .write(Mockito.anyString()); + Mockito.doThrow(new IOException("Error while writing bytes to output stream")).when(outputStreamWriter).write(Mockito.anyString()); setupMocksForOpenSearchPingSuccess(); Mockito.doNothing().when(socket).close(); - SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil("127.0.0.1", 443, socket, outputStreamWriter, inputStreamReader); + SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil( + "127.0.0.1", + 443, + socket, + outputStreamWriter, + inputStreamReader + ); SSLConnectionTestResult result = connectionTestUtil.testConnection(); verifyClientHelloSend(); @@ -99,11 +115,16 @@ public void testConnectionOpenSearchPingFailed() throws Exception { Mockito.when(socket.getOutputStream()).thenReturn(outputStream); Mockito.when(socket.getInputStream()).thenReturn(inputStream); Mockito.doNothing().when(outputStream).write(Mockito.any(byte[].class)); - Mockito.when(inputStream.read()) - .thenReturn(-1); + Mockito.when(inputStream.read()).thenReturn(-1); Mockito.doNothing().when(socket).close(); - SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil("127.0.0.1", 443, socket, outputStreamWriter, inputStreamReader); + SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil( + "127.0.0.1", + 443, + socket, + outputStreamWriter, + inputStreamReader + ); SSLConnectionTestResult result = connectionTestUtil.testConnection(); verifyClientHelloSend(); @@ -119,15 +140,21 @@ public void testConnectionOpenSearchPingFailedInvalidReply() throws Exception { Mockito.when(socket.getInputStream()).thenReturn(inputStream); Mockito.doNothing().when(outputStream).write(Mockito.any(byte[].class)); Mockito.when(inputStream.read()) - .thenReturn((int)'E') - .thenReturn((int)'E') + .thenReturn((int) 'E') + .thenReturn((int) 'E') .thenReturn(0xFF) .thenReturn(0xFF) .thenReturn(0xFF) .thenReturn(0xFF); Mockito.doNothing().when(socket).close(); - SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil("127.0.0.1", 443, socket, outputStreamWriter, inputStreamReader); + SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil( + "127.0.0.1", + 443, + socket, + outputStreamWriter, + inputStreamReader + ); SSLConnectionTestResult result = connectionTestUtil.testConnection(); verifyClientHelloSend(); @@ -144,7 +171,13 @@ public void testConnectionOpenSearchPingFailedIOException() throws Exception { Mockito.doThrow(new IOException("Error while writing bytes to output stream")).when(outputStream).write(Mockito.any(byte[].class)); Mockito.doNothing().when(socket).close(); - SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil("127.0.0.1", 443, socket, outputStreamWriter, inputStreamReader); + SSLConnectionTestUtil connectionTestUtil = new SSLConnectionTestUtil( + "127.0.0.1", + 443, + socket, + outputStreamWriter, + inputStreamReader + ); SSLConnectionTestResult result = connectionTestUtil.testConnection(); verifyClientHelloSend(); @@ -156,9 +189,7 @@ public void testConnectionOpenSearchPingFailedIOException() throws Exception { private void verifyClientHelloSend() throws IOException { ArgumentCaptor clientHelloMsgArgCaptor = ArgumentCaptor.forClass(String.class); - Mockito.verify(outputStreamWriter, - Mockito.times(1)) - .write(clientHelloMsgArgCaptor.capture()); + Mockito.verify(outputStreamWriter, Mockito.times(1)).write(clientHelloMsgArgCaptor.capture()); String msgWritten = clientHelloMsgArgCaptor.getValue(); String expectedMsg = "DUALCM"; Assert.assertEquals("Unexpected Dual SSL Client Hello message written to socket", expectedMsg, msgWritten); @@ -166,20 +197,17 @@ private void verifyClientHelloSend() throws IOException { private void verifyOpenSearchPingSend() throws IOException { ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(byte[].class); - Mockito.verify(outputStream, - Mockito.times(1)) - .write(argumentCaptor.capture()); + Mockito.verify(outputStream, Mockito.times(1)).write(argumentCaptor.capture()); byte[] bytesWritten = argumentCaptor.getValue(); - byte[] expectedBytes = new byte[]{'E','S',(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF}; - for(int i = 0; i < bytesWritten.length; i++) { + byte[] expectedBytes = new byte[] { 'E', 'S', (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF }; + for (int i = 0; i < bytesWritten.length; i++) { Assert.assertEquals("Unexpected OpenSearch Ping bytes written to socket", expectedBytes[i], bytesWritten[i]); } } private void setupMocksForClientHelloFailure() throws IOException { Mockito.doNothing().when(outputStreamWriter).write(Mockito.anyString()); - Mockito.when(inputStreamReader.read()) - .thenReturn(-1); + Mockito.when(inputStreamReader.read()).thenReturn(-1); } private void setupMocksForOpenSearchPingSuccess() throws IOException { @@ -187,8 +215,8 @@ private void setupMocksForOpenSearchPingSuccess() throws IOException { Mockito.when(socket.getInputStream()).thenReturn(inputStream); Mockito.doNothing().when(outputStream).write(Mockito.any(byte[].class)); Mockito.when(inputStream.read()) - .thenReturn((int)'E') - .thenReturn((int)'S') + .thenReturn((int) 'E') + .thenReturn((int) 'S') .thenReturn(0xFF) .thenReturn(0xFF) .thenReturn(0xFF) diff --git a/src/test/java/org/opensearch/security/ssl/util/TLSUtilTests.java b/src/test/java/org/opensearch/security/ssl/util/TLSUtilTests.java index 83ef5668ac..c77f05b39f 100644 --- a/src/test/java/org/opensearch/security/ssl/util/TLSUtilTests.java +++ b/src/test/java/org/opensearch/security/ssl/util/TLSUtilTests.java @@ -49,7 +49,7 @@ public void testSSLUtilWrongTLSVersion() { for (int byteToSend = 20; byteToSend <= 24; byteToSend++) { ByteBuf buffer = ALLOCATOR.buffer(5); buffer.writeByte(byteToSend); - //setting invalid TLS version 100 + // setting invalid TLS version 100 buffer.writeByte(100); buffer.writeByte(TLS_MINOR_VERSION); buffer.writeByte(100); @@ -66,7 +66,7 @@ public void testSSLUtilInvalidContentLength() { buffer.writeByte(byteToSend); buffer.writeByte(TLS_MAJOR_VERSION); buffer.writeByte(TLS_MINOR_VERSION); - //setting content length as 0 + // setting content length as 0 buffer.writeShort(0); Assert.assertFalse(TLSUtil.isTLS(buffer)); } diff --git a/src/test/java/org/opensearch/security/support/GuardedSearchOperationWrapperTest.java b/src/test/java/org/opensearch/security/support/GuardedSearchOperationWrapperTest.java index 982d1108ad..67090e9b3d 100644 --- a/src/test/java/org/opensearch/security/support/GuardedSearchOperationWrapperTest.java +++ b/src/test/java/org/opensearch/security/support/GuardedSearchOperationWrapperTest.java @@ -26,7 +26,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; - public class GuardedSearchOperationWrapperTest { @Test @@ -115,26 +114,21 @@ public void onQueryPhase(SearchContext context, long tookInNanos) { private static class DefaultingGuardedSearchOperationWrapper implements GuardedSearchOperationWrapper { @Override - public void onNewReaderContext(ReaderContext readerContext) { - } + public void onNewReaderContext(ReaderContext readerContext) {} @Override - public void onNewScrollContext(ReaderContext readerContext) { - } + public void onNewScrollContext(ReaderContext readerContext) {} @Override - public void onPreQueryPhase(SearchContext context) { - } + public void onPreQueryPhase(SearchContext context) {} @Override - public void onQueryPhase(SearchContext searchContext, long tookInNanos) { - } + public void onQueryPhase(SearchContext searchContext, long tookInNanos) {} @Override - public void validateReaderContext(ReaderContext readerContext, TransportRequest transportRequest) { - } + public void validateReaderContext(ReaderContext readerContext, TransportRequest transportRequest) {} - void exerciseAllMethods(){ + void exerciseAllMethods() { final SearchOperationListener sol = this.toListener(); sol.onNewReaderContext(mock(ReaderContext.class)); sol.onNewScrollContext(mock(ReaderContext.class)); diff --git a/src/test/java/org/opensearch/security/support/SecurityUtilsTest.java b/src/test/java/org/opensearch/security/support/SecurityUtilsTest.java index ed6a471421..f0645d4958 100644 --- a/src/test/java/org/opensearch/security/support/SecurityUtilsTest.java +++ b/src/test/java/org/opensearch/security/support/SecurityUtilsTest.java @@ -60,14 +60,14 @@ private void checkKeysWithPredicate(Collection keys, String predicateNam final String prefixWithKeyName = "${" + predicateName + "." + envKeyName; final String baseKeyName = prefixWithKeyName + "}"; - assertThat("Testing " + envKeyName + ", " + baseKeyName, - predicate.test(baseKeyName), - equalTo(true)); + assertThat("Testing " + envKeyName + ", " + baseKeyName, predicate.test(baseKeyName), equalTo(true)); final String baseKeyNameWithDefault = prefixWithKeyName + ":-tTt}"; - assertThat("Testing " + envKeyName + " with defaultValue, " + baseKeyNameWithDefault, + assertThat( + "Testing " + envKeyName + " with defaultValue, " + baseKeyNameWithDefault, predicate.test(baseKeyNameWithDefault), - equalTo(true)); + equalTo(true) + ); }); } } diff --git a/src/test/java/org/opensearch/security/system_indices/SystemIndicesTests.java b/src/test/java/org/opensearch/security/system_indices/SystemIndicesTests.java index 273214b0fe..e298ae45c7 100644 --- a/src/test/java/org/opensearch/security/system_indices/SystemIndicesTests.java +++ b/src/test/java/org/opensearch/security/system_indices/SystemIndicesTests.java @@ -53,46 +53,51 @@ public class SystemIndicesTests extends SingleClusterTest { private static final String matchAllQuery = "{\n\"query\": {\"match_all\": {}}}"; private static final String allAccessUser = "admin_all_access"; private static final Header allAccessUserHeader = encodeBasicHeader(allAccessUser, allAccessUser); - private static final String generalErrorMessage = String.format("no permissions for [] and User [name=%s, backend_roles=[], requestedTenant=null]", allAccessUser); + private static final String generalErrorMessage = String.format( + "no permissions for [] and User [name=%s, backend_roles=[], requestedTenant=null]", + allAccessUser + ); private void setupSystemIndicesDisabledWithSsl() throws Exception { Settings systemIndexSettings = Settings.builder() - .put(ConfigConstants.SECURITY_SYSTEM_INDICES_ENABLED_KEY, false) - .putList(ConfigConstants.SECURITY_SYSTEM_INDICES_KEY, listOfIndexesToTest) - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .put("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .build(); - setup(Settings.EMPTY, - new DynamicSecurityConfig() - .setConfig("config_system_indices.yml") - .setSecurityRoles("roles_system_indices.yml") - .setSecurityInternalUsers("internal_users_system_indices.yml") - .setSecurityRolesMapping("roles_mapping_system_indices.yml"), - systemIndexSettings, - true); + .put(ConfigConstants.SECURITY_SYSTEM_INDICES_ENABLED_KEY, false) + .putList(ConfigConstants.SECURITY_SYSTEM_INDICES_KEY, listOfIndexesToTest) + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .put("path.repo", repositoryPath.getRoot().getAbsolutePath()) + .build(); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setConfig("config_system_indices.yml") + .setSecurityRoles("roles_system_indices.yml") + .setSecurityInternalUsers("internal_users_system_indices.yml") + .setSecurityRolesMapping("roles_mapping_system_indices.yml"), + systemIndexSettings, + true + ); } private void setupSystemIndicesEnabledWithSsl() throws Exception { Settings systemIndexSettings = Settings.builder() - .put(ConfigConstants.SECURITY_SYSTEM_INDICES_ENABLED_KEY, true) - .putList(ConfigConstants.SECURITY_SYSTEM_INDICES_KEY, listOfIndexesToTest) - .put("plugins.security.ssl.http.enabled",true) - .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) - .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) - .put("path.repo", repositoryPath.getRoot().getAbsolutePath()) - .build(); - setup(Settings.EMPTY, - new DynamicSecurityConfig() - .setConfig("config_system_indices.yml") - .setSecurityRoles("roles_system_indices.yml") - .setSecurityInternalUsers("internal_users_system_indices.yml") - .setSecurityRolesMapping("roles_mapping_system_indices.yml"), - systemIndexSettings, - true); + .put(ConfigConstants.SECURITY_SYSTEM_INDICES_ENABLED_KEY, true) + .putList(ConfigConstants.SECURITY_SYSTEM_INDICES_KEY, listOfIndexesToTest) + .put("plugins.security.ssl.http.enabled", true) + .put("plugins.security.ssl.http.keystore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("node-0-keystore.jks")) + .put("plugins.security.ssl.http.truststore_filepath", FileHelper.getAbsoluteFilePathFromClassPath("truststore.jks")) + .put("path.repo", repositoryPath.getRoot().getAbsolutePath()) + .build(); + setup( + Settings.EMPTY, + new DynamicSecurityConfig().setConfig("config_system_indices.yml") + .setSecurityRoles("roles_system_indices.yml") + .setSecurityInternalUsers("internal_users_system_indices.yml") + .setSecurityRolesMapping("roles_mapping_system_indices.yml"), + systemIndexSettings, + true + ); } /** @@ -104,7 +109,11 @@ private void createTestIndicesAndDocs() { try (Client tc = getClient()) { for (String index : listOfIndexesToTest) { tc.admin().indices().create(new CreateIndexRequest(index)).actionGet(); - tc.index(new IndexRequest(index).setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).id("document1").source("{ \"foo\": \"bar\" }", XContentType.JSON)).actionGet(); + tc.index( + new IndexRequest(index).setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .id("document1") + .source("{ \"foo\": \"bar\" }", XContentType.JSON) + ).actionGet(); } } } @@ -112,8 +121,19 @@ private void createTestIndicesAndDocs() { private void createSnapshots() { try (Client tc = getClient()) { for (String index : listOfIndexesToTest) { - tc.admin().cluster().putRepository(new PutRepositoryRequest(index).type("fs").settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/" + index))).actionGet(); - tc.admin().cluster().createSnapshot(new CreateSnapshotRequest(index, index + "_1").indices(index).includeGlobalState(true).waitForCompletion(true)).actionGet(); + tc.admin() + .cluster() + .putRepository( + new PutRepositoryRequest(index).type("fs") + .settings(Settings.builder().put("location", repositoryPath.getRoot().getAbsolutePath() + "/" + index)) + ) + .actionGet(); + tc.admin() + .cluster() + .createSnapshot( + new CreateSnapshotRequest(index, index + "_1").indices(index).includeGlobalState(true).waitForCompletion(true) + ) + .actionGet(); } } } @@ -140,7 +160,8 @@ private RestHelper sslRestHelper() { private void validateSearchResponse(RestHelper.HttpResponse response, int expectecdHits) throws IOException { assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); assertEquals(RestStatus.OK, searchResponse.status()); assertEquals(expectecdHits, searchResponse.getHits().getHits().length); @@ -154,12 +175,12 @@ public void testSearchAsSuperAdmin() throws Exception { createTestIndicesAndDocs(); RestHelper restHelper = keyStoreRestHelper(); - //search system indices + // search system indices for (String index : listOfIndexesToTest) { validateSearchResponse(restHelper.executePostRequest(index + "/_search", matchAllQuery), 1); } - //search all indices + // search all indices RestHelper.HttpResponse response = restHelper.executePostRequest("/_search", matchAllQuery); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); } @@ -170,12 +191,12 @@ public void testSearchAsAdmin() throws Exception { createTestIndicesAndDocs(); RestHelper restHelper = sslRestHelper(); - //search system indices + // search system indices for (String index : listOfIndexesToTest) { validateSearchResponse(restHelper.executePostRequest(index + "/_search", matchAllQuery, allAccessUserHeader), 1); } - //search all indices + // search all indices RestHelper.HttpResponse response = restHelper.executePostRequest("/_search", matchAllQuery, allAccessUserHeader); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); } @@ -186,17 +207,16 @@ public void testSearchWithSystemIndicesAsSuperAdmin() throws Exception { createTestIndicesAndDocs(); RestHelper restHelper = keyStoreRestHelper(); - //search system indices + // search system indices for (String index : listOfIndexesToTest) { validateSearchResponse(restHelper.executePostRequest(index + "/_search", matchAllQuery), 1); } - //search all indices + // search all indices RestHelper.HttpResponse response = restHelper.executePostRequest("/_search", matchAllQuery); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); } - @Test public void testSearchWithSystemIndicesAsAdmin() throws Exception { setupSystemIndicesEnabledWithSsl(); @@ -207,10 +227,11 @@ public void testSearchWithSystemIndicesAsAdmin() throws Exception { validateSearchResponse(restHelper.executePostRequest(index + "/_search", matchAllQuery, allAccessUserHeader), 0); } - //search all indices + // search all indices RestHelper.HttpResponse response = restHelper.executePostRequest("/_search", matchAllQuery, allAccessUserHeader); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); - XContentParser xcp = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); + XContentParser xcp = XContentType.JSON.xContent() + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, response.getBody()); SearchResponse searchResponse = SearchResponse.fromXContent(xcp); assertEquals(RestStatus.OK, searchResponse.status()); assertEquals(0, searchResponse.getHits().getHits().length); @@ -227,7 +248,7 @@ public void testDelete() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse responseDoc = keyStoreRestHelper.executeDeleteRequest(index + "/_doc/document1"); assertEquals(RestStatus.OK.getStatus(), responseDoc.getStatusCode()); @@ -237,7 +258,7 @@ public void testDelete() throws Exception { } createTestIndicesAndDocs(); - //as admin + // as admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse responseDoc = sslRestHelper.executeDeleteRequest(index + "/_doc/document1", allAccessUserHeader); assertEquals(RestStatus.OK.getStatus(), responseDoc.getStatusCode()); @@ -254,7 +275,7 @@ public void testDeleteWithSystemIndices() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse responseDoc = keyStoreRestHelper.executeDeleteRequest(index + "/_doc/document1"); assertEquals(RestStatus.OK.getStatus(), responseDoc.getStatusCode()); @@ -264,7 +285,7 @@ public void testDeleteWithSystemIndices() throws Exception { } createTestIndicesAndDocs(); - //as admin + // as admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse responseDoc = sslRestHelper.executeDeleteRequest(index + "/_doc/document1", allAccessUserHeader); assertEquals(RestStatus.FORBIDDEN.getStatus(), responseDoc.getStatusCode()); @@ -285,18 +306,18 @@ public void testCloseOpen() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse responseClose = keyStoreRestHelper.executePostRequest(index + "/_close",""); + RestHelper.HttpResponse responseClose = keyStoreRestHelper.executePostRequest(index + "/_close", ""); assertEquals(RestStatus.OK.getStatus(), responseClose.getStatusCode()); RestHelper.HttpResponse responseOpen = keyStoreRestHelper.executePostRequest(index + "/_open", ""); assertEquals(RestStatus.OK.getStatus(), responseOpen.getStatusCode()); } - //as admin + // as admin for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse responseClose = sslRestHelper.executePostRequest(index + "/_close","", allAccessUserHeader); + RestHelper.HttpResponse responseClose = sslRestHelper.executePostRequest(index + "/_close", "", allAccessUserHeader); assertEquals(RestStatus.OK.getStatus(), responseClose.getStatusCode()); RestHelper.HttpResponse responseOpen = sslRestHelper.executePostRequest(index + "/_open", "", allAccessUserHeader); @@ -311,18 +332,18 @@ public void testCloseOpenWithSystemIndices() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse responseClose = keyStoreRestHelper.executePostRequest(index + "/_close",""); + RestHelper.HttpResponse responseClose = keyStoreRestHelper.executePostRequest(index + "/_close", ""); assertEquals(RestStatus.OK.getStatus(), responseClose.getStatusCode()); RestHelper.HttpResponse responseOpen = keyStoreRestHelper.executePostRequest(index + "/_open", ""); assertEquals(RestStatus.OK.getStatus(), responseOpen.getStatusCode()); } - //as admin + // as admin for (String index : listOfIndexesToTest) { - RestHelper.HttpResponse responseClose = sslRestHelper.executePostRequest(index + "/_close","", allAccessUserHeader); + RestHelper.HttpResponse responseClose = sslRestHelper.executePostRequest(index + "/_close", "", allAccessUserHeader); assertEquals(RestStatus.FORBIDDEN.getStatus(), responseClose.getStatusCode()); RestHelper.HttpResponse responseOpen = sslRestHelper.executePostRequest(index + "/_open", "", allAccessUserHeader); @@ -341,18 +362,14 @@ public void testUpdateIndexSettings() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - String indexSettings = "{\n" + - " \"index\" : {\n" + - " \"refresh_interval\" : null\n" + - " }\n" + - "}"; + String indexSettings = "{\n" + " \"index\" : {\n" + " \"refresh_interval\" : null\n" + " }\n" + "}"; - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = keyStoreRestHelper.executePutRequest(index + "/_settings", indexSettings); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); } - //as admin + // as admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = sslRestHelper.executePutRequest(index + "/_settings", indexSettings, allAccessUserHeader); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); @@ -366,23 +383,20 @@ public void testUpdateIndexSettingsWithSystemIndices() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - String indexSettings = "{\n" + - " \"index\" : {\n" + - " \"refresh_interval\" : null\n" + - " }\n" + - "}"; + String indexSettings = "{\n" + " \"index\" : {\n" + " \"refresh_interval\" : null\n" + " }\n" + "}"; - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = keyStoreRestHelper.executePutRequest(index + "/_settings", indexSettings); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); } - //as admin + // as admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = sslRestHelper.executePutRequest(index + "/_settings", indexSettings, allAccessUserHeader); assertEquals(RestStatus.FORBIDDEN.getStatus(), response.getStatusCode()); } } + /*************************************************************************************************************************** * Index mappings. indices:admin/mapping/put ************************************************************************************************************************** */ @@ -394,18 +408,15 @@ public void testUpdateMappings() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - String newMappings = "{\"properties\": {" + - "\"user_name\": {" + - "\"type\": \"text\"" + - "}}}"; + String newMappings = "{\"properties\": {" + "\"user_name\": {" + "\"type\": \"text\"" + "}}}"; - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = keyStoreRestHelper.executePutRequest(index + "/_mapping", newMappings); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); } - //as admin + // as admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = sslRestHelper.executePutRequest(index + "/_mapping", newMappings, allAccessUserHeader); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); @@ -419,18 +430,15 @@ public void testUpdateMappingsWithSystemIndices() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - String newMappings = "{\"properties\": {" + - "\"user_name\": {" + - "\"type\": \"text\"" + - "}}}"; + String newMappings = "{\"properties\": {" + "\"user_name\": {" + "\"type\": \"text\"" + "}}}"; - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = keyStoreRestHelper.executePutRequest(index + "/_mapping", newMappings); assertEquals(RestStatus.OK.getStatus(), response.getStatusCode()); } - //as admin + // as admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse response = sslRestHelper.executePutRequest(index + "/_mapping", newMappings, allAccessUserHeader); assertEquals(RestStatus.FORBIDDEN.getStatus(), response.getStatusCode()); @@ -448,16 +456,16 @@ public void testCreate() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - String indexSettings = "{\n" + - " \"settings\" : {\n" + - " \"index\" : {\n" + - " \"number_of_shards\" : 3, \n" + - " \"number_of_replicas\" : 2 \n" + - " }\n" + - " }\n" + - "}"; + String indexSettings = "{\n" + + " \"settings\" : {\n" + + " \"index\" : {\n" + + " \"number_of_shards\" : 3, \n" + + " \"number_of_replicas\" : 2 \n" + + " }\n" + + " }\n" + + "}"; - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse responseIndex = keyStoreRestHelper.executePutRequest(index, indexSettings); assertEquals(RestStatus.OK.getStatus(), responseIndex.getStatusCode()); @@ -470,7 +478,7 @@ public void testCreate() throws Exception { keyStoreRestHelper.executeDeleteRequest(index); } - //as admin + // as admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse responseIndex = sslRestHelper.executePutRequest(index, indexSettings, allAccessUserHeader); assertEquals(RestStatus.OK.getStatus(), responseIndex.getStatusCode()); @@ -486,16 +494,16 @@ public void testCreateWithSystemIndices() throws Exception { RestHelper keyStoreRestHelper = keyStoreRestHelper(); RestHelper sslRestHelper = sslRestHelper(); - String indexSettings = "{\n" + - " \"settings\" : {\n" + - " \"index\" : {\n" + - " \"number_of_shards\" : 3, \n" + - " \"number_of_replicas\" : 2 \n" + - " }\n" + - " }\n" + - "}"; + String indexSettings = "{\n" + + " \"settings\" : {\n" + + " \"index\" : {\n" + + " \"number_of_shards\" : 3, \n" + + " \"number_of_replicas\" : 2 \n" + + " }\n" + + " }\n" + + "}"; - //as super-admin + // as super-admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse responseIndex = keyStoreRestHelper.executePutRequest(index, indexSettings); assertEquals(RestStatus.OK.getStatus(), responseIndex.getStatusCode()); @@ -508,7 +516,7 @@ public void testCreateWithSystemIndices() throws Exception { keyStoreRestHelper.executeDeleteRequest(index); } - //as admin + // as admin for (String index : listOfIndexesToTest) { RestHelper.HttpResponse responseIndex = sslRestHelper.executePutRequest(index, indexSettings, allAccessUserHeader); assertEquals(RestStatus.OK.getStatus(), responseIndex.getStatusCode()); @@ -536,9 +544,26 @@ public void testSnapshotWithSystemIndices() throws Exception { RestHelper sslRestHelper = sslRestHelper(); // as admin for (String index : listOfIndexesToTest) { - assertEquals(HttpStatus.SC_OK, sslRestHelper.executeGetRequest("_snapshot/" + index + "/" + index + "_1", allAccessUserHeader).getStatusCode()); - assertEquals(HttpStatus.SC_OK, sslRestHelper.executePostRequest("_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true","{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", allAccessUserHeader).getStatusCode()); - assertEquals(HttpStatus.SC_FORBIDDEN, sslRestHelper.executePostRequest("_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true", "", allAccessUserHeader).getStatusCode()); + assertEquals( + HttpStatus.SC_OK, + sslRestHelper.executeGetRequest("_snapshot/" + index + "/" + index + "_1", allAccessUserHeader).getStatusCode() + ); + assertEquals( + HttpStatus.SC_OK, + sslRestHelper.executePostRequest( + "_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true", + "{ \"rename_pattern\": \"(.+)\", \"rename_replacement\": \"restored_index_with_global_state_$1\" }", + allAccessUserHeader + ).getStatusCode() + ); + assertEquals( + HttpStatus.SC_FORBIDDEN, + sslRestHelper.executePostRequest( + "_snapshot/" + index + "/" + index + "_1/_restore?wait_for_completion=true", + "", + allAccessUserHeader + ).getStatusCode() + ); } } } diff --git a/src/test/java/org/opensearch/security/test/AbstractSecurityUnitTest.java b/src/test/java/org/opensearch/security/test/AbstractSecurityUnitTest.java index 72b05abb91..975db57701 100644 --- a/src/test/java/org/opensearch/security/test/AbstractSecurityUnitTest.java +++ b/src/test/java/org/opensearch/security/test/AbstractSecurityUnitTest.java @@ -95,11 +95,11 @@ import org.opensearch.threadpool.ThreadPool; /* - * There are real thread leaks during test execution, not all threads are + * There are real thread leaks during test execution, not all threads are * properly waited on or interrupted. While this normally doesn't create test * failures, retries mitigate this. Remove this attribute to explore these * issues. - */ + */ @ThreadLeakScope(Scope.NONE) public abstract class AbstractSecurityUnitTest extends RandomizedTest { @@ -109,26 +109,32 @@ public abstract class AbstractSecurityUnitTest extends RandomizedTest { static { - System.out.println("OS: " + System.getProperty("os.name") + " " + System.getProperty("os.arch") + " " - + System.getProperty("os.version")); System.out.println( - "Java Version: " + System.getProperty("java.version") + " " + System.getProperty("java.vendor")); - System.out.println("JVM Impl.: " + System.getProperty("java.vm.version") + " " - + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name")); + "OS: " + System.getProperty("os.name") + " " + System.getProperty("os.arch") + " " + System.getProperty("os.version") + ); + System.out.println("Java Version: " + System.getProperty("java.version") + " " + System.getProperty("java.vendor")); + System.out.println( + "JVM Impl.: " + + System.getProperty("java.vm.version") + + " " + + System.getProperty("java.vm.vendor") + + " " + + System.getProperty("java.vm.name") + ); System.out.println("Open SSL available: " + OpenSsl.isAvailable()); System.out.println("Open SSL version: " + OpenSsl.versionString()); withRemoteCluster = Boolean.parseBoolean(System.getenv("TESTARG_unittests_with_remote_cluster")); System.out.println("With remote cluster: " + withRemoteCluster); - //System.setProperty("security.display_lic_none","true"); + // System.setProperty("security.display_lic_none","true"); } protected final Logger log = LogManager.getLogger(this.getClass()); - public static final ThreadPool MOCK_POOL = new ThreadPool(Settings.builder().put("node.name", "mock").build()); + public static final ThreadPool MOCK_POOL = new ThreadPool(Settings.builder().put("node.name", "mock").build()); - //TODO Test Matrix - protected boolean allowOpenSSL = false; //disabled, we test this already in SSL Plugin - //enable//disable enterprise modules - //1node and 3 node + // TODO Test Matrix + protected boolean allowOpenSSL = false; // disabled, we test this already in SSL Plugin + // enable//disable enterprise modules + // 1node and 3 node @Rule public TestName name = new TestName(); @@ -136,63 +142,68 @@ public abstract class AbstractSecurityUnitTest extends RandomizedTest { @Rule public final TemporaryFolder repositoryPath = new TemporaryFolder(); - @Rule - public final TestWatcher testWatcher = new SecurityTestWatcher(); + @Rule + public final TestWatcher testWatcher = new SecurityTestWatcher(); public static Header encodeBasicHeader(final String username, final String password) { - return new BasicHeader("Authorization", "Basic "+Base64.getEncoder().encodeToString( - (username + ":" + Objects.requireNonNull(password)).getBytes(StandardCharsets.UTF_8))); + return new BasicHeader( + "Authorization", + "Basic " + + Base64.getEncoder().encodeToString((username + ":" + Objects.requireNonNull(password)).getBytes(StandardCharsets.UTF_8)) + ); } protected RestHighLevelClient getRestClient(ClusterInfo info, String keyStoreName, String trustStoreName) { return getRestClient(info, keyStoreName, trustStoreName, null); } - protected RestHighLevelClient getRestClient(ClusterInfo info, String keyStoreName, String trustStoreName, HttpVersionPolicy httpVersionPolicy) { - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; + protected RestHighLevelClient getRestClient( + ClusterInfo info, + String keyStoreName, + String trustStoreName, + HttpVersionPolicy httpVersionPolicy + ) { + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; try { SSLContextBuilder sslContextBuilder = SSLContexts.custom(); File keyStoreFile = FileHelper.getAbsoluteFilePathFromClassPath(prefix + keyStoreName).toFile(); - KeyStore keyStore = KeyStore.getInstance(keyStoreName.endsWith(".jks")?"JKS":"PKCS12"); + KeyStore keyStore = KeyStore.getInstance(keyStoreName.endsWith(".jks") ? "JKS" : "PKCS12"); keyStore.load(new FileInputStream(keyStoreFile), null); sslContextBuilder.loadKeyMaterial(keyStore, "changeit".toCharArray()); - KeyStore trustStore = KeyStore.getInstance(trustStoreName.endsWith(".jks")?"JKS":"PKCS12"); + KeyStore trustStore = KeyStore.getInstance(trustStoreName.endsWith(".jks") ? "JKS" : "PKCS12"); File trustStoreFile = FileHelper.getAbsoluteFilePathFromClassPath(prefix + trustStoreName).toFile(); - trustStore.load(new FileInputStream(trustStoreFile), - "changeit".toCharArray()); + trustStore.load(new FileInputStream(trustStoreFile), "changeit".toCharArray()); sslContextBuilder.loadTrustMaterial(trustStore, null); SSLContext sslContext = sslContextBuilder.build(); HttpHost httpHost = new HttpHost("https", info.httpHost, info.httpPort); - RestClientBuilder restClientBuilder = RestClient.builder(httpHost) - .setHttpClientConfigCallback( - builder -> { - TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() - .setSslContext(sslContext) - .setTlsVersions(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "SSLv3"}) - .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) - // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 - .setTlsDetailsFactory(new Factory() { - @Override - public TlsDetails create(final SSLEngine sslEngine) { - return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); - } - }) - .build(); - - final AsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(tlsStrategy) - .build(); - builder.setConnectionManager(cm); - if (httpVersionPolicy != null) { - builder.setVersionPolicy(httpVersionPolicy); - } - return builder; - }); + RestClientBuilder restClientBuilder = RestClient.builder(httpHost).setHttpClientConfigCallback(builder -> { + TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() + .setSslContext(sslContext) + .setTlsVersions(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "SSLv3" }) + .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) + // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 + .setTlsDetailsFactory(new Factory() { + @Override + public TlsDetails create(final SSLEngine sslEngine) { + return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); + } + }) + .build(); + + final AsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create() + .setTlsStrategy(tlsStrategy) + .build(); + builder.setConnectionManager(cm); + if (httpVersionPolicy != null) { + builder.setVersionPolicy(httpVersionPolicy); + } + return builder; + }); return new RestHighLevelClient(restClientBuilder); } catch (Exception e) { log.error("Cannot create client", e); @@ -210,7 +221,7 @@ public void waitForInit(Client client) { retainedException = Optional.empty(); return; } catch (OpenSearchSecurityException ex) { - if(ex.getMessage().contains("OpenSearch Security not initialized")) { + if (ex.getMessage().contains("OpenSearch Security not initialized")) { retainedException = Optional.of(ex); try { Thread.sleep(500); @@ -227,7 +238,11 @@ public void waitForInit(Client client) { } } - public static Settings.Builder nodeRolesSettings(final Settings.Builder settingsBuilder, final boolean isClusterManager, final boolean isDataNode) { + public static Settings.Builder nodeRolesSettings( + final Settings.Builder settingsBuilder, + final boolean isClusterManager, + final boolean isDataNode + ) { final ImmutableList.Builder nodeRolesBuilder = ImmutableList.builder(); if (isDataNode) { nodeRolesBuilder.add(DiscoveryNodeRole.DATA_ROLE.roleName()); @@ -245,29 +260,29 @@ public static Settings.Builder mergeNodeRolesAndSettings(final Settings.Builder .addAll(settingsBuilder.build().getAsList(NODE_ROLE_KEY, ImmutableList.of())) .addAll(otherSettings.getAsList(NODE_ROLE_KEY, ImmutableList.of())); - return settingsBuilder.put(otherSettings) - .putList(NODE_ROLE_KEY, originalRoles.build().asList()); + return settingsBuilder.put(otherSettings).putList(NODE_ROLE_KEY, originalRoles.build().asList()); } - protected void initialize(ClusterHelper clusterHelper, ClusterInfo clusterInfo, DynamicSecurityConfig securityConfig) throws IOException { + protected void initialize(ClusterHelper clusterHelper, ClusterInfo clusterInfo, DynamicSecurityConfig securityConfig) + throws IOException { try (Client tc = clusterHelper.nodeClient()) { - Assert.assertEquals(clusterInfo.numNodes, - tc.admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); + Assert.assertEquals(clusterInfo.numNodes, tc.admin().cluster().nodesInfo(new NodesInfoRequest()).actionGet().getNodes().size()); try { tc.admin().indices().create(new CreateIndexRequest(".opendistro_security")).actionGet(); } catch (Exception e) { - //ignore + // ignore } List indexRequests = securityConfig.getDynamicConfig(getResourceFolder()); - for(IndexRequest ir: indexRequests) { + for (IndexRequest ir : indexRequests) { tc.index(ir).actionGet(); } - ConfigUpdateResponse cur = tc - .execute(ConfigUpdateAction.INSTANCE, new ConfigUpdateRequest(CType.lcStringValues().toArray(new String[0]))) - .actionGet(); + ConfigUpdateResponse cur = tc.execute( + ConfigUpdateAction.INSTANCE, + new ConfigUpdateRequest(CType.lcStringValues().toArray(new String[0])) + ).actionGet(); Assert.assertFalse(cur.failures().toString(), cur.hasFailures()); Assert.assertEquals(clusterInfo.numNodes, cur.getNodes().size()); @@ -278,22 +293,27 @@ protected void initialize(ClusterHelper clusterHelper, ClusterInfo clusterInfo, protected Settings.Builder minimumSecuritySettingsBuilder(int node, boolean sslOnly, Settings other) { - final String prefix = getResourceFolder()==null?"":getResourceFolder()+"/"; + final String prefix = getResourceFolder() == null ? "" : getResourceFolder() + "/"; Settings.Builder builder = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL); + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL) + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLE_OPENSSL_IF_AVAILABLE, allowOpenSSL); // If custom transport settings are not defined use defaults if (!hasCustomTransportSettings(other)) { builder.put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_ALIAS, "node-0") - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, - FileHelper.getAbsoluteFilePathFromClassPath(prefix+"node-0-keystore.jks")) - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, FileHelper.getAbsoluteFilePathFromClassPath(prefix+"truststore.jks")) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath(prefix + "node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath(prefix + "truststore.jks") + ) .put("plugins.security.ssl.transport.enforce_hostname_verification", false); } - if(!sslOnly) { + if (!sslOnly) { builder.putList("plugins.security.authcz.admin_dn", "CN=kirk,OU=client,O=client,l=tEst, C=De"); builder.put(ConfigConstants.SECURITY_BACKGROUND_INIT_IF_SECURITYINDEX_NOT_EXIST, false); } @@ -340,8 +360,8 @@ protected NodeSettingsSupplier genericMinimumSecuritySettings(List oth assert i > 0; // i is 1-indexed // Set to default if input does not have value at (i-1) index - boolean sslOnlyFlag = i > sslOnly.size() ? false : sslOnly.get(i-1); - Settings settings = i > others.size() ? Settings.EMPTY : others.get(i-1); + boolean sslOnlyFlag = i > sslOnly.size() ? false : sslOnly.get(i - 1); + Settings settings = i > others.size() ? Settings.EMPTY : others.get(i - 1); return minimumSecuritySettingsBuilder(i, sslOnlyFlag, settings).build(); }; @@ -363,7 +383,6 @@ protected String getResourceFolder() { return null; } - /** * Check if transport certs are is mentioned in the custom settings * @param customSettings custom settings from the test class @@ -371,7 +390,7 @@ protected String getResourceFolder() { */ protected boolean hasCustomTransportSettings(Settings customSettings) { // If Transport key extended usage is enabled this is true - return Boolean.parseBoolean(customSettings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_EXTENDED_KEY_USAGE_ENABLED)) || - customSettings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH) != null; + return Boolean.parseBoolean(customSettings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_EXTENDED_KEY_USAGE_ENABLED)) + || customSettings.get(SSLConfigConstants.SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH) != null; } } diff --git a/src/test/java/org/opensearch/security/test/DynamicSecurityConfig.java b/src/test/java/org/opensearch/security/test/DynamicSecurityConfig.java index 3573c7c274..9213d36070 100644 --- a/src/test/java/org/opensearch/security/test/DynamicSecurityConfig.java +++ b/src/test/java/org/opensearch/security/test/DynamicSecurityConfig.java @@ -45,8 +45,8 @@ public class DynamicSecurityConfig { private String securityInternalUsers = "internal_users.yml"; private String securityActionGroups = "action_groups.yml"; private String securityNodesDn = "nodes_dn.yml"; - private String securityWhitelist= "whitelist.yml"; - private String securityAllowlist= "allowlist.yml"; + private String securityWhitelist = "whitelist.yml"; + private String securityAllowlist = "allowlist.yml"; private String securityAudit = "audit.yml"; private String securityConfigAsYamlString = null; private String legacyConfigFolder = ""; @@ -95,12 +95,12 @@ public DynamicSecurityConfig setSecurityNodesDn(String nodesDn) { return this; } - public DynamicSecurityConfig setSecurityWhitelist(String whitelist){ + public DynamicSecurityConfig setSecurityWhitelist(String whitelist) { this.securityWhitelist = whitelist; return this; } - public DynamicSecurityConfig setSecurityAllowlist(String allowlist){ + public DynamicSecurityConfig setSecurityAllowlist(String allowlist) { this.securityAllowlist = allowlist; return this; } @@ -117,71 +117,86 @@ public DynamicSecurityConfig setLegacy() { public List getDynamicConfig(String folder) { - final String prefix = legacyConfigFolder+(folder == null?"":folder+"/"); + final String prefix = legacyConfigFolder + (folder == null ? "" : folder + "/"); List ret = new ArrayList(); - ret.add(new IndexRequest(securityIndexName) - .id(CType.CONFIG.toLCString()) + ret.add( + new IndexRequest(securityIndexName).id(CType.CONFIG.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.CONFIG.toLCString(), securityConfigAsYamlString==null? FileHelper.readYamlContent(prefix+securityConfig):FileHelper.readYamlContentFromString(securityConfigAsYamlString))); - - ret.add(new IndexRequest(securityIndexName) - .id(CType.ACTIONGROUPS.toLCString()) + .source( + CType.CONFIG.toLCString(), + securityConfigAsYamlString == null + ? FileHelper.readYamlContent(prefix + securityConfig) + : FileHelper.readYamlContentFromString(securityConfigAsYamlString) + ) + ); + + ret.add( + new IndexRequest(securityIndexName).id(CType.ACTIONGROUPS.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.ACTIONGROUPS.toLCString(), FileHelper.readYamlContent(prefix+securityActionGroups))); + .source(CType.ACTIONGROUPS.toLCString(), FileHelper.readYamlContent(prefix + securityActionGroups)) + ); - ret.add(new IndexRequest(securityIndexName) - .id(CType.INTERNALUSERS.toLCString()) + ret.add( + new IndexRequest(securityIndexName).id(CType.INTERNALUSERS.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.INTERNALUSERS.toLCString(), FileHelper.readYamlContent(prefix+securityInternalUsers))); + .source(CType.INTERNALUSERS.toLCString(), FileHelper.readYamlContent(prefix + securityInternalUsers)) + ); - ret.add(new IndexRequest(securityIndexName) - .id(CType.ROLES.toLCString()) + ret.add( + new IndexRequest(securityIndexName).id(CType.ROLES.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.ROLES.toLCString(), FileHelper.readYamlContent(prefix+securityRoles))); + .source(CType.ROLES.toLCString(), FileHelper.readYamlContent(prefix + securityRoles)) + ); - ret.add(new IndexRequest(securityIndexName) - .id(CType.ROLESMAPPING.toLCString()) + ret.add( + new IndexRequest(securityIndexName).id(CType.ROLESMAPPING.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.ROLESMAPPING.toLCString(), FileHelper.readYamlContent(prefix+securityRolesMapping))); - if("".equals(legacyConfigFolder)) { - ret.add(new IndexRequest(securityIndexName) - .id(CType.TENANTS.toLCString()) + .source(CType.ROLESMAPPING.toLCString(), FileHelper.readYamlContent(prefix + securityRolesMapping)) + ); + if ("".equals(legacyConfigFolder)) { + ret.add( + new IndexRequest(securityIndexName).id(CType.TENANTS.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.TENANTS.toLCString(), FileHelper.readYamlContent(prefix+securityTenants))); + .source(CType.TENANTS.toLCString(), FileHelper.readYamlContent(prefix + securityTenants)) + ); } if (null != FileHelper.getAbsoluteFilePathFromClassPath(prefix + securityNodesDn)) { - ret.add(new IndexRequest(securityIndexName) - .id(CType.NODESDN.toLCString()) + ret.add( + new IndexRequest(securityIndexName).id(CType.NODESDN.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.NODESDN.toLCString(), FileHelper.readYamlContent(prefix + securityNodesDn))); + .source(CType.NODESDN.toLCString(), FileHelper.readYamlContent(prefix + securityNodesDn)) + ); } final String whitelistYmlFile = prefix + securityWhitelist; if (null != FileHelper.getAbsoluteFilePathFromClassPath(whitelistYmlFile)) { - ret.add(new IndexRequest(securityIndexName) - .id(CType.WHITELIST.toLCString()) + ret.add( + new IndexRequest(securityIndexName).id(CType.WHITELIST.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.WHITELIST.toLCString(), FileHelper.readYamlContent(whitelistYmlFile))); + .source(CType.WHITELIST.toLCString(), FileHelper.readYamlContent(whitelistYmlFile)) + ); } final String allowlistYmlFile = prefix + securityAllowlist; if (null != FileHelper.getAbsoluteFilePathFromClassPath(allowlistYmlFile)) { - ret.add(new IndexRequest(securityIndexName) - .id(CType.ALLOWLIST.toLCString()) + ret.add( + new IndexRequest(securityIndexName).id(CType.ALLOWLIST.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.ALLOWLIST.toLCString(), FileHelper.readYamlContent(allowlistYmlFile))); + .source(CType.ALLOWLIST.toLCString(), FileHelper.readYamlContent(allowlistYmlFile)) + ); } final String auditYmlFile = prefix + securityAudit; if (null != FileHelper.getAbsoluteFilePathFromClassPath(auditYmlFile)) { - ret.add(new IndexRequest(securityIndexName) - .id(CType.AUDIT.toLCString()) + ret.add( + new IndexRequest(securityIndexName).id(CType.AUDIT.toLCString()) .setRefreshPolicy(RefreshPolicy.IMMEDIATE) - .source(CType.AUDIT.toLCString(), FileHelper.readYamlContent(auditYmlFile))); + .source(CType.AUDIT.toLCString(), FileHelper.readYamlContent(auditYmlFile)) + ); } return Collections.unmodifiableList(ret); diff --git a/src/test/java/org/opensearch/security/test/SingleClusterTest.java b/src/test/java/org/opensearch/security/test/SingleClusterTest.java index 0c2f3bfc07..2839e1e283 100644 --- a/src/test/java/org/opensearch/security/test/SingleClusterTest.java +++ b/src/test/java/org/opensearch/security/test/SingleClusterTest.java @@ -48,10 +48,13 @@ public abstract class SingleClusterTest extends AbstractSecurityUnitTest { private static final int DEFAULT_CLUSTER_MANAGER_NODE_NUM = 3; private static final int DEFAULT_FIRST_DATA_NODE_NUM = 2; - protected ClusterHelper clusterHelper = new ClusterHelper("utest_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()); + protected ClusterHelper clusterHelper = new ClusterHelper( + "utest_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime() + ); protected ClusterInfo clusterInfo; - private ClusterHelper remoteClusterHelper = withRemoteCluster ? - new ClusterHelper("crl2_n"+num.incrementAndGet()+"_f"+System.getProperty("forkno")+"_t"+System.nanoTime()) : null; + private ClusterHelper remoteClusterHelper = withRemoteCluster + ? new ClusterHelper("crl2_n" + num.incrementAndGet() + "_f" + System.getProperty("forkno") + "_t" + System.nanoTime()) + : null; private ClusterInfo remoteClusterInfo; protected void setup(Settings nodeOverride) throws Exception { @@ -66,48 +69,71 @@ protected void setup() throws Exception { setup(Settings.EMPTY, new DynamicSecurityConfig(), Settings.EMPTY, true); } - protected void setup(Settings initTransportClientSettings, DynamicSecurityConfig dynamicSecuritySettings, Settings nodeOverride) throws Exception { + protected void setup(Settings initTransportClientSettings, DynamicSecurityConfig dynamicSecuritySettings, Settings nodeOverride) + throws Exception { setup(initTransportClientSettings, dynamicSecuritySettings, nodeOverride, true); } - protected void setup(Settings initTransportClientSettings, DynamicSecurityConfig dynamicSecuritySettings, Settings nodeOverride, boolean initSecurityIndex) throws Exception { + protected void setup( + Settings initTransportClientSettings, + DynamicSecurityConfig dynamicSecuritySettings, + Settings nodeOverride, + boolean initSecurityIndex + ) throws Exception { setup(initTransportClientSettings, dynamicSecuritySettings, nodeOverride, initSecurityIndex, ClusterConfiguration.DEFAULT); } - protected void restart(Settings initTransportClientSettings, DynamicSecurityConfig dynamicSecuritySettings, Settings nodeOverride, boolean initOpendistroSecurityIndex) throws Exception { + protected void restart( + Settings initTransportClientSettings, + DynamicSecurityConfig dynamicSecuritySettings, + Settings nodeOverride, + boolean initOpendistroSecurityIndex + ) throws Exception { clusterInfo = clusterHelper.startCluster(minimumSecuritySettings(ccs(nodeOverride)), ClusterConfiguration.DEFAULT); - if(initOpendistroSecurityIndex && dynamicSecuritySettings != null) { + if (initOpendistroSecurityIndex && dynamicSecuritySettings != null) { initialize(clusterHelper, clusterInfo, dynamicSecuritySettings); } } private Settings ccs(Settings nodeOverride) throws Exception { - if(remoteClusterHelper != null) { + if (remoteClusterHelper != null) { Assert.assertNull("No remote clusters", remoteClusterInfo); remoteClusterInfo = remoteClusterHelper.startCluster(minimumSecuritySettings(Settings.EMPTY), ClusterConfiguration.SINGLENODE); Settings.Builder builder = Settings.builder() - .put(nodeOverride) - .putList("cluster.remote.cross_cluster_two.seeds", remoteClusterInfo.nodeHost+":"+remoteClusterInfo.nodePort); + .put(nodeOverride) + .putList("cluster.remote.cross_cluster_two.seeds", remoteClusterInfo.nodeHost + ":" + remoteClusterInfo.nodePort); return builder.build(); } else { return nodeOverride; } } - - protected void setup(Settings initTransportClientSettings, DynamicSecurityConfig dynamicSecuritySettings, Settings nodeOverride, boolean initSecurityIndex, ClusterConfiguration clusterConfiguration) throws Exception { + protected void setup( + Settings initTransportClientSettings, + DynamicSecurityConfig dynamicSecuritySettings, + Settings nodeOverride, + boolean initSecurityIndex, + ClusterConfiguration clusterConfiguration + ) throws Exception { Assert.assertNull("No cluster", clusterInfo); clusterInfo = clusterHelper.startCluster(minimumSecuritySettings(ccs(nodeOverride)), clusterConfiguration); - if(initSecurityIndex && dynamicSecuritySettings != null) { + if (initSecurityIndex && dynamicSecuritySettings != null) { initialize(clusterHelper, clusterInfo, dynamicSecuritySettings); } } - protected void setup(Settings initTransportClientSettings, DynamicSecurityConfig dynamicSecuritySettings, Settings nodeOverride - , boolean initSecurityIndex, ClusterConfiguration clusterConfiguration, int timeout, Integer nodes) throws Exception { + protected void setup( + Settings initTransportClientSettings, + DynamicSecurityConfig dynamicSecuritySettings, + Settings nodeOverride, + boolean initSecurityIndex, + ClusterConfiguration clusterConfiguration, + int timeout, + Integer nodes + ) throws Exception { Assert.assertNull("No cluster", clusterInfo); clusterInfo = clusterHelper.startCluster(minimumSecuritySettings(ccs(nodeOverride)), clusterConfiguration, timeout, nodes); - if(initSecurityIndex) { + if (initSecurityIndex) { initialize(clusterHelper, clusterInfo, dynamicSecuritySettings); } } @@ -119,20 +145,24 @@ protected void setupSslOnlyMode(Settings nodeOverride) throws Exception { protected void setupSslOnlyModeWithClusterManagerNodeWithoutSSL(Settings nodeOverride) throws Exception { Assert.assertNull("No cluster", clusterInfo); - clusterInfo = clusterHelper.startCluster(minimumSecuritySettingsSslOnlyWithOneNodeNonSSL(nodeOverride, - DEFAULT_CLUSTER_MANAGER_NODE_NUM), ClusterConfiguration.DEFAULT_CLUSTER_MANAGER_WITHOUT_SECURITY_PLUGIN); + clusterInfo = clusterHelper.startCluster( + minimumSecuritySettingsSslOnlyWithOneNodeNonSSL(nodeOverride, DEFAULT_CLUSTER_MANAGER_NODE_NUM), + ClusterConfiguration.DEFAULT_CLUSTER_MANAGER_WITHOUT_SECURITY_PLUGIN + ); } protected void setupSslOnlyModeWithDataNodeWithoutSSL(Settings nodeOverride) throws Exception { Assert.assertNull("No cluster", clusterInfo); - clusterInfo = clusterHelper.startCluster(minimumSecuritySettingsSslOnlyWithOneNodeNonSSL(nodeOverride, - DEFAULT_FIRST_DATA_NODE_NUM), ClusterConfiguration.DEFAULT_ONE_DATA_NODE_WITHOUT_SECURITY_PLUGIN); + clusterInfo = clusterHelper.startCluster( + minimumSecuritySettingsSslOnlyWithOneNodeNonSSL(nodeOverride, DEFAULT_FIRST_DATA_NODE_NUM), + ClusterConfiguration.DEFAULT_ONE_DATA_NODE_WITHOUT_SECURITY_PLUGIN + ); } - protected void setupGenericNodes(List nodeOverride, List sslOnly, ClusterConfiguration clusterConfiguration) throws Exception { + protected void setupGenericNodes(List nodeOverride, List sslOnly, ClusterConfiguration clusterConfiguration) + throws Exception { Assert.assertNull("No cluster", clusterInfo); - clusterInfo = clusterHelper.startCluster(genericMinimumSecuritySettings(nodeOverride, sslOnly), - clusterConfiguration); + clusterInfo = clusterHelper.startCluster(genericMinimumSecuritySettings(nodeOverride, sslOnly), clusterConfiguration); } protected RestHelper restHelper() { @@ -147,11 +177,10 @@ protected Client getClient() { return clusterHelper.nodeClient(); } - @After public void tearDown() { - if(remoteClusterInfo != null) { + if (remoteClusterInfo != null) { try { remoteClusterHelper.stopCluster(); } catch (Exception e) { @@ -161,7 +190,7 @@ public void tearDown() { remoteClusterInfo = null; } - if(clusterInfo != null) { + if (clusterInfo != null) { try { clusterHelper.stopCluster(); } catch (Exception e) { diff --git a/src/test/java/org/opensearch/security/test/helper/cluster/ClusterConfiguration.java b/src/test/java/org/opensearch/security/test/helper/cluster/ClusterConfiguration.java index 871cf5a59d..e9b503e669 100644 --- a/src/test/java/org/opensearch/security/test/helper/cluster/ClusterConfiguration.java +++ b/src/test/java/org/opensearch/security/test/helper/cluster/ClusterConfiguration.java @@ -45,90 +45,111 @@ import org.opensearch.transport.Netty4ModulePlugin; public enum ClusterConfiguration { - //first one needs to be a cluster manager - //HUGE(new NodeSettings(true, false, false), new NodeSettings(true, false, false), new NodeSettings(true, false, false), new NodeSettings(false, true,false), new NodeSettings(false, true, false)), - - //3 nodes (1m, 2d) + // first one needs to be a cluster manager + // HUGE(new NodeSettings(true, false, false), new NodeSettings(true, false, false), new NodeSettings(true, false, false), new + // NodeSettings(false, true,false), new NodeSettings(false, true, false)), + + // 3 nodes (1m, 2d) DEFAULT(new NodeSettings(true, false), new NodeSettings(false, true), new NodeSettings(false, true)), - //2 nodes (1m, 3d) - ONE_CLUSTER_MANAGER_THREE_DATA(new NodeSettings(true, false), new NodeSettings(false, true), new NodeSettings(false, true), new NodeSettings(false, true)), - - DEFAULT_CLUSTER_MANAGER_WITHOUT_SECURITY_PLUGIN(new NodeSettings(true, false) - .removePluginIfPresent(OpenSearchSecurityPlugin.class) - , new NodeSettings(false, true) - , new NodeSettings(false, true)), - - DEFAULT_ONE_DATA_NODE_WITHOUT_SECURITY_PLUGIN(new NodeSettings(true, false) - , new NodeSettings(false, true).removePluginIfPresent(OpenSearchSecurityPlugin.class) - , new NodeSettings(false, true)), - - //1 node (1md) - SINGLENODE(new NodeSettings(true, true)), - - //4 node (1m, 2d, 1c) - CLIENTNODE(new NodeSettings(true, false), new NodeSettings(false, true), new NodeSettings(false, true), new NodeSettings(false, false)), - - //3 nodes (1m, 2d) plus additional UserInjectorPlugin - USERINJECTOR(new NodeSettings(true, false, Lists.newArrayList(UserInjectorPlugin.class)), new NodeSettings(false, true, Lists.newArrayList(UserInjectorPlugin.class)), new NodeSettings(false, true, Lists.newArrayList(UserInjectorPlugin.class))); - - private List nodeSettings = new LinkedList<>(); - - private ClusterConfiguration(NodeSettings ... settings) { - nodeSettings.addAll(Arrays.asList(settings)); - } - - public List getNodeSettings() { - return Collections.unmodifiableList(nodeSettings); - } - - public List getClusterManagerNodeSettings() { - return Collections.unmodifiableList(nodeSettings.stream().filter(a->a.clusterManagerNode).collect(Collectors.toList())); + // 2 nodes (1m, 3d) + ONE_CLUSTER_MANAGER_THREE_DATA( + new NodeSettings(true, false), + new NodeSettings(false, true), + new NodeSettings(false, true), + new NodeSettings(false, true) + ), + + DEFAULT_CLUSTER_MANAGER_WITHOUT_SECURITY_PLUGIN( + new NodeSettings(true, false).removePluginIfPresent(OpenSearchSecurityPlugin.class), + new NodeSettings(false, true), + new NodeSettings(false, true) + ), + + DEFAULT_ONE_DATA_NODE_WITHOUT_SECURITY_PLUGIN( + new NodeSettings(true, false), + new NodeSettings(false, true).removePluginIfPresent(OpenSearchSecurityPlugin.class), + new NodeSettings(false, true) + ), + + // 1 node (1md) + SINGLENODE(new NodeSettings(true, true)), + + // 4 node (1m, 2d, 1c) + CLIENTNODE(new NodeSettings(true, false), new NodeSettings(false, true), new NodeSettings(false, true), new NodeSettings(false, false)), + + // 3 nodes (1m, 2d) plus additional UserInjectorPlugin + USERINJECTOR( + new NodeSettings(true, false, Lists.newArrayList(UserInjectorPlugin.class)), + new NodeSettings(false, true, Lists.newArrayList(UserInjectorPlugin.class)), + new NodeSettings(false, true, Lists.newArrayList(UserInjectorPlugin.class)) + ); + + private List nodeSettings = new LinkedList<>(); + + private ClusterConfiguration(NodeSettings... settings) { + nodeSettings.addAll(Arrays.asList(settings)); + } + + public List getNodeSettings() { + return Collections.unmodifiableList(nodeSettings); } - - public List getNonClusterManagerNodeSettings() { - return Collections.unmodifiableList(nodeSettings.stream().filter(a->!a.clusterManagerNode).collect(Collectors.toList())); + + public List getClusterManagerNodeSettings() { + return Collections.unmodifiableList(nodeSettings.stream().filter(a -> a.clusterManagerNode).collect(Collectors.toList())); + } + + public List getNonClusterManagerNodeSettings() { + return Collections.unmodifiableList(nodeSettings.stream().filter(a -> !a.clusterManagerNode).collect(Collectors.toList())); } - - public int getNodes() { + + public int getNodes() { return nodeSettings.size(); } - - public int getClusterManagerNodes() { - return (int) nodeSettings.stream().filter(a->a.clusterManagerNode).count(); + + public int getClusterManagerNodes() { + return (int) nodeSettings.stream().filter(a -> a.clusterManagerNode).count(); } - - public int getDataNodes() { - return (int) nodeSettings.stream().filter(a->a.dataNode).count(); + + public int getDataNodes() { + return (int) nodeSettings.stream().filter(a -> a.dataNode).count(); } - - public int getClientNodes() { - return (int) nodeSettings.stream().filter(a->!a.clusterManagerNode && !a.dataNode).count(); + + public int getClientNodes() { + return (int) nodeSettings.stream().filter(a -> !a.clusterManagerNode && !a.dataNode).count(); } - - public static class NodeSettings { - public boolean clusterManagerNode; - public boolean dataNode; - public List> plugins = Lists.newArrayList(Netty4ModulePlugin.class, OpenSearchSecurityPlugin.class, MatrixAggregationModulePlugin.class, MustacheModulePlugin.class, ParentJoinModulePlugin.class, PercolatorModulePlugin.class, ReindexModulePlugin.class); - - public NodeSettings(boolean clusterManagerNode, boolean dataNode) { - super(); - this.clusterManagerNode = clusterManagerNode; - this.dataNode = dataNode; - } - - public NodeSettings(boolean clusterManagerNode, boolean dataNode, List> additionalPlugins) { + + public static class NodeSettings { + public boolean clusterManagerNode; + public boolean dataNode; + public List> plugins = Lists.newArrayList( + Netty4ModulePlugin.class, + OpenSearchSecurityPlugin.class, + MatrixAggregationModulePlugin.class, + MustacheModulePlugin.class, + ParentJoinModulePlugin.class, + PercolatorModulePlugin.class, + ReindexModulePlugin.class + ); + + public NodeSettings(boolean clusterManagerNode, boolean dataNode) { + super(); + this.clusterManagerNode = clusterManagerNode; + this.dataNode = dataNode; + } + + public NodeSettings(boolean clusterManagerNode, boolean dataNode, List> additionalPlugins) { this(clusterManagerNode, dataNode); this.plugins.addAll(additionalPlugins); } - public NodeSettings removePluginIfPresent(Class pluginToRemove){ - this.plugins.remove(pluginToRemove); - return this; - } - - public Class[] getPlugins() { - return plugins.toArray(new Class[0] ); - } - } + public NodeSettings removePluginIfPresent(Class pluginToRemove) { + this.plugins.remove(pluginToRemove); + return this; + } + + public Class[] getPlugins() { + return plugins.toArray(new Class[0]); + } + } } diff --git a/src/test/java/org/opensearch/security/test/helper/cluster/ClusterHelper.java b/src/test/java/org/opensearch/security/test/helper/cluster/ClusterHelper.java index 5aea8f7dfe..e60fab8e48 100644 --- a/src/test/java/org/opensearch/security/test/helper/cluster/ClusterHelper.java +++ b/src/test/java/org/opensearch/security/test/helper/cluster/ClusterHelper.java @@ -74,17 +74,17 @@ public final class ClusterHelper { static { resetSystemProperties(); } - + /** Resets all system properties associated with a cluster */ public static void resetSystemProperties() { System.setProperty("opensearch.enforce.bootstrap.checks", "true"); - updateDefaultDirectory(new File( SingleClusterTest.PROJECT_ROOT_RELATIVE_PATH + "config").getAbsolutePath()); + updateDefaultDirectory(new File(SingleClusterTest.PROJECT_ROOT_RELATIVE_PATH + "config").getAbsolutePath()); } /** * Update the default directory used by the security plugin * NOTE: this setting is system wide, use ClusterHelper.resetSystemProperties() to restore the original state - * + * * @return the previous value if one was set, otherwise null */ public static String updateDefaultDirectory(final String newValue) { @@ -115,12 +115,17 @@ public String getClusterName() { * @throws Exception */ - public final ClusterInfo startCluster(final NodeSettingsSupplier nodeSettingsSupplier, ClusterConfiguration clusterConfiguration) throws Exception { + public final ClusterInfo startCluster(final NodeSettingsSupplier nodeSettingsSupplier, ClusterConfiguration clusterConfiguration) + throws Exception { return startCluster(nodeSettingsSupplier, clusterConfiguration, 10, null); } - public final synchronized ClusterInfo startCluster(final NodeSettingsSupplier nodeSettingsSupplier, ClusterConfiguration clusterConfiguration, int timeout, Integer nodes) - throws Exception { + public final synchronized ClusterInfo startCluster( + final NodeSettingsSupplier nodeSettingsSupplier, + ClusterConfiguration clusterConfiguration, + int timeout, + Integer nodes + ) throws Exception { switch (clusterState) { case UNINITIALIZED: @@ -140,27 +145,40 @@ public final synchronized ClusterInfo startCluster(final NodeSettingsSupplier no final String forkno = System.getProperty("forkno"); int forkNumber = 1; - if(forkno != null && forkno.length() > 0) { + if (forkno != null && forkno.length() > 0) { forkNumber = Integer.parseInt(forkno.split("_")[1]); } - final int min = SocketUtils.PORT_RANGE_MIN+(forkNumber*5000); - final int max = SocketUtils.PORT_RANGE_MIN+((forkNumber+1)*5000)-1; + final int min = SocketUtils.PORT_RANGE_MIN + (forkNumber * 5000); + final int max = SocketUtils.PORT_RANGE_MIN + ((forkNumber + 1) * 5000) - 1; - final SortedSet freePorts = SocketUtils.findAvailableTcpPorts(internalNodeSettings.size()*2, min, max); - assert freePorts.size() == internalNodeSettings.size()*2; + final SortedSet freePorts = SocketUtils.findAvailableTcpPorts(internalNodeSettings.size() * 2, min, max); + assert freePorts.size() == internalNodeSettings.size() * 2; final SortedSet tcpClusterManagerPortsOnly = new TreeSet(); final SortedSet tcpAllPorts = new TreeSet(); - freePorts.stream().limit(clusterConfiguration.getClusterManagerNodes()).forEach(el->tcpClusterManagerPortsOnly.add(el)); - freePorts.stream().limit(internalNodeSettings.size()).forEach(el->tcpAllPorts.add(el)); + freePorts.stream().limit(clusterConfiguration.getClusterManagerNodes()).forEach(el -> tcpClusterManagerPortsOnly.add(el)); + freePorts.stream().limit(internalNodeSettings.size()).forEach(el -> tcpAllPorts.add(el)); final Iterator tcpPortsAllIt = tcpAllPorts.iterator(); final SortedSet httpPorts = new TreeSet(); - freePorts.stream().skip(internalNodeSettings.size()).limit(internalNodeSettings.size()).forEach(el->httpPorts.add(el)); + freePorts.stream().skip(internalNodeSettings.size()).limit(internalNodeSettings.size()).forEach(el -> httpPorts.add(el)); final Iterator httpPortsIt = httpPorts.iterator(); - System.out.println("tcpClusterManagerPorts: "+tcpClusterManagerPortsOnly+"/tcpAllPorts: "+tcpAllPorts+"/httpPorts: "+httpPorts+" for ("+min+"-"+max+") fork "+forkNumber); + System.out.println( + "tcpClusterManagerPorts: " + + tcpClusterManagerPortsOnly + + "/tcpAllPorts: " + + tcpAllPorts + + "/httpPorts: " + + httpPorts + + " for (" + + min + + "-" + + max + + ") fork " + + forkNumber + ); final CountDownLatch latch = new CountDownLatch(internalNodeSettings.size()); @@ -174,7 +192,15 @@ public final synchronized ClusterInfo startCluster(final NodeSettingsSupplier no for (int i = 0; i < internalClusterManagerNodeSettings.size(); i++) { NodeSettings setting = internalClusterManagerNodeSettings.get(i); int nodeNum = nodeNumCounter--; - final Settings.Builder nodeSettingsBuilder = getMinimumNonSecurityNodeSettingsBuilder(nodeNum, setting.clusterManagerNode, setting.dataNode, internalNodeSettings.size(), tcpClusterManagerPortsOnly, tcpPortsAllIt.next(), httpPortsIt.next()); + final Settings.Builder nodeSettingsBuilder = getMinimumNonSecurityNodeSettingsBuilder( + nodeNum, + setting.clusterManagerNode, + setting.dataNode, + internalNodeSettings.size(), + tcpClusterManagerPortsOnly, + tcpPortsAllIt.next(), + httpPortsIt.next() + ); final Settings settingsForNode; if (nodeSettingsSupplier != null) { final Settings suppliedSettings = nodeSettingsSupplier.get(nodeNum); @@ -206,7 +232,15 @@ public void run() { for (int i = 0; i < internalNonClusterManagerNodeSettings.size(); i++) { NodeSettings setting = internalNonClusterManagerNodeSettings.get(i); int nodeNum = nodeNumCounter--; - final Settings.Builder nodeSettingsBuilder = getMinimumNonSecurityNodeSettingsBuilder(nodeNum, setting.clusterManagerNode, setting.dataNode, internalNodeSettings.size(), tcpClusterManagerPortsOnly, tcpPortsAllIt.next(), httpPortsIt.next()); + final Settings.Builder nodeSettingsBuilder = getMinimumNonSecurityNodeSettingsBuilder( + nodeNum, + setting.clusterManagerNode, + setting.dataNode, + internalNodeSettings.size(), + tcpClusterManagerPortsOnly, + tcpPortsAllIt.next(), + httpPortsIt.next() + ); final Settings settingsForNode; if (nodeSettingsSupplier != null) { final Settings suppliedSettings = nodeSettingsSupplier.get(nodeNum); @@ -239,27 +273,34 @@ public void run() { latch.await(); - if(err.get() != null) { - throw new RuntimeException("Could not start all nodes "+err.get(),err.get()); + if (err.get() != null) { + throw new RuntimeException("Could not start all nodes " + err.get(), err.get()); } - ClusterInfo cInfo = waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(timeout), nodes == null?opensearchNodes.size():nodes.intValue()); + ClusterInfo cInfo = waitForCluster( + ClusterHealthStatus.GREEN, + TimeValue.timeValueSeconds(timeout), + nodes == null ? opensearchNodes.size() : nodes.intValue() + ); cInfo.numNodes = internalNodeSettings.size(); cInfo.clustername = clustername; - cInfo.tcpClusterManagerPortsOnly = tcpClusterManagerPortsOnly.stream().map(s->"127.0.0.1:"+s).collect(Collectors.toList()); - - final String defaultTemplate = "{\n" + - " \"index_patterns\": [\"*\"],\n" + - " \"order\": -1,\n" + - " \"settings\": {\n" + - " \"number_of_shards\": \"5\",\n" + - " \"number_of_replicas\": \"1\"\n" + - " }\n" + - " }"; - - final AcknowledgedResponse templateAck = nodeClient().admin().indices().putTemplate(new PutIndexTemplateRequest("default").source(defaultTemplate, XContentType.JSON)).actionGet(); - - if(!templateAck.isAcknowledged()) { + cInfo.tcpClusterManagerPortsOnly = tcpClusterManagerPortsOnly.stream().map(s -> "127.0.0.1:" + s).collect(Collectors.toList()); + + final String defaultTemplate = "{\n" + + " \"index_patterns\": [\"*\"],\n" + + " \"order\": -1,\n" + + " \"settings\": {\n" + + " \"number_of_shards\": \"5\",\n" + + " \"number_of_replicas\": \"1\"\n" + + " }\n" + + " }"; + + final AcknowledgedResponse templateAck = nodeClient().admin() + .indices() + .putTemplate(new PutIndexTemplateRequest("default").source(defaultTemplate, XContentType.JSON)) + .actionGet(); + + if (!templateAck.isAcknowledged()) { throw new RuntimeException("Default template could not be created"); } @@ -269,15 +310,15 @@ public void run() { public final void stopCluster() throws Exception { closeAllNodes(); - FileUtils.deleteDirectory(new File("./target/data/"+clustername)); + FileUtils.deleteDirectory(new File("./target/data/" + clustername)); } - private void closeAllNodes() throws Exception { - //close non cluster manager nodes - opensearchNodes.stream().filter(n->!n.isClusterManagerEligible()).forEach(ClusterHelper::closeNode); + private void closeAllNodes() throws Exception { + // close non cluster manager nodes + opensearchNodes.stream().filter(n -> !n.isClusterManagerEligible()).forEach(ClusterHelper::closeNode); - //close cluster manager nodes - opensearchNodes.stream().filter(n->n.isClusterManagerEligible()).forEach(ClusterHelper::closeNode); + // close cluster manager nodes + opensearchNodes.stream().filter(n -> n.isClusterManagerEligible()).forEach(ClusterHelper::closeNode); opensearchNodes.clear(); clusterState = ClusterState.STOPPED; } @@ -287,16 +328,16 @@ private static void closeNode(Node node) { node.close(); node.awaitClose(250, TimeUnit.MILLISECONDS); } catch (Throwable e) { - //ignore + // ignore } } - public Client nodeClient() { return opensearchNodes.get(0).client(); } - public ClusterInfo waitForCluster(final ClusterHealthStatus status, final TimeValue timeout, final int expectedNodeCount) throws IOException { + public ClusterInfo waitForCluster(final ClusterHealthStatus status, final TimeValue timeout, final int expectedNodeCount) + throws IOException { if (opensearchNodes.isEmpty()) { throw new RuntimeException("List of nodes was empty."); } @@ -307,12 +348,19 @@ public ClusterInfo waitForCluster(final ClusterHealthStatus status, final TimeVa Client client = node.client(); try { log.debug("waiting for cluster state {} and {} nodes", status.name(), expectedNodeCount); - final ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth() - .setWaitForStatus(status).setTimeout(timeout).setClusterManagerNodeTimeout(timeout).setWaitForNodes("" + expectedNodeCount).execute() - .actionGet(); + final ClusterHealthResponse healthResponse = client.admin() + .cluster() + .prepareHealth() + .setWaitForStatus(status) + .setTimeout(timeout) + .setClusterManagerNodeTimeout(timeout) + .setWaitForNodes("" + expectedNodeCount) + .execute() + .actionGet(); if (healthResponse.isTimedOut()) { - throw new IOException("cluster state is " + healthResponse.getStatus().name() + " with " - + healthResponse.getNumberOfNodes() + " nodes"); + throw new IOException( + "cluster state is " + healthResponse.getStatus().name() + " with " + healthResponse.getNumberOfNodes() + " nodes" + ); } else { log.debug("... cluster state ok {} with {} nodes", healthResponse.getStatus().name(), healthResponse.getNumberOfNodes()); } @@ -323,21 +371,32 @@ public ClusterInfo waitForCluster(final ClusterHealthStatus status, final TimeVa final List nodes = res.getNodes(); - final List clusterManagerNodes = nodes.stream().filter(n->n.getNode().getRoles().contains(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE)).collect(Collectors.toList()); - final List dataNodes = nodes.stream().filter(n->n.getNode().getRoles().contains(DiscoveryNodeRole.DATA_ROLE) && !n.getNode().getRoles().contains(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE)).collect(Collectors.toList()); + final List clusterManagerNodes = nodes.stream() + .filter(n -> n.getNode().getRoles().contains(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE)) + .collect(Collectors.toList()); + final List dataNodes = nodes.stream() + .filter( + n -> n.getNode().getRoles().contains(DiscoveryNodeRole.DATA_ROLE) + && !n.getNode().getRoles().contains(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE) + ) + .collect(Collectors.toList()); // Sorting the nodes so that the node receiving the http requests is always deterministic dataNodes.sort(Comparator.comparing(nodeInfo -> nodeInfo.getNode().getName())); - final List clientNodes = nodes.stream().filter(n->!n.getNode().getRoles().contains(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE) && !n.getNode().getRoles().contains(DiscoveryNodeRole.DATA_ROLE)).collect(Collectors.toList()); - - - for (NodeInfo nodeInfo: clusterManagerNodes) { + final List clientNodes = nodes.stream() + .filter( + n -> !n.getNode().getRoles().contains(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE) + && !n.getNode().getRoles().contains(DiscoveryNodeRole.DATA_ROLE) + ) + .collect(Collectors.toList()); + + for (NodeInfo nodeInfo : clusterManagerNodes) { final TransportInfo transportInfo = nodeInfo.getInfo(TransportInfo.class); final TransportAddress transportAddress = transportInfo.getAddress().publishAddress(); clusterInfo.nodePort = transportAddress.getPort(); clusterInfo.nodeHost = transportAddress.getAddress(); } - if(!clientNodes.isEmpty()) { + if (!clientNodes.isEmpty()) { NodeInfo nodeInfo = clientNodes.get(0); final HttpInfo httpInfo = nodeInfo.getInfo(HttpInfo.class); if (httpInfo != null && httpInfo.address() != null) { @@ -348,9 +407,9 @@ public ClusterInfo waitForCluster(final ClusterHealthStatus status, final TimeVa } else { throw new RuntimeException("no http host/port for client node"); } - } else if(!dataNodes.isEmpty()) { + } else if (!dataNodes.isEmpty()) { - for (NodeInfo nodeInfo: dataNodes) { + for (NodeInfo nodeInfo : dataNodes) { final HttpInfo httpInfo = nodeInfo.getInfo(HttpInfo.class); if (httpInfo != null && httpInfo.address() != null) { final TransportAddress transportAddress = httpInfo.address().publishAddress(); @@ -360,9 +419,9 @@ public ClusterInfo waitForCluster(final ClusterHealthStatus status, final TimeVa break; } } - } else { + } else { - for (NodeInfo nodeInfo: nodes) { + for (NodeInfo nodeInfo : nodes) { final HttpInfo httpInfo = nodeInfo.getInfo(HttpInfo.class); if (httpInfo != null && httpInfo.address() != null) { final TransportAddress transportAddress = httpInfo.address().publishAddress(); @@ -374,32 +433,41 @@ public ClusterInfo waitForCluster(final ClusterHealthStatus status, final TimeVa } } } catch (final OpenSearchTimeoutException e) { - throw new IOException( - "timeout, cluster does not respond to health request, cowardly refusing to continue with operations"); + throw new IOException("timeout, cluster does not respond to health request, cowardly refusing to continue with operations"); } return clusterInfo; } // @formatter:off - private Settings.Builder getMinimumNonSecurityNodeSettingsBuilder(final int nodenum, final boolean isClusterManagerNode, - final boolean isDataNode, int nodeCount, SortedSet clusterManagerTcpPorts, int tcpPort, int httpPort) { + private Settings.Builder getMinimumNonSecurityNodeSettingsBuilder( + final int nodenum, + final boolean isClusterManagerNode, + final boolean isDataNode, + int nodeCount, + SortedSet clusterManagerTcpPorts, + int tcpPort, + int httpPort + ) { return AbstractSecurityUnitTest.nodeRolesSettings(Settings.builder(), isClusterManagerNode, isDataNode) - .put("node.name", "node_"+clustername+ "_num" + nodenum) - .put("cluster.name", clustername) - .put("path.data", "./target/data/"+clustername+"/data") - .put("path.logs", "./target/data/"+clustername+"/logs") - .put("node.max_local_storage_nodes", nodeCount) - .putList("cluster.initial_cluster_manager_nodes", clusterManagerTcpPorts.stream().map(s->"127.0.0.1:"+s).collect(Collectors.toList())) - .put("discovery.initial_state_timeout","8s") - .putList("discovery.seed_hosts", clusterManagerTcpPorts.stream().map(s->"127.0.0.1:"+s).collect(Collectors.toList())) - .put("transport.tcp.port", tcpPort) - .put("http.port", httpPort) - .put("http.cors.enabled", true) - .put("path.home", "./target"); + .put("node.name", "node_" + clustername + "_num" + nodenum) + .put("cluster.name", clustername) + .put("path.data", "./target/data/" + clustername + "/data") + .put("path.logs", "./target/data/" + clustername + "/logs") + .put("node.max_local_storage_nodes", nodeCount) + .putList( + "cluster.initial_cluster_manager_nodes", + clusterManagerTcpPorts.stream().map(s -> "127.0.0.1:" + s).collect(Collectors.toList()) + ) + .put("discovery.initial_state_timeout", "8s") + .putList("discovery.seed_hosts", clusterManagerTcpPorts.stream().map(s -> "127.0.0.1:" + s).collect(Collectors.toList())) + .put("transport.tcp.port", tcpPort) + .put("http.port", httpPort) + .put("http.cors.enabled", true) + .put("path.home", "./target"); } - private enum ClusterState{ + private enum ClusterState { UNINITIALIZED, STARTED, STOPPED diff --git a/src/test/java/org/opensearch/security/test/helper/cluster/ClusterInfo.java b/src/test/java/org/opensearch/security/test/helper/cluster/ClusterInfo.java index bb59450752..d50274e0e0 100644 --- a/src/test/java/org/opensearch/security/test/helper/cluster/ClusterInfo.java +++ b/src/test/java/org/opensearch/security/test/helper/cluster/ClusterInfo.java @@ -33,12 +33,12 @@ import org.opensearch.common.transport.TransportAddress; public class ClusterInfo { - public int numNodes; - public String httpHost = null; - public int httpPort = -1; - public Set httpAdresses = new HashSet(); - public String nodeHost; - public int nodePort; - public String clustername; + public int numNodes; + public String httpHost = null; + public int httpPort = -1; + public Set httpAdresses = new HashSet(); + public String nodeHost; + public int nodePort; + public String clustername; public List tcpClusterManagerPortsOnly; } diff --git a/src/test/java/org/opensearch/security/test/helper/file/FileHelper.java b/src/test/java/org/opensearch/security/test/helper/file/FileHelper.java index 6aadd2acbb..acb4a7d217 100644 --- a/src/test/java/org/opensearch/security/test/helper/file/FileHelper.java +++ b/src/test/java/org/opensearch/security/test/helper/file/FileHelper.java @@ -57,90 +57,90 @@ public class FileHelper { - protected final static Logger log = LogManager.getLogger(FileHelper.class); - - public static KeyStore getKeystoreFromClassPath(final String fileNameFromClasspath, String password) throws Exception { - Path path = getAbsoluteFilePathFromClassPath(fileNameFromClasspath); - if(path==null) { - return null; - } - - KeyStore ks = KeyStore.getInstance("JKS"); - try (FileInputStream fin = new FileInputStream(path.toFile())) { - ks.load(fin, password==null||password.isEmpty()?null:password.toCharArray()); - } - return ks; - } - - public static Path getAbsoluteFilePathFromClassPath(final String fileNameFromClasspath) { - File file = null; - final URL fileUrl = FileHelper.class.getClassLoader().getResource(fileNameFromClasspath); - if (fileUrl != null) { - try { - file = new File(URLDecoder.decode(fileUrl.getFile(), "UTF-8")); - } catch (final UnsupportedEncodingException e) { - return null; - } - - if (file.exists() && file.canRead()) { - return Paths.get(file.getAbsolutePath()); - } else { - log.error("Cannot read from {}, maybe the file does not exists? ", file.getAbsolutePath()); - } - - } else { - log.error("Failed to load {}", fileNameFromClasspath); - } - return null; - } - - public static final String loadFile(final String file) throws IOException { - final StringWriter sw = new StringWriter(); - IOUtils.copy(FileHelper.class.getResourceAsStream("/" + file), sw, StandardCharsets.UTF_8); - return sw.toString(); - } - + protected final static Logger log = LogManager.getLogger(FileHelper.class); + + public static KeyStore getKeystoreFromClassPath(final String fileNameFromClasspath, String password) throws Exception { + Path path = getAbsoluteFilePathFromClassPath(fileNameFromClasspath); + if (path == null) { + return null; + } + + KeyStore ks = KeyStore.getInstance("JKS"); + try (FileInputStream fin = new FileInputStream(path.toFile())) { + ks.load(fin, password == null || password.isEmpty() ? null : password.toCharArray()); + } + return ks; + } + + public static Path getAbsoluteFilePathFromClassPath(final String fileNameFromClasspath) { + File file = null; + final URL fileUrl = FileHelper.class.getClassLoader().getResource(fileNameFromClasspath); + if (fileUrl != null) { + try { + file = new File(URLDecoder.decode(fileUrl.getFile(), "UTF-8")); + } catch (final UnsupportedEncodingException e) { + return null; + } + + if (file.exists() && file.canRead()) { + return Paths.get(file.getAbsolutePath()); + } else { + log.error("Cannot read from {}, maybe the file does not exists? ", file.getAbsolutePath()); + } + + } else { + log.error("Failed to load {}", fileNameFromClasspath); + } + return null; + } + + public static final String loadFile(final String file) throws IOException { + final StringWriter sw = new StringWriter(); + IOUtils.copy(FileHelper.class.getResourceAsStream("/" + file), sw, StandardCharsets.UTF_8); + return sw.toString(); + } + public static BytesReference readYamlContent(final String file) { - + XContentParser parser = null; try { - parser = XContentFactory.xContent(XContentType.YAML).createParser(NamedXContentRegistry.EMPTY, THROW_UNSUPPORTED_OPERATION, new StringReader(loadFile(file))); + parser = XContentFactory.xContent(XContentType.YAML) + .createParser(NamedXContentRegistry.EMPTY, THROW_UNSUPPORTED_OPERATION, new StringReader(loadFile(file))); parser.nextToken(); final XContentBuilder builder = XContentFactory.jsonBuilder(); builder.copyCurrentStructure(parser); return BytesReference.bytes(builder); } catch (Exception e) { throw new RuntimeException(e); - } - finally { + } finally { if (parser != null) { try { parser.close(); } catch (IOException e) { - //ignore + // ignore } } } - } - + } + public static BytesReference readYamlContentFromString(final String yaml) { - + XContentParser parser = null; try { - parser = XContentFactory.xContent(XContentType.YAML).createParser(NamedXContentRegistry.EMPTY, THROW_UNSUPPORTED_OPERATION, new StringReader(yaml)); + parser = XContentFactory.xContent(XContentType.YAML) + .createParser(NamedXContentRegistry.EMPTY, THROW_UNSUPPORTED_OPERATION, new StringReader(yaml)); parser.nextToken(); final XContentBuilder builder = XContentFactory.jsonBuilder(); builder.copyCurrentStructure(parser); return BytesReference.bytes(builder); } catch (Exception e) { throw new RuntimeException(e); - } - finally { + } finally { if (parser != null) { try { parser.close(); } catch (IOException e) { - //ignore + // ignore } } } diff --git a/src/test/java/org/opensearch/security/test/helper/network/SocketUtils.java b/src/test/java/org/opensearch/security/test/helper/network/SocketUtils.java index 1d264025e0..b9f014960c 100644 --- a/src/test/java/org/opensearch/security/test/helper/network/SocketUtils.java +++ b/src/test/java/org/opensearch/security/test/helper/network/SocketUtils.java @@ -79,10 +79,8 @@ public class SocketUtils { */ public static final int PORT_RANGE_MAX = 65535; - private static final Random random = new Random(System.currentTimeMillis()); - /** * Although {@code SocketUtils} consists solely of static utility methods, * this constructor is intentionally {@code public}. @@ -103,7 +101,6 @@ public SocketUtils() { /* no-op */ } - /** * Find an available TCP port randomly selected from the range * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. @@ -218,19 +215,17 @@ public static SortedSet findAvailableUdpPorts(int numRequested, int min return SocketType.UDP.findAvailablePorts(numRequested, minPort, maxPort); } - private enum SocketType { TCP { @Override protected boolean isPortAvailable(int port) { try { - ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket( - port, 1, InetAddress.getByName("localhost")); + ServerSocket serverSocket = ServerSocketFactory.getDefault() + .createServerSocket(port, 1, InetAddress.getByName("localhost")); serverSocket.close(); return true; - } - catch (Exception ex) { + } catch (Exception ex) { return false; } } @@ -243,8 +238,7 @@ protected boolean isPortAvailable(int port) { DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost")); socket.close(); return true; - } - catch (Exception ex) { + } catch (Exception ex) { return false; } } @@ -277,23 +271,28 @@ private int findRandomPort(int minPort, int maxPort) { * @throws IllegalStateException if no available port could be found */ int findAvailablePort(int minPort, int maxPort) { - //Assert.assertTrue(minPort > 0, "'minPort' must be greater than 0"); - //Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equal to 'minPort'"); - //Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); + // Assert.assertTrue(minPort > 0, "'minPort' must be greater than 0"); + // Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equal to 'minPort'"); + // Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); int portRange = maxPort - minPort; int candidatePort; int searchCounter = 0; do { if (searchCounter > portRange) { - throw new IllegalStateException(String.format( + throw new IllegalStateException( + String.format( "Could not find an available %s port in the range [%d, %d] after %d attempts", - name(), minPort, maxPort, searchCounter)); + name(), + minPort, + maxPort, + searchCounter + ) + ); } candidatePort = findRandomPort(minPort, maxPort); searchCounter++; - } - while (!isPortAvailable(candidatePort)); + } while (!isPortAvailable(candidatePort)); return candidatePort; } @@ -308,12 +307,12 @@ int findAvailablePort(int minPort, int maxPort) { * @throws IllegalStateException if the requested number of available ports could not be found */ SortedSet findAvailablePorts(int numRequested, int minPort, int maxPort) { - //Assert.isTrue(minPort > 0, "'minPort' must be greater than 0"); - //Assert.isTrue(maxPort > minPort, "'maxPort' must be greater than 'minPort'"); - //Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); - //Assert.isTrue(numRequested > 0, "'numRequested' must be greater than 0"); - //Assert.isTrue((maxPort - minPort) >= numRequested, - // "'numRequested' must not be greater than 'maxPort' - 'minPort'"); + // Assert.isTrue(minPort > 0, "'minPort' must be greater than 0"); + // Assert.isTrue(maxPort > minPort, "'maxPort' must be greater than 'minPort'"); + // Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); + // Assert.isTrue(numRequested > 0, "'numRequested' must be greater than 0"); + // Assert.isTrue((maxPort - minPort) >= numRequested, + // "'numRequested' must not be greater than 'maxPort' - 'minPort'"); SortedSet availablePorts = new TreeSet<>(); int attemptCount = 0; @@ -322,9 +321,9 @@ SortedSet findAvailablePorts(int numRequested, int minPort, int maxPort } if (availablePorts.size() != numRequested) { - throw new IllegalStateException(String.format( - "Could not find %d available %s ports in the range [%d, %d]", - numRequested, name(), minPort, maxPort)); + throw new IllegalStateException( + String.format("Could not find %d available %s ports in the range [%d, %d]", numRequested, name(), minPort, maxPort) + ); } return availablePorts; diff --git a/src/test/java/org/opensearch/security/test/helper/rest/RestHelper.java b/src/test/java/org/opensearch/security/test/helper/rest/RestHelper.java index 367332f160..730a22f18f 100644 --- a/src/test/java/org/opensearch/security/test/helper/rest/RestHelper.java +++ b/src/test/java/org/opensearch/security/test/helper/rest/RestHelper.java @@ -94,450 +94,479 @@ public class RestHelper { - protected final Logger log = LogManager.getLogger(RestHelper.class); - - public boolean enableHTTPClientSSL = true; - public boolean enableHTTPClientSSLv3Only = false; - public boolean sendAdminCertificate = false; - public boolean trustHTTPServerCertificate = true; - public boolean sendHTTPClientCredentials = false; - public String keystore = "node-0-keystore.jks"; - public final String prefix; - //public String truststore = "truststore.jks"; - private ClusterInfo clusterInfo; - - public RestHelper(ClusterInfo clusterInfo, String prefix) { - this.clusterInfo = clusterInfo; - this.prefix = prefix; - } - - public RestHelper(ClusterInfo clusterInfo, boolean enableHTTPClientSSL, boolean trustHTTPServerCertificate, String prefix) { - this.clusterInfo = clusterInfo; - this.enableHTTPClientSSL = enableHTTPClientSSL; - this.trustHTTPServerCertificate = trustHTTPServerCertificate; - this.prefix = prefix; - } - public String executeSimpleRequest(final String request) throws Exception { - - CloseableHttpAsyncClient httpClient = null; - - try { - httpClient = getHTTPClient(); - httpClient.start(); - - final CompletableFuture future = new CompletableFuture<>(); - final SimpleHttpRequest simpleRequest = SimpleRequestBuilder.copy(new HttpGet(getRequestUri(request))).build(); - httpClient.execute(simpleRequest, new FutureCallback() { - @Override - public void completed(SimpleHttpResponse result) { - future.complete(result); - } - - @Override - public void failed(Exception ex) { - future.completeExceptionally(ex); - } - - @Override - public void cancelled() { - future.cancel(true); - } - }); - - final SimpleHttpResponse response = future.join(); - if (response.getCode() >= 300) { - throw new Exception("Statuscode " + response.getCode()); - } - - if (enableHTTPClientSSL && !response.getVersion().equals(HttpVersion.HTTP_2)) { - throw new IllegalStateException("HTTP/2 expected for HTTPS communication but " + response.getVersion() + " was used"); - } - - return response.getBodyText(); - } catch (final CompletionException e) { - final Throwable cause = e.getCause(); - // Make it compatible with DefaultHttpResponseParser::createConnectionClosedException() - if (cause instanceof ConnectionClosedException) { - throw new NoHttpResponseException(cause.getMessage(), cause); - } else { - throw (Exception)cause; - } - } finally { - if (httpClient != null) { - httpClient.close(); - } - } - } - - public HttpResponse[] executeMultipleAsyncPutRequest(final int numOfRequests, final String request, String body) throws Exception { - final ExecutorService executorService = Executors.newFixedThreadPool(numOfRequests); - Future[] futures = new Future[numOfRequests]; - for (int i = 0; i < numOfRequests; i++) { - futures[i] = executorService.submit(() -> executePutRequest(request, body, new Header[0])); - } - executorService.shutdown(); - return Arrays.stream(futures) - .map(HttpResponse::from) - .toArray(s -> new HttpResponse[s]); - } - - public HttpResponse executeGetRequest(final String request, Header... header) { - return executeRequest(new HttpGet(getRequestUri(request)), header); - } - - public HttpResponse executeGetRequest(final String request, String body, Header... header) { - HttpGet getRequest = new HttpGet(getRequestUri(request)); - getRequest.setEntity(createStringEntity(body)); - getRequest.addHeader(HttpHeaders.CONTENT_TYPE, "application/json"); - return executeRequest(getRequest, header); - } - - public HttpResponse executeHeadRequest(final String request, Header... header) { - return executeRequest(new HttpHead(getRequestUri(request)), header); - } - - public HttpResponse executeOptionsRequest(final String request) { - return executeRequest(new HttpOptions(getRequestUri(request))); - } - - public HttpResponse executePutRequest(final String request, String body, Header... header) { - HttpPut uriRequest = new HttpPut(getRequestUri(request)); - if (body != null && !body.isEmpty()) { - uriRequest.setEntity(createStringEntity(body)); - } - return executeRequest(uriRequest, header); - } - - public HttpResponse executeDeleteRequest(final String request, Header... header) { - return executeRequest(new HttpDelete(getRequestUri(request)), header); - } - - public HttpResponse executeDeleteRequest(final String request, String body, Header... header) { - HttpDelete delRequest = new HttpDelete(getRequestUri(request)); - delRequest.setEntity(createStringEntity(body)); - delRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); - return executeRequest(delRequest, header); - } - - - public HttpResponse executePostRequest(final String request, String body, Header... header) { - HttpPost uriRequest = new HttpPost(getRequestUri(request)); - if (body != null && !body.isEmpty()) { - uriRequest.setEntity(createStringEntity(body)); - } - - return executeRequest(uriRequest, header); - } - - public HttpResponse executePatchRequest(final String request, String body, Header... header) { - HttpPatch uriRequest = new HttpPatch(getRequestUri(request)); - if (body != null && !body.isEmpty()) { - uriRequest.setEntity(createStringEntity(body)); - } - return executeRequest(uriRequest, header); - } - - public HttpResponse executeRequest(HttpUriRequest uriRequest, Header... header) { - - CloseableHttpAsyncClient httpClient = null; - try { - - httpClient = getHTTPClient(); - httpClient.start(); - - if (header != null && header.length > 0) { - for (int i = 0; i < header.length; i++) { - Header h = header[i]; - uriRequest.addHeader(h); - } - } - - if (!uriRequest.containsHeader("Content-Type")) { - uriRequest.addHeader("Content-Type","application/json"); - } - - final CompletableFuture future = new CompletableFuture<>(); - final SimpleHttpRequest simpleRequest = SimpleRequestBuilder.copy(uriRequest).build(); - if (uriRequest.getEntity() != null) { - simpleRequest.setBody(EntityUtils.toByteArray(uriRequest.getEntity()), - ContentType.parse(uriRequest.getEntity().getContentType())); - } - httpClient.execute(simpleRequest, new FutureCallback() { - @Override - public void completed(SimpleHttpResponse result) { - future.complete(result); - } - - @Override - public void failed(Exception ex) { - future.completeExceptionally(ex); - } - - @Override - public void cancelled() { - future.cancel(true); - } - }); - - final HttpResponse res = new HttpResponse(future.join()); - if (enableHTTPClientSSL && !res.getProtocolVersion().equals(HttpVersion.HTTP_2)) { - throw new IllegalStateException("HTTP/2 expected for HTTPS communication but " + res.getProtocolVersion() + " was used"); - } - - log.debug(res.getBody()); - return res; - } catch (final CompletionException e) { - final Throwable cause = e.getCause(); - // Make it compatible with DefaultHttpResponseParser::createConnectionClosedException() - if (cause instanceof ConnectionClosedException) { - throw new RuntimeException(new NoHttpResponseException(cause.getMessage(), cause)); - } else if (cause instanceof RuntimeException) { - throw (RuntimeException)cause; - } else { - throw new RuntimeException(cause); - } - } catch (final Exception e) { - throw new RuntimeException(e); - } finally { - - if (httpClient != null) { - try { - httpClient.close(); - } catch (final Exception e) { - throw new RuntimeException(e); - } - } - } - } - - private HttpEntity createStringEntity(String body) { - return new StringEntity(body); - } - - protected final String getHttpServerUri() { - final String address = "http" + (enableHTTPClientSSL ? "s" : "") + "://" + clusterInfo.httpHost + ":" + clusterInfo.httpPort; - log.debug("Connect to {}", address); - return address; - } - - protected final String getRequestUri(String request) { - return getHttpServerUri() + "/" + StringUtils.strip(request, "/"); - } - - protected final CloseableHttpAsyncClient getHTTPClient() throws Exception { - - final HttpAsyncClientBuilder hcb = HttpAsyncClients.custom(); - - if (sendHTTPClientCredentials) { - UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("sarek", "sarek".toCharArray()); - BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(null, -1), credentials); - hcb.setDefaultCredentialsProvider(credentialsProvider); - } - - if (enableHTTPClientSSL) { - - log.debug("Configure HTTP client with SSL"); - - if(prefix != null && !keystore.contains("/")) { - keystore = prefix+"/"+keystore; - } - - final String keyStorePath = FileHelper.getAbsoluteFilePathFromClassPath(keystore).toFile().getParent(); - - final KeyStore myTrustStore = KeyStore.getInstance("JKS"); - myTrustStore.load(new FileInputStream(keyStorePath+"/truststore.jks"), - "changeit".toCharArray()); - - final KeyStore keyStore = KeyStore.getInstance("JKS"); - keyStore.load(new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath(keystore).toFile()), "changeit".toCharArray()); - - final SSLContextBuilder sslContextbBuilder = SSLContexts.custom(); - - if (trustHTTPServerCertificate) { - sslContextbBuilder.loadTrustMaterial(myTrustStore, null); - } - - if (sendAdminCertificate) { - sslContextbBuilder.loadKeyMaterial(keyStore, "changeit".toCharArray()); - } - - final SSLContext sslContext = sslContextbBuilder.build(); - - String[] protocols = null; - - if (enableHTTPClientSSLv3Only) { - protocols = new String[] { "SSLv3" }; - } else { - protocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" }; - } - - final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder - .create() - .setSslContext(sslContext) - .setTlsVersions(protocols) - .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) - // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 - .setTlsDetailsFactory(new Factory() { - @Override - public TlsDetails create(final SSLEngine sslEngine) { - return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); - } - }) - .build(); - - final AsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(tlsStrategy) - .build(); - - hcb.setConnectionManager(cm); - } - - final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom() - .setResponseTimeout(Timeout.ofSeconds(60)); - - return hcb.setDefaultRequestConfig(requestConfigBuilder.build()).disableAutomaticRetries().build(); - } - - - public static class HttpResponse { - private final SimpleHttpResponse inner; - private final String body; - private final Header[] header; - private final int statusCode; - private final String statusReason; - private final ProtocolVersion protocolVersion; - - public HttpResponse(SimpleHttpResponse inner) throws IllegalStateException, IOException { - super(); - this.inner = inner; - if(inner.getBody() == null) { //head request does not have a entity - this.body = ""; - } else { - this.body = inner.getBodyText(); - } - this.header = inner.getHeaders(); - this.statusCode = inner.getCode(); - this.statusReason = inner.getReasonPhrase(); - this.protocolVersion = inner.getVersion(); - } - - public String getContentType() { - Header h = getInner().getFirstHeader("content-type"); - if(h!= null) { - return h.getValue(); - } - return null; - } - - public boolean isJsonContentType() { - String ct = getContentType(); - if(ct == null) { - return false; - } - return ct.contains("application/json"); - } - - public SimpleHttpResponse getInner() { - return inner; - } - - public String getBody() { - return body; - } - - public Header[] getHeader() { - return header; - } - - public int getStatusCode() { - return statusCode; - } - - public String getStatusReason() { - return statusReason; - } - - public List
getHeaders() { - return header==null?Collections.emptyList():Arrays.asList(header); - } - - public ProtocolVersion getProtocolVersion() { - return protocolVersion; - } - - @Override - public String toString() { - return "HttpResponse [inner=" + inner + ", body=" + body + ", header=" + Arrays.toString(header) + ", statusCode=" + statusCode - + ", statusReason=" + statusReason + "]"; - } - - /** - * Given a json path with dots delimiated returns the object at the leaf - */ - public String findValueInJson(final String jsonDotPath) { - // Make sure its json / then parse it - if (!isJsonContentType()) { - throw new RuntimeException("Response was expected to be JSON, body was: \n" + body); - } - JsonNode currentNode = null; - try { - currentNode = DefaultObjectMapper.readTree(body); - } catch (final Exception e) { - throw new RuntimeException(e); - } - - // Break the path into parts, and scan into the json object - try (final Scanner jsonPathScanner = new Scanner(jsonDotPath).useDelimiter("\\.")) { - if (!jsonPathScanner.hasNext()) { - throw new RuntimeException("Invalid json dot path '" + jsonDotPath + "', rewrite with '.' characters between path elements."); - } - do { - String pathEntry = jsonPathScanner.next(); - // if pathEntry is an array lookup - int arrayEntryIdx = -1; - - // Looks for an array-lookup pattern in the path - // e.g. root_cause[1] -> will match - // e.g. root_cause[2aasd] -> won't match - final Pattern r = Pattern.compile("(.+?)\\[(\\d+)\\]"); - final Matcher m = r.matcher(pathEntry); - if(m.find()) { - pathEntry = m.group(1); - arrayEntryIdx = Integer.parseInt(m.group(2)); - } - - if (!currentNode.has(pathEntry)) { - throw new RuntimeException("Unable to resolve '" + jsonDotPath + "', on path entry '" + pathEntry + "' from available fields " + currentNode.toPrettyString()); - } - currentNode = currentNode.get(pathEntry); - - // if it's an Array lookup we get the requested index item - if (arrayEntryIdx > -1) { - if(!currentNode.isArray()) { - throw new RuntimeException("Unable to resolve '" + jsonDotPath + "', the '" + pathEntry + "' field is not an array " + currentNode.toPrettyString()); - } else if (!currentNode.has(arrayEntryIdx)) { - throw new RuntimeException("Unable to resolve '" + jsonDotPath + "', index '" + arrayEntryIdx + "' is out of bounds for array '" + pathEntry + "' \n" + currentNode.toPrettyString()); - } - currentNode = currentNode.get(arrayEntryIdx); - } - } while (jsonPathScanner.hasNext()); - - if (!currentNode.isValueNode()) { - throw new RuntimeException("Unexpected value note, index directly to the object to reference, object\n" + currentNode.toPrettyString()); - } - return currentNode.asText(); - } - } - - private static HttpResponse from(Future future) { - try { - return future.get(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - + protected final Logger log = LogManager.getLogger(RestHelper.class); + + public boolean enableHTTPClientSSL = true; + public boolean enableHTTPClientSSLv3Only = false; + public boolean sendAdminCertificate = false; + public boolean trustHTTPServerCertificate = true; + public boolean sendHTTPClientCredentials = false; + public String keystore = "node-0-keystore.jks"; + public final String prefix; + // public String truststore = "truststore.jks"; + private ClusterInfo clusterInfo; + + public RestHelper(ClusterInfo clusterInfo, String prefix) { + this.clusterInfo = clusterInfo; + this.prefix = prefix; + } + + public RestHelper(ClusterInfo clusterInfo, boolean enableHTTPClientSSL, boolean trustHTTPServerCertificate, String prefix) { + this.clusterInfo = clusterInfo; + this.enableHTTPClientSSL = enableHTTPClientSSL; + this.trustHTTPServerCertificate = trustHTTPServerCertificate; + this.prefix = prefix; + } + + public String executeSimpleRequest(final String request) throws Exception { + + CloseableHttpAsyncClient httpClient = null; + + try { + httpClient = getHTTPClient(); + httpClient.start(); + + final CompletableFuture future = new CompletableFuture<>(); + final SimpleHttpRequest simpleRequest = SimpleRequestBuilder.copy(new HttpGet(getRequestUri(request))).build(); + httpClient.execute(simpleRequest, new FutureCallback() { + @Override + public void completed(SimpleHttpResponse result) { + future.complete(result); + } + + @Override + public void failed(Exception ex) { + future.completeExceptionally(ex); + } + + @Override + public void cancelled() { + future.cancel(true); + } + }); + + final SimpleHttpResponse response = future.join(); + if (response.getCode() >= 300) { + throw new Exception("Statuscode " + response.getCode()); + } + + if (enableHTTPClientSSL && !response.getVersion().equals(HttpVersion.HTTP_2)) { + throw new IllegalStateException("HTTP/2 expected for HTTPS communication but " + response.getVersion() + " was used"); + } + + return response.getBodyText(); + } catch (final CompletionException e) { + final Throwable cause = e.getCause(); + // Make it compatible with DefaultHttpResponseParser::createConnectionClosedException() + if (cause instanceof ConnectionClosedException) { + throw new NoHttpResponseException(cause.getMessage(), cause); + } else { + throw (Exception) cause; + } + } finally { + if (httpClient != null) { + httpClient.close(); + } + } + } + + public HttpResponse[] executeMultipleAsyncPutRequest(final int numOfRequests, final String request, String body) throws Exception { + final ExecutorService executorService = Executors.newFixedThreadPool(numOfRequests); + Future[] futures = new Future[numOfRequests]; + for (int i = 0; i < numOfRequests; i++) { + futures[i] = executorService.submit(() -> executePutRequest(request, body, new Header[0])); + } + executorService.shutdown(); + return Arrays.stream(futures).map(HttpResponse::from).toArray(s -> new HttpResponse[s]); + } + + public HttpResponse executeGetRequest(final String request, Header... header) { + return executeRequest(new HttpGet(getRequestUri(request)), header); + } + + public HttpResponse executeGetRequest(final String request, String body, Header... header) { + HttpGet getRequest = new HttpGet(getRequestUri(request)); + getRequest.setEntity(createStringEntity(body)); + getRequest.addHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + return executeRequest(getRequest, header); + } + + public HttpResponse executeHeadRequest(final String request, Header... header) { + return executeRequest(new HttpHead(getRequestUri(request)), header); + } + + public HttpResponse executeOptionsRequest(final String request) { + return executeRequest(new HttpOptions(getRequestUri(request))); + } + + public HttpResponse executePutRequest(final String request, String body, Header... header) { + HttpPut uriRequest = new HttpPut(getRequestUri(request)); + if (body != null && !body.isEmpty()) { + uriRequest.setEntity(createStringEntity(body)); + } + return executeRequest(uriRequest, header); + } + + public HttpResponse executeDeleteRequest(final String request, Header... header) { + return executeRequest(new HttpDelete(getRequestUri(request)), header); + } + + public HttpResponse executeDeleteRequest(final String request, String body, Header... header) { + HttpDelete delRequest = new HttpDelete(getRequestUri(request)); + delRequest.setEntity(createStringEntity(body)); + delRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + return executeRequest(delRequest, header); + } + + public HttpResponse executePostRequest(final String request, String body, Header... header) { + HttpPost uriRequest = new HttpPost(getRequestUri(request)); + if (body != null && !body.isEmpty()) { + uriRequest.setEntity(createStringEntity(body)); + } + + return executeRequest(uriRequest, header); + } + + public HttpResponse executePatchRequest(final String request, String body, Header... header) { + HttpPatch uriRequest = new HttpPatch(getRequestUri(request)); + if (body != null && !body.isEmpty()) { + uriRequest.setEntity(createStringEntity(body)); + } + return executeRequest(uriRequest, header); + } + + public HttpResponse executeRequest(HttpUriRequest uriRequest, Header... header) { + + CloseableHttpAsyncClient httpClient = null; + try { + + httpClient = getHTTPClient(); + httpClient.start(); + + if (header != null && header.length > 0) { + for (int i = 0; i < header.length; i++) { + Header h = header[i]; + uriRequest.addHeader(h); + } + } + + if (!uriRequest.containsHeader("Content-Type")) { + uriRequest.addHeader("Content-Type", "application/json"); + } + + final CompletableFuture future = new CompletableFuture<>(); + final SimpleHttpRequest simpleRequest = SimpleRequestBuilder.copy(uriRequest).build(); + if (uriRequest.getEntity() != null) { + simpleRequest.setBody( + EntityUtils.toByteArray(uriRequest.getEntity()), + ContentType.parse(uriRequest.getEntity().getContentType()) + ); + } + httpClient.execute(simpleRequest, new FutureCallback() { + @Override + public void completed(SimpleHttpResponse result) { + future.complete(result); + } + + @Override + public void failed(Exception ex) { + future.completeExceptionally(ex); + } + + @Override + public void cancelled() { + future.cancel(true); + } + }); + + final HttpResponse res = new HttpResponse(future.join()); + if (enableHTTPClientSSL && !res.getProtocolVersion().equals(HttpVersion.HTTP_2)) { + throw new IllegalStateException("HTTP/2 expected for HTTPS communication but " + res.getProtocolVersion() + " was used"); + } + + log.debug(res.getBody()); + return res; + } catch (final CompletionException e) { + final Throwable cause = e.getCause(); + // Make it compatible with DefaultHttpResponseParser::createConnectionClosedException() + if (cause instanceof ConnectionClosedException) { + throw new RuntimeException(new NoHttpResponseException(cause.getMessage(), cause)); + } else if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else { + throw new RuntimeException(cause); + } + } catch (final Exception e) { + throw new RuntimeException(e); + } finally { + + if (httpClient != null) { + try { + httpClient.close(); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + } + } + + private HttpEntity createStringEntity(String body) { + return new StringEntity(body); + } + + protected final String getHttpServerUri() { + final String address = "http" + (enableHTTPClientSSL ? "s" : "") + "://" + clusterInfo.httpHost + ":" + clusterInfo.httpPort; + log.debug("Connect to {}", address); + return address; + } + + protected final String getRequestUri(String request) { + return getHttpServerUri() + "/" + StringUtils.strip(request, "/"); + } + + protected final CloseableHttpAsyncClient getHTTPClient() throws Exception { + + final HttpAsyncClientBuilder hcb = HttpAsyncClients.custom(); + + if (sendHTTPClientCredentials) { + UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("sarek", "sarek".toCharArray()); + BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(null, -1), credentials); + hcb.setDefaultCredentialsProvider(credentialsProvider); + } + + if (enableHTTPClientSSL) { + + log.debug("Configure HTTP client with SSL"); + + if (prefix != null && !keystore.contains("/")) { + keystore = prefix + "/" + keystore; + } + + final String keyStorePath = FileHelper.getAbsoluteFilePathFromClassPath(keystore).toFile().getParent(); + + final KeyStore myTrustStore = KeyStore.getInstance("JKS"); + myTrustStore.load(new FileInputStream(keyStorePath + "/truststore.jks"), "changeit".toCharArray()); + + final KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath(keystore).toFile()), "changeit".toCharArray()); + + final SSLContextBuilder sslContextbBuilder = SSLContexts.custom(); + + if (trustHTTPServerCertificate) { + sslContextbBuilder.loadTrustMaterial(myTrustStore, null); + } + + if (sendAdminCertificate) { + sslContextbBuilder.loadKeyMaterial(keyStore, "changeit".toCharArray()); + } + + final SSLContext sslContext = sslContextbBuilder.build(); + + String[] protocols = null; + + if (enableHTTPClientSSLv3Only) { + protocols = new String[] { "SSLv3" }; + } else { + protocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" }; + } + + final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() + .setSslContext(sslContext) + .setTlsVersions(protocols) + .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) + // See please https://issues.apache.org/jira/browse/HTTPCLIENT-2219 + .setTlsDetailsFactory(new Factory() { + @Override + public TlsDetails create(final SSLEngine sslEngine) { + return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); + } + }) + .build(); + + final AsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(tlsStrategy).build(); + + hcb.setConnectionManager(cm); + } + + final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setResponseTimeout(Timeout.ofSeconds(60)); + + return hcb.setDefaultRequestConfig(requestConfigBuilder.build()).disableAutomaticRetries().build(); + } + + public static class HttpResponse { + private final SimpleHttpResponse inner; + private final String body; + private final Header[] header; + private final int statusCode; + private final String statusReason; + private final ProtocolVersion protocolVersion; + + public HttpResponse(SimpleHttpResponse inner) throws IllegalStateException, IOException { + super(); + this.inner = inner; + if (inner.getBody() == null) { // head request does not have a entity + this.body = ""; + } else { + this.body = inner.getBodyText(); + } + this.header = inner.getHeaders(); + this.statusCode = inner.getCode(); + this.statusReason = inner.getReasonPhrase(); + this.protocolVersion = inner.getVersion(); + } + + public String getContentType() { + Header h = getInner().getFirstHeader("content-type"); + if (h != null) { + return h.getValue(); + } + return null; + } + + public boolean isJsonContentType() { + String ct = getContentType(); + if (ct == null) { + return false; + } + return ct.contains("application/json"); + } + + public SimpleHttpResponse getInner() { + return inner; + } + + public String getBody() { + return body; + } + + public Header[] getHeader() { + return header; + } + + public int getStatusCode() { + return statusCode; + } + + public String getStatusReason() { + return statusReason; + } + + public List
getHeaders() { + return header == null ? Collections.emptyList() : Arrays.asList(header); + } + + public ProtocolVersion getProtocolVersion() { + return protocolVersion; + } + + @Override + public String toString() { + return "HttpResponse [inner=" + + inner + + ", body=" + + body + + ", header=" + + Arrays.toString(header) + + ", statusCode=" + + statusCode + + ", statusReason=" + + statusReason + + "]"; + } + + /** + * Given a json path with dots delimiated returns the object at the leaf + */ + public String findValueInJson(final String jsonDotPath) { + // Make sure its json / then parse it + if (!isJsonContentType()) { + throw new RuntimeException("Response was expected to be JSON, body was: \n" + body); + } + JsonNode currentNode = null; + try { + currentNode = DefaultObjectMapper.readTree(body); + } catch (final Exception e) { + throw new RuntimeException(e); + } + + // Break the path into parts, and scan into the json object + try (final Scanner jsonPathScanner = new Scanner(jsonDotPath).useDelimiter("\\.")) { + if (!jsonPathScanner.hasNext()) { + throw new RuntimeException( + "Invalid json dot path '" + jsonDotPath + "', rewrite with '.' characters between path elements." + ); + } + do { + String pathEntry = jsonPathScanner.next(); + // if pathEntry is an array lookup + int arrayEntryIdx = -1; + + // Looks for an array-lookup pattern in the path + // e.g. root_cause[1] -> will match + // e.g. root_cause[2aasd] -> won't match + final Pattern r = Pattern.compile("(.+?)\\[(\\d+)\\]"); + final Matcher m = r.matcher(pathEntry); + if (m.find()) { + pathEntry = m.group(1); + arrayEntryIdx = Integer.parseInt(m.group(2)); + } + + if (!currentNode.has(pathEntry)) { + throw new RuntimeException( + "Unable to resolve '" + + jsonDotPath + + "', on path entry '" + + pathEntry + + "' from available fields " + + currentNode.toPrettyString() + ); + } + currentNode = currentNode.get(pathEntry); + + // if it's an Array lookup we get the requested index item + if (arrayEntryIdx > -1) { + if (!currentNode.isArray()) { + throw new RuntimeException( + "Unable to resolve '" + + jsonDotPath + + "', the '" + + pathEntry + + "' field is not an array " + + currentNode.toPrettyString() + ); + } else if (!currentNode.has(arrayEntryIdx)) { + throw new RuntimeException( + "Unable to resolve '" + + jsonDotPath + + "', index '" + + arrayEntryIdx + + "' is out of bounds for array '" + + pathEntry + + "' \n" + + currentNode.toPrettyString() + ); + } + currentNode = currentNode.get(arrayEntryIdx); + } + } while (jsonPathScanner.hasNext()); + + if (!currentNode.isValueNode()) { + throw new RuntimeException( + "Unexpected value note, index directly to the object to reference, object\n" + currentNode.toPrettyString() + ); + } + return currentNode.asText(); + } + } + + private static HttpResponse from(Future future) { + try { + return future.get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } diff --git a/src/test/java/org/opensearch/security/test/helper/rules/SecurityTestWatcher.java b/src/test/java/org/opensearch/security/test/helper/rules/SecurityTestWatcher.java index b0ee40384d..b888bfbc35 100644 --- a/src/test/java/org/opensearch/security/test/helper/rules/SecurityTestWatcher.java +++ b/src/test/java/org/opensearch/security/test/helper/rules/SecurityTestWatcher.java @@ -29,27 +29,27 @@ import org.junit.rules.TestWatcher; import org.junit.runner.Description; -public class SecurityTestWatcher extends TestWatcher{ - - @Override - protected void starting(final Description description) { - final String methodName = description.getMethodName(); - String className = description.getClassName(); - className = className.substring(className.lastIndexOf('.') + 1); - System.out.println("---------------- Starting JUnit-test: " + className + " " + methodName + " ----------------"); - } - - @Override - protected void failed(final Throwable e, final Description description) { - final String methodName = description.getMethodName(); - String className = description.getClassName(); - className = className.substring(className.lastIndexOf('.') + 1); - System.out.println(">>>> " + className + " " + methodName + " FAILED due to " + e); - } - - @Override - protected void finished(final Description description) { - // System.out.println("-----------------------------------------------------------------------------------------"); - } +public class SecurityTestWatcher extends TestWatcher { + + @Override + protected void starting(final Description description) { + final String methodName = description.getMethodName(); + String className = description.getClassName(); + className = className.substring(className.lastIndexOf('.') + 1); + System.out.println("---------------- Starting JUnit-test: " + className + " " + methodName + " ----------------"); + } + + @Override + protected void failed(final Throwable e, final Description description) { + final String methodName = description.getMethodName(); + String className = description.getClassName(); + className = className.substring(className.lastIndexOf('.') + 1); + System.out.println(">>>> " + className + " " + methodName + " FAILED due to " + e); + } + + @Override + protected void finished(final Description description) { + // System.out.println("-----------------------------------------------------------------------------------------"); + } } diff --git a/src/test/java/org/opensearch/security/test/plugin/UserInjectorPlugin.java b/src/test/java/org/opensearch/security/test/plugin/UserInjectorPlugin.java index ae6f5116a1..227dd6699d 100644 --- a/src/test/java/org/opensearch/security/test/plugin/UserInjectorPlugin.java +++ b/src/test/java/org/opensearch/security/test/plugin/UserInjectorPlugin.java @@ -58,36 +58,63 @@ * @author jkressin */ public class UserInjectorPlugin extends Plugin implements NetworkPlugin { - + Settings settings; private final SharedGroupFactory sharedGroupFactory; ThreadPool threadPool; - - public UserInjectorPlugin(final Settings settings, final Path configPath) { + + public UserInjectorPlugin(final Settings settings, final Path configPath) { this.settings = settings; sharedGroupFactory = new SharedGroupFactory(settings); } @Override - public Map> getHttpTransports(Settings settings, ThreadPool threadPool, BigArrays bigArrays, - PageCacheRecycler pageCacheRecycler, CircuitBreakerService circuitBreakerService, NamedXContentRegistry xContentRegistry, - NetworkService networkService, Dispatcher dispatcher, ClusterSettings clusterSettings) { + public Map> getHttpTransports( + Settings settings, + ThreadPool threadPool, + BigArrays bigArrays, + PageCacheRecycler pageCacheRecycler, + CircuitBreakerService circuitBreakerService, + NamedXContentRegistry xContentRegistry, + NetworkService networkService, + Dispatcher dispatcher, + ClusterSettings clusterSettings + ) { final UserInjectingDispatcher validatingDispatcher = new UserInjectingDispatcher(dispatcher); - return ImmutableMap.of("org.opensearch.security.http.UserInjectingServerTransport", - () -> new UserInjectingServerTransport(settings, networkService, bigArrays, threadPool, xContentRegistry, validatingDispatcher, clusterSettings, sharedGroupFactory)); + return ImmutableMap.of( + "org.opensearch.security.http.UserInjectingServerTransport", + () -> new UserInjectingServerTransport( + settings, + networkService, + bigArrays, + threadPool, + xContentRegistry, + validatingDispatcher, + clusterSettings, + sharedGroupFactory + ) + ); } - + class UserInjectingServerTransport extends Netty4HttpServerTransport { - - public UserInjectingServerTransport(final Settings settings, final NetworkService networkService, final BigArrays bigArrays, - final ThreadPool threadPool, final NamedXContentRegistry namedXContentRegistry, final Dispatcher dispatcher, ClusterSettings clusterSettings, SharedGroupFactory sharedGroupFactory) { + + public UserInjectingServerTransport( + final Settings settings, + final NetworkService networkService, + final BigArrays bigArrays, + final ThreadPool threadPool, + final NamedXContentRegistry namedXContentRegistry, + final Dispatcher dispatcher, + ClusterSettings clusterSettings, + SharedGroupFactory sharedGroupFactory + ) { super(settings, networkService, bigArrays, threadPool, namedXContentRegistry, dispatcher, clusterSettings, sharedGroupFactory); } } - + class UserInjectingDispatcher implements Dispatcher { - + private Dispatcher originalDispatcher; public UserInjectingDispatcher(final Dispatcher originalDispatcher) { @@ -97,14 +124,20 @@ public UserInjectingDispatcher(final Dispatcher originalDispatcher) { @Override public void dispatchRequest(RestRequest request, RestChannel channel, ThreadContext threadContext) { - threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, request.header(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER)); + threadContext.putTransient( + ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, + request.header(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER) + ); originalDispatcher.dispatchRequest(request, channel, threadContext); - + } @Override public void dispatchBadRequest(RestChannel channel, ThreadContext threadContext, Throwable cause) { - threadContext.putTransient(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, channel.request().header(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER)); + threadContext.putTransient( + ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER, + channel.request().header(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_USER) + ); originalDispatcher.dispatchBadRequest(channel, threadContext, cause); } } diff --git a/src/test/java/org/opensearch/security/util/FakeRestRequest.java b/src/test/java/org/opensearch/security/util/FakeRestRequest.java index 989b775709..05e69ef614 100644 --- a/src/test/java/org/opensearch/security/util/FakeRestRequest.java +++ b/src/test/java/org/opensearch/security/util/FakeRestRequest.java @@ -21,11 +21,10 @@ public class FakeRestRequest extends RestRequest { - //private final Map headers; + // private final Map headers; private final BytesReference content; private final Method method; - public FakeRestRequest() { this(new HashMap<>(), new HashMap<>(), null, Method.GET, "/"); } @@ -35,10 +34,10 @@ public FakeRestRequest(Map headers, Map params) } private FakeRestRequest(Map headers, Map params, BytesReference content, Method method, String path) { - //NamedXContentRegistry xContentRegistry, Map params, String path, - //Map> headers, HttpRequest httpRequest, HttpChannel httpChannel + // NamedXContentRegistry xContentRegistry, Map params, String path, + // Map> headers, HttpRequest httpRequest, HttpChannel httpChannel super(null, params, path, convert(headers), null, null); - //this.headers = headers; + // this.headers = headers; this.content = content; this.method = method; } @@ -108,7 +107,7 @@ public FakeRestRequest build() { private static Map> convert(Map headers) { Map> ret = new HashMap>(); - for (String h:headers.keySet()) { + for (String h : headers.keySet()) { ret.put(h, Collections.singletonList(headers.get(h))); } return ret; diff --git a/src/test/java/org/opensearch/security/util/SettingsBasedSSLConfiguratorV4Test.java b/src/test/java/org/opensearch/security/util/SettingsBasedSSLConfiguratorV4Test.java index cc75ec6eb0..976f085ce4 100644 --- a/src/test/java/org/opensearch/security/util/SettingsBasedSSLConfiguratorV4Test.java +++ b/src/test/java/org/opensearch/security/util/SettingsBasedSSLConfiguratorV4Test.java @@ -84,25 +84,32 @@ public class SettingsBasedSSLConfiguratorV4Test { @Test public void testPemTrust() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/pem/truststore.jks", - "sslConfigurator/pem/node1-keystore.jks", "secret", false)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/pem/truststore.jks", + "sslConfigurator/pem/node1-keystore.jks", + "secret", + false + ) + ) { Path rootCaPemPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/pem/root-ca.pem"); Assert.assertTrue(rootCaPemPath.toFile().exists()); Settings settings = Settings.builder() - .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) - .put("prefix.enable_ssl", "true") - .put("path.home", rootCaPemPath.getParent().toString()) - .build(); + .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) + .put("prefix.enable_ssl", "true") + .put("path.home", rootCaPemPath.getParent().toString()) + .build(); Path configPath = rootCaPemPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { try (CloseableHttpResponse response = httpClient.execute(new HttpGet(testServer.getUri()))) { // Success @@ -115,23 +122,30 @@ public void testPemTrust() throws Exception { @Test public void testPemWrongTrust() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/pem/truststore.jks", - "sslConfigurator/pem/node1-keystore.jks", "secret", false)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/pem/truststore.jks", + "sslConfigurator/pem/node1-keystore.jks", + "secret", + false + ) + ) { Path rootCaPemPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/pem/other-root-ca.pem"); Settings settings = Settings.builder() - .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) - .put("prefix.enable_ssl", "true") - .put("path.home", rootCaPemPath.getParent().toString()) - .build(); + .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) + .put("prefix.enable_ssl", "true") + .put("path.home", rootCaPemPath.getParent().toString()) + .build(); Path configPath = rootCaPemPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { thrown.expect(SSLHandshakeException.class); @@ -146,27 +160,34 @@ public void testPemWrongTrust() throws Exception { @Test public void testPemClientAuth() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/pem/truststore.jks", - "sslConfigurator/pem/node1-keystore.jks", "secret", true)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/pem/truststore.jks", + "sslConfigurator/pem/node1-keystore.jks", + "secret", + true + ) + ) { Path rootCaPemPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/pem/root-ca.pem"); Settings settings = Settings.builder() - .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) - .put("prefix.enable_ssl", "true") - .put("path.home", rootCaPemPath.getParent().toString()) - .put("prefix.enable_ssl_client_auth", "true") - .put("prefix.pemcert_filepath", "kirk.pem") - .put("prefix.pemkey_filepath", "kirk.key") - .put("prefix.pemkey_password", "secret") - .build(); + .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) + .put("prefix.enable_ssl", "true") + .put("path.home", rootCaPemPath.getParent().toString()) + .put("prefix.enable_ssl_client_auth", "true") + .put("prefix.pemcert_filepath", "kirk.pem") + .put("prefix.pemkey_filepath", "kirk.key") + .put("prefix.pemkey_password", "secret") + .build(); Path configPath = rootCaPemPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { try (CloseableHttpResponse response = httpClient.execute(new HttpGet(testServer.getUri()))) { // Success @@ -179,33 +200,43 @@ public void testPemClientAuth() throws Exception { @Test public void testPemClientAuthFailure() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/pem/truststore.jks", - "sslConfigurator/pem/node1-keystore.jks", "secret", true)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/pem/truststore.jks", + "sslConfigurator/pem/node1-keystore.jks", + "secret", + true + ) + ) { Path rootCaPemPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/pem/root-ca.pem"); Settings settings = Settings.builder() - .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) - .put("prefix.enable_ssl", "true") - .put("path.home", rootCaPemPath.getParent().toString()) - .put("prefix.enable_ssl_client_auth", "true") - .put("prefix.pemcert_filepath", "wrong-kirk.pem") - .put("prefix.pemkey_filepath", "wrong-kirk.key") - .put("prefix.pemkey_password", "G0CVtComen4a") - .build(); + .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) + .put("prefix.enable_ssl", "true") + .put("path.home", rootCaPemPath.getParent().toString()) + .put("prefix.enable_ssl_client_auth", "true") + .put("prefix.pemcert_filepath", "wrong-kirk.pem") + .put("prefix.pemkey_filepath", "wrong-kirk.key") + .put("prefix.pemkey_password", "G0CVtComen4a") + .build(); Path configPath = rootCaPemPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { // Due to some race condition in Java's internal network stack, this can be one // of the following exceptions - thrown.expect(either(instanceOf(SocketException.class)).or(instanceOf(SSLHandshakeException.class)) - .or(instanceOf(SSLException.class)) // Java 11: javax.net.ssl.SSLException: readHandshakeRecord + thrown.expect( + either(instanceOf(SocketException.class)).or(instanceOf(SSLHandshakeException.class)).or(instanceOf(SSLException.class)) // Java + // 11: + // javax.net.ssl.SSLException: + // readHandshakeRecord ); try (CloseableHttpResponse response = httpClient.execute(new HttpGet(testServer.getUri()))) { @@ -218,24 +249,31 @@ public void testPemClientAuthFailure() throws Exception { @Test public void testPemHostnameVerificationFailure() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/pem/truststore.jks", - "sslConfigurator/pem/node-wrong-hostname-keystore.jks", "secret", false)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/pem/truststore.jks", + "sslConfigurator/pem/node-wrong-hostname-keystore.jks", + "secret", + false + ) + ) { Path rootCaPemPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/pem/root-ca.pem"); Settings settings = Settings.builder() - .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) - .put("prefix.enable_ssl", "true") - .put("prefix.verify_hostnames", "true") - .put("path.home", rootCaPemPath.getParent().toString()) - .build(); + .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) + .put("prefix.enable_ssl", "true") + .put("prefix.verify_hostnames", "true") + .put("path.home", rootCaPemPath.getParent().toString()) + .build(); Path configPath = rootCaPemPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { thrown.expect(SSLPeerUnverifiedException.class); @@ -249,24 +287,31 @@ public void testPemHostnameVerificationFailure() throws Exception { @Test public void testPemHostnameVerificationOff() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/pem/truststore.jks", - "sslConfigurator/pem/node-wrong-hostname-keystore.jks", "secret", false)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/pem/truststore.jks", + "sslConfigurator/pem/node-wrong-hostname-keystore.jks", + "secret", + false + ) + ) { Path rootCaPemPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/pem/root-ca.pem"); Settings settings = Settings.builder() - .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) - .put("prefix.enable_ssl", "true") - .put("prefix.verify_hostnames", "false") - .put("path.home", rootCaPemPath.getParent().toString()) - .build(); + .put("prefix.pemtrustedcas_filepath", rootCaPemPath.getFileName().toString()) + .put("prefix.enable_ssl", "true") + .put("prefix.verify_hostnames", "false") + .put("path.home", rootCaPemPath.getParent().toString()) + .build(); Path configPath = rootCaPemPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { try (CloseableHttpResponse response = httpClient.execute(new HttpGet(testServer.getUri()))) { // Success @@ -278,26 +323,33 @@ public void testPemHostnameVerificationOff() throws Exception { @Test public void testJksTrust() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/jks/truststore.jks", - "sslConfigurator/jks/node1-keystore.jks", "secret", false)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/jks/truststore.jks", + "sslConfigurator/jks/node1-keystore.jks", + "secret", + false + ) + ) { Path rootCaJksPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/jks/truststore.jks"); MockSecureSettings mockSecureSettings = new MockSecureSettings(); mockSecureSettings.setString(SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.propertyName, "secret"); Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, rootCaJksPath.getFileName().toString()) - .put("prefix.enable_ssl", "true") - .put("path.home", rootCaJksPath.getParent().toString()) - .setSecureSettings(mockSecureSettings) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, rootCaJksPath.getFileName().toString()) + .put("prefix.enable_ssl", "true") + .put("path.home", rootCaJksPath.getParent().toString()) + .setSecureSettings(mockSecureSettings) + .build(); Path configPath = rootCaJksPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { try (CloseableHttpResponse response = httpClient.execute(new HttpGet(testServer.getUri()))) { // Success @@ -310,26 +362,33 @@ public void testJksTrust() throws Exception { @Test public void testJksWrongTrust() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/jks/truststore.jks", - "sslConfigurator/jks/node1-keystore.jks", "secret", false)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/jks/truststore.jks", + "sslConfigurator/jks/node1-keystore.jks", + "secret", + false + ) + ) { Path rootCaJksPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/jks/other-root-ca.jks"); MockSecureSettings mockSecureSettings = new MockSecureSettings(); mockSecureSettings.setString(SECURITY_SSL_TRANSPORT_TRUSTSTORE_PASSWORD.propertyName, "secret"); Settings settings = Settings.builder() - .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, rootCaJksPath.getFileName().toString()) - .put("prefix.enable_ssl", "true") - .put("path.home", rootCaJksPath.getParent().toString()) - .setSecureSettings(mockSecureSettings) - .build(); + .put(SSLConfigConstants.SECURITY_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, rootCaJksPath.getFileName().toString()) + .put("prefix.enable_ssl", "true") + .put("path.home", rootCaJksPath.getParent().toString()) + .setSecureSettings(mockSecureSettings) + .build(); Path configPath = rootCaJksPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { thrown.expect(SSLHandshakeException.class); @@ -342,23 +401,30 @@ public void testJksWrongTrust() throws Exception { @Test public void testTrustAll() throws Exception { - try (TestServer testServer = new TestServer("sslConfigurator/jks/truststore.jks", - "sslConfigurator/jks/node1-keystore.jks", "secret", false)) { + try ( + TestServer testServer = new TestServer( + "sslConfigurator/jks/truststore.jks", + "sslConfigurator/jks/node1-keystore.jks", + "secret", + false + ) + ) { Path rootCaJksPath = FileHelper.getAbsoluteFilePathFromClassPath("sslConfigurator/jks/other-root-ca.jks"); Settings settings = Settings.builder() - .put("prefix.enable_ssl", "true") - .put("prefix.trust_all", "true") - .put("path.home", rootCaJksPath.getParent().toString()) - .build(); + .put("prefix.enable_ssl", "true") + .put("prefix.trust_all", "true") + .put("path.home", rootCaJksPath.getParent().toString()) + .build(); Path configPath = rootCaJksPath.getParent(); SettingsBasedSSLConfiguratorV4 sbsc = new SettingsBasedSSLConfiguratorV4(settings, configPath, "prefix"); SSLConfig sslConfig = sbsc.buildSSLConfig(); - try (CloseableHttpClient httpClient = HttpClients.custom() - .setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build()) { + try ( + CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConfig.toSSLConnectionSocketFactory()).build() + ) { try (CloseableHttpResponse response = httpClient.execute(new HttpGet(testServer.getUri()))) { // Success @@ -379,43 +445,50 @@ String getUri() { return "https://localhost:" + port + "/test"; } - private void createHttpServer(String trustStore, String keyStore, String password, boolean clientAuth) - throws IOException { + private void createHttpServer(String trustStore, String keyStore, String password, boolean clientAuth) throws IOException { this.port = SocketUtils.findAvailableTcpPort(); - ServerBootstrap serverBootstrap = ServerBootstrap.bootstrap().setListenerPort(port).registerHandler("test", - new HttpRequestHandler() { + ServerBootstrap serverBootstrap = ServerBootstrap.bootstrap() + .setListenerPort(port) + .registerHandler("test", new HttpRequestHandler() { - @Override - public void handle(HttpRequest request, HttpResponse response, HttpContext context) - throws HttpException, IOException { + @Override + public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { - } - }); + } + }); serverBootstrap = serverBootstrap.setSslContext(createSSLContext(trustStore, keyStore, password)) - .setSslSetupHandler(new SSLServerSetupHandler() { + .setSslSetupHandler(new SSLServerSetupHandler() { - @Override - public void initialize(SSLServerSocket socket) throws SSLException { - if (clientAuth) { - socket.setNeedClientAuth(true); - } - } - }).setConnectionFactory(new HttpConnectionFactory() { - - private ConnectionConfig cconfig = ConnectionConfig.DEFAULT; - - @Override - public DefaultBHttpServerConnection createConnection(final Socket socket) throws IOException { - final SSLTestHttpServerConnection conn = new SSLTestHttpServerConnection( - this.cconfig.getBufferSize(), this.cconfig.getFragmentSizeHint(), - ConnSupport.createDecoder(this.cconfig), ConnSupport.createEncoder(this.cconfig), - this.cconfig.getMessageConstraints(), null, null, null, null); - conn.bind(socket); - return conn; + @Override + public void initialize(SSLServerSocket socket) throws SSLException { + if (clientAuth) { + socket.setNeedClientAuth(true); } - }); + } + }) + .setConnectionFactory(new HttpConnectionFactory() { + + private ConnectionConfig cconfig = ConnectionConfig.DEFAULT; + + @Override + public DefaultBHttpServerConnection createConnection(final Socket socket) throws IOException { + final SSLTestHttpServerConnection conn = new SSLTestHttpServerConnection( + this.cconfig.getBufferSize(), + this.cconfig.getFragmentSizeHint(), + ConnSupport.createDecoder(this.cconfig), + ConnSupport.createEncoder(this.cconfig), + this.cconfig.getMessageConstraints(), + null, + null, + null, + null + ); + conn.bind(socket); + return conn; + } + }); this.httpServer = serverBootstrap.create(); @@ -434,8 +507,7 @@ private SSLContext createSSLContext(String trustStorePath, String keyStorePath, try { TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); KeyStore trustStore = KeyStore.getInstance("JKS"); - InputStream trustStream = new FileInputStream( - FileHelper.getAbsoluteFilePathFromClassPath(trustStorePath).toFile()); + InputStream trustStream = new FileInputStream(FileHelper.getAbsoluteFilePathFromClassPath(trustStorePath).toFile()); trustStore.load(trustStream, password.toCharArray()); tmf.init(trustStore); @@ -472,14 +544,28 @@ public String chooseAlias(Map aliases, Socket socket) } static class SSLTestHttpServerConnection extends DefaultBHttpServerConnection { - public SSLTestHttpServerConnection(final int buffersize, final int fragmentSizeHint, - final CharsetDecoder chardecoder, final CharsetEncoder charencoder, - final MessageConstraints constraints, final ContentLengthStrategy incomingContentStrategy, - final ContentLengthStrategy outgoingContentStrategy, - final HttpMessageParserFactory requestParserFactory, - final HttpMessageWriterFactory responseWriterFactory) { - super(buffersize, fragmentSizeHint, chardecoder, charencoder, constraints, incomingContentStrategy, - outgoingContentStrategy, requestParserFactory, responseWriterFactory); + public SSLTestHttpServerConnection( + final int buffersize, + final int fragmentSizeHint, + final CharsetDecoder chardecoder, + final CharsetEncoder charencoder, + final MessageConstraints constraints, + final ContentLengthStrategy incomingContentStrategy, + final ContentLengthStrategy outgoingContentStrategy, + final HttpMessageParserFactory requestParserFactory, + final HttpMessageWriterFactory responseWriterFactory + ) { + super( + buffersize, + fragmentSizeHint, + chardecoder, + charencoder, + constraints, + incomingContentStrategy, + outgoingContentStrategy, + requestParserFactory, + responseWriterFactory + ); } public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { diff --git a/src/test/resources/auditlog/data2.json b/src/test/resources/auditlog/data2.json index 1d37b6abc2..cc4748ed82 100644 --- a/src/test/resources/auditlog/data2.json +++ b/src/test/resources/auditlog/data2.json @@ -1,6 +1,6 @@ { "text": "text question value", "joinfield": { - "name": "question" + "name": "question" } } diff --git a/src/test/resources/auditlog/data3.json b/src/test/resources/auditlog/data3.json index 05c678b114..6846fe0f68 100644 --- a/src/test/resources/auditlog/data3.json +++ b/src/test/resources/auditlog/data3.json @@ -1,7 +1,7 @@ { "text": "text answer value", "joinfield": { - "name": "answer", - "parent": "1" + "name": "answer", + "parent": "1" } } diff --git a/src/test/resources/auditlog/endpoints/configuration_wrong_endpoint_names.yml b/src/test/resources/auditlog/endpoints/configuration_wrong_endpoint_names.yml index 24fb5dcae5..dee8c95641 100644 --- a/src/test/resources/auditlog/endpoints/configuration_wrong_endpoint_names.yml +++ b/src/test/resources/auditlog/endpoints/configuration_wrong_endpoint_names.yml @@ -7,7 +7,7 @@ plugins.security: type: external_opensearch config: http_endpoints: ['localhost:9200','localhost:9201','localhost:9202'] - index: auditlog + index: auditlog username: auditloguser password: auditlogpassword enable_ssl: false diff --git a/src/test/resources/auditlog/endpoints/routing/configuration_valid.yml b/src/test/resources/auditlog/endpoints/routing/configuration_valid.yml index 75df18aac7..046e4d6ee5 100644 --- a/src/test/resources/auditlog/endpoints/routing/configuration_valid.yml +++ b/src/test/resources/auditlog/endpoints/routing/configuration_valid.yml @@ -3,7 +3,7 @@ plugins.security: type: external_opensearch config: http_endpoints: ['localhost:9200','localhost:9201','localhost:9202'] - index: auditlog + index: auditlog username: auditloguser password: auditlogpassword enable_ssl: false @@ -16,7 +16,7 @@ plugins.security: type: external_opensearch config: http_endpoints: ['localhost:9200','localhost:9201','localhost:9202'] - index: auditlog + index: auditlog username: auditloguser password: auditlogpassword enable_ssl: false diff --git a/src/test/resources/auditlog/endpoints/routing/configuration_wrong_endpoint_names.yml b/src/test/resources/auditlog/endpoints/routing/configuration_wrong_endpoint_names.yml index 2361b6049b..2b96265492 100644 --- a/src/test/resources/auditlog/endpoints/routing/configuration_wrong_endpoint_names.yml +++ b/src/test/resources/auditlog/endpoints/routing/configuration_wrong_endpoint_names.yml @@ -8,7 +8,7 @@ plugins.security: type: external_opensearch config: http_endpoints: ['localhost:9200','localhost:9201','localhost:9202'] - index: auditlog + index: auditlog username: auditloguser password: auditlogpassword enable_ssl: false diff --git a/src/test/resources/auditlog/endpoints/routing/configuration_wrong_endpoint_types.yml b/src/test/resources/auditlog/endpoints/routing/configuration_wrong_endpoint_types.yml index 6b6929b2c7..c59adc4ee1 100644 --- a/src/test/resources/auditlog/endpoints/routing/configuration_wrong_endpoint_types.yml +++ b/src/test/resources/auditlog/endpoints/routing/configuration_wrong_endpoint_types.yml @@ -8,7 +8,7 @@ plugins.security: type: external_opensearch config: http_endpoints: ['localhost:9200','localhost:9201','localhost:9202'] - index: auditlog + index: auditlog username: auditloguser password: auditlogpassword enable_ssl: false diff --git a/src/test/resources/auditlog/endpoints/routing/routing.yml b/src/test/resources/auditlog/endpoints/routing/routing.yml index ac6596424e..4135b800e2 100644 --- a/src/test/resources/auditlog/endpoints/routing/routing.yml +++ b/src/test/resources/auditlog/endpoints/routing/routing.yml @@ -19,4 +19,4 @@ plugins.security: - endpoint3 COMPLIANCE_DOC_WRITE: endpoints: - - default + - default diff --git a/src/test/resources/auditlog/endpoints/sink/configuration_all_variants.yml b/src/test/resources/auditlog/endpoints/sink/configuration_all_variants.yml index e441322c17..f1c8620e88 100644 --- a/src/test/resources/auditlog/endpoints/sink/configuration_all_variants.yml +++ b/src/test/resources/auditlog/endpoints/sink/configuration_all_variants.yml @@ -17,10 +17,10 @@ plugins.security: type: external_opensearch something: key: value - endpoint6: + endpoint6: something: key: value - endpoint7: + endpoint7: config: key: value endpoint8: diff --git a/src/test/resources/auditlog/endpoints/sink/configuration_no_default.yml b/src/test/resources/auditlog/endpoints/sink/configuration_no_default.yml index f81b37dde2..013410ea77 100644 --- a/src/test/resources/auditlog/endpoints/sink/configuration_no_default.yml +++ b/src/test/resources/auditlog/endpoints/sink/configuration_no_default.yml @@ -16,10 +16,10 @@ plugins.security: type: external_opensearch something: key: value - endpoint6: + endpoint6: something: key: value - endpoint7: + endpoint7: config: key: value endpoint8: diff --git a/src/test/resources/config_auth_ratelimiting.yml b/src/test/resources/config_auth_ratelimiting.yml index 3675afc33e..a55ad0b5d3 100644 --- a/src/test/resources/config_auth_ratelimiting.yml +++ b/src/test/resources/config_auth_ratelimiting.yml @@ -23,5 +23,5 @@ config: allowed_tries: 10 internal_authentication_backend_limiting: type: username - authentication_backend: intern + authentication_backend: intern allowed_tries: 3 diff --git a/src/test/resources/config_ldap.yml b/src/test/resources/config_ldap.yml index c2aebf869b..5dc0895d8d 100644 --- a/src/test/resources/config_ldap.yml +++ b/src/test/resources/config_ldap.yml @@ -7,7 +7,7 @@ plugins.security: remoteIpHeader: "x-forwarded-for" proxiesHeader: "x-forwarded-by" trustedProxies: "proxy1|proxy2" - authenticator: + authenticator: type: org.opensearch.security.http.HTTPBasicAuthenticator authcz: authentication_domain_basic_internal: diff --git a/src/test/resources/data2.json b/src/test/resources/data2.json index 1d37b6abc2..cc4748ed82 100644 --- a/src/test/resources/data2.json +++ b/src/test/resources/data2.json @@ -1,6 +1,6 @@ { "text": "text question value", "joinfield": { - "name": "question" + "name": "question" } } diff --git a/src/test/resources/data3.json b/src/test/resources/data3.json index 05c678b114..6846fe0f68 100644 --- a/src/test/resources/data3.json +++ b/src/test/resources/data3.json @@ -1,7 +1,7 @@ { "text": "text answer value", "joinfield": { - "name": "answer", - "parent": "1" + "name": "answer", + "parent": "1" } } diff --git a/src/test/resources/dlsfls/doc1.json b/src/test/resources/dlsfls/doc1.json index 6067eedc9a..7dccde9b93 100644 --- a/src/test/resources/dlsfls/doc1.json +++ b/src/test/resources/dlsfls/doc1.json @@ -1,5 +1,5 @@ { - + "customer": { "name": "", "type": "normal", @@ -9,8 +9,8 @@ "street": "street1", "zip": "12345", "city": "mycity" - - } + + } }, "secret": "a secret value", @@ -34,7 +34,7 @@ "boolfield5": true, "boolfield6": false, "nullfield": null, - + "@timestamp": "", "timestamp": "" diff --git a/src/test/resources/dlsfls/flsquery.json b/src/test/resources/dlsfls/flsquery.json index 9418e8721b..19d3897971 100644 --- a/src/test/resources/dlsfls/flsquery.json +++ b/src/test/resources/dlsfls/flsquery.json @@ -34,9 +34,9 @@ } }, "query":{ - - - + + + "bool":{ "must":[ { @@ -53,8 +53,8 @@ ] } - - + + }, "stored_fields":[ "*", diff --git a/src/test/resources/dlsfls/flsquery2.json b/src/test/resources/dlsfls/flsquery2.json index a5ad1da20e..26fce316db 100644 --- a/src/test/resources/dlsfls/flsquery2.json +++ b/src/test/resources/dlsfls/flsquery2.json @@ -38,8 +38,8 @@ "match_all":{ - - + + } }, "stored_fields":[ diff --git a/src/test/resources/dlsfls/internal_users_tlq.yml b/src/test/resources/dlsfls/internal_users_tlq.yml index 5bbec586f0..dff0a67633 100644 --- a/src/test/resources/dlsfls/internal_users_tlq.yml +++ b/src/test/resources/dlsfls/internal_users_tlq.yml @@ -2,7 +2,7 @@ _meta: type: "internalusers" config_version: 2 - + tlq_1337: hash: "$2y$12$SP9z.rBgEHTlueKkiqSK/OxqB2PLJN/eRoNJ8WOPoHWIpirvbFAAy" # "password" backend_roles: ["os_dls_tlq_lookup"] diff --git a/src/test/resources/dlsfls/masked_field_mapping.json b/src/test/resources/dlsfls/masked_field_mapping.json index f3629282fd..56863f546c 100644 --- a/src/test/resources/dlsfls/masked_field_mapping.json +++ b/src/test/resources/dlsfls/masked_field_mapping.json @@ -1,5 +1,5 @@ { - + "_doc": { "properties": { @@ -142,6 +142,6 @@ } } } - - + + } diff --git a/src/test/resources/dlsfls/roles_tlq.yml b/src/test/resources/dlsfls/roles_tlq.yml index c2d08ca948..1420a7a965 100644 --- a/src/test/resources/dlsfls/roles_tlq.yml +++ b/src/test/resources/dlsfls/roles_tlq.yml @@ -2,7 +2,7 @@ _meta: type: "roles" config_version: 2 - + os_dls_tlq_lookup: cluster_permissions: - "*" diff --git a/src/test/resources/ldap/test1.yml b/src/test/resources/ldap/test1.yml index e1e396ba01..e0ad96ceea 100644 --- a/src/test/resources/ldap/test1.yml +++ b/src/test/resources/ldap/test1.yml @@ -1,8 +1,8 @@ ---- +--- enable_ssl: true enable_ssl_client_auth: false enable_start_tls: false -#hosts: +#hosts: # - "localhost:${ldapport}" path.home: "." pemcert_content: | diff --git a/src/test/resources/legacy/securityconfig_v6/action_groups.yml b/src/test/resources/legacy/securityconfig_v6/action_groups.yml index 5acbe1aea8..ac564e7421 100644 --- a/src/test/resources/legacy/securityconfig_v6/action_groups.yml +++ b/src/test/resources/legacy/securityconfig_v6/action_groups.yml @@ -128,7 +128,7 @@ OPENDISTRO_SECURITY_CLUSTER_COMPOSITE_OPS: - "indices:admin/aliases*" - "indices:data/write/reindex" - CLUSTER_COMPOSITE_OPS_RO - + OPENDISTRO_SECURITY_MANAGE_SNAPSHOTS: readonly: true permissions: diff --git a/src/test/resources/legacy/securityconfig_v6/config.yml b/src/test/resources/legacy/securityconfig_v6/config.yml index 031be9bb15..19b1fd76cd 100644 --- a/src/test/resources/legacy/securityconfig_v6/config.yml +++ b/src/test/resources/legacy/securityconfig_v6/config.yml @@ -1,14 +1,14 @@ # This is the main OpenSearch Security configuration file where authentication # and authorization is defined. -# +# # You need to configure at least one authentication domain in the authc of this file. -# An authentication domain is responsible for extracting the user credentials from -# the request and for validating them against an authentication backend like Active Directory for example. +# An authentication domain is responsible for extracting the user credentials from +# the request and for validating them against an authentication backend like Active Directory for example. # -# If more than one authentication domain is configured the first one which succeeds wins. +# If more than one authentication domain is configured the first one which succeeds wins. # If all authentication domains fail then the request is unauthenticated. # In this case an exception is thrown and/or the HTTP status is set to 401. -# +# # After authentication authorization (authz) will be applied. There can be zero or more authorizers which collect # the roles from a given backend for the authenticated user. # @@ -21,18 +21,18 @@ # For HTTP it is possible to allow anonymous authentication. If that is the case then the HTTP authenticators try to # find user credentials in the HTTP request. If credentials are found then the user gets regularly authenticated. # If none can be found the user will be authenticated as an "anonymous" user. This user has always the username "opendistro_security_anonymous" -# and one role named "opendistro_security_anonymous_backendrole". +# and one role named "opendistro_security_anonymous_backendrole". # If you enable anonymous authentication all HTTP authenticators will not challenge. -# +# # # Note: If you define more than one HTTP authenticators make sure to put non-challenging authenticators like "proxy" or "clientcert" -# first and the challenging one last. +# first and the challenging one last. # Because it's not possible to challenge a client with two different authentication methods (for example # Kerberos and Basic) only one can have the challenge flag set to true. You can cope with this situation # by using pre-authentication, e.g. sending a HTTP Basic authentication header in the request. # # Default value of the challenge flag is true. -# +# # # HTTP # basic (challenging) @@ -77,7 +77,7 @@ opendistro_security: ###### and here https://tools.ietf.org/html/rfc7239 ###### and https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Remote_IP_Valve authc: - kerberos_auth_domain: + kerberos_auth_domain: http_enabled: false transport_enabled: false order: 6 @@ -91,7 +91,7 @@ opendistro_security: strip_realm_from_principal: true authentication_backend: type: noop - basic_internal_auth_domain: + basic_internal_auth_domain: http_enabled: true transport_enabled: true order: 4 @@ -163,11 +163,11 @@ opendistro_security: password: null userbase: 'ou=people,dc=example,dc=com' # Filter to search for users (currently in the whole subtree beneath userbase) - # {0} is substituted with the username + # {0} is substituted with the username usersearch: '(sAMAccountName={0})' # Use this attribute from the user as username (if not set then DN is used) username_attribute: null - authz: + authz: roles_from_myldap: http_enabled: false transport_enabled: false @@ -190,8 +190,8 @@ opendistro_security: rolebase: 'ou=groups,dc=example,dc=com' # Filter to search for roles (currently in the whole subtree beneath rolebase) # {0} is substituted with the DN of the user - # {1} is substituted with the username - # {2} is substituted with an attribute value from user's directory entry, of the authenticated user. Use userroleattribute to specify the name of the attribute + # {1} is substituted with the username + # {2} is substituted with an attribute value from user's directory entry, of the authenticated user. Use userroleattribute to specify the name of the attribute rolesearch: '(member={0})' # Specify the name of the attribute which value should be substituted with {2} above userroleattribute: null @@ -205,12 +205,12 @@ opendistro_security: resolve_nested_roles: true userbase: 'ou=people,dc=example,dc=com' # Filter to search for users (currently in the whole subtree beneath userbase) - # {0} is substituted with the username + # {0} is substituted with the username usersearch: '(uid={0})' # Skip users matching a user name, a wildcard or a regex pattern - #skip_users: + #skip_users: # - 'cn=Michael Jackson,ou*people,o=TEST' - # - '/\S*/' + # - '/\S*/' roles_from_another_ldap: enabled: false authorization_backend: diff --git a/src/test/resources/legacy/securityconfig_v6/internal_users.yml b/src/test/resources/legacy/securityconfig_v6/internal_users.yml index d8d5b0d3a4..64b6295bbe 100644 --- a/src/test/resources/legacy/securityconfig_v6/internal_users.yml +++ b/src/test/resources/legacy/securityconfig_v6/internal_users.yml @@ -19,13 +19,13 @@ opendistro_security_logstash: roles: - logstash -#password is: kibanaserver +#password is: kibanaserver kibanaserver: readonly: true hash: $2a$12$4AcgAt3xwOWadA5s5blL6ev39OXDNhmOesEoo33eZtrq2N0YrU3H. #password is: kibanaro -kibanaro: +kibanaro: hash: $2a$12$JJSXNfTowz7Uu5ttXfeYpeYE0arACvcwlPBStB1F.MI7f0U9Z4DGC roles: - kibanauser diff --git a/src/test/resources/legacy/securityconfig_v6/migration/roles.yml b/src/test/resources/legacy/securityconfig_v6/migration/roles.yml index 0163e4a7bb..52f9dd60a4 100644 --- a/src/test/resources/legacy/securityconfig_v6/migration/roles.yml +++ b/src/test/resources/legacy/securityconfig_v6/migration/roles.yml @@ -3,7 +3,7 @@ # - '' # indices: # '': -# '': +# '': # - '' # _dls_: '' # _fls_: @@ -15,9 +15,9 @@ # and a type. If a request is executed against all indices (or all types) then the asterix ('*') is needed. # Every role a user has will be examined if it allows the action against an index (or type). At least one role must match # for the request to be successful. If no role match then the request will be denied. Currently a match must happen within -# one single role - that means that permissions can not span multiple roles. +# one single role - that means that permissions can not span multiple roles. -# For , and simple wildcards and regular expressions are possible. +# For , and simple wildcards and regular expressions are possible. # A asterix (*) will match any character sequence (or an empty sequence) # A question mark (?) will match any single character (but NOT empty character) # Example: '*my*index' will match 'my_first_index' as well as 'myindex' but not 'myindex1' @@ -27,7 +27,7 @@ # '//' # Example: '/\S*/' will match any non whitespace characters -# Important: +# Important: # Index, alias or type names can not contain dots (.) in the or expression. # Reason is that we currently parse the config file into a opensearch settings object which cannot cope with dots in keys. # Workaround: Just configure something like '?kibana' instead of '.kibana' or 'my?index' instead of 'my.index' @@ -54,7 +54,7 @@ opendistro_security_readall: '*': - READ -# Read all and monitor, but no write permissions +# Read all and monitor, but no write permissions opendistro_security_readall_and_monitor: cluster: - CLUSTER_MONITOR diff --git a/src/test/resources/legacy/securityconfig_v6/roles.yml b/src/test/resources/legacy/securityconfig_v6/roles.yml index d755d67dbe..65f02a7106 100644 --- a/src/test/resources/legacy/securityconfig_v6/roles.yml +++ b/src/test/resources/legacy/securityconfig_v6/roles.yml @@ -3,7 +3,7 @@ # - '' # indices: # '': -# '': +# '': # - '' # _dls_: '' # _fls_: @@ -15,9 +15,9 @@ # and a type. If a request is executed against all indices (or all types) then the asterix ('*') is needed. # Every role a user has will be examined if it allows the action against an index (or type). At least one role must match # for the request to be successful. If no role match then the request will be denied. Currently a match must happen within -# one single role - that means that permissions can not span multiple roles. +# one single role - that means that permissions can not span multiple roles. -# For , and simple wildcards and regular expressions are possible. +# For , and simple wildcards and regular expressions are possible. # A asterix (*) will match any character sequence (or an empty sequence) # A question mark (?) will match any single character (but NOT empty character) # Example: '*my*index' will match 'my_first_index' as well as 'myindex' but not 'myindex1' @@ -27,7 +27,7 @@ # '//' # Example: '/\S*/' will match any non whitespace characters -# Important: +# Important: # Index, alias or type names can not contain dots (.) in the or expression. # Reason is that we currently parse the config file into a opensearch settings object which cannot cope with dots in keys. # Workaround: Just configure something like '?kibana' instead of '.kibana' or 'my?index' instead of 'my.index' @@ -57,7 +57,7 @@ opendistro_security_readall: '*': - READ -# Read all and monitor, but no write permissions +# Read all and monitor, but no write permissions opendistro_security_readall_and_monitor: cluster: - CLUSTER_MONITOR @@ -97,7 +97,7 @@ opendistro_security_kibana_user: - INDICES_ALL '?management-beats': '*': - - INDICES_ALL + - INDICES_ALL '*': '*': - indices:data/read/field_caps* @@ -133,7 +133,7 @@ opendistro_security_kibana_server: - "indices:admin/aliases*" # For logstash and beats -opendistro_security_logstash: +opendistro_security_logstash: cluster: - CLUSTER_MONITOR - CLUSTER_COMPOSITE_OPS diff --git a/src/test/resources/legacy/securityconfig_v6/roles_mapping.yml b/src/test/resources/legacy/securityconfig_v6/roles_mapping.yml index b3263eb234..588ba13f6e 100644 --- a/src/test/resources/legacy/securityconfig_v6/roles_mapping.yml +++ b/src/test/resources/legacy/securityconfig_v6/roles_mapping.yml @@ -9,12 +9,12 @@ opendistro_security_all_access: opendistro_security_logstash: backendroles: - logstash - + opendistro_security_kibana_server: readonly: true users: - kibanaserver - + opendistro_security_kibana_user: backendroles: - kibanauser diff --git a/src/test/resources/multitenancy/config_basic_auth.yml b/src/test/resources/multitenancy/config_basic_auth.yml index f60caab0b7..72f73f8305 100644 --- a/src/test/resources/multitenancy/config_basic_auth.yml +++ b/src/test/resources/multitenancy/config_basic_auth.yml @@ -22,7 +22,7 @@ config: internalProxies: ".*" remoteIpHeader: "x-forwarded-for" authc: - basic_internal_auth_domain: + basic_internal_auth_domain: http_enabled: true transport_enabled: true order: 0 diff --git a/src/test/resources/restapi/audit.yml b/src/test/resources/restapi/audit.yml index 06eb47a56d..796c92f828 100644 --- a/src/test/resources/restapi/audit.yml +++ b/src/test/resources/restapi/audit.yml @@ -33,7 +33,7 @@ config: # configs internal_config: true external_config: false - + # compliance read read_metadata_only: false read_watched_fields: {} diff --git a/src/test/resources/restapi/security_config.json b/src/test/resources/restapi/security_config.json index e8acc0a22a..e5c09050cc 100644 --- a/src/test/resources/restapi/security_config.json +++ b/src/test/resources/restapi/security_config.json @@ -1,5 +1,5 @@ { - + "dynamic":{ "filtered_alias_mode":"warn", "disable_rest_auth": false, @@ -29,13 +29,13 @@ "challenge":true, "type":"kerberos", "config":{ - + } }, "authentication_backend":{ "type":"noop", "config":{ - + } }, "description":"Migrated from v6" @@ -48,13 +48,13 @@ "challenge":true, "type":"clientcert", "config":{ - + } }, "authentication_backend":{ "type":"noop", "config":{ - + } }, "description":"Migrated from v6" @@ -74,7 +74,7 @@ "authentication_backend":{ "type":"noop", "config":{ - + } }, "description":"Migrated from v6" @@ -87,13 +87,13 @@ "challenge":true, "type":"basic", "config":{ - + } }, "authentication_backend":{ "type":"intern", "config":{ - + } }, "description":"Migrated from v6" @@ -106,7 +106,7 @@ "authorization_backend":{ "type":"xxx", "config":{ - + } }, "description":"Migrated from v6" @@ -127,12 +127,12 @@ } }, "auth_failure_listeners":{ - + }, "do_not_fail_on_forbidden":false, "multi_rolespan_enabled":false, "hosts_resolver_mode":"ip-only", "do_not_fail_on_forbidden_empty":false } - + } diff --git a/src/test/resources/restapi/users_key_not_quoted.json b/src/test/resources/restapi/users_key_not_quoted.json index e69de29bb2..8b13789179 100644 --- a/src/test/resources/restapi/users_key_not_quoted.json +++ b/src/test/resources/restapi/users_key_not_quoted.json @@ -0,0 +1 @@ + diff --git a/src/test/resources/roles_invalidxcontent.yml b/src/test/resources/roles_invalidxcontent.yml index 8d805273cf..f67c09a823 100644 --- a/src/test/resources/roles_invalidxcontent.yml +++ b/src/test/resources/roles_invalidxcontent.yml @@ -5,6 +5,6 @@ opendistro_security_public: indices: indices: '.notexistingindexcvnjl9809991' - '*': + '*': - ALL invalid yml diff --git a/tools/install_demo_configuration.sh b/tools/install_demo_configuration.sh index 6d6203124a..21174e6f63 100755 --- a/tools/install_demo_configuration.sh +++ b/tools/install_demo_configuration.sh @@ -383,7 +383,7 @@ echo "plugins.security.enable_snapshot_restore_privilege: true" | $SUDO_CMD tee echo "plugins.security.check_snapshot_restore_write_privileges: true" | $SUDO_CMD tee -a "$OPENSEARCH_CONF_FILE" > /dev/null echo 'plugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]' | $SUDO_CMD tee -a "$OPENSEARCH_CONF_FILE" > /dev/null echo 'plugins.security.system_indices.enabled: true' | $SUDO_CMD tee -a "$OPENSEARCH_CONF_FILE" > /dev/null -echo 'plugins.security.system_indices.indices: [".plugins-ml-model", ".plugins-ml-task", ".opendistro-alerting-config", ".opendistro-alerting-alert*", ".opendistro-anomaly-results*", ".opendistro-anomaly-detector*", ".opendistro-anomaly-checkpoints", ".opendistro-anomaly-detection-state", ".opendistro-reports-*", ".opensearch-notifications-*", ".opensearch-notebooks", ".opensearch-observability", ".ql-datasources", ".opendistro-asynchronous-search-response*", ".replication-metadata-store", ".opensearch-knn-models"]' | $SUDO_CMD tee -a "$OPENSEARCH_CONF_FILE" > /dev/null +echo 'plugins.security.system_indices.indices: [".plugins-ml-model-group", ".plugins-ml-model", ".plugins-ml-task", ".opendistro-alerting-config", ".opendistro-alerting-alert*", ".opendistro-anomaly-results*", ".opendistro-anomaly-detector*", ".opendistro-anomaly-checkpoints", ".opendistro-anomaly-detection-state", ".opendistro-reports-*", ".opensearch-notifications-*", ".opensearch-notebooks", ".opensearch-observability", ".ql-datasources", ".opendistro-asynchronous-search-response*", ".replication-metadata-store", ".opensearch-knn-models"]' | $SUDO_CMD tee -a "$OPENSEARCH_CONF_FILE" > /dev/null #network.host if $SUDO_CMD grep --quiet -i "^network.host" "$OPENSEARCH_CONF_FILE"; then