diff --git a/core/src/main/scala/org/broadinstitute/dsde/rawls/billing/BillingProjectLifecycle.scala b/core/src/main/scala/org/broadinstitute/dsde/rawls/billing/BillingProjectLifecycle.scala index 8b1e1312bb..7fd7e56166 100644 --- a/core/src/main/scala/org/broadinstitute/dsde/rawls/billing/BillingProjectLifecycle.scala +++ b/core/src/main/scala/org/broadinstitute/dsde/rawls/billing/BillingProjectLifecycle.scala @@ -8,9 +8,9 @@ import org.broadinstitute.dsde.rawls.config.MultiCloudWorkspaceConfig import org.broadinstitute.dsde.rawls.dataaccess.SamDAO import org.broadinstitute.dsde.rawls.dataaccess.slick.WorkspaceManagerResourceMonitorRecord.JobType.JobType import org.broadinstitute.dsde.rawls.model.CreationStatuses.CreationStatus -import org.broadinstitute.dsde.rawls.model.{CreateRawlsV2BillingProjectFullRequest, ErrorReport, RawlsRequestContext} +import org.broadinstitute.dsde.rawls.model.{CreateRawlsV2BillingProjectFullRequest, ErrorReport, ProjectAccessUpdate, ProjectRoles, RawlsRequestContext} -import scala.concurrent.{blocking, ExecutionContext, Future} +import scala.concurrent.{ExecutionContext, Future, blocking} /** * Handles provisioning and deleting billing projects with external providers. Implementors of this trait are not concerned @@ -63,7 +63,10 @@ trait BillingProjectLifecycle extends LazyLogging { createProjectRequest: CreateRawlsV2BillingProjectFullRequest, ctx: RawlsRequestContext )(implicit executionContext: ExecutionContext): Future[Set[Unit]] = { - val members = createProjectRequest.members.getOrElse(Set.empty) + val members = createProjectRequest.members.getOrElse(Set.empty) ++ samDAO.getRawlsIdentityEmail.map { + email => + ProjectAccessUpdate(email, ProjectRoles.Owner) + } Future.traverse(members) { member => Future(blocking { billingProfileManagerDAO.addProfilePolicyMember(profileModel.getId, diff --git a/core/src/main/scala/org/broadinstitute/dsde/rawls/billing/BillingProjectOrchestrator.scala b/core/src/main/scala/org/broadinstitute/dsde/rawls/billing/BillingProjectOrchestrator.scala index ebe63be46e..1fd7439a65 100644 --- a/core/src/main/scala/org/broadinstitute/dsde/rawls/billing/BillingProjectOrchestrator.scala +++ b/core/src/main/scala/org/broadinstitute/dsde/rawls/billing/BillingProjectOrchestrator.scala @@ -116,7 +116,10 @@ class BillingProjectOrchestrator(ctx: RawlsRequestContext, ctx: RawlsRequestContext ): Future[Unit] = { - val additionalMembers = createProjectRequest.members.getOrElse(Set.empty) + val additionalMembers = createProjectRequest.members.getOrElse(Set.empty) ++ samDAO.getRawlsIdentityEmail.map { + email => + ProjectAccessUpdate(email, ProjectRoles.Owner) + } val policies = BillingProjectOrchestrator.buildBillingProjectPolicies(additionalMembers, ctx) val inviteUsersNotFound = createProjectRequest.inviteUsersNotFound.getOrElse(false) diff --git a/core/src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/HttpSamDAO.scala b/core/src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/HttpSamDAO.scala index b351b7b592..17bea3674c 100644 --- a/core/src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/HttpSamDAO.scala +++ b/core/src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/HttpSamDAO.scala @@ -4,6 +4,7 @@ import akka.actor.ActorSystem import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers.OAuth2BearerToken import bio.terra.common.tracing.OkHttpClientTracingInterceptor +import com.nimbusds.jwt.{JWT, JWTParser} import com.typesafe.scalalogging.LazyLogging import io.opentelemetry.api.GlobalOpenTelemetry import io.opentelemetry.context.Context @@ -27,8 +28,8 @@ import scala.jdk.DurationConverters._ import scala.util.{Try, Using} /** - * Created by mbemis on 9/11/17. - */ + * Created by mbemis on 9/11/17. + */ class HttpSamDAO(baseSamServiceURL: String, rawlsCredential: RawlsCredential, timeout: FiniteDuration)(implicit val system: ActorSystem, val executionContext: ExecutionContext @@ -68,8 +69,12 @@ class HttpSamDAO(baseSamServiceURL: String, rawlsCredential: RawlsCredential, ti protected def adminApi(ctx: RawlsRequestContext) = new AdminApi(getApiClient(ctx)) - private def rawlsSAContext = RawlsRequestContext( - UserInfo(RawlsUserEmail(""), OAuth2BearerToken(getRawlsIdentityAccessToken), 0, RawlsUserSubjectId("")) + override def rawlsSAContext = RawlsRequestContext( + UserInfo(RawlsUserEmail(getRawlsIdentityEmail.getOrElse("")), + OAuth2BearerToken(getRawlsIdentityAccessToken), + 0, + RawlsUserSubjectId("") + ) ) protected def when401or5xx: Predicate[Throwable] = anyOf(DsdeHttpDAO.when5xx, DsdeHttpDAO.whenUnauthorized) @@ -575,6 +580,18 @@ class HttpSamDAO(baseSamServiceURL: String, rawlsCredential: RawlsCredential, ti rawlsCredential.getAccessToken } + override def getRawlsIdentityEmail: Option[String] = + try { + val email = Option(JWTParser.parse(getRawlsIdentityAccessToken).getJWTClaimsSet.getClaim("sub")) + .map(_.toString + "@uami.terra.bio") + if (email.isEmpty) logger.info("Error parsing Rawls identity email from token, sub claim not found") + email + } catch { + case e: Exception => + logger.info("Error parsing Rawls identity email from token", e) + None + } + override def getResourceAuthDomain(resourceTypeName: SamResourceTypeName, resourceId: String, ctx: RawlsRequestContext diff --git a/core/src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/SamDAO.scala b/core/src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/SamDAO.scala index 7865d3471d..0d99b5597a 100644 --- a/core/src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/SamDAO.scala +++ b/core/src/main/scala/org/broadinstitute/dsde/rawls/dataaccess/SamDAO.scala @@ -1,5 +1,6 @@ package org.broadinstitute.dsde.rawls.dataaccess +import akka.http.scaladsl.model.headers.OAuth2BearerToken import cats.effect.Async import cats.effect.kernel.Resource import org.broadinstitute.dsde.rawls.model.{ @@ -7,6 +8,7 @@ import org.broadinstitute.dsde.rawls.model.{ RawlsRequestContext, RawlsUser, RawlsUserEmail, + RawlsUserSubjectId, SamCreateResourceResponse, SamFullyQualifiedResourceId, SamPolicy, @@ -29,8 +31,8 @@ import org.broadinstitute.dsde.workbench.model._ import scala.concurrent.Future /** - * Created by mbemis on 9/11/17. - */ + * Created by mbemis on 9/11/17. + */ trait SamDAO { val errorReportSource = ErrorReportSource("sam") @@ -132,8 +134,8 @@ trait SamDAO { ): Future[Set[UserIdInfo]] /** - * @return a json blob - */ + * @return a json blob + */ def getPetServiceAccountKeyForUser(googleProject: GoogleProjectId, userEmail: RawlsUserEmail): Future[String] def getDefaultPetServiceAccountKeyForUser(ctx: RawlsRequestContext): Future[String] @@ -152,6 +154,12 @@ trait SamDAO { ): Future[Seq[SamFullyQualifiedResourceId]] def admin: SamAdminDAO + + def getRawlsIdentityEmail: Option[String] = None + + def rawlsSAContext: RawlsRequestContext = RawlsRequestContext( + UserInfo(RawlsUserEmail(""), OAuth2BearerToken(""), 0, RawlsUserSubjectId(""), None) + ) } trait SamAdminDAO { diff --git a/core/src/main/scala/org/broadinstitute/dsde/rawls/monitor/workspace/runners/UserCtxCreator.scala b/core/src/main/scala/org/broadinstitute/dsde/rawls/monitor/workspace/runners/UserCtxCreator.scala index 71883c1bf2..9460ffd7e5 100644 --- a/core/src/main/scala/org/broadinstitute/dsde/rawls/monitor/workspace/runners/UserCtxCreator.scala +++ b/core/src/main/scala/org/broadinstitute/dsde/rawls/monitor/workspace/runners/UserCtxCreator.scala @@ -10,9 +10,8 @@ trait UserCtxCreator { val samDAO: SamDAO val gcsDAO: GoogleServicesDAO - def getUserCtx(userEmail: String)(implicit executionContext: ExecutionContext): Future[RawlsRequestContext] = for { - petKey <- samDAO.getUserArbitraryPetServiceAccountKey(userEmail) - userInfo <- gcsDAO.getUserInfoUsingJson(petKey) - } yield RawlsRequestContext(userInfo) + def getUserCtx(userEmail: String)(implicit executionContext: ExecutionContext): Future[RawlsRequestContext] = Future( + samDAO.rawlsSAContext + ) }