|
13 | 13 | import org.elasticsearch.http.HttpPreRequest; |
14 | 14 | import org.elasticsearch.rest.RestStatus; |
15 | 15 | import org.elasticsearch.test.ESTestCase; |
| 16 | +import org.elasticsearch.transport.TransportRequest; |
16 | 17 | import org.elasticsearch.xpack.core.XPackField; |
17 | 18 |
|
18 | 19 | import java.util.Arrays; |
|
21 | 22 | import java.util.List; |
22 | 23 | import java.util.Map; |
23 | 24 |
|
| 25 | +import static org.elasticsearch.xpack.core.security.authc.DefaultAuthenticationFailureHandler.ACCESS_DENIED_METADATA_KEY; |
24 | 26 | import static org.hamcrest.Matchers.contains; |
| 27 | +import static org.hamcrest.Matchers.containsString; |
25 | 28 | import static org.hamcrest.Matchers.equalTo; |
26 | 29 | import static org.hamcrest.Matchers.is; |
27 | 30 | import static org.hamcrest.Matchers.notNullValue; |
@@ -112,6 +115,7 @@ public void testExceptionProcessingRequest() { |
112 | 115 | } else { |
113 | 116 | expectThrows( |
114 | 117 | AssertionError.class, |
| 118 | + containsString("rest status must be 401 UNAUTHORIZED"), |
115 | 119 | () -> failureHandler.exceptionProcessingRequest( |
116 | 120 | mock(HttpPreRequest.class), |
117 | 121 | cause, |
@@ -156,6 +160,92 @@ public void testSortsWWWAuthenticateHeaderValues() { |
156 | 160 | assertWWWAuthenticateWithSchemes(ese, negotiateAuthScheme, bearerAuthScheme, apiKeyAuthScheme, basicAuthScheme); |
157 | 161 | } |
158 | 162 |
|
| 163 | + public void testExceptionProcessingRequestWith403SecurityException() { |
| 164 | + final DefaultAuthenticationFailureHandler failureHandler = new DefaultAuthenticationFailureHandler(Collections.emptyMap()); |
| 165 | + final ThreadContext threadContext = new ThreadContext(Settings.builder().build()); |
| 166 | + |
| 167 | + // Test 1: 403 exception with es.security.access_denied metadata should be returned as-is |
| 168 | + { |
| 169 | + ElasticsearchSecurityException forbiddenWithMetadata = new ElasticsearchSecurityException( |
| 170 | + "failed to authorize user for project [test-project]", |
| 171 | + RestStatus.FORBIDDEN, |
| 172 | + null, |
| 173 | + (Object[]) null |
| 174 | + ); |
| 175 | + forbiddenWithMetadata.addMetadata(ACCESS_DENIED_METADATA_KEY, "true"); |
| 176 | + |
| 177 | + ElasticsearchSecurityException result = failureHandler.exceptionProcessingRequest( |
| 178 | + mock(HttpPreRequest.class), |
| 179 | + forbiddenWithMetadata, |
| 180 | + threadContext |
| 181 | + ); |
| 182 | + assertThat(result, is(sameInstance(forbiddenWithMetadata))); |
| 183 | + assertThat(result.status(), equalTo(RestStatus.FORBIDDEN)); |
| 184 | + |
| 185 | + result = failureHandler.exceptionProcessingRequest( |
| 186 | + mock(TransportRequest.class), |
| 187 | + "index:foo/bar", |
| 188 | + forbiddenWithMetadata, |
| 189 | + threadContext |
| 190 | + ); |
| 191 | + assertThat(result, is(sameInstance(forbiddenWithMetadata))); |
| 192 | + assertThat(result.status(), equalTo(RestStatus.FORBIDDEN)); |
| 193 | + } |
| 194 | + |
| 195 | + // Test 2: 403 exception without metadata should fail assertion |
| 196 | + { |
| 197 | + ElasticsearchSecurityException forbiddenWithoutMetadata = new ElasticsearchSecurityException( |
| 198 | + "some forbidden error", |
| 199 | + RestStatus.FORBIDDEN, |
| 200 | + null, |
| 201 | + (Object[]) null |
| 202 | + ); |
| 203 | + |
| 204 | + expectThrows( |
| 205 | + AssertionError.class, |
| 206 | + containsString("rest status must be 401 UNAUTHORIZED"), |
| 207 | + () -> failureHandler.exceptionProcessingRequest(mock(HttpPreRequest.class), forbiddenWithoutMetadata, threadContext) |
| 208 | + ); |
| 209 | + expectThrows( |
| 210 | + AssertionError.class, |
| 211 | + containsString("rest status must be 401 UNAUTHORIZED"), |
| 212 | + () -> failureHandler.exceptionProcessingRequest( |
| 213 | + mock(TransportRequest.class), |
| 214 | + "index:foo/bar", |
| 215 | + forbiddenWithoutMetadata, |
| 216 | + threadContext |
| 217 | + ) |
| 218 | + ); |
| 219 | + } |
| 220 | + |
| 221 | + // Test 3: 403 exception with different metadata should fail assertion |
| 222 | + { |
| 223 | + ElasticsearchSecurityException forbiddenWithDifferentMetadata = new ElasticsearchSecurityException( |
| 224 | + "some other forbidden error", |
| 225 | + RestStatus.FORBIDDEN, |
| 226 | + null, |
| 227 | + (Object[]) null |
| 228 | + ); |
| 229 | + forbiddenWithDifferentMetadata.addMetadata("es.some.other.metadata", "value"); |
| 230 | + |
| 231 | + expectThrows( |
| 232 | + AssertionError.class, |
| 233 | + containsString("rest status must be 401 UNAUTHORIZED"), |
| 234 | + () -> failureHandler.exceptionProcessingRequest(mock(HttpPreRequest.class), forbiddenWithDifferentMetadata, threadContext) |
| 235 | + ); |
| 236 | + expectThrows( |
| 237 | + AssertionError.class, |
| 238 | + containsString("rest status must be 401 UNAUTHORIZED"), |
| 239 | + () -> failureHandler.exceptionProcessingRequest( |
| 240 | + mock(TransportRequest.class), |
| 241 | + "index:foo/bar", |
| 242 | + forbiddenWithDifferentMetadata, |
| 243 | + threadContext |
| 244 | + ) |
| 245 | + ); |
| 246 | + } |
| 247 | + } |
| 248 | + |
159 | 249 | private void assertWWWAuthenticateWithSchemes(final ElasticsearchSecurityException ese, final String... schemes) { |
160 | 250 | assertThat(ese.getBodyHeader("WWW-Authenticate").size(), is(schemes.length)); |
161 | 251 | assertThat(ese.getBodyHeader("WWW-Authenticate"), contains(schemes)); |
|
0 commit comments