diff --git a/src/main/java/org/elasticsearch/shield/ShieldPlugin.java b/src/main/java/org/elasticsearch/shield/ShieldPlugin.java index 00670e5c1e9..6f2b5a3ca6e 100644 --- a/src/main/java/org/elasticsearch/shield/ShieldPlugin.java +++ b/src/main/java/org/elasticsearch/shield/ShieldPlugin.java @@ -14,8 +14,10 @@ import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.plugins.AbstractPlugin; +import org.elasticsearch.shield.authc.Realms; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; +import org.elasticsearch.shield.authz.store.FileRolesStore; import org.elasticsearch.shield.license.LicenseService; import java.io.File; @@ -59,7 +61,7 @@ public class ShieldPlugin extends AbstractPlugin { @Override public Collection> services() { return enabled && !clientMode ? - ImmutableList.>of(LicenseService.class) : + ImmutableList.>of(LicenseService.class, FileRolesStore.class, Realms.class) : ImmutableList.>of(); } diff --git a/src/main/java/org/elasticsearch/shield/authc/Realms.java b/src/main/java/org/elasticsearch/shield/authc/Realms.java index b4449ddb8f4..9c561850ac2 100644 --- a/src/main/java/org/elasticsearch/shield/authc/Realms.java +++ b/src/main/java/org/elasticsearch/shield/authc/Realms.java @@ -6,37 +6,45 @@ package org.elasticsearch.shield.authc; import org.apache.lucene.util.CollectionUtil; +import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.collect.Lists; import org.elasticsearch.common.collect.Sets; import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.ShieldSettingsException; import org.elasticsearch.shield.authc.esusers.ESUsersRealm; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; /** * Serves as a realms registry (also responsible for ordering the realms appropriately) */ -public class Realms extends AbstractComponent implements Iterable { +public class Realms extends AbstractLifecycleComponent implements Iterable { private final Map factories; - - private final List realms; + private List realms = Collections.EMPTY_LIST; @Inject public Realms(Settings settings, Map factories) { super(settings); this.factories = factories; + } + + @Override + protected void doStart() throws ElasticsearchException { realms = new CopyOnWriteArrayList<>(initRealms()); } + @Override + protected void doStop() throws ElasticsearchException {} + + @Override + protected void doClose() throws ElasticsearchException {} + @Override public Iterator iterator() { return realms.iterator(); @@ -112,4 +120,5 @@ public class Realms extends AbstractComponent implements Iterable { } return result != null ? result : ImmutableSettings.EMPTY; } + } diff --git a/src/main/java/org/elasticsearch/shield/authz/AuthorizationModule.java b/src/main/java/org/elasticsearch/shield/authz/AuthorizationModule.java index 755595bee3d..9dff62ed6cc 100644 --- a/src/main/java/org/elasticsearch/shield/authz/AuthorizationModule.java +++ b/src/main/java/org/elasticsearch/shield/authz/AuthorizationModule.java @@ -21,7 +21,9 @@ public class AuthorizationModule extends AbstractShieldModule.Node { @Override protected void configureNode() { + bind(FileRolesStore.class).asEagerSingleton(); bind(RolesStore.class).to(FileRolesStore.class).asEagerSingleton(); bind(AuthorizationService.class).to(InternalAuthorizationService.class).asEagerSingleton(); } + } diff --git a/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java b/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java index c0befea238e..662997d153a 100644 --- a/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java +++ b/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java @@ -8,13 +8,11 @@ package org.elasticsearch.shield.authz.store; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.ImmutableMap; -import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.jackson.dataformat.yaml.snakeyaml.error.YAMLException; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.yaml.YamlXContent; import org.elasticsearch.env.Environment; @@ -30,20 +28,18 @@ import org.elasticsearch.watcher.ResourceWatcherService; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.HashSet; -import java.util.Map; import java.util.Set; import java.util.regex.Pattern; /** * */ -public class FileRolesStore extends AbstractComponent implements RolesStore { +public class FileRolesStore extends AbstractLifecycleComponent implements RolesStore { private static final Pattern COMMA_DELIM = Pattern.compile("\\s*,\\s*"); @@ -59,12 +55,26 @@ public class FileRolesStore extends AbstractComponent implements RolesStore { public FileRolesStore(Settings settings, Environment env, ResourceWatcherService watcherService, Listener listener) { super(settings); - file = resolveFile(settings, env); - permissions = parseFile(file, logger); + this.file = resolveFile(settings, env); + this.listener = listener; + permissions = ImmutableMap.of(); + FileWatcher watcher = new FileWatcher(file.getParent().toFile()); watcher.addListener(new FileListener()); watcherService.add(watcher, ResourceWatcherService.Frequency.HIGH); - this.listener = listener; + } + + @Override + protected void doStart() throws ElasticsearchException { + permissions = parseFile(file, logger); + } + + @Override + protected void doStop() throws ElasticsearchException { + } + + @Override + protected void doClose() throws ElasticsearchException { } @Override diff --git a/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java b/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java index c08eb84a471..c383afda171 100644 --- a/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java @@ -65,6 +65,7 @@ public class InternalAuthenticationServiceTests extends ElasticsearchTestCase { return ImmutableList.of(firstRealm, secondRealm); } }; + realms.start(); signatureService = mock(SignatureService.class); auditTrail = mock(AuditTrail.class); diff --git a/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java b/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java index de839a03564..a7235eeb1f6 100644 --- a/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java @@ -5,7 +5,6 @@ */ package org.elasticsearch.shield.authc; -import com.carrotsearch.randomizedtesting.annotations.Repeat; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.rest.RestRequest; @@ -19,9 +18,7 @@ import org.junit.Test; import java.util.*; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.*; /** * @@ -55,6 +52,7 @@ public class RealmsTests extends ElasticsearchTestCase { orderToIndex.put(orders.get(i), i); } Realms realms = new Realms(builder.build(), factories); + realms.start(); int i = 0; for (Realm realm : realms) { assertThat(realm.order(), equalTo(i)); @@ -72,12 +70,13 @@ public class RealmsTests extends ElasticsearchTestCase { builder.put("shield.authc.realms.realm_1.order", 0); builder.put("shield.authc.realms.realm_2.type", ESUsersRealm.TYPE); builder.put("shield.authc.realms.realm_2.order", 1); - new Realms(builder.build(), factories); + new Realms(builder.build(), factories).start(); } @Test public void testWithEmptySettings() throws Exception { Realms realms = new Realms(ImmutableSettings.EMPTY, factories); + realms.start(); Iterator iter = realms.iterator(); assertThat(iter.hasNext(), is(true)); Realm realm = iter.next(); @@ -109,6 +108,7 @@ public class RealmsTests extends ElasticsearchTestCase { Settings settings = builder.build(); Realms realms = new Realms(settings, factories); + realms.start(); Iterator iterator = realms.iterator(); int count = 0; diff --git a/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java b/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java index 9687aac0ae8..d698c18cdd7 100644 --- a/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java +++ b/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java @@ -151,6 +151,7 @@ public class FileRolesStoreTests extends ElasticsearchTestCase { latch.countDown(); } }); + store.start(); Permission.Global.Role role = store.role("role1"); assertThat(role, notNullValue());