diff options
author | Morten Tokle <morten.tokle@gmail.com> | 2019-04-15 08:37:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-15 08:37:24 +0200 |
commit | 5318ae61a73db8b49552e16debd58b9af04ecf1d (patch) | |
tree | 9c6ea0bb954bfb47555da04dfdbf1900e6f3d064 | |
parent | 7b5706030db59c0cd7c268e2d0336a641498858a (diff) | |
parent | c90dd7b35849e42d0f2931a0bba5fb6e2888ba12 (diff) |
Merge pull request #9112 from vespa-engine/jvenstad/find-implied-roles
List implied roles in Controller
4 files changed, 74 insertions, 21 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java index a7596ce808f..9886e5c1329 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java @@ -23,7 +23,12 @@ import com.yahoo.vespa.hosted.controller.api.integration.github.GitHub; import com.yahoo.vespa.hosted.controller.api.integration.organization.Mailer; import com.yahoo.vespa.hosted.controller.api.integration.routing.RoutingGenerator; import com.yahoo.config.provision.zone.ZoneId; +import com.yahoo.vespa.hosted.controller.api.integration.user.UserRoles; import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry; +import com.yahoo.vespa.hosted.controller.api.role.ApplicationRole; +import com.yahoo.vespa.hosted.controller.api.role.Role; +import com.yahoo.vespa.hosted.controller.api.role.Roles; +import com.yahoo.vespa.hosted.controller.api.role.TenantRole; import com.yahoo.vespa.hosted.controller.auditlog.AuditLogger; import com.yahoo.vespa.hosted.controller.deployment.JobController; import com.yahoo.vespa.hosted.controller.persistence.CuratorDb; @@ -46,6 +51,7 @@ import java.util.function.Predicate; import java.util.function.Supplier; import java.util.logging.Logger; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * API to the controller. This contains the object model of everything the controller cares about, mainly tenants and @@ -76,6 +82,7 @@ public class Controller extends AbstractComponent { private final Mailer mailer; private final AuditLogger auditLogger; private final FlagSource flagSource; + private final UserRoles roles; /** * Creates a controller @@ -128,6 +135,7 @@ public class Controller extends AbstractComponent { ); tenantController = new TenantController(this, curator, accessControl); auditLogger = new AuditLogger(curator, clock); + roles = new UserRoles(new Roles(zoneRegistry.system())); // Record the version of this controller curator().writeControllerVersion(this.hostname(), Vtag.currentVersion); @@ -288,6 +296,22 @@ public class Controller extends AbstractComponent { return auditLogger; } + /** Returns all other roles the given tenant role implies. */ + public Set<Role> impliedRoles(TenantRole role) { + return Stream.concat(roles.tenantRoles(role.tenant()).stream(), + applications().asList(role.tenant()).stream() + .flatMap(application -> roles.applicationRoles(application.id().tenant(), application.id().application()).stream())) + .filter(role::implies) + .collect(Collectors.toUnmodifiableSet()); + } + + /** Returns all other roles the given application role implies. */ + public Set<Role> impliedRoles(ApplicationRole role) { + return roles.applicationRoles(role.tenant(), role.application()).stream() + .filter(role::implies) + .collect(Collectors.toUnmodifiableSet()); + } + private Set<CloudName> clouds() { return zoneRegistry.zones().all().ids().stream() .map(ZoneId::cloud) diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java index f5532a964fd..b8c904a80f6 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java @@ -26,7 +26,9 @@ import com.yahoo.vespa.hosted.controller.restapi.application.EmptyJsonResponse; import com.yahoo.yolean.Exceptions; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -109,7 +111,9 @@ public class UserApiHandler extends LoggingRequestHandler { Slime slime = new Slime(); Cursor root = slime.setObject(); root.setString("tenant", tenantName); - fillRoles(root, roles.tenantRoles(TenantName.from(tenantName))); + fillRoles(root, + roles.tenantRoles(TenantName.from(tenantName)), + Collections.emptyList()); return new SlimeJsonResponse(slime); } @@ -118,17 +122,21 @@ public class UserApiHandler extends LoggingRequestHandler { Cursor root = slime.setObject(); root.setString("tenant", tenantName); root.setString("application", applicationName); - fillRoles(root, roles.applicationRoles(TenantName.from(tenantName), ApplicationName.from(applicationName))); + fillRoles(root, + roles.applicationRoles(TenantName.from(tenantName), ApplicationName.from(applicationName)), + roles.tenantRoles(TenantName.from(tenantName))); return new SlimeJsonResponse(slime); } - private void fillRoles(Cursor root, List<? extends Role> roles) { + private void fillRoles(Cursor root, List<? extends Role> roles, List<? extends Role> superRoles) { Cursor rolesArray = root.setArray("roleNames"); for (Role role : roles) rolesArray.addString(valueOf(role)); - Map<UserId, List<Role>> memberships = new HashMap<>(); - for (Role role : roles) + Map<UserId, List<Role>> memberships = new LinkedHashMap<>(); + List<Role> allRoles = new ArrayList<>(superRoles); // Membership in a super role may imply membership in a role. + allRoles.addAll(roles); + for (Role role : allRoles) for (UserId user : users.listUsers(role)) { memberships.putIfAbsent(user, new ArrayList<>()); memberships.get(user).add(role); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/application-roles.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/application-roles.json index e6ecf86c4ec..45a5df5f6ce 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/application-roles.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/application-roles.json @@ -9,23 +9,23 @@ ], "users": [ { - "name": "reader@app", + "name": "owner@tenant", "roles": { "applicationAdmin": { "explicit": false, - "implied": false + "implied": true }, "applicationOperator": { "explicit": false, - "implied": false + "implied": true }, "applicationDeveloper": { "explicit": false, - "implied": false + "implied": true }, "applicationReader": { - "explicit": true, - "implied": false + "explicit": false, + "implied": true } } }, @@ -49,6 +49,27 @@ "implied": true } } + }, + { + "name": "reader@app", + "roles": { + "applicationAdmin": { + "explicit": false, + "implied": false + }, + "applicationOperator": { + "explicit": false, + "implied": false + }, + "applicationDeveloper": { + "explicit": false, + "implied": false + }, + "applicationReader": { + "explicit": true, + "implied": false + } + } } ] } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-roles.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-roles.json index 46f715b481b..74e5196db6e 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-roles.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-roles.json @@ -7,36 +7,36 @@ ], "users": [ { - "name": "operator@tenant", + "name": "owner@tenant", "roles": { "tenantOwner": { - "explicit": false, + "explicit": true, "implied": false }, "tenantAdmin": { "explicit": false, - "implied": false + "implied": true }, "tenantOperator": { - "explicit": true, - "implied": false + "explicit": false, + "implied": true } } }, { - "name": "owner@tenant", + "name": "operator@tenant", "roles": { "tenantOwner": { - "explicit": true, + "explicit": false, "implied": false }, "tenantAdmin": { "explicit": false, - "implied": true + "implied": false }, "tenantOperator": { - "explicit": false, - "implied": true + "explicit": true, + "implied": false } } } |