diff --git a/.github/workflows/plugin_install.yml b/.github/workflows/plugin_install.yml index 756e79d585..afbb0bf7d4 100644 --- a/.github/workflows/plugin_install.yml +++ b/.github/workflows/plugin_install.yml @@ -3,7 +3,7 @@ name: Plugin Install on: [push, pull_request, workflow_dispatch] env: - OPENSEARCH_VERSION: 1.3.11 + OPENSEARCH_VERSION: 1.3.13 PLUGIN_NAME: opensearch-security jobs: diff --git a/build.gradle b/build.gradle index d91919bb72..31529e440e 100644 --- a/build.gradle +++ b/build.gradle @@ -58,11 +58,11 @@ repositories { ext { isSnapshot = "true" == System.getProperty("build.snapshot", "true") - opensearch_version = System.getProperty("opensearch.version", "1.3.11-SNAPSHOT") + opensearch_version = System.getProperty("opensearch.version", "1.3.13-SNAPSHOT") buildVersionQualifier = System.getProperty("build.version_qualifier", "") version_tokens = opensearch_version.tokenize('-') opensearch_build = version_tokens[0] + '.0' - kafka_version = '3.4.0' + kafka_version = '3.5.1' if (buildVersionQualifier) { opensearch_build += "-${buildVersionQualifier}" @@ -84,7 +84,7 @@ configurations.all { force "org.apache.commons:commons-lang3:3.4" force "org.springframework:spring-core:5.3.28" force "org.springframework:spring-expression:5.3.28" - force "com.google.guava:guava:30.0-jre" + force "com.google.guava:guava:32.1.1-jre" force "com.fasterxml.woodstox:woodstox-core:6.4.0" force "org.scala-lang:scala-library:2.13.9" force "org.apache.bcel:bcel:6.6.0" // This line should be removed once Spotbugs is upgraded to 4.7.4 @@ -92,13 +92,20 @@ configurations.all { } dependencies { + + modules { + module("org.bouncycastle:bcprov-jdk15on") { + replacedBy("org.bouncycastle:bcprov-jdk15to18", "the jdk15on artifacts are not supported anymore") + } + } + 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 'com.google.guava:guava:30.0-jre' + implementation 'com.google.guava:guava:32.1.1-jre' implementation 'org.greenrobot:eventbus:3.2.0' implementation 'commons-cli:commons-cli:1.3.1' - implementation 'org.bouncycastle:bcprov-jdk15on:1.70' + implementation 'org.bouncycastle:bcprov-jdk15to18:1.75' implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.1' implementation 'org.ldaptive:ldaptive:1.2.3' implementation 'org.apache.httpcomponents:httpclient-cache:4.5.13' @@ -133,7 +140,7 @@ dependencies { testImplementation 'junit:junit:4.13.1' testImplementation 'org.apache.httpcomponents:fluent-hc:4.5.13' testImplementation 'org.mockito:mockito-core:2.23.0' - testImplementation 'org.springframework.kafka:spring-kafka-test:2.9.6' + testImplementation 'org.springframework.kafka:spring-kafka-test:2.9.10' testImplementation 'javax.servlet:servlet-api:2.5' testImplementation 'com.unboundid:unboundid-ldapsdk:4.0.9' testImplementation 'com.github.stephenc.jcip:jcip-annotations:1.0-1' @@ -410,4 +417,4 @@ task updateVersion { } ant.replaceregexp(file:'build.gradle', match: '"opensearch.version", "\\d.*"', replace: '"opensearch.version", "' + newVersion.tokenize('-')[0] + '-SNAPSHOT"', flags:'g', byline:true) } -} +} diff --git a/plugin-security.policy b/plugin-security.policy index d34b40f1a9..a0b51c26a8 100644 --- a/plugin-security.policy +++ b/plugin-security.policy @@ -59,10 +59,13 @@ grant { permission java.net.NetPermission "getNetworkInformation"; permission java.net.NetPermission "getProxySelector"; permission java.net.SocketPermission "*", "connect,accept,resolve"; - + + // BouncyCastle permissions permission java.security.SecurityPermission "putProviderProperty.BC"; permission java.security.SecurityPermission "insertProvider.BC"; - + permission java.security.SecurityPermission "removeProviderProperty.BC"; + permission java.util.PropertyPermission "jdk.tls.rejectClientInitiatedRenegotiation", "write"; + permission java.lang.RuntimePermission "accessUserInformation"; permission java.security.SecurityPermission "org.apache.xml.security.register"; diff --git a/release-notes/opensearch-security.release-notes-1.3.12.0.md b/release-notes/opensearch-security.release-notes-1.3.12.0.md new file mode 100644 index 0000000000..d942c19a86 --- /dev/null +++ b/release-notes/opensearch-security.release-notes-1.3.12.0.md @@ -0,0 +1,9 @@ +## 2023-08-10 Version 1.3.12.0 + +Compatible with OpenSearch 1.3.12 + +### Maintenance + +* Bump BouncyCastle from jdk15on to jdk15to18 ([#2901](https://github.com/opensearch-project/security/pull/2901)) [#2931](https://github.com/opensearch-project/security/pull/2931) +* Update guava to address CVE-2023-2976 ([#3060](https://github.com/opensearch-project/security/pull/3060)) +* Bump the version of kafka and spring-kafka-test (CVE Related) ([#3087](https://github.com/opensearch-project/security/pull/3087)) diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index 240e7bf9f2..524061338a 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -99,8 +99,6 @@ import org.opensearch.security.support.WildcardMatcher; import org.opensearch.security.user.User; -import com.google.common.collect.Sets; - import static org.opensearch.security.OpenSearchSecurityPlugin.traceAction; import static org.opensearch.security.support.ConfigConstants.OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT; @@ -184,12 +182,12 @@ public boolean isInitialized() { return configModel !=null && configModel.getSecurityRoles() != null && dcm != null; } - private void setUserInfoInThreadContext(User user, Set mappedRoles) { + private void setUserInfoInThreadContext(User user) { if (threadContext.getTransient(OPENDISTRO_SECURITY_USER_INFO_THREAD_CONTEXT) == null) { StringJoiner joiner = new StringJoiner("|"); joiner.add(user.getName()); joiner.add(String.join(",", user.getRoles())); - joiner.add(String.join(",", Sets.union(user.getSecurityRoles(), mappedRoles))); + joiner.add(String.join(",", user.getSecurityRoles())); String requestedTenant = user.getRequestedTenant(); if (!Strings.isNullOrEmpty(requestedTenant)) { joiner.add(requestedTenant); @@ -235,7 +233,9 @@ public PrivilegesEvaluatorResponse evaluate(final User user, String action0, fin presponse.resolvedSecurityRoles.addAll(mappedRoles); final SecurityRoles securityRoles = getSecurityRoles(mappedRoles); - setUserInfoInThreadContext(user, mappedRoles); + // Add the security roles for this user so that they can be used for DLS parameter substitution. + user.addSecurityRoles(mappedRoles); + setUserInfoInThreadContext(user); final boolean isDebugEnabled = log.isDebugEnabled(); if (isDebugEnabled) { diff --git a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java index 982364fd73..39ad5d7b7e 100644 --- a/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java +++ b/src/main/java/org/opensearch/security/ssl/DefaultSecurityKeyStore.java @@ -17,6 +17,7 @@ package org.opensearch.security.ssl; +import com.google.common.collect.ImmutableList; import io.netty.buffer.PooledByteBufAllocator; import io.netty.handler.ssl.ApplicationProtocolConfig; import io.netty.handler.ssl.ClientAuth; @@ -58,6 +59,7 @@ import javax.net.ssl.SSLException; import javax.net.ssl.SSLParameters; +import org.bouncycastle.asn1.ASN1Object; import org.opensearch.security.ssl.util.CertFileProps; import org.opensearch.security.ssl.util.CertFromFile; import org.opensearch.security.ssl.util.CertFromKeystore; @@ -985,34 +987,27 @@ public String getSubjectAlternativeNames(X509Certificate cert) { } private List getOtherName(List altName) { - ASN1Primitive oct = null; - try { - byte[] altNameBytes = (byte[]) altName.get(1); - oct = (new ASN1InputStream(new ByteArrayInputStream(altNameBytes)).readObject()); - } catch (IOException e) { - throw new RuntimeException("Could not read ASN1InputStream", e); - } - if (oct instanceof ASN1TaggedObject) { - oct = ((ASN1TaggedObject) oct).getObject(); - } - ASN1Sequence seq = ASN1Sequence.getInstance(oct); - - // Get object identifier from first in sequence - ASN1ObjectIdentifier asnOID = (ASN1ObjectIdentifier) seq.getObjectAt(0); - String oid = asnOID.getId(); - - // Get value of object from second element - final ASN1TaggedObject obj = (ASN1TaggedObject) seq.getObjectAt(1); - // Could be tagged twice due to bug in java cert.getSubjectAltName - ASN1Primitive prim = obj.getObject(); - if (prim instanceof ASN1TaggedObject) { - prim = ASN1TaggedObject.getInstance(((ASN1TaggedObject) prim)).getObject(); - } - - if (prim instanceof ASN1String) { - return Collections.unmodifiableList(Arrays.asList(oid, ((ASN1String) prim).getString())); + if (altName.size() < 2) { + log.warn("Couldn't parse subject alternative names"); + return null; + } + try (final ASN1InputStream in = new ASN1InputStream((byte[]) altName.get(1))) { + final ASN1Primitive asn1Primitive = in.readObject(); + final ASN1Sequence sequence = ASN1Sequence.getInstance(asn1Primitive); + final ASN1ObjectIdentifier asn1ObjectIdentifier = ASN1ObjectIdentifier.getInstance(sequence.getObjectAt(0)); + final ASN1TaggedObject asn1TaggedObject = ASN1TaggedObject.getInstance(sequence.getObjectAt(1)); + ASN1Object maybeTaggedAsn1Primitive = asn1TaggedObject.getBaseObject(); + if (maybeTaggedAsn1Primitive instanceof ASN1TaggedObject) { + maybeTaggedAsn1Primitive = ASN1TaggedObject.getInstance(maybeTaggedAsn1Primitive).getBaseObject(); + } + if (maybeTaggedAsn1Primitive instanceof ASN1String) { + return ImmutableList.of(asn1ObjectIdentifier.getId(), maybeTaggedAsn1Primitive.toString()); + } else { + log.warn("Couldn't parse subject alternative names"); + return null; + } + } catch (final Exception ioe) { // catch all exception here since BC throws diff exceptions + throw new RuntimeException("Couldn't parse subject alternative names", ioe); } - - return null; } } 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 e150f33d65..24ccd41aac 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 @@ -19,6 +19,7 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; +import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -36,7 +37,6 @@ import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; -import org.mockito.internal.util.reflection.FieldSetter; import org.opensearch.security.user.AuthCredentials; import org.opensearch.security.util.FakeRestRequest; @@ -192,14 +192,17 @@ public void testBasicAuthHeader() throws Exception { Settings settings = Settings.builder().put("signing_key", BaseEncoding.base64().encode(secretKey)).build(); HTTPJwtAuthenticator jwtAuth = new HTTPJwtAuthenticator(settings, null); JwtParser jwtParser = Mockito.spy(JwtParser.class); - FieldSetter.setField(jwtAuth, HTTPJwtAuthenticator.class.getDeclaredField("jwtParser"), jwtParser); + + Field jwtParserField = HTTPJwtAuthenticator.class.getDeclaredField("jwtParser"); + jwtParserField.setAccessible(true); + jwtParserField.set(jwtAuth, jwtParser); String basicAuth = BaseEncoding.base64().encode("user:password".getBytes(StandardCharsets.UTF_8)); Map headers = Collections.singletonMap(HttpHeaders.AUTHORIZATION, "Basic " + basicAuth); AuthCredentials creds = jwtAuth.extractCredentials(new FakeRestRequest(headers, Collections.emptyMap()), null); Assert.assertNull(creds); - Mockito.verifyZeroInteractions(jwtParser); + Mockito.verifyNoInteractions(jwtParser); } @Test 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 a8efa0fc3b..ca0acd5864 100644 --- a/src/test/java/org/opensearch/security/ssl/util/SSLConnectionTestUtilTests.java +++ b/src/test/java/org/opensearch/security/ssl/util/SSLConnectionTestUtilTests.java @@ -90,7 +90,7 @@ public void testConnectionSSLNotAvailableIOException() throws Exception { SSLConnectionTestResult result = connectionTestUtil.testConnection(); verifyClientHelloSend(); - Mockito.verifyZeroInteractions(inputStreamReader); + Mockito.verifyNoMoreInteractions(inputStreamReader); verifyOpenSearchPingSend(); Mockito.verify(socket, Mockito.times(2)).close(); Assert.assertEquals("Unexpected result for testConnection invocation", SSLConnectionTestResult.SSL_NOT_AVAILABLE, result); @@ -152,7 +152,7 @@ public void testConnectionOpenSearchPingFailedIOException() throws Exception { verifyClientHelloSend(); verifyOpenSearchPingSend(); - Mockito.verifyZeroInteractions(inputStream); + Mockito.verifyNoInteractions(inputStream); Mockito.verify(socket, Mockito.times(2)).close(); Assert.assertEquals("Unexpected result for testConnection invocation", SSLConnectionTestResult.OPENSEARCH_PING_FAILED, result); }