Skip to content

Commit

Permalink
compare spend report permission to workspace ownership
Browse files Browse the repository at this point in the history
  • Loading branch information
calypsomatic committed Nov 21, 2024
1 parent 9ad4c7e commit b07bbb1
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -519,9 +519,10 @@ class HttpSamDAO(baseSamServiceURL: String, rawlsCredential: RawlsCredential, ti
}
}

override def listResourcesWithActions(resourceTypeName: SamResourceTypeName,
action: SamResourceAction,
ctx: RawlsRequestContext
override def listResourcesWithRolesOrActions(resourceTypeName: SamResourceTypeName,
actions: Seq[SamResourceAction],
roles: Seq[SamResourceRole],
ctx: RawlsRequestContext
): Future[Seq[SamUserResource]] =
retry(when401or5xx) { () =>
val callback = new SamApiCallback[ListResourcesV2200Response]("listResourcesV2")
Expand All @@ -530,8 +531,8 @@ class HttpSamDAO(baseSamServiceURL: String, rawlsCredential: RawlsCredential, ti
/* format = */ "hierarchical",
/* resourceTypes = */ util.List.of(resourceTypeName.value),
/* policies = */ util.List.of(),
/* roles = */ util.List.of,
/* actions = */ util.List.of(action.value),
/* roles = */ roles.map(_.toString).asJava,
/* actions = */ actions.map(_.toString).asJava,
/* includePublic = */ false,
callback
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ trait SamDAO {

def listUserResources(resourceTypeName: SamResourceTypeName, ctx: RawlsRequestContext): Future[Seq[SamUserResource]]

def listResourcesWithActions(resourceTypeName: SamResourceTypeName,
action: SamResourceAction,
ctx: RawlsRequestContext
def listResourcesWithRolesOrActions(resourceTypeName: SamResourceTypeName,
actions: Seq[SamResourceAction],
roles: Seq[SamResourceRole],
ctx: RawlsRequestContext
): Future[Seq[SamUserResource]]

def listPoliciesForResource(resourceTypeName: SamResourceTypeName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,15 +568,26 @@ class SpendReportingService(
def getBillingWithSpendPermission(
): Future[Map[BillingProjectSpendExport, Seq[(GoogleProjectId, WorkspaceName)]]] =
for {
billingProjectResources <- samDAO.listResourcesWithActions(SamResourceTypeNames.billingProject,
SamBillingProjectActions.readSpendReport,
ctx
billingProjectResources <- samDAO.listResourcesWithRolesOrActions(SamResourceTypeNames.billingProject,
List(SamBillingProjectActions.readSpendReport),
List(),
ctx
)
ownerWorkspaces <- samDAO.listResourcesWithRolesOrActions(
SamResourceTypeNames.workspace,
List(),
List(SamWorkspaceRoles.owner), // TODO: owner only or owner + project-owner?
ctx
)
billingProjectIds = billingProjectResources.map(resource => RawlsBillingProjectName(resource.resourceId)).toList
groupedWorkspaces <- workspaceServiceConstructor(ctx).getGCPWorkspacesByBillingProjects(billingProjectIds)
ownerWorkspaceSet = ownerWorkspaces.map(_.resourceId).toSet
filteredGroupedWorkspaces = groupedWorkspaces.map { case (key, workspaces) =>
key -> workspaces.filter(ws => ownerWorkspaceSet.contains(ws.name))
}
// Only use the BPs we know exist in the DB and are GCP
spendConfigs <- getSpendExportConfigurations(groupedWorkspaces.keys.toList)
spendConfigs <- getSpendExportConfigurations(filteredGroupedWorkspaces.keys.toList)
} yield spendConfigs.map { config =>
config -> groupedWorkspaces(config.billingProjectName).map(ws => (ws.googleProjectId, ws.toWorkspaceName))
config -> filteredGroupedWorkspaces(config.billingProjectName).map(ws => (ws.googleProjectId, ws.toWorkspaceName))
}.toMap
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,10 @@ class MockSamDAO(dataSource: SlickDataSource)(implicit executionContext: Executi
case _ => Future.successful(Seq.empty)
}

override def listResourcesWithActions(resourceTypeName: SamResourceTypeName,
action: SamResourceAction,
ctx: RawlsRequestContext
override def listResourcesWithRolesOrActions(resourceTypeName: SamResourceTypeName,
actions: Seq[SamResourceAction],
roles: Seq[SamResourceRole],
ctx: RawlsRequestContext
): Future[Seq[SamUserResource]] =
resourceTypeName match {
case SamResourceTypeNames.workspace =>
Expand All @@ -251,7 +252,7 @@ class MockSamDAO(dataSource: SlickDataSource)(implicit executionContext: Executi
_.map(workspace =>
SamUserResource(
workspace.workspaceId,
SamRolesAndActions(Set(SamWorkspaceRoles.owner), Set(action)),
SamRolesAndActions(roles.toSet, actions.toSet),
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
Set.empty,
Expand All @@ -267,7 +268,7 @@ class MockSamDAO(dataSource: SlickDataSource)(implicit executionContext: Executi
_.map(project =>
SamUserResource(
project.projectName.value,
SamRolesAndActions(Set(SamBillingProjectRoles.owner), Set(action)),
SamRolesAndActions(roles.toSet, actions.toSet),
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
Set.empty,
Expand Down Expand Up @@ -426,16 +427,17 @@ class CustomizableMockSamDAO(dataSource: SlickDataSource)(implicit executionCont
}
}

override def listResourcesWithActions(resourceTypeName: SamResourceTypeName,
action: SamResourceAction,
ctx: RawlsRequestContext
override def listResourcesWithRolesOrActions(resourceTypeName: SamResourceTypeName,
actions: Seq[SamResourceAction],
roles: Seq[SamResourceRole],
ctx: RawlsRequestContext
): Future[Seq[SamUserResource]] = {
val userResources = for {
((typeName, resourceId), resourcePolicies) <- policies if typeName == resourceTypeName
userResource <- constructResourceFromPolicies(ctx, resourceId, resourcePolicies.values)
} yield userResource
if (userResources.isEmpty) {
super.listResourcesWithActions(resourceTypeName, action, ctx)
super.listResourcesWithRolesOrActions(resourceTypeName, actions, roles, ctx)
} else {
Future.successful(userResources.toSeq)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1344,7 +1344,48 @@ class SpendReportingServiceSpec extends AnyFlatSpecLike with Matchers with Mocki
)
)
.when(samDAO)
.listResourcesWithActions(any(), any(), any())
.listResourcesWithRolesOrActions(mockitoEq(SamResourceTypeNames.billingProject), any(), any(), any())

doReturn(
Future.successful(
Seq(
SamUserResource(
"workspace1Billing1",
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
Set.empty,
Set.empty
),
SamUserResource(
"workspace2Billing1",
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
Set.empty,
Set.empty
),
SamUserResource(
"workspace1Billing2",
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
Set.empty,
Set.empty
),
SamUserResource(
"workspace1Billing3",
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
SamRolesAndActions(Set.empty, Set.empty),
Set.empty,
Set.empty
)
)
)
)
.when(samDAO)
.listResourcesWithRolesOrActions(mockitoEq(SamResourceTypeNames.workspace), any(), any(), any())

val workspace1Billing1 =
TestData.workspace("workspace1Billing1",
Expand Down

0 comments on commit b07bbb1

Please sign in to comment.