From 3df6aaa0a16cd641ca8225ffd52c782b016db364 Mon Sep 17 00:00:00 2001 From: Sriharsha Chintalapani Date: Wed, 25 Feb 2015 19:17:35 -0800 Subject: [PATCH 1/2] STORM-689. SimpleACLAuthorizer should provide a way to restrict who can submit topologies. --- storm-core/src/jvm/backtype/storm/Config.java | 13 ++++++++++--- .../auth/authorizer/SimpleACLAuthorizer.java | 10 +++++++++- .../backtype/storm/security/auth/auth_test.clj | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/storm-core/src/jvm/backtype/storm/Config.java b/storm-core/src/jvm/backtype/storm/Config.java index 73a1976ff39..a098555b9f7 100644 --- a/storm-core/src/jvm/backtype/storm/Config.java +++ b/storm-core/src/jvm/backtype/storm/Config.java @@ -60,11 +60,11 @@ public class Config extends HashMap { */ public static final String STORM_MESSAGING_NETTY_BUFFER_SIZE = "storm.messaging.netty.buffer_size"; public static final Object STORM_MESSAGING_NETTY_BUFFER_SIZE_SCHEMA = ConfigValidation.IntegerValidator; - + /** * Netty based messaging: Sets the backlog value to specify when the channel binds to a local address */ - public static final String STORM_MESSAGING_NETTY_SOCKET_BACKLOG = "storm.messaging.netty.socket.backlog"; + public static final String STORM_MESSAGING_NETTY_SOCKET_BACKLOG = "storm.messaging.netty.socket.backlog"; public static final Object STORM_MESSAGING_NETTY_SOCKET_BACKLOG_SCHEMA = ConfigValidation.IntegerValidator; /** @@ -338,6 +338,13 @@ public class Config extends HashMap { public static final String NIMBUS_ADMINS = "nimbus.admins"; public static final Object NIMBUS_ADMINS_SCHEMA = ConfigValidation.StringsValidator; + /** + * A list of users that are the only ones allowed to run user operation on storm cluster. + * To use this set nimbus.authorizer to backtype.storm.security.auth.authorizer.SimpleACLAuthorizer + */ + public static final String NIMBUS_USERS = "nimbus.users"; + public static final Object NIMBUS_USERS_SCHEMA = ConfigValidation.StringsValidator; + /** * A list of users that run the supervisors and should be authorized to interact with * nimbus as a supervisor would. To use this set @@ -465,7 +472,7 @@ public class Config extends HashMap { */ public static final String UI_HOST = "ui.host"; public static final Object UI_HOST_SCHEMA = String.class; - + /** * Storm UI binds to this port. */ diff --git a/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java b/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java index 1a3433ed6ac..d3d49ef4576 100644 --- a/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java +++ b/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java @@ -48,6 +48,7 @@ public class SimpleACLAuthorizer implements IAuthorizer { protected Set _admins; protected Set _supervisors; + protected Set _nimbusUsers; protected IPrincipalToLocal _ptol; protected IGroupMappingServiceProvider _groupMappingProvider; /** @@ -58,6 +59,7 @@ public class SimpleACLAuthorizer implements IAuthorizer { public void prepare(Map conf) { _admins = new HashSet(); _supervisors = new HashSet(); + _nimbusUsers = new HashSet(); if (conf.containsKey(Config.NIMBUS_ADMINS)) { _admins.addAll((Collection)conf.get(Config.NIMBUS_ADMINS)); @@ -65,6 +67,9 @@ public void prepare(Map conf) { if (conf.containsKey(Config.NIMBUS_SUPERVISOR_USERS)) { _supervisors.addAll((Collection)conf.get(Config.NIMBUS_SUPERVISOR_USERS)); } + if (conf.containsKey(Config.NIMBUS_USERS)) { + _nimbusUsers.addAll((Collection)conf.get(Config.NIMBUS_USERS)); + } _ptol = AuthUtils.GetPrincipalToLocalPlugin(conf); _groupMappingProvider = AuthUtils.GetGroupMappingServiceProviderPlugin(conf); @@ -96,7 +101,10 @@ public boolean permit(ReqContext context, String operation, Map topology_conf) { } if (_userCommands.contains(operation)) { - return true; + if (_nimbusUsers.size() > 0 && _nimbusUsers.contains(user)) + return true; + else if (_nimbusUsers.size() == 0) + return true; } if (_topoCommands.contains(operation)) { diff --git a/storm-core/test/clj/backtype/storm/security/auth/auth_test.clj b/storm-core/test/clj/backtype/storm/security/auth/auth_test.clj index 7ad3aa4a047..7df73729691 100644 --- a/storm-core/test/clj/backtype/storm/security/auth/auth_test.clj +++ b/storm-core/test/clj/backtype/storm/security/auth/auth_test.clj @@ -277,6 +277,22 @@ (is (= false (.permit authorizer (ReqContext. supervisor-user) "getTopologyInfo" {TOPOLOGY-USERS ["user-a"]}))) )) +(deftest simple-acl-nimbus-users-auth-test + (let [cluster-conf (merge (read-storm-config) + {NIMBUS-ADMINS ["admin"] + NIMBUS-SUPERVISOR-USERS ["supervisor"] + NIMBUS-USERS ["user-a"]}) + authorizer (SimpleACLAuthorizer. ) + admin-user (mk-subject "admin") + supervisor-user (mk-subject "supervisor") + user-a (mk-subject "user-a") + user-b (mk-subject "user-b")] + (.prepare authorizer cluster-conf) + (is (= true (.permit authorizer (ReqContext. user-a) "submitTopology" {}))) + (is (= false (.permit authorizer (ReqContext. user-b) "submitTopology" {}))) + (is (= true (.permit authorizer (ReqContext. admin-user) "fileUpload" nil))) + (is (= true (.permit authorizer (ReqContext. supervisor-user) "fileDownload" nil))))) + (deftest shell-based-groups-mapping-test (let [cluster-conf (read-storm-config) groups (ShellBasedGroupsMapping. ) From 6f6f48dbb2a11988a96e1cad59ed4c468ef9ac6c Mon Sep 17 00:00:00 2001 From: Sriharsha Chintalapani Date: Thu, 12 Mar 2015 15:31:53 -0700 Subject: [PATCH 2/2] STORM-689. SimpleACLAuthorizer should provide a way to restrict who can submit topologies. Added nimbus.groups. --- SECURITY.md | 23 +++++++++++ storm-core/src/jvm/backtype/storm/Config.java | 7 ++++ .../auth/authorizer/SimpleACLAuthorizer.java | 41 ++++++++++++------- 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 51007359284..7da95b86657 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -361,5 +361,28 @@ The Logviewer daemon now is also responsible for cleaning up old log files for d | logviewer.cleanup.interval.secs | Interval of time in seconds that the logviewer cleans up worker logs. | +### Allowing specific users or groups to access storm + + With SimpleACLAuthorizer any user with valid kerberos ticket can deploy a topology or do further operations such as activate, deactivate , access cluster information. + One can restrict this access by specifying nimbus.users or nimbus.groups. If nimbus.users configured only the users in the list can deploy a topology or access cluster. + Similarly nimbus.groups restrict storm cluster access to users who belong to those groups. + + To configure specify the following config in storm.yaml + +```yaml +nimbus.users: + - "testuser" +``` + +or + +```yaml +nimbus.groups: + - "storm" +``` + + ### DRPC Hopefully more on this soon + + diff --git a/storm-core/src/jvm/backtype/storm/Config.java b/storm-core/src/jvm/backtype/storm/Config.java index a098555b9f7..ccfd91ed1c6 100644 --- a/storm-core/src/jvm/backtype/storm/Config.java +++ b/storm-core/src/jvm/backtype/storm/Config.java @@ -345,6 +345,13 @@ public class Config extends HashMap { public static final String NIMBUS_USERS = "nimbus.users"; public static final Object NIMBUS_USERS_SCHEMA = ConfigValidation.StringsValidator; + /** + * A list of groups , users belong to these groups are the only ones allowed to run user operation on storm cluster. + * To use this set nimbus.authorizer to backtype.storm.security.auth.authorizer.SimpleACLAuthorizer + */ + public static final String NIMBUS_GROUPS = "nimbus.groups"; + public static final Object NIMBUS_GROUPS_SCHEMA = ConfigValidation.StringsValidator; + /** * A list of users that run the supervisors and should be authorized to interact with * nimbus as a supervisor would. To use this set diff --git a/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java b/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java index d3d49ef4576..2866d6dc9dd 100644 --- a/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java +++ b/storm-core/src/jvm/backtype/storm/security/auth/authorizer/SimpleACLAuthorizer.java @@ -49,6 +49,7 @@ public class SimpleACLAuthorizer implements IAuthorizer { protected Set _admins; protected Set _supervisors; protected Set _nimbusUsers; + protected Set _nimbusGroups; protected IPrincipalToLocal _ptol; protected IGroupMappingServiceProvider _groupMappingProvider; /** @@ -60,6 +61,7 @@ public void prepare(Map conf) { _admins = new HashSet(); _supervisors = new HashSet(); _nimbusUsers = new HashSet(); + _nimbusGroups = new HashSet(); if (conf.containsKey(Config.NIMBUS_ADMINS)) { _admins.addAll((Collection)conf.get(Config.NIMBUS_ADMINS)); @@ -71,6 +73,10 @@ public void prepare(Map conf) { _nimbusUsers.addAll((Collection)conf.get(Config.NIMBUS_USERS)); } + if (conf.containsKey(Config.NIMBUS_GROUPS)) { + _nimbusGroups.addAll((Collection)conf.get(Config.NIMBUS_GROUPS)); + } + _ptol = AuthUtils.GetPrincipalToLocalPlugin(conf); _groupMappingProvider = AuthUtils.GetGroupMappingServiceProviderPlugin(conf); } @@ -92,6 +98,16 @@ public boolean permit(ReqContext context, String operation, Map topology_conf) { String principal = context.principal().getName(); String user = _ptol.toLocal(context.principal()); + Set userGroups = new HashSet(); + + if (_groupMappingProvider != null) { + try { + userGroups = _groupMappingProvider.getGroups(user); + } catch(IOException e) { + LOG.warn("Error while trying to fetch user groups",e); + } + } + if (_admins.contains(principal) || _admins.contains(user)) { return true; } @@ -101,10 +117,7 @@ public boolean permit(ReqContext context, String operation, Map topology_conf) { } if (_userCommands.contains(operation)) { - if (_nimbusUsers.size() > 0 && _nimbusUsers.contains(user)) - return true; - else if (_nimbusUsers.size() == 0) - return true; + return _nimbusUsers.size() == 0 || _nimbusUsers.contains(user) || checkUserGroupAllowed(userGroups, _nimbusGroups); } if (_topoCommands.contains(operation)) { @@ -122,16 +135,16 @@ else if (_nimbusUsers.size() == 0) topoGroups.addAll((Collection)topology_conf.get(Config.TOPOLOGY_GROUPS)); } - if(_groupMappingProvider != null && topoGroups.size() > 0) { - try { - Set userGroups = _groupMappingProvider.getGroups(user); - for (String tgroup : topoGroups) { - if(userGroups.contains(tgroup)) - return true; - } - } catch(IOException e) { - LOG.warn("Error while trying to fetch user groups",e); - } + if (checkUserGroupAllowed(userGroups, topoGroups)) return true; + } + return false; + } + + private Boolean checkUserGroupAllowed(Set userGroups, Set configuredGroups) { + if(userGroups.size() > 0 && configuredGroups.size() > 0) { + for (String tgroup : configuredGroups) { + if(userGroups.contains(tgroup)) + return true; } } return false;