Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for deployment in Azure Government Cloud (Sam) #1603

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions src/main/resources/sam.conf
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ admin {

azureServices {
azureEnabled = ${?AZURE_ENABLED}
azureEnvironment = ${?AZURE_ENVIRONMENT} # defaults to AZURE
allowManagedIdentityUserCreation = ${?AZURE_ALLOW_MANAGED_IDENTITY_USER_CREATION}
managedAppServicePrincipal {
clientId = ${?AZURE_MANAGED_APP_CLIENT_ID}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import bio.terra.cloudres.common.ClientConfig
import bio.terra.cloudres.common.cleanup.CleanupConfig
import cats.effect.IO
import com.azure.core.credential.TokenCredential
import com.azure.core.management.AzureEnvironment
import com.azure.core.management.profile.AzureProfile
import com.azure.identity.{ChainedTokenCredentialBuilder, ClientSecretCredentialBuilder, ManagedIdentityCredentialBuilder}
import com.azure.resourcemanager.managedapplications.ApplicationManager
import com.azure.resourcemanager.msi.MsiManager
import com.azure.resourcemanager.resources.ResourceManager
import com.google.auth.oauth2.ServiceAccountCredentials
import com.typesafe.scalalogging.LazyLogging
import org.broadinstitute.dsde.workbench.sam.config.{AzureServicesConfig, JanitorConfig}

import java.io.FileInputStream
Expand All @@ -22,7 +22,7 @@ import scala.jdk.DurationConverters._
*
* Note: this class is Azure-specific for now because Sam uses workbench-libs for Google Cloud calls.
*/
class CrlService(config: AzureServicesConfig, janitorConfig: JanitorConfig) {
class CrlService(config: AzureServicesConfig, janitorConfig: JanitorConfig) extends LazyLogging {
val clientId = "sam"
val testResourceTimeToLive = 1 hour
val clientConfigBase = ClientConfig.Builder.newBuilder().setClient("sam")
Expand Down Expand Up @@ -72,14 +72,15 @@ class CrlService(config: AzureServicesConfig, janitorConfig: JanitorConfig) {
config.managedAppServicePrincipal.foreach { servicePrincipalConfig =>
credential.addLast(
new ClientSecretCredentialBuilder()
.authorityHost(config.azureEnvironment.getActiveDirectoryEndpoint)
.clientId(servicePrincipalConfig.clientId)
.clientSecret(servicePrincipalConfig.clientSecret)
.tenantId(servicePrincipalConfig.tenantId)
.build
)
}

val profile = new AzureProfile(tenantId.value, subscriptionId.value, AzureEnvironment.AZURE)
val profile = new AzureProfile(tenantId.value, subscriptionId.value, config.azureEnvironment)

(credential.build(), profile)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.broadinstitute.dsde.workbench.sam.config

import cats.data.NonEmptyList
import com.azure.core.management.AzureEnvironment
import com.google.api.client.json.gson.GsonFactory
import com.typesafe.config._
import net.ceedubs.ficus.Ficus._
Expand Down Expand Up @@ -196,6 +197,24 @@ object AppConfig {
} yield AzureServicePrincipalConfig(clientId, clientSecret, tenantId)
}

implicit val azureEnvironmentConfigReader: ValueReader[Option[AzureEnvironment]] = new ValueReader[Option[AzureEnvironment]] {
def read(config: Config, path: String): Option[AzureEnvironment] =
if (config.hasPath(path)) {
val azureEnvironment: String = config.getString(path)
val Azure: String = "AZURE"
val AzureGov: String = "AZURE_GOV"

azureEnvironment match {
case AzureGov => Some(AzureEnvironment.AZURE_US_GOVERNMENT)
case Azure => Some(AzureEnvironment.AZURE)
case _ => throw new IllegalArgumentException(s"Unknown Azure environment: $azureEnvironment")
}
} else {
None
}

}

implicit val azureServicesConfigReader: ValueReader[Option[AzureServicesConfig]] = ValueReader.relative { config =>
config
.getAs[Boolean]("azureEnabled")
Expand All @@ -207,7 +226,8 @@ object AppConfig {
config.as[Option[AzureServicePrincipalConfig]]("managedAppServicePrincipal"),
config.as[Option[AzureMarketPlace]]("azureMarketPlace"),
config.as[Option[AzureServiceCatalog]]("azureServiceCatalog"),
config.as[Option[Boolean]]("allowManagedIdentityUserCreation").getOrElse(false)
config.as[Option[Boolean]]("allowManagedIdentityUserCreation").getOrElse(false),
config.as[Option[AzureEnvironment]]("azureEnvironment").getOrElse(AzureEnvironment.AZURE)
)
)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.broadinstitute.dsde.workbench.sam.config

import com.azure.core.management.AzureEnvironment

case class ManagedAppPlan(name: String, publisher: String, authorizedUserKey: String)
case class AzureMarketPlace(managedAppPlans: Seq[ManagedAppPlan])
case class AzureServiceCatalog(authorizedUserKey: String, managedAppTypeServiceCatalog: String)
Expand All @@ -8,10 +10,12 @@ case class AzureServicePrincipalConfig(
clientSecret: String,
tenantId: String
)

case class AzureServicesConfig(
managedAppWorkloadClientId: Option[String],
managedAppServicePrincipal: Option[AzureServicePrincipalConfig],
azureMarketPlace: Option[AzureMarketPlace],
azureServiceCatalog: Option[AzureServiceCatalog],
allowManagedIdentityUserCreation: Boolean
allowManagedIdentityUserCreation: Boolean,
azureEnvironment: AzureEnvironment
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import akka.http.scaladsl.server.Directives.reject
import akka.http.scaladsl.server.{Directive, Directive0}
import akka.stream.Materializer
import cats.effect.unsafe.implicits.global
import com.azure.core.management.AzureEnvironment
import com.typesafe.config.ConfigFactory
import org.broadinstitute.dsde.workbench.google.GoogleDirectoryDAO
import org.broadinstitute.dsde.workbench.google.mock.MockGoogleDirectoryDAO
Expand Down Expand Up @@ -224,7 +225,8 @@ object TestSamRoutes {
Option(AzureServicePrincipalConfig("mock-managedapp-clientid", "mock-managedapp-clientsecret", "mock-managedapp-tenantid")),
azureMarketPlace,
azureServiceCatalog,
allowManagedIdentityUserCreation = true
allowManagedIdentityUserCreation = true,
azureEnvironment = AzureEnvironment.AZURE
)

val azureService =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.broadinstitute.dsde.workbench.sam.service.UserServiceSpecs

import com.azure.core.management.AzureEnvironment
import org.broadinstitute.dsde.workbench.model._
import org.broadinstitute.dsde.workbench.sam.Generator.{genNewWorkbenchUserAzureUami, genWorkbenchUserAzure, genWorkbenchUserBoth, genWorkbenchUserGoogle}
import org.broadinstitute.dsde.workbench.sam.config.AzureServicesConfig
Expand Down Expand Up @@ -81,7 +82,7 @@ class CreateUserSpec extends UserServiceTestTraits {
cloudExtensions,
Seq.empty,
defaultTosService,
Some(AzureServicesConfig(None, None, None, None, allowManagedIdentityUserCreation = true))
Some(AzureServicesConfig(None, None, None, None, allowManagedIdentityUserCreation = true, azureEnvironment = AzureEnvironment.AZURE))
)

// Act
Expand Down Expand Up @@ -295,7 +296,7 @@ class CreateUserSpec extends UserServiceTestTraits {
cloudExtensions,
Seq.empty,
defaultTosService,
Some(AzureServicesConfig(None, None, None, None, allowManagedIdentityUserCreation = false))
Some(AzureServicesConfig(None, None, None, None, allowManagedIdentityUserCreation = false, azureEnvironment = AzureEnvironment.AZURE))
)

// Act and Assert
Expand Down
Loading