summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Tokle <morten.tokle@gmail.com>2019-04-15 08:37:24 +0200
committerGitHub <noreply@github.com>2019-04-15 08:37:24 +0200
commit5318ae61a73db8b49552e16debd58b9af04ecf1d (patch)
tree9c6ea0bb954bfb47555da04dfdbf1900e6f3d064
parent7b5706030db59c0cd7c268e2d0336a641498858a (diff)
parentc90dd7b35849e42d0f2931a0bba5fb6e2888ba12 (diff)
Merge pull request #9112 from vespa-engine/jvenstad/find-implied-roles
List implied roles in Controller
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java24
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java18
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/application-roles.json33
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-roles.json20
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
}
}
}