/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authc/support/SecondaryAuthenticationTests.java

https://github.com/dadoonet/elasticsearch · Java · 162 lines · 130 code · 26 blank · 6 comment · 0 complexity · 3526fe4d8fbf6bada71275a6904c030b MD5 · raw file

  1. /*
  2. * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
  3. * or more contributor license agreements. Licensed under the Elastic License;
  4. * you may not use this file except in compliance with the Elastic License.
  5. */
  6. package org.elasticsearch.xpack.core.security.authc.support;
  7. import org.elasticsearch.Version;
  8. import org.elasticsearch.action.ActionListener;
  9. import org.elasticsearch.action.support.ContextPreservingActionListener;
  10. import org.elasticsearch.common.settings.Settings;
  11. import org.elasticsearch.common.util.concurrent.ThreadContext;
  12. import org.elasticsearch.test.ESTestCase;
  13. import org.elasticsearch.threadpool.TestThreadPool;
  14. import org.elasticsearch.threadpool.ThreadPool;
  15. import org.elasticsearch.xpack.core.security.SecurityContext;
  16. import org.elasticsearch.xpack.core.security.authc.Authentication;
  17. import org.elasticsearch.xpack.core.security.user.User;
  18. import org.elasticsearch.xpack.core.security.authc.support.SecondaryAuthentication;
  19. import org.junit.After;
  20. import org.junit.Before;
  21. import java.util.concurrent.Future;
  22. import java.util.concurrent.Semaphore;
  23. import java.util.concurrent.TimeUnit;
  24. import java.util.concurrent.atomic.AtomicReference;
  25. import static org.hamcrest.Matchers.equalTo;
  26. import static org.hamcrest.Matchers.notNullValue;
  27. import static org.hamcrest.Matchers.sameInstance;
  28. public class SecondaryAuthenticationTests extends ESTestCase {
  29. private SecurityContext securityContext;
  30. private ThreadPool threadPool;
  31. @Before
  32. public void setupObjects() {
  33. this.threadPool = new TestThreadPool(getTestName());
  34. this.securityContext = new SecurityContext(Settings.EMPTY, threadPool.getThreadContext());
  35. }
  36. @After
  37. public void cleanup() {
  38. this.threadPool.shutdownNow();
  39. }
  40. public void testCannotCreateObjectWithNullAuthentication() {
  41. expectThrows(NullPointerException.class, () -> new SecondaryAuthentication(securityContext, null));
  42. }
  43. public void testSynchronousExecuteInSecondaryContext() {
  44. final User user1 = new User("u1", "role1");
  45. securityContext.setUser(user1, Version.CURRENT);
  46. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  47. final Authentication authentication2 = new Authentication(new User("u2", "role2"), realm(), realm());
  48. final SecondaryAuthentication secondaryAuth = new SecondaryAuthentication(securityContext, authentication2);
  49. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  50. var result = secondaryAuth.execute(original -> {
  51. assertThat(securityContext.getUser().principal(), equalTo("u2"));
  52. assertThat(securityContext.getAuthentication(), sameInstance(authentication2));
  53. return "xyzzy";
  54. });
  55. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  56. assertThat(result, equalTo("xyzzy"));
  57. }
  58. public void testSecondaryContextCanBeRestored() {
  59. final User user1 = new User("u1", "role1");
  60. securityContext.setUser(user1, Version.CURRENT);
  61. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  62. final Authentication authentication2 = new Authentication(new User("u2", "role2"), realm(), realm());
  63. final SecondaryAuthentication secondaryAuth = new SecondaryAuthentication(securityContext, authentication2);
  64. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  65. final AtomicReference<ThreadContext.StoredContext> secondaryContext = new AtomicReference<>();
  66. secondaryAuth.execute(storedContext -> {
  67. assertThat(securityContext.getUser().principal(), equalTo("u2"));
  68. assertThat(securityContext.getAuthentication(), sameInstance(authentication2));
  69. secondaryContext.set(threadPool.getThreadContext().newStoredContext(false));
  70. storedContext.restore();
  71. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  72. return null;
  73. });
  74. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  75. secondaryContext.get().restore();
  76. assertThat(securityContext.getUser().principal(), equalTo("u2"));
  77. }
  78. public void testWrapRunnable() throws Exception {
  79. final User user1 = new User("u1", "role1");
  80. securityContext.setUser(user1, Version.CURRENT);
  81. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  82. final Authentication authentication2 = new Authentication(new User("u2", "role2"), realm(), realm());
  83. final SecondaryAuthentication secondaryAuth = new SecondaryAuthentication(securityContext, authentication2);
  84. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  85. final Semaphore semaphore = new Semaphore(0);
  86. final Future<?> future = threadPool.generic().submit(secondaryAuth.wrap(() -> {
  87. try {
  88. assertThat(securityContext.getUser().principal(), equalTo("u2"));
  89. semaphore.acquire();
  90. assertThat(securityContext.getUser().principal(), equalTo("u2"));
  91. semaphore.acquire();
  92. assertThat(securityContext.getUser().principal(), equalTo("u2"));
  93. } catch (InterruptedException e) {
  94. Thread.currentThread().interrupt();
  95. throw new RuntimeException(e);
  96. }
  97. }));
  98. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  99. semaphore.release();
  100. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  101. semaphore.release();
  102. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  103. // ensure that the runnable didn't throw any exceptions / assertions
  104. future.get(1, TimeUnit.SECONDS);
  105. }
  106. public void testPreserveSecondaryContextAcrossThreads() throws Exception {
  107. final User user1 = new User("u1", "role1");
  108. securityContext.setUser(user1, Version.CURRENT);
  109. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  110. final Authentication authentication2 = new Authentication(new User("u2", "role2"), realm(), realm());
  111. final SecondaryAuthentication secondaryAuth = new SecondaryAuthentication(securityContext, authentication2);
  112. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  113. final AtomicReference<User> threadUser = new AtomicReference<>();
  114. final AtomicReference<User> listenerUser = new AtomicReference<>();
  115. final ThreadContext threadContext = threadPool.getThreadContext();
  116. secondaryAuth.execute(originalContext -> {
  117. assertThat(securityContext.getUser().principal(), equalTo("u2"));
  118. ActionListener<Void> listener = new ContextPreservingActionListener<>(threadContext.newRestorableContext(false),
  119. ActionListener.wrap(() -> listenerUser.set(securityContext.getUser())));
  120. originalContext.restore();
  121. threadPool.generic().execute(() -> {
  122. threadUser.set(securityContext.getUser());
  123. listener.onResponse(null);
  124. });
  125. return null;
  126. });
  127. assertThat(securityContext.getUser().principal(), equalTo("u1"));
  128. assertBusy(() -> assertThat(listenerUser.get(), notNullValue()), 1, TimeUnit.SECONDS);
  129. assertThat(threadUser.get(), notNullValue());
  130. assertThat(threadUser.get().principal(), equalTo("u1"));
  131. assertThat(listenerUser.get().principal(), equalTo("u2"));
  132. }
  133. private Authentication.RealmRef realm() {
  134. return new Authentication.RealmRef(randomAlphaOfLengthBetween(4, 8), randomAlphaOfLengthBetween(2, 4), randomAlphaOfLength(12));
  135. }
  136. }