Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into upgrade-roles
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Nied <petern@amazon.com>
  • Loading branch information
peternied committed Mar 19, 2024
2 parents b71ee75 + 32ba887 commit 4f53ee2
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
working-directory: downloaded-artifacts

- name: Upload Coverage with retry
uses: Wandalen/wretry.action@v1.4.4
uses: Wandalen/wretry.action@v1.4.10
with:
attempt_limit: 5
attempt_delay: 2000
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/plugin_install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
shell: bash

- name: Run Opensearch with A Single Plugin
uses: derek-ho/start-opensearch@v2
uses: derek-ho/start-opensearch@v3
with:
opensearch-version: ${{ env.OPENSEARCH_VERSION }}
plugins: "file:$(pwd)/${{ env.PLUGIN_NAME }}.zip"
Expand Down
33 changes: 17 additions & 16 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ buildscript {
opensearch_build = version_tokens[0] + '.0'

common_utils_version = System.getProperty("common_utils.version", '3.0.0.0-SNAPSHOT')
kafka_version = '3.6.1'
apache_cxf_version = '4.0.3'
kafka_version = '3.7.0'
apache_cxf_version = '4.0.4'
open_saml_version = '4.3.0'
one_login_java_saml = '2.9.0'
jjwt_version = '0.12.5'
guava_version = '32.1.3-jre'
jaxb_version = '2.3.9'
spring_version = '5.3.32'
spring_version = '5.3.33'

if (buildVersionQualifier) {
opensearch_build += "-${buildVersionQualifier}"
Expand Down Expand Up @@ -64,7 +64,7 @@ plugins {
id 'maven-publish'
id 'com.diffplug.spotless' version '6.25.0'
id 'checkstyle'
id 'com.netflix.nebula.ospackage' version "11.8.0"
id 'com.netflix.nebula.ospackage' version "11.8.1"
id "org.gradle.test-retry" version "1.5.8"
id 'eclipse'
id "com.github.spotbugs" version "5.2.5"
Expand Down Expand Up @@ -476,7 +476,7 @@ configurations {
resolutionStrategy {
force 'commons-codec:commons-codec:1.16.1'
force 'org.slf4j:slf4j-api:1.7.36'
force 'org.scala-lang:scala-library:2.13.12'
force 'org.scala-lang:scala-library:2.13.13'
force "com.fasterxml.jackson:jackson-bom:${versions.jackson}"
force "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
force "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${versions.jackson}"
Expand All @@ -494,14 +494,14 @@ configurations {
force "org.apache.commons:commons-lang3:${versions.commonslang}"

// for spotless transitive dependency CVE
force "org.eclipse.platform:org.eclipse.core.runtime:3.30.0"
force "org.eclipse.platform:org.eclipse.core.runtime:3.31.0"

// For integrationTest
force "org.apache.httpcomponents:httpclient:4.5.14"
force "org.apache.httpcomponents:httpcore:4.4.16"
force "com.google.errorprone:error_prone_annotations:2.25.0"
force "com.google.errorprone:error_prone_annotations:2.26.1"
force "org.checkerframework:checker-qual:3.42.0"
force "ch.qos.logback:logback-classic:1.2.13"
force "ch.qos.logback:logback-classic:1.5.3"
}
}

Expand Down Expand Up @@ -609,9 +609,9 @@ dependencies {
runtimeOnly 'com.eclipsesource.minimal-json:minimal-json:0.9.5'
runtimeOnly 'commons-codec:commons-codec:1.16.1'
runtimeOnly 'org.cryptacular:cryptacular:1.2.6'
compileOnly 'com.google.errorprone:error_prone_annotations:2.25.0'
compileOnly 'com.google.errorprone:error_prone_annotations:2.26.1'
runtimeOnly 'com.sun.istack:istack-commons-runtime:4.2.0'
runtimeOnly 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.1'
runtimeOnly 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.2'
runtimeOnly 'org.ow2.asm:asm:9.6'

testImplementation 'org.apache.camel:camel-xmlsecurity:3.22.1'
Expand Down Expand Up @@ -649,7 +649,7 @@ dependencies {
runtimeOnly 'org.xerial.snappy:snappy-java:1.1.10.5'
runtimeOnly 'org.codehaus.woodstox:stax2-api:4.2.2'
runtimeOnly "org.glassfish.jaxb:txw2:${jaxb_version}"
runtimeOnly 'com.fasterxml.woodstox:woodstox-core:6.6.0'
runtimeOnly 'com.fasterxml.woodstox:woodstox-core:6.6.1'
runtimeOnly 'org.apache.ws.xmlschema:xmlschema-core:2.3.1'
runtimeOnly 'org.apache.santuario:xmlsec:2.3.4'
runtimeOnly "com.github.luben:zstd-jni:${versions.zstd}"
Expand Down Expand Up @@ -677,6 +677,7 @@ dependencies {
testImplementation 'org.apache.httpcomponents:fluent-hc:4.5.14'
testImplementation "org.apache.httpcomponents.client5:httpclient5-fluent:${versions.httpclient5}"
testImplementation "org.apache.kafka:kafka_2.13:${kafka_version}"
testImplementation "org.apache.kafka:kafka-server:${kafka_version}"
testImplementation "org.apache.kafka:kafka-server-common:${kafka_version}"
testImplementation "org.apache.kafka:kafka-server-common:${kafka_version}:test"
testImplementation "org.apache.kafka:kafka-group-coordinator:${kafka_version}"
Expand All @@ -687,7 +688,7 @@ dependencies {
testImplementation "org.springframework:spring-beans:${spring_version}"
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
testImplementation('org.awaitility:awaitility:4.2.0') {
testImplementation('org.awaitility:awaitility:4.2.1') {
exclude(group: 'org.hamcrest', module: 'hamcrest')
}
// Only osx-x86_64, osx-aarch_64, linux-x86_64, linux-aarch_64, windows-x86_64 are available
Expand All @@ -702,10 +703,10 @@ dependencies {
testRuntimeOnly ("org.springframework:spring-core:${spring_version}") {
exclude(group:'org.springframework', module: 'spring-jcl' )
}
testRuntimeOnly 'org.scala-lang:scala-library:2.13.12'
testRuntimeOnly 'org.scala-lang:scala-library:2.13.13'
testRuntimeOnly 'com.yammer.metrics:metrics-core:2.2.0'
testRuntimeOnly 'com.typesafe.scala-logging:scala-logging_3:3.9.5'
testRuntimeOnly('org.apache.zookeeper:zookeeper:3.9.1') {
testRuntimeOnly('org.apache.zookeeper:zookeeper:3.9.2') {
exclude(group:'ch.qos.logback', module: 'logback-classic' )
exclude(group:'ch.qos.logback', module: 'logback-core' )
}
Expand All @@ -730,7 +731,7 @@ dependencies {
integrationTestImplementation 'org.hamcrest:hamcrest:2.2'
integrationTestImplementation "org.bouncycastle:bcpkix-jdk18on:${versions.bouncycastle}"
integrationTestImplementation "org.bouncycastle:bcutil-jdk18on:${versions.bouncycastle}"
integrationTestImplementation('org.awaitility:awaitility:4.2.0') {
integrationTestImplementation('org.awaitility:awaitility:4.2.1') {
exclude(group: 'org.hamcrest', module: 'hamcrest')
}
integrationTestImplementation 'com.unboundid:unboundid-ldapsdk:4.0.14'
Expand All @@ -741,7 +742,7 @@ dependencies {
integrationTestImplementation "org.apache.httpcomponents:httpasyncclient:4.1.5"

//spotless
implementation('com.google.googlejavaformat:google-java-format:1.19.2') {
implementation('com.google.googlejavaformat:google-java-format:1.21.0') {
exclude group: 'com.google.guava'
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,20 @@ public OpenSearchSecurityPlugin(final Settings settings, final Path configPath)
return;
}

if (settings.hasValue(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS)) {
verifyTLSVersion(
SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS,
settings.getAsList(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS)
);
}

if (settings.hasValue(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS)) {
verifyTLSVersion(
SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS,
settings.getAsList(SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS)
);
}

if (SSLConfig.isSslOnlyMode()) {
this.sslCertReloadEnabled = false;
log.warn("OpenSearch Security plugin run in ssl only mode. No authentication or authorization is performed");
Expand Down Expand Up @@ -437,6 +451,20 @@ public List<String> run() {
}
}

private void verifyTLSVersion(final String settings, final List<String> configuredProtocols) {
for (final var tls : configuredProtocols) {
if (tls.equalsIgnoreCase("TLSv1") || tls.equalsIgnoreCase("TLSv1.1")) {
deprecationLogger.deprecate(
settings,
"The '{}' setting contains {} protocol version which was deprecated since 2021 (RFC 8996). "
+ "Support for it will be removed in the next major release.",
settings,
tls
);
}
}
}

private String sha256(Path p) {

if (!Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public final class SSLConfigConstants {

private static final String[] _SECURE_SSL_PROTOCOLS = { "TLSv1.3", "TLSv1.2", "TLSv1.1" };

public static final String[] getSecureSSLProtocols(Settings settings, boolean http) {
public static String[] getSecureSSLProtocols(Settings settings, boolean http) {
List<String> configuredProtocols = null;

if (settings != null) {
Expand Down Expand Up @@ -233,7 +233,7 @@ public static final String[] getSecureSSLProtocols(Settings settings, boolean ht
};
// @formatter:on

public static final List<String> getSecureSSLCiphers(Settings settings, boolean http) {
public static List<String> getSecureSSLCiphers(Settings settings, boolean http) {

List<String> configuredCiphers = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public class SecuritySettingsConfigurer {
".plugins-flow-framework-templates",
".plugins-flow-framework-state"
);
static final Integer DEFAULT_PASSWORD_MIN_LENGTH = 8;
static String ADMIN_PASSWORD = "";
static String ADMIN_USERNAME = "admin";

Expand Down Expand Up @@ -131,7 +132,7 @@ void updateAdminPassword() {
final PasswordValidator passwordValidator = PasswordValidator.of(
Settings.builder()
.put(SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}")
.put(SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, 8)
.put(SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, DEFAULT_PASSWORD_MIN_LENGTH)
.build()
);

Expand All @@ -142,11 +143,19 @@ void updateAdminPassword() {
}

// If script execution environment is set to demo, validate custom password, else if set to test, skip validation
if (shouldValidatePassword
&& !ADMIN_PASSWORD.isEmpty()
&& passwordValidator.validate(ADMIN_USERNAME, ADMIN_PASSWORD) != RequestContentValidator.ValidationError.NONE) {
System.out.println("Password " + ADMIN_PASSWORD + " is weak. Please re-try with a stronger password.");
System.exit(-1);
if (shouldValidatePassword && !ADMIN_PASSWORD.isEmpty()) {
RequestContentValidator.ValidationError response = passwordValidator.validate(ADMIN_USERNAME, ADMIN_PASSWORD);
if (!RequestContentValidator.ValidationError.NONE.equals(response)) {
System.out.println(
String.format(
"Password %s failed validation: \"%s\". Please re-try with a minimum %d character password and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character that is strong. Password strength can be tested here: https://lowe.github.io/tryzxcvbn",
ADMIN_PASSWORD,
response.message(),
DEFAULT_PASSWORD_MIN_LENGTH
)
);
System.exit(-1);
}
}

// if ADMIN_PASSWORD is still an empty string, it implies no custom password was provided. We exit the setup.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.security.ssl.util;

import java.util.List;

import org.junit.Test;

import org.opensearch.common.settings.Settings;

import static org.opensearch.security.ssl.util.SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED_PROTOCOLS;
import static org.opensearch.security.ssl.util.SSLConfigConstants.SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS;
import static org.junit.Assert.assertArrayEquals;

public class SSLConfigConstantsTest {

@Test
public void testDefaultTLSProtocols() {
final var tlsDefaultProtocols = SSLConfigConstants.getSecureSSLProtocols(Settings.EMPTY, false);
assertArrayEquals(new String[] { "TLSv1.3", "TLSv1.2", "TLSv1.1" }, tlsDefaultProtocols);
}

@Test
public void testDefaultSSLProtocols() {
final var sslDefaultProtocols = SSLConfigConstants.getSecureSSLProtocols(Settings.EMPTY, true);
assertArrayEquals(new String[] { "TLSv1.3", "TLSv1.2", "TLSv1.1" }, sslDefaultProtocols);
}

@Test
public void testCustomTLSProtocols() {
final var tlsDefaultProtocols = SSLConfigConstants.getSecureSSLProtocols(
Settings.builder().putList(SECURITY_SSL_TRANSPORT_ENABLED_PROTOCOLS, List.of("TLSv1", "TLSv1.1")).build(),
false
);
assertArrayEquals(new String[] { "TLSv1", "TLSv1.1" }, tlsDefaultProtocols);
}

@Test
public void testCustomSSLProtocols() {
final var sslDefaultProtocols = SSLConfigConstants.getSecureSSLProtocols(
Settings.builder().putList(SECURITY_SSL_HTTP_ENABLED_PROTOCOLS, List.of("TLSv1", "TLSv1.1")).build(),
true
);
assertArrayEquals(new String[] { "TLSv1", "TLSv1.1" }, sslDefaultProtocols);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.opensearch.security.dlic.rest.validation.RequestContentValidator.ValidationError.INVALID_PASSWORD_INVALID_REGEX;
import static org.opensearch.security.dlic.rest.validation.RequestContentValidator.ValidationError.INVALID_PASSWORD_TOO_SHORT;
import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.DEFAULT_PASSWORD_MIN_LENGTH;
import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.REST_ENABLED_ROLES;
import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.SYSTEM_INDICES;
import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.isKeyPresentInYMLFile;
Expand All @@ -55,6 +58,9 @@ public class SecuritySettingsConfigurerTests {

private final String adminPasswordKey = ConfigConstants.OPENSEARCH_INITIAL_ADMIN_PASSWORD;

private static final String PASSWORD_VALIDATION_FAILURE_MESSAGE =
"Password %s failed validation: \"%s\". Please re-try with a minimum %d character password and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character that is strong. Password strength can be tested here: https://lowe.github.io/tryzxcvbn";

private static SecuritySettingsConfigurer securitySettingsConfigurer;

private static Installer installer;
Expand Down Expand Up @@ -125,7 +131,32 @@ public void testUpdateAdminPasswordWithWeakPassword() throws NoSuchFieldExceptio
System.setSecurityManager(null);
}

verifyStdOutContainsString("Password weakpassword is weak. Please re-try with a stronger password.");
verifyStdOutContainsString(
String.format(
PASSWORD_VALIDATION_FAILURE_MESSAGE,
"weakpassword",
INVALID_PASSWORD_INVALID_REGEX.message(),
DEFAULT_PASSWORD_MIN_LENGTH
)
);
}

@Test
public void testUpdateAdminPasswordWithShortPassword() throws NoSuchFieldException, IllegalAccessException {

setEnv(adminPasswordKey, "short");
try {
System.setSecurityManager(new NoExitSecurityManager());
securitySettingsConfigurer.updateAdminPassword();
} catch (SecurityException e) {
assertThat(e.getMessage(), equalTo("System.exit(-1) blocked to allow print statement testing."));
} finally {
System.setSecurityManager(null);
}

verifyStdOutContainsString(
String.format(PASSWORD_VALIDATION_FAILURE_MESSAGE, "short", INVALID_PASSWORD_TOO_SHORT.message(), DEFAULT_PASSWORD_MIN_LENGTH)
);
}

@Test
Expand Down

0 comments on commit 4f53ee2

Please sign in to comment.