public gcpIamCustomRole() { gcpConfig = new Config("gcp"); this.roleId = gcpConfig.Require("RoleId"); this.roleTitle = gcpConfig.Require("RoleTitle"); this.rolePermissions = gcpConfig.GetObject <string[]>("RolePermissions"); this.roleDescription = $"{gcpConfig.Require("RoleDescription")}"; ProvisionRole(); }
public ActiveDirectoryResource(Output <string> currentUserObjectId) { var config = new Config("azureactivedirectory"); ClientId = config.Require("clientid"); ClientSecret = config.GetSecret("clientsecret"); Domain = config.Require("domain"); TenantId = config.Require("tenantId"); _currentUserObjectId = currentUserObjectId; }
public KanbernetesStack() { var config = new Config(); var azureResources = CreateBaseAzureInfrastructure(config); var clusterOptions = new ClusterOptions { Domain = config.Require("domain"), Namespace = config.Require("kubernetes-namespace"), CertificateIssuerAcmeEmail = config.Require("certmanager-acme-email") }; ConfigureKubernetesCluster(azureResources, clusterOptions); }
public AzureStack() { var config = new Pulumi.Config(); var deployTo = config.Require("DeployTo"); // Create an Azure Resource Group var resourceGroupName = $"rg-ne-rpc-demo-{deployTo}"; var resourceGroup = new ResourceGroup( resourceGroupName, new ResourceGroupArgs { Name = resourceGroupName }); // Create an Azure Storage Account var storageAccount = new Account($"nerpcdemo{deployTo}", new AccountArgs { ResourceGroupName = resourceGroup.Name, AccountReplicationType = "LRS", AccountTier = "Standard" }); // Export the connection string for the storage account this.StorageAccountName = storageAccount.Name; }
static Task <int> Main() => Deployment.RunAsync(async() => { // Fetch the Docker Hub auth info from config. var config = new Pulumi.Config(); var username = config.Require("dockerUsername"); var password = config.RequireSecret("dockerPassword"); // Populate the registry info (creds and endpoint). var imageName = $"{username}/myapp"; var registryInfo = new ImageRegistry { Server = "docker.io", Username = username, Password = password, }; // Build and publish the app image. var image = new Image("my-image", new ImageArgs { ImageName = username + "/myapp", Build = new DockerBuild { Context = "app" }, Registry = registryInfo, }); // Export the resulting image name. return(new Dictionary <string, object> { { "imageName", image.ImageName }, }); });
private void ProvisionRole() { switch (gcpConfig.Require("RoleScope").ToLower()) { case "project": { var projIamCustomRole = new Projects.IAMCustomRole("projIamCustomRole", new Projects.IAMCustomRoleArgs { Description = roleDescription, Permissions = rolePermissions, Project = gcpConfig.Require("project"), RoleId = roleId, Title = roleTitle, } /// To import an existing role uncomment the following block, update PROJECT_ID AND ROLE_ID then /// run Pulumi Up, details, verify property alignment for import, run Pulumi Up, yes, recomment this block // ,new CustomResourceOptions { // ImportId = "projects/[PROJECT_ID]/roles/[ROLE_ID]" // } ); break; } default: { var orgIamCustomRole = new Organizations.IAMCustomRole("orgIamCustomRole", new Organizations.IAMCustomRoleArgs { Description = roleDescription, Permissions = rolePermissions, OrgId = gcpConfig.Require("orgid"), RoleId = roleId, Title = roleTitle, } /// To import an existing role uncomment the following block, update ORG_ID AND ROLE_ID // ,new CustomResourceOptions { // ImportId = "organizations/[ORG_ID]/roles/[ROLE_ID]" // } ); break; } } }
public CreateRoleStack() { var config = new Pulumi.Config(); var unprivilegedUsername = config.Require("unprivilegedUsername"); var unprivilegedUser = new Iam.User("unprivilegedUser", new Iam.UserArgs { Name = unprivilegedUsername, }); var unprivilegedUserCreds = new Iam.AccessKey("unprivileged-user-key", new Iam.AccessKeyArgs { User = unprivilegedUser.Name, }, // additional_secret_outputs specify properties that must be encrypted as secrets // https://www.pulumi.com/docs/intro/concepts/programming-model/#additionalsecretoutputs new CustomResourceOptions { AdditionalSecretOutputs = { "secret" } }); var tempPolicy = unprivilegedUser.Arn.Apply((string arn) => { AssumeRolePolicyArgs policyArgs = new AssumeRolePolicyArgs(arn); return(JsonSerializer.Serialize <AssumeRolePolicyArgs>(policyArgs)); }); var allowS3ManagementRole = new Iam.Role("allow-s3-management", new Iam.RoleArgs { Description = "Allow management of S3 buckets", AssumeRolePolicy = tempPolicy }); var rolePolicy = new Iam.RolePolicy("allow-s3-management-policy", new Iam.RolePolicyArgs { Role = allowS3ManagementRole.Name, Policy = @"{ ""Version"": ""2012-10-17"", ""Statement"": [{ ""Effect"": ""Allow"", ""Action"": ""s3:*"", ""Resource"": ""*"", ""Sid"": ""allowS3Access"" }] }" }, new CustomResourceOptions { Parent = allowS3ManagementRole } ); this.roleArn = allowS3ManagementRole.Arn; this.accessKeyId = unprivilegedUserCreds.Id; this.secretAccessKey = unprivilegedUserCreds.Secret; }
public PetDoctorStack() { var config = new Config(); var azureResources = CreateBaseAzureInfrastructure(config); var clusterOptions = new PetDoctorClusterOptions { Domain = config.Require("domain"), Namespace = config.Require("kubernetes-namespace"), CertificateIssuerAcmeEmail = config.Require("certmanager-acme-email"), AppointmentApi = new ReplicaSetConfiguration { AadPodIdentityBindingName = "appointments-api-pod-identity-binding", AadPodIdentityName = "appointments-api-pod-identity", AadPodIdentitySelector = "appointments-api", DeploymentName = "appointments-api", IngressName = "appointments-api-ingress", ServiceName = "appointments-api-svc", Image = azureResources.Registry.LoginServer.Apply(loginServer => $"{loginServer}/pet-doctor/appointments/api:{config.Require("versions-appointments-api")}"), Port = 80, ReplicaCount = 2, Cpu = new ResourceLimit { Request = "25m", Limit = "50m" }, Memory = new ResourceLimit { Request = "250Mi", Limit = "400Mi" }, SecretName = "appointments-api-secrets" } }; ConfigureKubernetesCluster(azureResources, clusterOptions); var appointmentApiAzureResources = CreateAppointmentApiAzureResources(azureResources, config, clusterOptions.AppointmentApi.Image); SetupAppointmentApiInKubernetes(azureResources, appointmentApiAzureResources, clusterOptions); }
static Task <int> Main() { return(Deployment.RunAsync(() => { var config = new Pulumi.Config(); var companyCode = config.Require("company_code"); var location = config.Require("location"); var environment = config.Require("environment"); ResourceFactory factory = new ResourceFactory(companyCode, location, environment); // Create an Azure Resource Group var resourceGroup = factory.GetResourceGroup("00"); // Create an Azure Storage Account var storageAccount = factory.GetStorageAccount("00", resourceGroup.Name); // Export the connection string for the storage account return new Dictionary <string, object?> { { "connectionString", storageAccount.PrimaryConnectionString }, }; })); }
public MyStack() { var config = new Pulumi.Config(); var zoneId = config.Require("zone_id"); var foobar = new Cloudflare.Record("foobar", new Cloudflare.RecordArgs { Name = "my-record-csharp", ZoneId = zoneId, Value = "162.168.0.14", Type = "A", Ttl = 3600, }); }
public KeyVaultStack() { // Get current Subscription var currentSubscription = Output.Create(GetSubscription.InvokeAsync()); var tenantId = currentSubscription.Apply(currentSubscription => currentSubscription.TenantId); // Get current Client Config var currentClient = Output.Create(GetClientConfig.InvokeAsync()); var objectId = currentClient.Apply(currentClient => currentClient.ObjectId); var config = new Pulumi.Config(); var resourceGroupName = config.Require("resource_group_name"); var keyVaultName = config.Require("key_vault_name"); // Create an Azure Resource Group var resourceGroup = new ResourceGroup(resourceGroupName); // Create an Azure Key Vault var keyVault = new KeyVault(keyVaultName, new KeyVaultArgs { ResourceGroupName = resourceGroup.Name, SkuName = "standard", TenantId = tenantId, AccessPolicies = { new KeyVaultAccessPolicyArgs { TenantId = tenantId, ObjectId = objectId, SecretPermissions ={ "list", "get" } } } }); this.VaultUri = keyVault.VaultUri; }
public AssumeRoleStack() { var awsConfig = new Pulumi.Config("aws"); var config = new Pulumi.Config(); var roleToAssumeARN = config.Require("roleToAssumeARN"); var provider = new Aws.Provider("privileged", new Aws.ProviderArgs { AssumeRole = new Aws.Inputs.ProviderAssumeRoleArgs { RoleArn = roleToAssumeARN, SessionName = "PulumiSession", ExternalId = "PulumiApplication" }, Region = awsConfig.Require("region"), }); var bucket = new Aws.S3.Bucket("myBucket", null, new CustomResourceOptions { Provider = provider }); }
public MyStack() { var config = new Pulumi.Config(); var location = config.Get("location") ?? "WestUS"; var resourceGroup = new ResourceGroup("resourceGroup", new ResourceGroupArgs { ResourceGroupName = "synapse-rg", Location = location }); var storageAccount = new StorageAccount("storageAccount", new StorageAccountArgs { ResourceGroupName = resourceGroup.Name, Location = resourceGroup.Location, AccountName = "synapsesa", AccessTier = "Hot", EnableHttpsTrafficOnly = true, IsHnsEnabled = true, Kind = "StorageV2", Sku = new SkuArgs { Name = "Standard_RAGRS" }, }); var dataLakeStorageAccountUrl = Output.Format($"https://{storageAccount.Name}.dfs.core.windows.net"); var users = new BlobContainer("users", new BlobContainerArgs { ResourceGroupName = resourceGroup.Name, AccountName = storageAccount.Name, ContainerName = "users", PublicAccess = "None" }); var workspace = new Workspace("workspace", new WorkspaceArgs { ResourceGroupName = resourceGroup.Name, Location = resourceGroup.Location, WorkspaceName = "my-workspace", DefaultDataLakeStorage = new DataLakeStorageAccountDetailsArgs { AccountUrl = dataLakeStorageAccountUrl, Filesystem = "users" }, Identity = new ManagedIdentityArgs { Type = "SystemAssigned" }, SqlAdministratorLogin = "******", SqlAdministratorLoginPassword = "******" }); var allowAll = new IpFirewallRule("allowAll", new IpFirewallRuleArgs { ResourceGroupName = resourceGroup.Name, WorkspaceName = workspace.Name, RuleName = "allowAll", EndIpAddress = "255.255.255.255", StartIpAddress = "0.0.0.0" }); var subscriptionId = resourceGroup.Id.Apply(id => id.Split('/')[2]); var roleDefinitionId = $"/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe"; var storageAccess = new RoleAssignment("storageAccess", new RoleAssignmentArgs { RoleAssignmentName = new RandomUuid("roleName").Result, Scope = storageAccount.Id, PrincipalId = workspace.Identity.Apply(identity => identity.PrincipalId).Apply(v => v ?? "<preview>"), PrincipalType = "ServicePrincipal", RoleDefinitionId = roleDefinitionId }); var userAccess = new RoleAssignment("userAccess", new RoleAssignmentArgs { RoleAssignmentName = new RandomUuid("userRoleName").Result, Scope = storageAccount.Id, PrincipalId = config.Require("userObjectId"), PrincipalType = "User", RoleDefinitionId = roleDefinitionId }); var sqlPool = new SqlPool("sqlPool", new SqlPoolArgs { ResourceGroupName = resourceGroup.Name, Location = resourceGroup.Location, WorkspaceName = workspace.Name, SqlPoolName = "SQLPOOL1", Collation = "SQL_Latin1_General_CP1_CI_AS", CreateMode = "Default", Sku = new Pulumi.AzureNextGen.Synapse.V20190601Preview.Inputs.SkuArgs { Name = "DW100c" }, }); var sparkPool = new BigDataPool("sparkPool", new BigDataPoolArgs { ResourceGroupName = resourceGroup.Name, Location = resourceGroup.Location, WorkspaceName = workspace.Name, BigDataPoolName = "Spark1", AutoPause = new AutoPausePropertiesArgs { DelayInMinutes = 15, Enabled = true, }, AutoScale = new AutoScalePropertiesArgs { Enabled = true, MaxNodeCount = 3, MinNodeCount = 3, }, NodeCount = 3, NodeSize = "Small", NodeSizeFamily = "MemoryOptimized", SparkVersion = "2.4" }); }
public MyStack() { var config = new Pulumi.Config(); // Per-cluster config var aksClusterConfigs = new[] { new { Name = "east", Location = "eastus", NodeCount = 2, NodeSize = ContainerServiceVMSizeTypes.Standard_D2_v2, }, new { Name = "west", Location = "westus", NodeCount = 5, NodeSize = ContainerServiceVMSizeTypes.Standard_D2_v2, }, }; // Create an Azure Resource Group var resourceGroup = new ResourceGroup("aks", new ResourceGroupArgs { Location = config.Get("location") ?? "eastus", }); // Create the AD service principal for the K8s cluster. var adApp = new Application("aks", new ApplicationArgs { DisplayName = "my-aks-multicluster", }); var adSp = new ServicePrincipal("aksSp", new ServicePrincipalArgs { ApplicationId = adApp.ApplicationId }); var adSpPassword = new ServicePrincipalPassword("aksSpPassword", new ServicePrincipalPasswordArgs { ServicePrincipalId = adSp.Id, Value = config.Require("password"), EndDate = "2099-01-01T00:00:00Z", }); // Create the individual clusters var aksClusterNames = new List <Output <string> >(); foreach (var perClusterConfig in aksClusterConfigs) { var cluster = new ManagedCluster($"aksCluster-{perClusterConfig.Name}", new ManagedClusterArgs { // Global config arguments ResourceGroupName = resourceGroup.Name, LinuxProfile = new ContainerServiceLinuxProfileArgs { AdminUsername = "******", Ssh = new ContainerServiceSshConfigurationArgs { PublicKeys = { new ContainerServiceSshPublicKeyArgs { KeyData = config.Require("sshPublicKey"), } } } }, ServicePrincipalProfile = new ManagedClusterServicePrincipalProfileArgs { ClientId = adApp.ApplicationId, Secret = adSpPassword.Value }, // Per-cluster config arguments Location = perClusterConfig.Location, AgentPoolProfiles = { new ManagedClusterAgentPoolProfileArgs { Mode = AgentPoolMode.System, Name = "agentpool", Count = perClusterConfig.NodeCount, VmSize = perClusterConfig.NodeSize, } }, DnsPrefix = $"{Pulumi.Deployment.Instance.StackName}-kube", KubernetesVersion = "1.18.14", }); aksClusterNames.Add(cluster.Name); } ; this.aksClusterNames = Output.All(aksClusterNames); }
public BotStack() { var config = new Pulumi.Config(); var botName = config.Require("botName"); var resourceGroup = new ResourceGroup("botservice-rg"); var storageAccount = new Storage.Account("sa", new Storage.AccountArgs { ResourceGroupName = resourceGroup.Name, AccountReplicationType = "LRS", AccountTier = "Standard" }); var appServicePlan = new Plan("asp", new PlanArgs { ResourceGroupName = resourceGroup.Name, Kind = "App", Sku = new PlanSkuArgs { Tier = "Basic", Size = "B1" } }); var container = new Storage.Container("zips", new Storage.ContainerArgs { StorageAccountName = storageAccount.Name, ContainerAccessType = "private", }); var blob = new Storage.Blob("zip", new Storage.BlobArgs { StorageAccountName = storageAccount.Name, StorageContainerName = container.Name, Type = "Block", Source = new FileArchive("bot/publish") }); var codeBlobUrl = Storage.SharedAccessSignature.SignedBlobReadUrl(blob, storageAccount); var appInsights = new Insights("ai", new InsightsArgs { ApplicationType = "web", ResourceGroupName = resourceGroup.Name }); var appInsightApiKey = new ApiKey("ai", new ApiKeyArgs { ApplicationInsightsId = appInsights.Id, ReadPermissions = "api", }); var luis = new Cognitive.Account("cs", new Cognitive.AccountArgs { Kind = "CognitiveServices", // includes LUIS ResourceGroupName = resourceGroup.Name, SkuName = "S0" }); var msa = new Application("msapp", new ApplicationArgs { Oauth2AllowImplicitFlow = false, AvailableToOtherTenants = true, PublicClient = true }); var pwd = new RandomPassword("password", new RandomPasswordArgs { Length = 16, MinNumeric = 1, MinSpecial = 1, MinUpper = 1, MinLower = 1 }); var msaSecret = new ApplicationPassword("msasecret", new ApplicationPasswordArgs { ApplicationObjectId = msa.ObjectId, EndDateRelative = "8640h", Value = pwd.Result }); var app = new AppService("app", new AppServiceArgs { ResourceGroupName = resourceGroup.Name, AppServicePlanId = appServicePlan.Id, AppSettings = { { "WEBSITE_RUN_FROM_PACKAGE", codeBlobUrl }, { "MicrosoftAppId", msa.ApplicationId }, { "MicrosoftAppPassword", msaSecret.Value }, { "LuisApiKey", luis.PrimaryAccessKey }, }, HttpsOnly = true }); var bot = new WebApp(botName, new WebAppArgs { DisplayName = botName, MicrosoftAppId = msa.ApplicationId, ResourceGroupName = resourceGroup.Name, Sku = "F0", Location = "global", Endpoint = Output.Format($"https://{app.DefaultSiteHostname}/api/messages"), DeveloperAppInsightsApiKey = appInsightApiKey.Key, DeveloperAppInsightsApplicationId = appInsights.AppId, DeveloperAppInsightsKey = appInsights.InstrumentationKey }); this.BotEndpoint = bot.Endpoint; this.MicrosoftAppId = msa.ApplicationId; this.MicrosoftAppPassword = msaSecret.Value; }
static Task <int> Main() { return(Deployment.RunAsync(async() => { var config = new Pulumi.Config(); var environment = config.Require("environment"); var companyCode = config.Require("company_code"); var scope = config.Require("default_scope"); var location = config.Require("location"); var webAppPath = config.Require("webAppPath"); var sourcePath = config.Require("sourcePath"); ResourceFactory factory = new ResourceFactory(companyCode, location, environment, scope); Dictionary <string, string> scopeTag = new Dictionary <string, string>(); scopeTag.Add("scope", scope); // Create a resource group var resourceGroup = factory.GetResourceGroup(tags: scopeTag); // Create a storage account for Blobs var storageAccount = factory.GetStorageAccount("Standard", "LRS", resourceGroup.Name, tags: scopeTag); // The container to put our files into var storageContainer = factory.GetContainer(storageAccountName: storageAccount.Name); // Azure SQL Server that we want to access from the application var administratorLoginPassword = factory.GetRandomPassword(length: 16).Result; var sqlServer = factory.GetSqlServer(resourceGroupName: resourceGroup.Name, administratorLogin: "******", administratorLoginPassword: administratorLoginPassword, version: "12.0", tags: scopeTag); // Azure SQL Database that we want to access from the application var database = factory.GetDatabase(resourceGroupName: resourceGroup.Name, sqlServerName: sqlServer.Name, requestedServiceObjectiveName: "S0", tags: scopeTag); // The connection string that has no credentials in it: authertication will come through MSI var connectionString = Output.Format($"Server=tcp:{sqlServer.Name}.database.windows.net;Database={database.Name};"); // A file in Blob Storage that we want to access from the application var textBlob = factory.GetBlob(storageAccountName: storageAccount.Name, storageContainerName: storageContainer.Name, type: "block", source: sourcePath); // A plan to host the App Service var appServicePlanSku = factory.GetPlanSku(tier: "Basic", size: "B1"); var appServicePlan = factory.GetPlan(resourceGroupName: resourceGroup.Name, sku: appServicePlanSku, kind: "App", tags: scopeTag); // ASP.NET deployment package var content = new FileArchive(webAppPath); var blob = factory.GetZipBlob(storageAccountName: storageAccount.Name, storageContainerName: storageContainer.Name, type: "block", content: content); var clientConfig = await Pulumi.Azure.Core.Invokes.GetClientConfig(); var tenantId = clientConfig.TenantId; var currentPrincipal = clientConfig.ObjectId; // Key Vault to store secrets (e.g. Blob URL with SAS) var vaultAccessPolicies = factory.GetKeyVaultAccessPolicy(tenantId: Output.Create(tenantId), objectId: Output.Create(currentPrincipal), secretPermissions: new List <string> { "delete", "get", "list", "set" }); var vault = factory.GetKeyVault(resourceGroupName: resourceGroup.Name, tenantId: Output.Create(tenantId), accessPolicies: vaultAccessPolicies, tags: scopeTag); // Put the URL of the zip Blob to KV var secret = factory.GetSecret(keyVaultId: vault.Id, blob: blob, storageAccount: storageAccount, tags: scopeTag); var secretUri = Output.Format($"{secret.VaultUri}secrets/{secret.Name}/{secret.Version}"); // The application hosted in App Service var app = factory.GetAppService(resourceGroupName: resourceGroup.Name, appServicePlanId: appServicePlan.Id, blobUrl: textBlob.Url, secretUri: secretUri, connectionString: connectionString, connectionStringName: "db", connectionStringType: "SQLAzure", tags: scopeTag); // Work around a preview issue https://github.com/pulumi/pulumi-azure/issues/192 var principalId = app.Identity.Apply(id => id.PrincipalId ?? "11111111-1111-1111-1111-111111111111"); // Grant App Service access to KV secrets var policy = factory.GetAccessPolicy(keyVaultId: vault.Id, tenantId: Output.Create(tenantId), objectId: principalId, secretPermissions: new List <string> { "get" }); // Make the App Service the admin of the SQL Server (double check if you want a more fine-grained security model in your real app) var sqlAdmin = factory.GetActiveDirectoryAdministrator(resourceGroupName: resourceGroup.Name, tenantId: Output.Create(tenantId), objectId: principalId, loginUsername: "******", sqlServerName: sqlServer.Name); // Grant access from App Service to the container in the storage var blobPermission = factory.GetAssignment(principalId: principalId, storageAccountId: storageAccount.Id, storageContainerName: storageContainer.Name, roleDefinitionName: "Storage Blob Data Reader"); // Add SQL firewall exceptions var firewallRules = app.OutboundIpAddresses.Apply( ips => ips.Split(",").Select(ip => factory.GetFirewallRule(resourceGroupName: resourceGroup.Name, startIpAddress: ip, endIpAddress: ip, sqlServerName: sqlServer.Name)).ToList()); return new Dictionary <string, object?> { { "endpoint", Output.Format($"https://{app.DefaultSiteHostname}") }, }; })); }
public DeploymentStack() { // Define variables var config = new Pulumi.Config(); var rgName = string.Format("{0}-{1}-{2}-{3}", config.Require("prefix"), config.Require("resourceFunction"), config.Require("environment"), config.Require("azureRegion")); var storageAccountName = string.Format("{0}{1}sa{2}{3}", config.Require("prefix"), config.Require("resourceFunction"), config.Require("environment"), config.Require("azureRegion")); var apimName = string.Format("{0}-{1}-{2}-{3}", config.Require("prefix"), config.Require("resourceFunction"), config.Require("environment"), config.Require("azureRegion")); var kvName = string.Format("{0}-{1}-kv-{2}-{3}", config.Require("prefix"), config.Require("resourceFunction"), config.Require("environment"), config.Require("azureRegion")); var appInsightsName = string.Format("{0}-{1}-appinsights-{2}-{3}", config.Require("prefix"), config.Require("resourceFunction"), config.Require("environment"), config.Require("azureRegion")); var tags = new InputMap <string>() { { "belongsto", "Core Resources" }, { "environment", "Development" }, { "costcenter", "Backend" }, { "owner", "IT" } }; // Get current identity details var clientConfig = Output.Create(Pulumi.Azure.Core.Invokes.GetClientConfig()); var tenantId = clientConfig.Apply(c => c.TenantId); var currentPrincipal = clientConfig.Apply(c => c.ObjectId); // Create the Azure Resource Group var rg = new ResourceGroup("rg", new ResourceGroupArgs() { Name = rgName, Location = config.Require("azureLocation"), Tags = tags }); // Create the storage account to contain policy, OpenApi and other deployment related files var sa = new Account("sa", new AccountArgs { ResourceGroupName = rg.Name, Name = storageAccountName, AccountKind = "StorageV2", AccountReplicationType = "LRS", AccountTier = "Standard", EnableHttpsTrafficOnly = true, Tags = tags }, new CustomResourceOptions() { DependsOn = { rg } }); var saContainerApim = new Container("apim-files", new ContainerArgs() { StorageAccountName = sa.Name, ContainerAccessType = "private" }, new CustomResourceOptions() { DependsOn = { rg } }); var saContainerApi = new Container("api-files", new ContainerArgs() { StorageAccountName = sa.Name, ContainerAccessType = "private" }, new CustomResourceOptions() { DependsOn = { rg } }); // Create key vault to contain the certificate secret var kv = new KV.KeyVault("kv", new KV.KeyVaultArgs() { Name = kvName, ResourceGroupName = rg.Name, EnabledForDiskEncryption = false, SkuName = "standard", TenantId = tenantId, AccessPolicies = { new KeyVaultAccessPoliciesArgs { TenantId = tenantId, ObjectId = currentPrincipal, SecretPermissions = { "get" }, CertificatePermissions ={ "delete", "create", "get", "import", "list", "update" }, } }, Tags = tags }); // Upload the certificate to Key Vault --> Currently disabled because no valid pfx which breaks the deployment // var pfxBytes = System.IO.File.ReadAllBytes("certificates/"+ config.Require("customDomainsCertificateName")); // var cert = new KV.Certificate("apim-tls-certificate", new KV.CertificateArgs() // { // Name = "apim-tls-certificate", // KeyVaultId = kv.Id, // KeyVaultCertificate = new CertificateCertificateArgs() // { // Contents = System.Convert.ToBase64String(pfxBytes), // Password = config.Require("customDomainsCertificatePasword") // }, // CertificatePolicy = new CertificateCertificatePolicyArgs() // { // IssuerParameters = new CertificateCertificatePolicyIssuerParametersArgs() // { // Name = config.Require("customDomainsCertificateIssuer") // }, // KeyProperties = new CertificateCertificatePolicyKeyPropertiesArgs() // { // Exportable = true, // KeySize = 2048, // KeyType = "RSA", // ReuseKey = false // }, // SecretProperties = new CertificateCertificatePolicySecretPropertiesArgs() // { // ContentType = "application/x-pkcs12" // } // } // }, // new CustomResourceOptions() // { // DependsOn = { rg, kv } // }); // APIM resource var apim = new Service("apim", new ServiceArgs() { Name = apimName, ResourceGroupName = rg.Name, SkuName = "Developer_1", PublisherEmail = config.Require("publisherEmail"), PublisherName = config.Require("publisherName"), Tags = tags, Identity = new ServiceIdentityArgs() { Type = "SystemAssigned" } }, new CustomResourceOptions() { CustomTimeouts = new CustomTimeouts { Create = TimeSpan.FromMinutes(60) }, DependsOn = { rg, sa, kv } }); // Change Key Vault policy to be able to have APIM access the certificate // var kvApimPolicy = new KV.AccessPolicy("apim-policy", new KV.AccessPolicyArgs() // { // TenantId = tenantId, // ObjectId = apim.Identity.PrincipalId, // SecretPermissions = {"get"}, // CertificatePermissions = {"get", "list"}, // KeyVaultId = kv.Id // }); // Set custom domain // Call Powershell to assign custom domain to APIM instance // Create product on APIM var apimProduct = new Product("apimProduct", new ProductArgs() { ResourceGroupName = rg.Name, ApiManagementName = apim.Name, DisplayName = config.Require("productName"), ProductId = config.Require("productId"), ApprovalRequired = bool.Parse(config.Require("productApprovalRequired")), Published = bool.Parse(config.Require("productPublished")), SubscriptionRequired = bool.Parse(config.Require("productSubscriptionRequired")), SubscriptionsLimit = int.Parse(config.Require("productSubscriptionLimit")) }, new CustomResourceOptions() { DependsOn = { apim } }); var apimProductPolicy = new ProductPolicy("apimProductPolicy", new ProductPolicyArgs() { ResourceGroupName = rg.Name, ApiManagementName = apim.Name, ProductId = config.Require("productId"), XmlContent = @"<policies> <inbound> <base /> </inbound> <backend> <base /> </backend> <outbound> <set-header name='Server' exists-action='delete' /> <set-header name='X-Powered-By' exists-action='delete' /> <set-header name='X-AspNet-Version' exists-action='delete' /> <base /> </outbound> <on-error> <base /> </on-error> </policies>" }, new CustomResourceOptions() { DependsOn = { apim, apimProduct } }); // Create user var apimUser = new User("user", new UserArgs() { ResourceGroupName = rg.Name, ApiManagementName = apim.Name, UserId = string.Format("{0}-user", config.Require("productId")), Email = string.Format("{0}-{1}@didago.nl", config.Require("productId"), config.Require("environment")), FirstName = "user", LastName = config.Require("productName"), State = "active" }, new CustomResourceOptions() { DependsOn = { apim } }); // Create subscription var apimSubscription = new Subscription("subscription", new SubscriptionArgs() { ResourceGroupName = rg.Name, ApiManagementName = apim.Name, DisplayName = "Some subscription", ProductId = apimProduct.Id, UserId = apimUser.Id, PrimaryKey = config.Require("productSubscriptionKey") }, new CustomResourceOptions() { DependsOn = { apim, apimProduct, apimUser } }); // Create Application Insights var appInsights = new Insights("appinsights", new InsightsArgs() { Name = appInsightsName, ResourceGroupName = rg.Name, ApplicationType = "web", Tags = tags }); // Create APIM diagnostics logger var apimLogger = new Logger("apimLogger", new LoggerArgs() { Name = $"{apimName}-logger", ResourceGroupName = rg.Name, ApiManagementName = apim.Name, ApplicationInsights = new LoggerApplicationInsightsArgs() { InstrumentationKey = appInsights.InstrumentationKey } }, new CustomResourceOptions() { DependsOn = { appInsights, apim } }); // Add health probe to APIM, create operation, policy and assign to product var apiHealthProbe = new Api("healthProbe", new ApiArgs() { ResourceGroupName = rg.Name, ApiManagementName = apim.Name, DisplayName = "Health probe", Path = "health-probe", Protocols = "https", Revision = "1" }, new CustomResourceOptions() { DependsOn = { apim } }); var apimHealthProbeOperation = new ApiOperation("pingOperation", new ApiOperationArgs() { ResourceGroupName = rg.Name, ApiManagementName = apim.Name, ApiName = apiHealthProbe.Name, DisplayName = "Ping", Method = "GET", UrlTemplate = "/", OperationId = "get-ping" }, new CustomResourceOptions() { DependsOn = { apiHealthProbe } }); var apiHealthProbePolicy = new ApiPolicy("healthProbePolicy", new ApiPolicyArgs() { ResourceGroupName = rg.Name, ApiManagementName = apim.Name, ApiName = apiHealthProbe.Name, XmlContent = @"<policies> <inbound> <return-response> <set-status code='200' /> </return-response> <base /> </inbound> </policies>" }, new CustomResourceOptions() { DependsOn = { apimHealthProbeOperation } }); var apiHealtProbeProduct = new ProductApi("healthProbeProduct", new ProductApiArgs() { ResourceGroupName = rg.Name, ApiManagementName = apim.Name, ApiName = apiHealthProbe.Name, ProductId = apimProduct.ProductId }, new CustomResourceOptions() { DependsOn = { apim, apimProduct, apiHealthProbePolicy } }); }
private Pipeline CreatePipeline(Bucket bucket, Role pipelineRole, Project buildProject, Role cloudFormationRole) { Pipeline pipeline = new Pipeline("WakerUpper", new PipelineArgs { ArtifactStore = new PipelineArtifactStoreArgs { Type = "S3", Location = bucket.BucketName, }, RoleArn = pipelineRole.Arn, Stages = { new PipelineStageArgs { Name = "Source", Actions = { new PipelineStageActionArgs { Name = "Source", Category = "Source", Owner = "ThirdParty", Provider = "GitHub", Version = "1", Configuration = { { "Owner", Config.Require("githubOwner") }, { "Repo", Config.Require("githubRepo") }, { "Branch", Config.Require("githubBranch") }, { "OAuthToken", GitHubConfig.RequireSecret("token") }, { "PollForSourceChanges", "false" }, }, OutputArtifacts ={ "SourceArtifact" }, }, }, }, new PipelineStageArgs { Name = "Build", Actions = { new PipelineStageActionArgs { Name = "Api-Build", Category = "Build", Owner = "AWS", Provider = "CodeBuild", Version = "1", InputArtifacts ={ "SourceArtifact" }, Configuration = { { "ProjectName", buildProject.Name }, { "EnvironmentVariables", "[ { \"name\": \"ProjectPath\", \"value\": \"WakerUpper.Api\" } ]" }, }, OutputArtifacts ={ "ApiBuildArtifact" }, RunOrder = 1, }, new PipelineStageActionArgs { Name = "WebApp-Build", Category = "Build", Owner = "AWS", Provider = "CodeBuild", Version = "1", InputArtifacts ={ "SourceArtifact" }, Configuration = { { "ProjectName", buildProject.Name }, { "EnvironmentVariables", "[ { \"name\": \"ProjectPath\", \"value\": \"WakerUpper.WebApp\" } ]" }, }, OutputArtifacts ={ "WebAppBuildArtifact" }, RunOrder = 1, }, }, }, new PipelineStageArgs { Name = "Deploy", Actions = { new PipelineStageActionArgs { Name = "Api-CreateChangeSet", Category = "Deploy", Owner = "AWS", Provider = "CloudFormation", Version = "1", InputArtifacts ={ "ApiBuildArtifact" },
static Task <int> Main() { return(Deployment.RunAsync(async() => { // Get the configuration and required variables var config = new Pulumi.Config(); var location = config.Require("location"); var companyCode = config.Require("company_code"); var environment = config.Require("environment"); var scope = config.Require("default_scope"); var tenantId = Output.Create <string>(config.Require("tenant_id")); var rbacGroups = config.RequireObject <JsonElement>("rbac_groups"); List <string> rbacGroupsList = new List <string>(); foreach (JsonElement group in rbacGroups.EnumerateArray()) { rbacGroupsList.Add(group.ToString()); } // Create the factory ResourceFactory factory = new ResourceFactory(companyCode, location, environment, scope); // Create the tags to be applied to these resources: scope Dictionary <string, string> tags = new Dictionary <string, string>(); tags.Add("scope", scope); // Create the resource group, analytics workspace and automation account var resourceGroup = factory.GetResourceGroup(tags: tags); var workspace = factory.GetAnalyticsWorkspace(resourceGroupName: resourceGroup.Name, tags: tags); var automationAccount = factory.GetAutomationAccount(resourceGroupName: resourceGroup.Name, tags: tags); #region Runbooks // Runbook for UpdatePowershellModules DateTime now = DateTime.Now; int start = (int)now.DayOfWeek; int target = (int)DayOfWeek.Sunday; target = (target <= start ? target + 7 : target); DateTime nextSunday = now.AddDays(target - start); string publishContentLink = "https://raw.githubusercontent.com/Daniel-Jennings/PulumiTemplates/master/sub-tcms-pul-infra/Runbooks/UpdatePowershellModules.ps1"; string runbookDescription = "A runbook to update all of the Powershell modules used in the automation account. Should be run weekly to ensure latest module code is available"; string startTime = nextSunday.ToString("yyyy'-'MM'-'dd") + "T20:00:00-04:00"; string scheduleDescription = "Run a task weekly on Sunday at 8PM"; Dictionary <string, string> parameters = new Dictionary <string, string> { { "resourcegroupname", factory.ResourceNames["rg"][0] }, { "automationaccountname", factory.ResourceNames["aacc"][0] } }; var updatePowershellModulesRunbook = factory.GetAutomationRunbook(name: "UpdatePowershellModules", resourceGroupName: resourceGroup.Name, automationAccountName: automationAccount.Name, publishContentLink: publishContentLink, description: runbookDescription, runbookType: "PowerShell", tags: tags); var updatePowershellModulesSchedule = factory.GetAutomationSchedule(name: "WeeklySunday8PM", resourceGroupName: resourceGroup.Name, automationAccountName: automationAccount.Name, description: scheduleDescription, frequency: "Week", startTime: startTime, timezone: "America/Toronto", interval: 1, weekDays: new List <string> { "Sunday" }); var updatePowershellModulesJob = factory.GetAutomationJobSchedule(resourceGroupName: resourceGroup.Name, automationAccountName: automationAccount.Name, runbookName: updatePowershellModulesRunbook.Name, scheduleName: updatePowershellModulesSchedule.Name, parameters: parameters); // Runbook for ShutdownSchedule DateTime tomorrow = now.AddDays(1); publishContentLink = "https://raw.githubusercontent.com/Daniel-Jennings/PulumiTemplates/master/sub-tcms-pul-infra/Runbooks/ShutdownSchedule.ps1"; runbookDescription = "A runbook to control shutdown / startup schedules for VMs and Scale Sets"; var shutdownScheduleRunbook = factory.GetAutomationRunbook(name: "ShutdownSchedule", resourceGroupName: resourceGroup.Name, automationAccountName: automationAccount.Name, publishContentLink: publishContentLink, description: runbookDescription, runbookType: "PowerShellWorkflow", tags: tags); // Schedule for Startup startTime = tomorrow.ToString("yyyy'-'MM'-'dd") + "T07:00:00-04:00"; scheduleDescription = "Run a task daily at 7AM"; parameters = new Dictionary <string, string> { { "shutdown", "false" }, { "verboselogging", "false" } }; var shutdownScheduleScheduleStartup = factory.GetAutomationSchedule(name: "Daily7AM", resourceGroupName: resourceGroup.Name, automationAccountName: automationAccount.Name, description: scheduleDescription, frequency: "Day", startTime: startTime, timezone: "America/Toronto", interval: 1); var shutdownScheduleJobStartup = factory.GetAutomationJobSchedule(resourceGroupName: resourceGroup.Name, automationAccountName: automationAccount.Name, runbookName: shutdownScheduleRunbook.Name, scheduleName: shutdownScheduleScheduleStartup.Name, parameters: parameters); // Schedule for Shutdown startTime = tomorrow.ToString("yyyy'-'MM'-'dd") + "T19:00:00-04:00"; scheduleDescription = "Run a task daily at 7PM"; parameters = new Dictionary <string, string> { { "shutdown", "true" }, { "verboselogging", "false" } }; var shutdownScheduleScheduleShutdown = factory.GetAutomationSchedule(name: "Daily7PM", resourceGroupName: resourceGroup.Name, automationAccountName: automationAccount.Name, description: scheduleDescription, frequency: "Day", startTime: startTime, timezone: "America/Toronto", interval: 1); var shutdownScheduleJobShutdown = factory.GetAutomationJobSchedule(resourceGroupName: resourceGroup.Name, automationAccountName: automationAccount.Name, runbookName: shutdownScheduleRunbook.Name, scheduleName: shutdownScheduleScheduleShutdown.Name, parameters: parameters); #endregion // Return any outputs that may be required for subsequent steps return new Dictionary <string, object?> { { "resourceGroupId", resourceGroup.Id }, { "resourceGroupName", resourceGroup.Name }, { "workspaceId", workspace.WorkspaceId }, }; })); }
public AwsStack() { var config = new Pulumi.Config(); var deployTo = config.Require("DeployTo"); var tags = new InputMap <string> { { "User:Project", Pulumi.Deployment.Instance.ProjectName }, { "User:Stack", Pulumi.Deployment.Instance.StackName } }; // Create an AWS resource (S3 Bucket) var dataBucket = new Bucket( $"ne-rpc-demo-data-{deployTo}", new BucketArgs { Tags = tags } ); // Create a role to run the lambda var lambdaRole = new Role("lambdaRole", new RoleArgs { AssumeRolePolicy = @"{ ""Version"": ""2012-10-17"", ""Statement"": [ { ""Action"": ""sts:AssumeRole"", ""Principal"": { ""Service"": ""lambda.amazonaws.com"" }, ""Effect"": ""Allow"", ""Sid"": """" } ] }" } ); var logPolicy = new RolePolicy("lambdaLogPolicy", new RolePolicyArgs { Role = lambdaRole.Id, Policy = @"{ ""Version"": ""2012-10-17"", ""Statement"": [{ ""Effect"": ""Allow"", ""Action"": [ ""logs:CreateLogGroup"", ""logs:CreateLogStream"", ""logs:PutLogEvents"" ], ""Resource"": ""arn:aws:logs:*:*:*"" }] }" }); var bucketPolicy = new RolePolicy("lambdaBucketPolicy", new RolePolicyArgs { Role = lambdaRole.Id, Policy = Output.Format($@"{{ ""Version"": ""2012-10-17"", ""Statement"": [ {{ ""Effect"": ""Allow"", ""Action"": [ ""s3:*"" ], ""Resource"": ""{dataBucket.Arn}"" }}, {{ ""Effect"": ""Allow"", ""Action"": [ ""s3:*"" ], ""Resource"": ""{dataBucket.Arn}/*"" }} ] }}") }); var quoteFetch = new Function( "quote-fetch-lambda", new FunctionArgs { Runtime = "dotnetcore3.1", Code = new FileArchive("../aws-lambda/publish"), Handler = "aws-lambda::Recumbent.Demo.Aws.AwsLambda::FunctionHandler", Environment = new FunctionEnvironmentArgs { Variables = new InputMap <string> { { "QuoteServerHost", "https://vn651r8t22.execute-api.eu-west-2.amazonaws.com/Prod" }, { "DataBucket", dataBucket.Id }, } }, Role = lambdaRole.Arn, Timeout = 60, Tags = tags } ); // Export useful things this.DataBucketName = dataBucket.Id; this.DataBucketArn = dataBucket.Arn; this.FunctionInvokeArn = quoteFetch.InvokeArn; }
static Task <int> Main(string[] args) { return(Pulumi.Deployment.RunAsync(() => { var config = new Pulumi.Config(); var pw = config.RequireSecret("message"); var rawPw = config.Require("message"); var cmData = new CoreV1.ConfigMap("cmdata", new ConfigMapArgs { Data = new InputMap <string> { { "password", pw }, } }); var cmBinaryData = new CoreV1.ConfigMap("cmbinarydata", new ConfigMapArgs { BinaryData = new InputMap <string> { { "password", pw.Apply(v => Base64Encode(v)) }, } }); var sStringData = new CoreV1.Secret("sstringdata", new SecretArgs { StringData = new InputMap <string> { { "password", rawPw } } }); var sData = new CoreV1.Secret("sdata", new SecretArgs { Data = new InputMap <string> { { "password", Base64Encode(rawPw) } } }); var name = $"test-{RandomString()}"; var secretYAML = $@" apiVersion: v1 kind: Secret metadata: name: {name} stringData: password: {rawPw} "; var cg = new Yaml.ConfigGroup("example", new Yaml.ConfigGroupArgs { Yaml = secretYAML }); var cgSecret = cg.GetResource <CoreV1.Secret>(name); return new Dictionary <string, object> { { "cmData", cmData.Data }, { "cmBinaryData", cmData.BinaryData }, { "sStringData", sStringData.StringData }, { "sData", sStringData.Data }, { "cgData", cgSecret.Apply(v => v.Data) }, }; })); }
static Task <int> Main() { return(Deployment.RunAsync(() => { var config = new Pulumi.Config(); var subscriptionId = config.Require("subscriptionId"); var azureADGroup = new Group( "AzureUsersGroup", new GroupArgs { Name = "All Azure Users" }); var role = new RoleDefinition( "Role", new RoleDefinitionArgs { Name = "Register Azure resource providers", Description = "Can register Azure resource providers", Permissions = new RoleDefinitionPermissionsArgs { Actions = "*/register/action" }, AssignableScopes = $"/subscriptions/{subscriptionId}", Scope = $"/subscriptions/{subscriptionId}" }); var roleAssignment = new Assignment( "RoleAssignment", new AssignmentArgs { RoleDefinitionName = role.Name, PrincipalId = azureADGroup.Id, Scope = $"/subscriptions/{subscriptionId}" }); const string resourceGroupName = "Pulumi"; var resourceGroup = new ResourceGroup( "ResourceGroup", new ResourceGroupArgs { Location = "CanadaEast", Name = resourceGroupName }); var application = new Application( "Application", new ApplicationArgs { Name = "PulumiAzureSetup" }); var servicePrincipal = new ServicePrincipal( "ServicePrincipal", new ServicePrincipalArgs { ApplicationId = application.ApplicationId }); var groupMembers = new GroupMember( "GroupMembership", new GroupMemberArgs { GroupObjectId = azureADGroup.ObjectId, MemberObjectId = servicePrincipal.ObjectId }); var roleAssignmentResourceGroup = new Assignment( "RoleAssignmentRG", new AssignmentArgs { RoleDefinitionName = "Contributor", PrincipalId = servicePrincipal.Id, Scope = $"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}" }); })); }
public ApimStack() { var config = new Pulumi.Config(); var tenantId = config.Require("tenantId"); var authorizationEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize"; var tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token"; var defaultScope = config.Require("scope"); var clientId = config.Require("clientId"); var clientSecret = config.Require("clientSecret"); // Create an Azure Resource Group var resourceGroup = new ResourceGroup("rg-chris-apim"); //Service Plan var appServicePlan = new Plan("plan-api", new PlanArgs { ResourceGroupName = resourceGroup.Name, Kind = "App", Sku = new PlanSkuArgs { Tier = "Basic", Size = "B1" } }); var app = new AppService("app-api", new AppServiceArgs { ResourceGroupName = resourceGroup.Name, AppServicePlanId = appServicePlan.Id }); var apim = new Service("apim-api", new ServiceArgs { ResourceGroupName = resourceGroup.Name, PublisherName = "chrisjensenuk", PublisherEmail = "*****@*****.**", SkuName = "Developer_1" }); var apimAuth = new AuthorizationServer("apim-oauth", new AuthorizationServerArgs { ApiManagementName = apim.Name, ResourceGroupName = resourceGroup.Name, DisplayName = "apim-oauth", ClientRegistrationEndpoint = "http://localhost", GrantTypes = { "authorizationCode" }, AuthorizationEndpoint = authorizationEndpoint, AuthorizationMethods = { "GET", "POST" }, TokenEndpoint = tokenEndpoint, ClientAuthenticationMethods = "Body", BearerTokenSendingMethods = "authorizationHeader", DefaultScope = defaultScope, ClientId = clientId, ClientSecret = clientSecret }); var api = new Api("example-api", new ApiArgs { ResourceGroupName = resourceGroup.Name, ApiManagementName = apim.Name, Revision = "1", DisplayName = "Example API", Path = "example", Protocols = { "https" }, Oauth2Authorization = new ApiOauth2AuthorizationArgs { AuthorizationServerName = apimAuth.Name }, Import = new ApiImportArgs { ContentFormat = "openapi+json", ContentValue = Constants.SwaggerJson }, ServiceUrl = app.Name.Apply(n => $"http://{n}.azurewebsites.net") }); var policy = new ApiPolicy("example-api-policy", new ApiPolicyArgs { ResourceGroupName = resourceGroup.Name, ApiManagementName = apim.Name, ApiName = api.Name, XmlContent = Constants.ApiPolicyXml }); }
private static AppointmentApiAzureResourceBag CreateAppointmentApiAzureResources(AzureResourceBag azureResources, Config config, Input <string> registryImageName) { var tenantId = config.Require("azure-tenantid"); var appointmentApiDb = new Database("appointments-api-db", new DatabaseArgs { ResourceGroupName = azureResources.ResourceGroup.Name, Name = "appointment-api", ServerName = azureResources.SqlServer.Name, RequestedServiceObjectiveName = "S0", Tags = azureResources.Tags }); var image = new Image("appointments-api-docker-image", new ImageArgs { Build = $".{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}", Registry = new ImageRegistry { Server = azureResources.Registry.LoginServer, Username = azureResources.Registry.AdminUsername, Password = azureResources.Registry.AdminPassword }, ImageName = registryImageName }, new ComponentResourceOptions { DependsOn = new InputList <Resource> { azureResources.Registry } }); var appointmentApiIdentity = new UserAssignedIdentity("appointments-api", new UserAssignedIdentityArgs { ResourceGroupName = azureResources.ResourceGroup.Name, Name = "appointments-api", Tags = azureResources.Tags }); // AKS service principal needs to have Managed Identity Operator rights over the user assigned identity else AAD pod identity won't work var aksSpAppointmentApiAccessPolicy = new Assignment("aks-sp-appontment-api-access", new AssignmentArgs { PrincipalId = azureResources.AksServicePrincipal.ObjectId, RoleDefinitionName = "Managed Identity Operator", Scope = appointmentApiIdentity.Id }); var sqlAdmin = new ActiveDirectoryAdministrator("appointments-api-sql-access", new ActiveDirectoryAdministratorArgs { ResourceGroupName = azureResources.ResourceGroup.Name, TenantId = tenantId, ObjectId = appointmentApiIdentity.PrincipalId, Login = "******", ServerName = azureResources.SqlServer.Name }); var clientConfig = Output.Create(GetClientConfig.InvokeAsync()); var currentPrincipalTenantId = clientConfig.Apply(c => c.TenantId); var currentPrincipal = clientConfig.Apply(c => c.ObjectId); var appointmentApiKeyVault = new KeyVault("appointment-api-keyvault", new KeyVaultArgs { ResourceGroupName = azureResources.ResourceGroup.Name, Name = "appointments-api", EnabledForDiskEncryption = true, TenantId = tenantId, SkuName = "standard", AccessPolicies = new InputList <KeyVaultAccessPolicyArgs> { new KeyVaultAccessPolicyArgs { TenantId = tenantId, ObjectId = azureResources.AksServicePrincipal.ObjectId, SecretPermissions = new[] { "get", "list" } }, new KeyVaultAccessPolicyArgs { TenantId = tenantId, ObjectId = appointmentApiIdentity.PrincipalId, SecretPermissions = new[] { "get", "list" } }, new KeyVaultAccessPolicyArgs { TenantId = currentPrincipalTenantId, ObjectId = currentPrincipal, SecretPermissions = { "delete", "get", "list", "set" }, } }, NetworkAcls = new KeyVaultNetworkAclsArgs { DefaultAction = "Deny", Bypass = "******", VirtualNetworkSubnetIds = new InputList <string> { azureResources.Subnet.Id }, // Need to whitelist the local public IP address otherwise setting secrets will fail IpRules = new InputList <string> { GetMyPublicIpAddress() } }, Tags = azureResources.Tags }); var secret = new Pulumi.Azure.KeyVault.Secret("appointments-api-db-connection-string", new Pulumi.Azure.KeyVault.SecretArgs { KeyVaultId = appointmentApiKeyVault.Id, Name = "ConnectionStrings--PetDoctorContext", Value = Output.Tuple(azureResources.SqlServer.Name, azureResources.SqlServer.Name, azureResources.SqlServer.AdministratorLogin, azureResources.SqlServer.AdministratorLoginPassword).Apply( t => { var(server, database, administratorLogin, administratorLoginPassword) = t; return ($"Server=tcp:{server}.database.windows.net;Database={database};User ID={administratorLogin};Password={administratorLoginPassword}"); }) }, new CustomResourceOptions { DependsOn = new InputList <Resource> { azureResources.SqlServer, appointmentApiKeyVault } }); return(new AppointmentApiAzureResourceBag { Identity = appointmentApiIdentity, KeyVault = appointmentApiKeyVault }); }
public AzureStack() { var config = new Pulumi.Config(); var deployTo = config.Require("DeployTo"); // Create an Azure Resource Group var resourceGroupName = $"rg-ne-rpc-demo-{deployTo}"; var resourceGroup = new ResourceGroup(resourceGroupName, new ResourceGroupArgs { Name = resourceGroupName }); // Create an Azure Storage Account var storageAccount = new Account($"nerpcdemo{deployTo}", new AccountArgs { ResourceGroupName = resourceGroup.Name, AccountReplicationType = "LRS", AccountTier = "Standard" }); // Container for deployment artefacts var zipContainer = new Container("zips", new ContainerArgs { StorageAccountName = storageAccount.Name, ContainerAccessType = "private" }); var dataContainer = new Container("data", new ContainerArgs { StorageAccountName = storageAccount.Name, ContainerAccessType = "private", Name = "data" }); var appServicePlan = new Plan($"plan-{deployTo}", new PlanArgs { ResourceGroupName = resourceGroup.Name, Kind = "FunctionApp", Sku = new PlanSkuArgs { Tier = "Dynamic", Size = "Y1", } }); var blob = new Blob("azure-func", new BlobArgs { StorageAccountName = storageAccount.Name, StorageContainerName = zipContainer.Name, Type = "Block", Source = new FileArchive("../azure-func/publish") }); var codeBlobUrl = SharedAccessSignature.SignedBlobReadUrl(blob, storageAccount); var app = new FunctionApp("app", new FunctionAppArgs { ResourceGroupName = resourceGroup.Name, AppServicePlanId = appServicePlan.Id, AppSettings = { { "runtime", "dotnet" }, { "WEBSITE_RUN_FROM_PACKAGE", codeBlobUrl }, { "QuoteServerHost", "https://vn651r8t22.execute-api.eu-west-2.amazonaws.com/Prod" }, { "DataConnectionString", storageAccount.PrimaryBlobConnectionString }, { "DataContainer", dataContainer.Name } }, StorageAccountName = storageAccount.Name, StorageAccountAccessKey = storageAccount.PrimaryAccessKey, Version = "~3" }); this.StorageAccountName = storageAccount.Name; this.Endpoint = Output.Format($"https://{app.DefaultHostname}/api/lookup"); this.DataContainer = dataContainer.Name; }
private static AzureResourceBag CreateBaseAzureInfrastructure(Config config) { var location = config.Require("azure-location"); var environment = config.Require("azure-tags-environment"); var owner = config.Require("azure-tags-owner"); var createdBy = config.Require("azure-tags-createdby"); var kubernetesVersion = config.Require("kubernetes-version"); var kubernetesNodeCount = config.RequireInt32("kubernetes-scaling-nodecount"); var sqlUser = config.RequireSecret("azure-sqlserver-username"); var sqlPassword = config.RequireSecret("azure-sqlserver-password"); var tags = new InputMap <string> { { "Environment", environment }, { "CreatedBy", createdBy }, { "Owner", owner } }; var resourceGroup = new ResourceGroup("pet-doctor-resource-group", new ResourceGroupArgs { Name = "pet-doctor", Location = location, Tags = tags }); var vnet = new VirtualNetwork("pet-doctor-vnet", new VirtualNetworkArgs { ResourceGroupName = resourceGroup.Name, Name = "petdoctorvnet", AddressSpaces = { "10.0.0.0/8" }, Tags = tags }); var subnet = new Subnet("pet-doctor-subnet", new SubnetArgs { ResourceGroupName = resourceGroup.Name, Name = "petdoctorsubet", AddressPrefixes = { "10.240.0.0/16" }, VirtualNetworkName = vnet.Name, ServiceEndpoints = new InputList <string> { "Microsoft.KeyVault", "Microsoft.Sql" } }); var registry = new Registry("pet-doctor-acr", new RegistryArgs { ResourceGroupName = resourceGroup.Name, Name = "petdoctoracr", Sku = "Standard", AdminEnabled = true, Tags = tags }); var aksServicePrincipalPassword = new RandomPassword("pet-doctor-aks-ad-sp-password", new RandomPasswordArgs { Length = 20, Special = true, }).Result; var clusterAdApp = new Application("pet-doctor-aks-ad-app", new ApplicationArgs { Name = "petdoctoraks" }); var clusterAdServicePrincipal = new ServicePrincipal("aks-app-sp", new ServicePrincipalArgs { ApplicationId = clusterAdApp.ApplicationId }); var clusterAdServicePrincipalPassword = new ServicePrincipalPassword("aks-app-sp-pwd", new ServicePrincipalPasswordArgs { ServicePrincipalId = clusterAdServicePrincipal.ObjectId, EndDate = "2099-01-01T00:00:00Z", Value = aksServicePrincipalPassword }); // Grant networking permissions to the SP (needed e.g. to provision Load Balancers) var subnetAssignment = new Assignment("pet-doctor-aks-sp-subnet-assignment", new AssignmentArgs { PrincipalId = clusterAdServicePrincipal.Id, RoleDefinitionName = "Network Contributor", Scope = subnet.Id }); var acrAssignment = new Assignment("pet-doctor-aks-sp-acr-assignment", new AssignmentArgs { PrincipalId = clusterAdServicePrincipal.Id, RoleDefinitionName = "AcrPull", Scope = registry.Id }); var logAnalyticsWorkspace = new AnalyticsWorkspace("pet-doctor-aks-log-analytics", new AnalyticsWorkspaceArgs { ResourceGroupName = resourceGroup.Name, Name = "petdoctorloganalytics", Sku = "PerGB2018", Tags = tags }); var logAnalyticsSolution = new AnalyticsSolution("pet-doctor-aks-analytics-solution", new AnalyticsSolutionArgs { ResourceGroupName = resourceGroup.Name, SolutionName = "ContainerInsights", WorkspaceName = logAnalyticsWorkspace.Name, WorkspaceResourceId = logAnalyticsWorkspace.Id, Plan = new AnalyticsSolutionPlanArgs { Product = "OMSGallery/ContainerInsights", Publisher = "Microsoft" } }); var sshPublicKey = new PrivateKey("ssh-key", new PrivateKeyArgs { Algorithm = "RSA", RsaBits = 4096, }); var cluster = new KubernetesCluster("pet-doctor-aks", new KubernetesClusterArgs { ResourceGroupName = resourceGroup.Name, Name = "petdoctoraks", DnsPrefix = "dns", KubernetesVersion = kubernetesVersion, DefaultNodePool = new KubernetesClusterDefaultNodePoolArgs { Name = "aksagentpool", NodeCount = kubernetesNodeCount, VmSize = "Standard_D2_v2", OsDiskSizeGb = 30, VnetSubnetId = subnet.Id }, LinuxProfile = new KubernetesClusterLinuxProfileArgs { AdminUsername = "******", SshKey = new KubernetesClusterLinuxProfileSshKeyArgs { KeyData = sshPublicKey.PublicKeyOpenssh } }, ServicePrincipal = new KubernetesClusterServicePrincipalArgs { ClientId = clusterAdApp.ApplicationId, ClientSecret = clusterAdServicePrincipalPassword.Value }, RoleBasedAccessControl = new KubernetesClusterRoleBasedAccessControlArgs { Enabled = true }, NetworkProfile = new KubernetesClusterNetworkProfileArgs { NetworkPlugin = "azure", ServiceCidr = "10.2.0.0/24", DnsServiceIp = "10.2.0.10", DockerBridgeCidr = "172.17.0.1/16" }, AddonProfile = new KubernetesClusterAddonProfileArgs { OmsAgent = new KubernetesClusterAddonProfileOmsAgentArgs { Enabled = true, LogAnalyticsWorkspaceId = logAnalyticsWorkspace.Id } }, Tags = tags }); var sqlServer = new SqlServer("pet-doctor-sql", new SqlServerArgs { ResourceGroupName = resourceGroup.Name, Name = "petdoctorsql", Tags = tags, Version = "12.0", AdministratorLogin = sqlUser, AdministratorLoginPassword = sqlPassword }); var sqlvnetrule = new VirtualNetworkRule("pet-doctor-sql", new VirtualNetworkRuleArgs { ResourceGroupName = resourceGroup.Name, Name = "petdoctorsql", ServerName = sqlServer.Name, SubnetId = subnet.Id, }); var appInsights = new Insights("pet-doctor-ai", new InsightsArgs { ApplicationType = "web", Name = "petdoctor", ResourceGroupName = resourceGroup.Name, Tags = tags }); var provider = new Provider("pet-doctor-aks-provider", new ProviderArgs { KubeConfig = cluster.KubeConfigRaw }); return(new AzureResourceBag { ResourceGroup = resourceGroup, SqlServer = sqlServer, Cluster = cluster, ClusterProvider = provider, AppInsights = appInsights, AksServicePrincipal = clusterAdServicePrincipal, Subnet = subnet, Registry = registry, Tags = tags }); }
public DevOpsInfra() { _config = new Config("ado"); #pragma warning disable Pulumi.InputMap <string> tags = JsonConvert.DeserializeObject <Dictionary <string, string> >(_config.RequireObject <JsonElement>("tags").ToString()); #region AzureNative.Resources.ResourceGroup (-rg) var resourceGroup = new Pulumi.AzureNative.Resources.ResourceGroup($"{_config.Require("resourceGroup")}-{_config.Require("env")}-rg-", new Pulumi.AzureNative.Resources.ResourceGroupArgs { Location = _config.Require("location"), Tags = tags, }); this.ResourceGroupName = resourceGroup.Name; #endregion #region NetworkSecurityGroup (-nsg) // NSGs can be connected to Subnets or Network cards (NICs). // When applied to the subnet, the NSG applies to all VMs on that subnet. If you apply only to the NIC card, just that one VM is affected. string myIp = new System.Net.WebClient().DownloadString("https://api.ipify.org"); var networkSecurityGroup = new Pulumi.AzureNative.Network.NetworkSecurityGroup($"{_config.Require("vnet.name")}-{_config.Require("env")}-nsg-", new Pulumi.AzureNative.Network.NetworkSecurityGroupArgs { ResourceGroupName = resourceGroup.Name, SecurityRules = { new Pulumi.AzureNative.Network.Inputs.SecurityRuleArgs { Name = "allow-rdp", Protocol = SecurityRuleProtocol.Tcp, SourcePortRange = "*", DestinationPortRange = "3389", SourceAddressPrefix = myIp, DestinationAddressPrefix = "*", Access = "Allow", Priority = 300, Direction = "Inbound", }, new Pulumi.AzureNative.Network.Inputs.SecurityRuleArgs { Name = "allow-http", // _config.Require("nsg.name"), Protocol = SecurityRuleProtocol.Tcp, SourcePortRange = "*", DestinationPortRange = "443", SourceAddressPrefix = "*", DestinationAddressPrefix = "*", Access = "Allow", Priority = 301, Direction = "Inbound", }, }, }); #endregion #region VirtualNetwork (-vnet) var network = new VirtualNetwork($"{_config.Require("vnet.name")}-{_config.Require("env")}-vnet-", new VirtualNetworkArgs { AddressSpace = new Pulumi.AzureNative.Network.Inputs.AddressSpaceArgs { AddressPrefixes = { _config.Require("vnet.cidr"), }, }, Location = _config.Require("location"), ResourceGroupName = resourceGroup.Name, Subnets = { new Pulumi.AzureNative.Network.Inputs.SubnetArgs { AddressPrefix = _config.Require("bastion.cidr"), Name = "AzureBastionSubnet", }, new Pulumi.AzureNative.Network.Inputs.SubnetArgs { AddressPrefix = _config.Require("snet.cidr"), Name = _config.Require("snet.name"), NetworkSecurityGroup = new Pulumi.AzureNative.Network.Inputs.NetworkSecurityGroupArgs { Id = networkSecurityGroup.Id, }, }, }, VirtualNetworkName = "AzureDevOps", // VirtualNetworkPeerings EnableDdosProtection = false, } ); #endregion #region PublicIp (-ip) var publicIp = new Pulumi.AzureNative.Network.PublicIPAddress($"bastion-{_config.Require("env")}-ip-", new Pulumi.AzureNative.Network.PublicIPAddressArgs { PublicIPAddressVersion = IPVersion.IPv4, PublicIPAllocationMethod = IPAllocationMethod.Static, IdleTimeoutInMinutes = 4, Location = _config.Require("location"), ResourceGroupName = resourceGroup.Name, Sku = new Pulumi.AzureNative.Network.Inputs.PublicIPAddressSkuArgs { Name = PublicIPAddressSkuName.Standard, Tier = PublicIPAddressSkuTier.Regional, }, }); var vmPublicIp = new Pulumi.AzureNative.Network.PublicIPAddress($"{_config.Require("agent.name")}-{_config.Require("env")}-ip-", new Pulumi.AzureNative.Network.PublicIPAddressArgs { PublicIPAddressVersion = IPVersion.IPv4, PublicIPAllocationMethod = IPAllocationMethod.Static, IdleTimeoutInMinutes = 4, Location = _config.Require("location"), ResourceGroupName = resourceGroup.Name, Sku = new Pulumi.AzureNative.Network.Inputs.PublicIPAddressSkuArgs { Name = PublicIPAddressSkuName.Standard, Tier = PublicIPAddressSkuTier.Regional, }, }); #endregion #region NetworkInterface (-nic) var networkInterface = new Pulumi.AzureNative.Network.NetworkInterface($"{_config.Require("agent.name")}-{_config.Require("env")}-nic-", new Pulumi.AzureNative.Network.NetworkInterfaceArgs { // AdoAgent has size Standard_B2s, which is not compatible with accelerated networking on network interface. // https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-powershell // EnableAcceleratedNetworking = true, IpConfigurations = { new Pulumi.AzureNative.Network.Inputs.NetworkInterfaceIPConfigurationArgs { Name = "ipconfig1", Primary = true, PrivateIPAllocationMethod = IPAllocationMethod.Dynamic, PrivateIPAddressVersion = "IPv4", PublicIPAddress = new Pulumi.AzureNative.Network.Inputs.PublicIPAddressArgs { Id = vmPublicIp.Id, }, Subnet = new Pulumi.AzureNative.Network.Inputs.SubnetArgs { #pragma warning disable Id = network.Subnets.Apply(s => s[1].Id), }, }, }, Location = _config.Require("location"), ResourceGroupName = resourceGroup.Name, }); #endregion #region VirtualMachine (-vm) var vm = new Pulumi.AzureNative.Compute.VirtualMachine($"{_config.Require("agent.name")}-{_config.Require("env")}-vmi-", new Pulumi.AzureNative.Compute.VirtualMachineArgs { ResourceGroupName = resourceGroup.Name, HardwareProfile = new Pulumi.AzureNative.Compute.Inputs.HardwareProfileArgs { VmSize = _config.Require("vm.vmSize") }, VmName = "AdoAgent", DiagnosticsProfile = new Pulumi.AzureNative.Compute.Inputs.DiagnosticsProfileArgs { BootDiagnostics = new Pulumi.AzureNative.Compute.Inputs.BootDiagnosticsArgs { Enabled = true } }, NetworkProfile = new Pulumi.AzureNative.Compute.Inputs.NetworkProfileArgs { NetworkInterfaces = { new Pulumi.AzureNative.Compute.Inputs.NetworkInterfaceReferenceArgs { Id = networkInterface.Id, Primary = true, }, } }, StorageProfile = new Pulumi.AzureNative.Compute.Inputs.StorageProfileArgs { ImageReference = new Pulumi.AzureNative.Compute.Inputs.ImageReferenceArgs { Publisher = "MicrosoftWindowsServer", Offer = "WindowsServer", Sku = "2019-Datacenter-with-Containers-smalldisk", Version = "latest" }, OsDisk = new Pulumi.AzureNative.Compute.Inputs.OSDiskArgs { OsType = Pulumi.AzureNative.Compute.OperatingSystemTypes.Windows, Name = "system", CreateOption = Pulumi.AzureNative.Compute.DiskCreateOptionTypes.FromImage, Caching = Pulumi.AzureNative.Compute.CachingTypes.ReadWrite, ManagedDisk = new Pulumi.AzureNative.Compute.Inputs.ManagedDiskParametersArgs { StorageAccountType = Pulumi.AzureNative.Compute.StorageAccountTypes.Standard_LRS, }, DiskSizeGB = 100, }, DataDisks = { new Pulumi.AzureNative.Compute.Inputs.DataDiskArgs { Name = "Data", CreateOption = Pulumi.AzureNative.Compute.DiskCreateOptionTypes.Empty, DiskSizeGB = _config.RequireInt32("vm.diskSizeGB"), Lun = 0, Caching = Pulumi.AzureNative.Compute.CachingTypes.None, }, }, }, OsProfile = new Pulumi.AzureNative.Compute.Inputs.OSProfileArgs { ComputerName = _config.Require("agent.name"), AdminUsername = _config.Require("admin.user"), AdminPassword = _config.RequireSecret("admin.pw"), WindowsConfiguration = new Pulumi.AzureNative.Compute.Inputs.WindowsConfigurationArgs { ProvisionVMAgent = true, EnableAutomaticUpdates = true, PatchSettings = new Pulumi.AzureNative.Compute.Inputs.PatchSettingsArgs { PatchMode = Pulumi.AzureNative.Compute.WindowsVMGuestPatchMode.AutomaticByOS, EnableHotpatching = false, }, }, }, }); // new CustomResourceOptions { DeleteBeforeReplace = true }); #endregion #region BastionHost (-bas) // Azure Bastion is a fully managed PaaS service that provides secure and seamless RDP and SSH access to virtual machines through the Azure Portal. // A BastionHost is provisioned within a Virtual Network (VNet) to provid SSL access to all VMs in the VNet without exposure through public IP addresses. var bastionHost = new Pulumi.AzureNative.Network.BastionHost($"{_config.Require("vnet.name")}-{_config.Require("env")}-bas-", new Pulumi.AzureNative.Network.BastionHostArgs { Location = resourceGroup.Location, ResourceGroupName = resourceGroup.Name, IpConfigurations = { new Pulumi.AzureNative.Network.Inputs.BastionHostIPConfigurationArgs { Name = "bastionHostIpConfiguration", PublicIPAddress = new Pulumi.AzureNative.Network.Inputs.SubResourceArgs { Id = publicIp.Id, }, Subnet = new Pulumi.AzureNative.Network.Inputs.SubResourceArgs { Id = network.Subnets.Apply(s => s[0].Id), }, }, }, }); #endregion }
public RecipeBankStack() { var config = new Pulumi.Config(); var resourceGroup = new ResourceGroup("RecipeBank"); // Create an Azure Storage Account var storageAccount = new Account("storage", new AccountArgs { ResourceGroupName = resourceGroup.Name, AccountReplicationType = "LRS", AccountTier = "Standard", EnableHttpsTrafficOnly = true }); var clientConfig = Output.Create(Pulumi.Azure.Core.Invokes.GetClientConfig()); var tenantId = clientConfig.Apply(c => c.TenantId); var currentPrincipal = clientConfig.Apply(c => c.ObjectId); // Key Vault to store secrets var vault = new KeyVault("vault", new KeyVaultArgs { ResourceGroupName = resourceGroup.Name, SkuName = "standard", TenantId = tenantId, AccessPolicies = { new KeyVaultAccessPoliciesArgs { TenantId = tenantId, // The current principal has to be granted permissions to Key Vault so that it can actually add and then remove // secrets to/from the Key Vault. Otherwise, 'pulumi up' and 'pulumi destroy' operations will fail. ObjectId = currentPrincipal, SecretPermissions ={ "delete", "get", "list", "set" }, } }, }); // A plan to host the App Service var appServicePlan = new Plan("api", new PlanArgs { ResourceGroupName = resourceGroup.Name, Kind = "Linux", Reserved = true, Sku = new PlanSkuArgs { Tier = "Free", Size = "F1", }, }); // The application hosted in App Service var app = new AppService("api", new AppServiceArgs { ResourceGroupName = resourceGroup.Name, AppServicePlanId = appServicePlan.Id, // A system-assigned managed service identity to be used for authentication and authorization to the Storage Identity = new AppServiceIdentityArgs { Type = "SystemAssigned" }, AppSettings = { { "KeyVaultName", vault.Name } }, HttpsOnly = true, Logs = new AppServiceLogsArgs() { HttpLogs = new AppServiceLogsHttpLogsArgs() { FileSystem = new AppServiceLogsHttpLogsFileSystemArgs() { RetentionInDays = 20, RetentionInMb = 30 } } } }); // Work around a preview issue https://github.com/pulumi/pulumi-azure/issues/192 var principalId = app.Identity.Apply(id => id.PrincipalId ?? "11111111-1111-1111-1111-111111111111"); // Grant App Service access to KV secrets var policy = new AccessPolicy("app-policy", new AccessPolicyArgs { KeyVaultId = vault.Id, TenantId = tenantId, ObjectId = principalId, // The .NET's KeyVault config provider needs the list permission to enumerate the secrets SecretPermissions = { "get", "list" }, }); // From pulumi secrets var dbConnectionStringSecret = new Secret("dbConnectionString", new SecretArgs() { KeyVaultId = vault.Id, Name = "DBConnectionString", Value = config.Require("dbConnectionString") }); this.Endpoint = Output.Format($"https://{app.DefaultSiteHostname}"); }