diff --git a/server/src/main/java/org/elasticsearch/action/support/IndexComponentSelector.java b/server/src/main/java/org/elasticsearch/action/support/IndexComponentSelector.java index 0f8533b5c5d55..62b4f42e5ac08 100644 --- a/server/src/main/java/org/elasticsearch/action/support/IndexComponentSelector.java +++ b/server/src/main/java/org/elasticsearch/action/support/IndexComponentSelector.java @@ -83,7 +83,7 @@ public static IndexComponentSelector getByKeyOrThrow(@Nullable String key) { } IndexComponentSelector selector = getByKey(key); if (selector == null) { - throw new IllegalArgumentException( + throw new InvalidSelectorException( "Unknown key of index component selector [" + key + "], available options are: " + KEY_REGISTRY.keySet() ); } @@ -107,7 +107,7 @@ public static IndexComponentSelector read(StreamInput in) throws IOException { static IndexComponentSelector getById(byte id) { IndexComponentSelector indexComponentSelector = ID_REGISTRY.get(id); if (indexComponentSelector == null) { - throw new IllegalArgumentException( + throw new InvalidSelectorException( "Unknown id of index component selector [" + id + "], available options are: " + ID_REGISTRY ); } diff --git a/server/src/main/java/org/elasticsearch/action/support/InvalidSelectorException.java b/server/src/main/java/org/elasticsearch/action/support/InvalidSelectorException.java new file mode 100644 index 0000000000000..d34aa6125664a --- /dev/null +++ b/server/src/main/java/org/elasticsearch/action/support/InvalidSelectorException.java @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.action.support; + +/** + * Exception thrown when a :: selector is invalid. + */ +public class InvalidSelectorException extends IllegalArgumentException { + + public InvalidSelectorException(String message) { + super(message); + } + + public InvalidSelectorException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/server/src/main/java/org/elasticsearch/action/support/UnsupportedSelectorException.java b/server/src/main/java/org/elasticsearch/action/support/UnsupportedSelectorException.java new file mode 100644 index 0000000000000..bf1b08dc5a63d --- /dev/null +++ b/server/src/main/java/org/elasticsearch/action/support/UnsupportedSelectorException.java @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.action.support; + +/** + * Exception thrown when a :: selector is not supported. + */ +public class UnsupportedSelectorException extends IllegalArgumentException { + + public UnsupportedSelectorException(String expression) { + super("Index component selectors are not supported in this context but found selector in expression [" + expression + "]"); + } + +} diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java index 6b8619cec34f9..b7aad5676321e 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.support.IndexComponentSelector; import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.action.support.UnsupportedSelectorException; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.core.Nullable; import org.elasticsearch.core.Tuple; @@ -57,11 +58,7 @@ public List resolveIndexAbstractions( Tuple expressionAndSelector = IndexNameExpressionResolver.splitSelectorExpression(indexAbstraction); String selectorString = expressionAndSelector.v2(); if (indicesOptions.allowSelectors() == false && selectorString != null) { - throw new IllegalArgumentException( - "Index component selectors are not supported in this context but found selector in expression [" - + indexAbstraction - + "]" - ); + throw new UnsupportedSelectorException(indexAbstraction); } indexAbstraction = expressionAndSelector.v1(); IndexComponentSelector selector = IndexComponentSelector.getByKeyOrThrow(selectorString); diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java index 97ca52332510f..19189a81a0187 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java @@ -15,6 +15,7 @@ import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.support.IndexComponentSelector; import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.action.support.UnsupportedSelectorException; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexAbstraction.Type; import org.elasticsearch.cluster.project.ProjectResolver; @@ -2394,13 +2395,11 @@ private static IndexComponentSelector resolveAndValidateSelectorString(Supplier< * Checks the selectors that have been returned from splitting an expression and throws an exception if any were present. * @param expression Original expression * @param selector Selectors to validate - * @throws IllegalArgumentException if selectors are present + * @throws UnsupportedSelectorException if selectors are present */ private static void ensureNoSelectorsProvided(String expression, IndexComponentSelector selector) { if (selector != null) { - throw new IllegalArgumentException( - "Index component selectors are not supported in this context but found selector in expression [" + expression + "]" - ); + throw new UnsupportedSelectorException(expression); } } diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/AbstractRemoteClusterSecurityFailureStoreRestIT.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/AbstractRemoteClusterSecurityFailureStoreRestIT.java index 91c6919a3a5fc..88e8853165574 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/AbstractRemoteClusterSecurityFailureStoreRestIT.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/AbstractRemoteClusterSecurityFailureStoreRestIT.java @@ -170,7 +170,7 @@ protected Tuple getSingleDataAndFailureIndices(String dataStream } protected static void assertSelectorsNotSupported(ResponseException exception) { - assertThat(exception.getResponse().getStatusLine().getStatusCode(), equalTo(403)); + assertThat(exception.getResponse().getStatusLine().getStatusCode(), equalTo(400)); assertThat(exception.getMessage(), containsString("Selectors are not yet supported on remote cluster patterns")); } diff --git a/x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/failurestore/FailureStoreSecurityRestIT.java b/x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/failurestore/FailureStoreSecurityRestIT.java index 6cdd439571f1c..2e5c021aa6e3b 100644 --- a/x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/failurestore/FailureStoreSecurityRestIT.java +++ b/x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/failurestore/FailureStoreSecurityRestIT.java @@ -1891,7 +1891,10 @@ public void testWriteAndManageOperations() throws IOException { expectThrows(() -> deleteDataStream(MANAGE_FAILURE_STORE_ACCESS, "test1"), 403); // selectors aren't supported for deletes so we get a 403 - expectThrows(() -> deleteDataStream(MANAGE_FAILURE_STORE_ACCESS, "test1::failures"), 403); + expectThrowsBadRequest( + () -> deleteDataStream(MANAGE_FAILURE_STORE_ACCESS, "test1::failures"), + containsString("Index component selectors are not supported in this context but found selector in expression [test1::failures]") + ); // manage user can delete data stream deleteDataStream(MANAGE_ACCESS, "test1"); @@ -2345,6 +2348,12 @@ private static void expectThrows(ThrowingRunnable runnable, int statusCode) { assertThat(ex.getResponse().getStatusLine().getStatusCode(), equalTo(statusCode)); } + private void expectThrowsBadRequest(ThrowingRunnable runnable, Matcher errorMatcher) { + ResponseException ex = expectThrows(ResponseException.class, runnable); + assertThat(ex.getResponse().getStatusLine().getStatusCode(), equalTo(400)); + assertThat(ex.getMessage(), errorMatcher); + } + private void expectThrowsUnauthorized(String user, Search search, Matcher errorMatcher) { ResponseException ex = expectThrows(ResponseException.class, () -> performRequestMaybeUsingApiKey(user, search.toSearchRequest())); assertThat(ex.getResponse().getStatusLine().getStatusCode(), equalTo(403)); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 6cd937cb2f8c7..f7f0f48f1c0fe 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -28,7 +28,9 @@ import org.elasticsearch.action.index.TransportIndexAction; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.support.GroupedActionListener; +import org.elasticsearch.action.support.InvalidSelectorException; import org.elasticsearch.action.support.SubscribableListener; +import org.elasticsearch.action.support.UnsupportedSelectorException; import org.elasticsearch.action.support.replication.TransportReplicationAction.ConcreteShardRequest; import org.elasticsearch.action.update.TransportUpdateAction; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; @@ -44,6 +46,7 @@ import org.elasticsearch.core.Nullable; import org.elasticsearch.core.Tuple; import org.elasticsearch.index.IndexNotFoundException; +import org.elasticsearch.indices.InvalidIndexNameException; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportActionProxy; @@ -502,6 +505,21 @@ private void authorizeAction( indicesAndAliasesResolver.resolve(action, request, projectMetadata, authorizedIndices) ), e -> { + if (e instanceof InvalidIndexNameException + || e instanceof InvalidSelectorException + || e instanceof UnsupportedSelectorException) { + logger.debug( + () -> Strings.format( + "failed [%s] action authorization for [%s] due to [%s] exception", + action, + authentication, + e.getClass().getSimpleName() + ), + e + ); + listener.onFailure(e); + return; + } auditTrail.accessDenied(requestId, authentication, action, request, authzInfo); if (e instanceof IndexNotFoundException) { listener.onFailure(e); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java index a7fee63ff5b0d..ff39fd587dc3a 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java @@ -15,6 +15,7 @@ import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.support.IndexComponentSelector; import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.action.support.UnsupportedSelectorException; import org.elasticsearch.cluster.metadata.AliasMetadata; import org.elasticsearch.cluster.metadata.IndexAbstraction; import org.elasticsearch.cluster.metadata.IndexAbstractionResolver; @@ -315,11 +316,7 @@ ResolvedIndices resolveIndicesAndAliases( // First, if a selector is present, check to make sure that selectors are even allowed here if (indicesOptions.allowSelectors() == false && allIndicesPatternSelector != null) { String originalIndexExpression = indicesRequest.indices()[0]; - throw new IllegalArgumentException( - "Index component selectors are not supported in this context but found selector in expression [" - + originalIndexExpression - + "]" - ); + throw new UnsupportedSelectorException(originalIndexExpression); } if (indicesOptions.expandWildcardExpressions()) { IndexComponentSelector selector = IndexComponentSelector.getByKeyOrThrow(allIndicesPatternSelector);