Skip to content

Commit

Permalink
Limit the use of extensions term in the codebase (opensearch-project#…
Browse files Browse the repository at this point in the history
…2748)

* Limit the use of extensions term in the codebase

Extensions are a big part of what we are building into OpenSearch and
Security.  While we need these features we should try to build them as
generically as possible, this checkstyle scan will help enforce this and
also allow for working around the term usage with comments as we do have
places where extensions need to be treated differently.

Signed-off-by: Peter Nied <petern@amazon.com>
  • Loading branch information
peternied committed May 9, 2023
1 parent 54d47ab commit f4def32
Show file tree
Hide file tree
Showing 16 changed files with 60 additions and 18 deletions.
9 changes: 8 additions & 1 deletion checkstyle/sun_checks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,21 @@
<property name="severity" value="error"/>
</module>

<module name="RegexpSingleline">
<property name="format" value="extension"/>
<property name="ignoreCase" value="true"/>
<property name="message" value="Extension should only be used sparingly to keep implementations as generic as possible" />
<property name="severity" value="error"/>
</module>

<module name="SuppressWithPlainTextCommentFilter">
<property name="offCommentFormat" value="CS-SUPPRESS-ALL: .+"/> <!-- Require an explaination after surpressing -->
<property name="onCommentFormat" value="CS-ENFORCE-ALL"/>
</module>

<module name="SuppressWithPlainTextCommentFilter">
<property name="offCommentFormat" value="CS-SUPPRESS-SINGLE\: ([\w\|]+) .+"/> <!-- Require an explaination after surpressing -->
<property name="onCommentFormat" value="CS-ENFORCE-SINGLE"/>
<property name="onCommentFormat" value="CS-ENFORCE-SINGLE()"/>
<property name="checkFormat" value="$1"/>
</module>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public SnapshotSteps(RestHighLevelClient restHighLevelClient) {

// CS-SUPPRESS-SINGLE: RegexpSingleline It is not possible to use phrase "cluster manager" instead of master here
public org.opensearch.action.support.master.AcknowledgedResponse createSnapshotRepository(String repositoryName, String snapshotDirPath, String type)
//CS-ENFORCE-SINGLE
// CS-ENFORCE-SINGLE
throws IOException {
PutRepositoryRequest createRepositoryRequest = new PutRepositoryRequest().name(repositoryName).type(type)
.settings(Map.of("location", snapshotDirPath));
Expand Down Expand Up @@ -70,7 +70,7 @@ public org.opensearch.action.support.master.AcknowledgedResponse deleteSnapshotR
return snapshotClient.deleteRepository(request, DEFAULT);
}

//CS-SUPPRESS-SINGLE: RegexpSingleline: It is not possible to use phrase "cluster manager" instead of master here
//CS-SUPPRESS-SINGLE: RegexpSingleline It is not possible to use phrase "cluster manager" instead of master here
public org.opensearch.action.support.master.AcknowledgedResponse deleteSnapshot(String repositoryName, String snapshotName) throws IOException {
//CS-ENFORCE-SINGLE
return snapshotClient.delete(new DeleteSnapshotRequest(repositoryName, snapshotName), DEFAULT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
package org.opensearch.test.framework.certificate;


// CS-SUPPRESS-SINGLE: RegexpSingleline Extension is used to refer to certificate extensions, keeping this rule disable for the whole file
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -218,3 +218,4 @@ ExtendedKeyUsage getExtendedKeyUsage() {
return new ExtendedKeyUsage(usages);
}
}
// CS-ENFORCE-SINGLE
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

package org.opensearch.test.framework.certificate;

// CS-SUPPRESS-SINGLE: RegexpSingleline Extension is used to refer to certificate extensions, keeping this rule disable for the whole file
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
Expand Down Expand Up @@ -222,3 +223,4 @@ private BigInteger generateNextCertificateSerialNumber() {
return BigInteger.valueOf(ID_COUNTER.incrementAndGet());
}
}
// CS-ENFORCE-SINGLE
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;

// CS-SUPPRESS-SINGLE: RegexpSingleline Extension is used to refer to certificate extensions
/**
* The class is associated with certificate extensions related to key usages. These extensions are defined by
* <a href="https://www.rfc-editor.org/rfc/rfc5280.html">RFC 5280</a> and describes allowed usage of public kay which is embedded in
Expand All @@ -25,6 +26,7 @@
*
* @see <a href="https://www.rfc-editor.org/rfc/rfc5280.html">RFC 5280</a>
*/
// CS-ENFORCE-SINGLE
enum PublicKeyUsage {
DIGITAL_SIGNATURE(KeyUsage.digitalSignature),
KEY_CERT_SIGN(KeyUsage.keyCertSign),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ public class TestCertificates {
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_EXTENSION = ".cert";
private static final String KEY_FILE_EXTENSION = ".key";
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<CertificateData> nodeCertificates;
Expand Down Expand Up @@ -106,7 +106,7 @@ public CertificateData createSelfSignedCertificate(String distinguishedName) {
* @return file which contains certificate in PEM format, defined by <a href="https://www.rfc-editor.org/rfc/rfc1421.txt">RFC 1421</a>
*/
public File getRootCertificate() {
return createTempFile("root", CERTIFICATE_FILE_EXTENSION, caCertificate.certificateInPemFormat());
return createTempFile("root", CERTIFICATE_FILE_EXT, caCertificate.certificateInPemFormat());
}

public CertificateData getRootCertificateData() {
Expand All @@ -120,7 +120,7 @@ public CertificateData getRootCertificateData() {
*/
public File getNodeCertificate(int node) {
CertificateData certificateData = getNodeCertificateData(node);
return createTempFile("node-" + node, CERTIFICATE_FILE_EXTENSION, certificateData.certificateInPemFormat());
return createTempFile("node-" + node, CERTIFICATE_FILE_EXT, certificateData.certificateInPemFormat());
}

public CertificateData getNodeCertificateData(int node) {
Expand Down Expand Up @@ -178,7 +178,7 @@ public CertificateData getLdapCertificateData() {
*/
public File getNodeKey(int node, String privateKeyPassword) {
CertificateData certificateData = nodeCertificates.get(node);
return createTempFile("node-" + node, KEY_FILE_EXTENSION, certificateData.privateKeyInPemFormat(privateKeyPassword));
return createTempFile("node-" + node, KEY_FILE_EXT, certificateData.privateKeyInPemFormat(privateKeyPassword));
}

/**
Expand All @@ -187,7 +187,7 @@ public File getNodeKey(int node, String privateKeyPassword) {
* @return file which contains certificate in PEM format, defined by <a href="https://www.rfc-editor.org/rfc/rfc1421.txt">RFC 1421</a>
*/
public File getAdminCertificate() {
return createTempFile("admin", CERTIFICATE_FILE_EXTENSION, adminCertificate.certificateInPemFormat());
return createTempFile("admin", CERTIFICATE_FILE_EXT, adminCertificate.certificateInPemFormat());
}

public CertificateData getAdminCertificateData() {
Expand All @@ -202,7 +202,7 @@ public CertificateData getAdminCertificateData() {
* by <a href="https://www.rfc-editor.org/rfc/rfc1421.txt">RFC 1421</a>
*/
public File getAdminKey(String privateKeyPassword) {
return createTempFile("admin", KEY_FILE_EXTENSION, adminCertificate.privateKeyInPemFormat(privateKeyPassword));
return createTempFile("admin", KEY_FILE_EXT, adminCertificate.privateKeyInPemFormat(privateKeyPassword));
}

public String[] getAdminDNs() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

package org.opensearch.security;

// CS-SUPPRESS-SINGLE: RegexpSingleline Extensions manager used to allow/disallow TLS connections to extensions
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
Expand Down Expand Up @@ -192,6 +193,7 @@
import org.opensearch.transport.TransportResponseHandler;
import org.opensearch.transport.TransportService;
import org.opensearch.watcher.ResourceWatcherService;
// CS-ENFORCE-SINGLE

public final class OpenSearchSecurityPlugin extends OpenSearchSecuritySSLPlugin implements ClusterPlugin, MapperPlugin {

Expand Down Expand Up @@ -1188,6 +1190,7 @@ public static class GuiceHolder implements LifecycleComponent {
private static IndicesService indicesService;
private static PitService pitService;

// CS-SUPPRESS-SINGLE: RegexpSingleline Extensions manager used to allow/disallow TLS connections to extensions
private static ExtensionsManager extensionsManager;

@Inject
Expand All @@ -1199,6 +1202,7 @@ public GuiceHolder(final RepositoriesService repositoriesService,
GuiceHolder.pitService = pitService;
GuiceHolder.extensionsManager = extensionsManager;
}
// CS-ENFORCE-SINGLE

public static RepositoriesService getRepositoriesService() {
return repositoriesService;
Expand All @@ -1214,7 +1218,9 @@ public static IndicesService getIndicesService() {

public static PitService getPitService() { return pitService; }

// CS-SUPPRESS-SINGLE: RegexpSingleline Extensions manager used to allow/disallow TLS connections to extensions
public static ExtensionsManager getExtensionsManager() { return extensionsManager; }
// CS-ENFORCE-SINGLE


@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private boolean handle() {
threadContext.putHeader(ConfigConstants.OPENDISTRO_SECURITY_FILTER_LEVEL_DLS_DONE, request.toString());

try {
if (!createQueryExtension()) {
if (!modifyQuery()) {
return true;
}

Expand Down Expand Up @@ -186,7 +186,7 @@ private boolean handle(SearchRequest searchRequest, StoredContext ctx) {

if (localClusterAlias != null) {
try {
createQueryExtension(localClusterAlias);
modifyQuery(localClusterAlias);
} catch (Exception e) {
log.error("Unable to handle filter level DLS", e);
listener.onFailure(new OpenSearchSecurityException("Unable to handle filter level DLS", e));
Expand Down Expand Up @@ -387,11 +387,11 @@ private GetResult searchHitToGetResult(SearchHit hit) {
documentFields, metadataFields);
}

private boolean createQueryExtension() throws IOException {
return createQueryExtension(null);
private boolean modifyQuery() throws IOException {
return modifyQuery(null);
}

private boolean createQueryExtension(String localClusterAlias) throws IOException {
private boolean modifyQuery(String localClusterAlias) throws IOException {
Map<String, Set<String>> filterLevelQueries = evaluatedDlsFlsConfig.getDlsQueriesByIndex();

BoolQueryBuilder dlsQueryBuilder = QueryBuilders.boolQuery().minimumShouldMatch(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,10 @@ private void printJCEWarnings() {
final int aesMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES");

if (aesMaxKeyLength < 256) {
// CS-SUPPRESS-SINGLE: RegexpSingleline Java Cryptography Extension is unrelated to OpenSearch extensions
log.info("AES-256 not supported, max key length for AES is {} bit."
+ " (This is not an issue, it just limits possible encryption strength. To enable AES 256, install 'Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files')", aesMaxKeyLength);
// CS-ENFORCE-SINGLE
}
} catch (final NoSuchAlgorithmException e) {
log.error("AES encryption not supported (SG 1). ", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.HashSet;
import java.util.Set;

// CS-SUPPRESS-SINGLE: RegexpSingleline certification extensions is unrelated to OpenSearch extensions
/**
* Convenience class to handle validation of certificates, aliases and keystores
*
Expand All @@ -62,6 +63,7 @@
* 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
{

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/opensearch/security/ssl/util/TLSUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ public class TLSUtil {
private static final int SSL_CONTENT_TYPE_ALERT = 21;
private static final int SSL_CONTENT_TYPE_HANDSHAKE = 22;
private static final int SSL_CONTENT_TYPE_APPLICATION_DATA = 23;
// CS-SUPPRESS-SINGLE: RegexpSingleline Extensions heartbeat needs special handling by security extension
private static final int SSL_CONTENT_TYPE_EXTENSION_HEARTBEAT = 24;
// CS-ENFORCE-SINGLE
private static final int SSL_RECORD_HEADER_LENGTH = 5;

private TLSUtil() {
Expand All @@ -39,9 +41,11 @@ public static boolean isTLS(ByteBuf buffer) {
case SSL_CONTENT_TYPE_ALERT:
case SSL_CONTENT_TYPE_HANDSHAKE:
case SSL_CONTENT_TYPE_APPLICATION_DATA:
// CS-SUPPRESS-SINGLE: RegexpSingleline Extensions heartbeat needs special handling by security extension
case SSL_CONTENT_TYPE_EXTENSION_HEARTBEAT:
tls = true;
break;
// CS-ENFORCE-SINGLE
default:
// SSLv2 or bad data
tls = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ public class ConfigConstants {

public static final String OPENDISTRO_SECURITY_SSL_TRANSPORT_TRUSTED_CLUSTER_REQUEST = OPENDISTRO_SECURITY_CONFIG_PREFIX+"ssl_transport_trustedcluster_request";

// CS-SUPPRESS-SINGLE: RegexpSingleline Extensions manager used to allow/disallow TLS connections to extensions
public static final String OPENDISTRO_SECURITY_SSL_TRANSPORT_EXTENSION_REQUEST = OPENDISTRO_SECURITY_CONFIG_PREFIX+"ssl_transport_extension_request";

// CS-ENFORCE-SINGLE

/**
* Set by the SSL plugin, this is the peer node certificate on the transport layer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ public static boolean isDirectRequest(final ThreadContext context) {
|| context.getTransient(ConfigConstants.OPENDISTRO_SECURITY_CHANNEL_TYPE) == null;
}

// CS-SUPPRESS-SINGLE: RegexpSingleline Java Cryptography Extension is unrelated to OpenSearch extensions
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) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,10 @@ public static int execute(final String[] args) throws Exception {
options.addOption( "nhnv", "disable-host-name-verification", false, "Disable hostname verification" );
options.addOption(Option.builder("ts").longOpt("truststore").hasArg().argName("file").desc("Path to truststore (JKS/PKCS12 format)").build());
options.addOption(Option.builder("ks").longOpt("keystore").hasArg().argName("file").desc("Path to keystore (JKS/PKCS12 format").build());
// CS-SUPPRESS-SINGLE: RegexpSingleline file extensions is unrelated to OpenSearch extensions
options.addOption(Option.builder("tst").longOpt("truststore-type").hasArg().argName("type").desc("JKS or PKCS12, if not given we use the file extension to dectect the type").build());
options.addOption(Option.builder("kst").longOpt("keystore-type").hasArg().argName("type").desc("JKS or PKCS12, if not given we use the file extension to dectect the type").build());
// CS-ENFORCE-SINGLE
options.addOption(Option.builder("tspass").longOpt("truststore-password").hasArg().argName("password").desc("Truststore password").build());
options.addOption(Option.builder("kspass").longOpt("keystore-password").hasArg().argName("password").desc("Keystore password").build());
options.addOption(Option.builder("cd").longOpt("configdir").hasArg().argName("directory").desc("Directory for config files").build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@
import org.opensearch.security.support.ConfigConstants;
import org.opensearch.transport.TransportRequest;

// CS-SUPPRESS-SINGLE: RegexpSingleline Java Cryptography Extension is unrelated to OpenSearch extensions
/**
* Implementation to evaluate a certificate extension with a given OID
* and value to the same value found on the peer certificate
*
*/
// CS-ENFORCE-SINGLE
public final class OIDClusterRequestEvaluator implements InterClusterRequestEvaluator {
private final String certOid;

Expand All @@ -49,8 +51,10 @@ public OIDClusterRequestEvaluator(final Settings settings) {
public boolean isInterClusterRequest(TransportRequest request, X509Certificate[] localCerts, X509Certificate[] peerCerts,
final String principal) {
if (localCerts != null && localCerts.length > 0 && peerCerts != null && peerCerts.length > 0) {
// CS-SUPPRESS-SINGLE: RegexpSingleline Java Cryptography Extension is unrelated to OpenSearch extensions
final byte[] localValue = localCerts[0].getExtensionValue(certOid);
final byte[] peerValue = peerCerts[0].getExtensionValue(certOid);
// CS-ENFORCE-SINGLE
if (localValue != null && peerValue != null) {
return Arrays.equals(localValue, peerValue);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

package org.opensearch.security.transport;

// CS-SUPPRESS-SINGLE: RegexpSingleline Extensions manager used to allow/disallow TLS connections to extensions
import java.net.InetSocketAddress;
import java.security.cert.X509Certificate;
import java.util.Objects;
Expand Down Expand Up @@ -62,6 +63,7 @@
import org.opensearch.transport.TransportRequestHandler;

import static org.opensearch.security.OpenSearchSecurityPlugin.isActionTraceEnabled;
// CS-ENFORCE-SINGLE

public class SecurityRequestHandler<T extends TransportRequest> extends SecuritySSLRequestHandler<T> {

Expand Down Expand Up @@ -195,11 +197,13 @@ else if(!Strings.isNullOrEmpty(injectedUserHeader)) {
//if the incoming request is an internal:* or a shard request allow only if request was sent by a server node
//if transport channel is not a netty channel but a direct or local channel (e.g. send via network) then allow it (regardless of beeing a internal: or shard request)
//also allow when issued from a remote cluster for cross cluster search
// CS-SUPPRESS-SINGLE: RegexpSingleline Used to allow/disallow TLS connections to extensions
if ( !HeaderHelper.isInterClusterRequest(getThreadContext())
&& !HeaderHelper.isTrustedClusterRequest(getThreadContext())
&& !HeaderHelper.isExtensionRequest(getThreadContext())
&& !task.getAction().equals("internal:transport/handshake")
&& (task.getAction().startsWith("internal:") || task.getAction().contains("["))) {
// CS-ENFORCE-SINGLE

auditLog.logMissingPrivileges(task.getAction(), request, task);
log.error("Internal or shard requests ("+task.getAction()+") not allowed from a non-server node for transport type "+transportChannel.getChannelType());
Expand All @@ -224,9 +228,11 @@ else if(!Strings.isNullOrEmpty(injectedUserHeader)) {
}

//network intercluster request or cross search cluster request
// CS-SUPPRESS-SINGLE: RegexpSingleline Used to allow/disallow TLS connections to extensions
if(HeaderHelper.isInterClusterRequest(getThreadContext())
|| HeaderHelper.isTrustedClusterRequest(getThreadContext())
|| HeaderHelper.isExtensionRequest(getThreadContext())) {
// CS-ENFORCE-SINGLE

final String userHeader = getThreadContext().getHeader(ConfigConstants.OPENDISTRO_SECURITY_USER_HEADER);
final String injectedRolesHeader = getThreadContext().getHeader(ConfigConstants.OPENDISTRO_SECURITY_INJECTED_ROLES_HEADER);
Expand Down Expand Up @@ -328,13 +334,15 @@ protected void addAdditionalContextValues(final String action, final TransportRe
}
}

// CS-SUPPRESS-SINGLE: RegexpSingleline Extensions manager used to allow/disallow TLS connections to extensions
String extensionUniqueId = getThreadContext().getHeader("extension_unique_id");
if (extensionUniqueId != null) {
ExtensionsManager extManager = OpenSearchSecurityPlugin.GuiceHolder.getExtensionsManager();
if (extManager.lookupInitializedExtensionById(extensionUniqueId).isPresent()) {
getThreadContext().putTransient(ConfigConstants.OPENDISTRO_SECURITY_SSL_TRANSPORT_EXTENSION_REQUEST, Boolean.TRUE);
}
}
// CS-ENFORCE-SINGLE

super.addAdditionalContextValues(action, request, localCerts, peerCerts, principal);
}
Expand Down

0 comments on commit f4def32

Please sign in to comment.