66 */
77package org .elasticsearch .xpack .security ;
88
9+ import org .elasticsearch .action .ActionListener ;
910import org .elasticsearch .client .Request ;
1011import org .elasticsearch .client .RequestOptions ;
1112import org .elasticsearch .client .Response ;
1213import org .elasticsearch .client .ResponseException ;
1314import org .elasticsearch .common .settings .SecureString ;
15+ import org .elasticsearch .common .settings .Setting ;
16+ import org .elasticsearch .common .settings .Settings ;
17+ import org .elasticsearch .common .util .concurrent .ThreadContext ;
18+ import org .elasticsearch .plugins .Plugin ;
1419import org .elasticsearch .test .SecurityIntegTestCase ;
1520import org .elasticsearch .test .SecuritySettingsSource ;
1621import org .elasticsearch .test .SecuritySettingsSourceField ;
22+ import org .elasticsearch .xpack .core .security .SecurityExtension ;
23+ import org .elasticsearch .xpack .core .security .authc .AuthenticationResult ;
24+ import org .elasticsearch .xpack .core .security .authc .AuthenticationToken ;
25+ import org .elasticsearch .xpack .core .security .authc .Realm ;
26+ import org .elasticsearch .xpack .core .security .authc .RealmConfig ;
27+ import org .elasticsearch .xpack .core .security .authc .RealmSettings ;
28+ import org .elasticsearch .xpack .core .security .authc .support .UsernamePasswordToken ;
29+ import org .elasticsearch .xpack .core .security .user .User ;
1730
31+ import java .io .Closeable ;
1832import java .io .IOException ;
33+ import java .nio .file .Path ;
34+ import java .util .ArrayList ;
35+ import java .util .Collection ;
36+ import java .util .List ;
37+ import java .util .Map ;
38+ import java .util .concurrent .atomic .AtomicBoolean ;
1939
2040import static org .elasticsearch .rest .RestStatus .OK ;
2141import static org .elasticsearch .rest .RestStatus .UNAUTHORIZED ;
@@ -29,6 +49,33 @@ protected boolean addMockHttpTransport() {
2949 return false ; // enable http
3050 }
3151
52+ @ Override
53+ protected Collection <Class <? extends Plugin >> nodePlugins () {
54+ final List <Class <? extends Plugin >> plugins = new ArrayList <>(super .nodePlugins ());
55+ {
56+ // replace the security plugin with the security plugin that contains a dummy realm
57+ plugins .remove (LocalStateSecurity .class );
58+ plugins .add (SecurityPluginTests .LocalStateWithDummyRealmAuthorizationEngineExtension .class );
59+ }
60+ return List .copyOf (plugins );
61+ }
62+
63+ @ Override
64+ protected Class <?> xpackPluginClass () {
65+ return SecurityPluginTests .LocalStateWithDummyRealmAuthorizationEngineExtension .class ;
66+ }
67+
68+ private static final AtomicBoolean REALM_CLOSE_FLAG = new AtomicBoolean (false );
69+ private static final AtomicBoolean REALM_INIT_FLAG = new AtomicBoolean (false );
70+
71+ @ Override
72+ protected Settings nodeSettings (int nodeOrdinal , Settings otherSettings ) {
73+ final Settings .Builder settingsBuilder = Settings .builder ();
74+ settingsBuilder .put (super .nodeSettings (nodeOrdinal , otherSettings ));
75+ settingsBuilder .put ("xpack.security.authc.realms.dummy.dummy10.order" , "10" );
76+ return settingsBuilder .build ();
77+ }
78+
3279 public void testThatPluginIsLoaded () throws IOException {
3380 try {
3481 logger .info ("executing unauthorized request to /_xpack info" );
@@ -53,4 +100,80 @@ public void testThatPluginIsLoaded() throws IOException {
53100 Response response = getRestClient ().performRequest (request );
54101 assertThat (response .getStatusLine ().getStatusCode (), is (OK .getStatus ()));
55102 }
103+
104+ public void testThatPluginRealmIsLoadedAndClosed () throws IOException {
105+ REALM_CLOSE_FLAG .set (false );
106+ REALM_INIT_FLAG .set (false );
107+ String nodeName = internalCluster ().startNode ();
108+ assertThat (REALM_INIT_FLAG .get (), is (true ));
109+ internalCluster ().stopNode (nodeName );
110+ assertThat (REALM_CLOSE_FLAG .get (), is (true ));
111+ }
112+
113+ public static class LocalStateWithDummyRealmAuthorizationEngineExtension extends LocalStateSecurity {
114+
115+ public LocalStateWithDummyRealmAuthorizationEngineExtension (Settings settings , Path configPath ) throws Exception {
116+ super (settings , configPath );
117+ }
118+
119+ @ Override
120+ protected List <SecurityExtension > securityExtensions () {
121+ return List .of (new DummyRealmAuthorizationEngineExtension ());
122+ }
123+
124+ @ Override
125+ public List <Setting <?>> getSettings () {
126+ ArrayList <Setting <?>> settings = new ArrayList <>();
127+ settings .addAll (super .getSettings ());
128+ settings .addAll (RealmSettings .getStandardSettings (DummyRealm .TYPE ));
129+ return settings ;
130+ }
131+ }
132+
133+ public static class DummyRealmAuthorizationEngineExtension implements SecurityExtension {
134+
135+ DummyRealmAuthorizationEngineExtension () {}
136+
137+ @ Override
138+ public Map <String , Realm .Factory > getRealms (SecurityComponents components ) {
139+ return Map .of (DummyRealm .TYPE , DummyRealm ::new );
140+ }
141+ }
142+
143+ public static class DummyRealm extends Realm implements Closeable {
144+
145+ public static final String TYPE = "dummy" ;
146+
147+ public DummyRealm (RealmConfig config ) {
148+ super (config );
149+ REALM_INIT_FLAG .set (true );
150+ }
151+
152+ @ Override
153+ public boolean supports (AuthenticationToken token ) {
154+ return false ;
155+ }
156+
157+ @ Override
158+ public UsernamePasswordToken token (ThreadContext threadContext ) {
159+ return null ;
160+ }
161+
162+ @ Override
163+ public void authenticate (AuthenticationToken authToken , ActionListener <AuthenticationResult <User >> listener ) {
164+ listener .onResponse (AuthenticationResult .notHandled ());
165+ }
166+
167+ @ Override
168+ public void lookupUser (String username , ActionListener <User > listener ) {
169+ // Lookup (run-as) is not supported in this realm
170+ listener .onResponse (null );
171+ }
172+
173+ @ Override
174+ public void close () {
175+ REALM_CLOSE_FLAG .set (true );
176+ }
177+ }
178+
56179}
0 commit comments