Skip to main content

Azure Resource Provisioning Example

So for example, we want to provision some Azure services like this:

  • A user assigned identity
  • A blob storage account that can only be accessed via the user assigned identity we created
  • A blob storage container under that account
  • An azure function, with our user assigned identity being used for its identity, meaning it would have access to the blob storage

That would look like this:

Managed User Assigned Identity

public class ProvisionUserAssignedIdentityModule : Module<UserAssignedIdentityResource>
{
protected override async Task<UserAssignedIdentityResource?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken)
{
var userAssignedIdentityProvisionResponse = await context.Azure().Provisioner.Security.UserAssignedIdentity(
new AzureResourceIdentifier("MySubscription", "MyResourceGroup", "MyUserIdentity"),
new UserAssignedIdentityData(AzureLocation.UKSouth)
);

return userAssignedIdentityProvisionResponse.Value;
}
}

Blob Storage Account

public class ProvisionBlobStorageAccountModule : Module<StorageAccountResource>
{
protected override async Task<StorageAccountResource?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken)
{
var blobStorageAccountProvisionResponse = await context.Azure().Provisioner.Storage.StorageAccount(
new AzureResourceIdentifier("MySubscription", "MyResourceGroup", "MyStorage"),
new StorageAccountCreateOrUpdateContent(new StorageSku(StorageSkuName.StandardGrs), StorageKind.BlobStorage, AzureLocation.UKSouth)
);

return blobStorageAccountProvisionResponse.Value;
}
}

Blob Storage Container

[DependsOn<ProvisionBlobStorageAccountModule>]
public class ProvisionBlobStorageContainerModule : Module<BlobContainerResource>
{
protected override async Task<BlobContainerResource?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken)
{
var blobStorageAccount = await GetModule<ProvisionBlobStorageAccountModule>();

var blobContainerProvisionResponse = await context.Azure().Provisioner.Storage.BlobContainer(
blobStorageAccount.Value!.Id,
"MyContainer",
new BlobContainerData()
);

return blobContainerProvisionResponse.Value;
}
}

Blob Storage Access via User Identity

[DependsOn<ProvisionBlobStorageAccountModule>]
[DependsOn<ProvisionUserAssignedIdentityModule>]
public class AssignAccessToBlobStorageModule : Module<RoleAssignmentResource>
{
protected override async Task<RoleAssignmentResource?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken)
{
var userAssignedIdentity = await GetModule<ProvisionUserAssignedIdentityModule>();

var storageAccount = await GetModule<ProvisionBlobStorageAccountModule>();

var roleAssignmentResource = await context.Azure().Provisioner.Security.RoleAssignment(
storageAccount.Value!.Id,
new RoleAssignmentCreateOrUpdateContent(WellKnownRoleDefinitions.BlobStorageOwnerDefinitionId, userAssignedIdentity.Value!.Data.PrincipalId!.Value)
);

return roleAssignmentResource.Value;
}
}

Azure Function

[DependsOn<ProvisionUserAssignedIdentityModule>]
[DependsOn<ProvisionBlobStorageAccountModule>]
[DependsOn<ProvisionBlobStorageContainerModule>]
public class ProvisionAzureFunction : Module<WebSiteResource>
{
protected override async Task<WebSiteResource?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken)
{
var userAssignedIdentity = await GetModule<ProvisionUserAssignedIdentityModule>();

var storageAccount = await GetModule<ProvisionBlobStorageAccountModule>();
var blobContainer = await GetModule<ProvisionBlobStorageContainerModule>();

var functionProvisionResponse = await context.Azure().Provisioner.Compute.WebSite(
new AzureResourceIdentifier("MySubscription", "MyResourceGroup", "MyFunction"),
new WebSiteData(AzureLocation.UKSouth)
{
Identity = new ManagedServiceIdentity(ManagedServiceIdentityType.UserAssigned)
{
UserAssignedIdentities = { { userAssignedIdentity.Value!.Id, new UserAssignedIdentity() } }
},
SiteConfig = new SiteConfigProperties
{
AppSettings = new List<AppServiceNameValuePair>
{
new()
{
Name = "BlobStorageConnectionString",
Value = storageAccount.Value!.Data.PrimaryEndpoints.BlobUri.AbsoluteUri
},
new()
{
Name = "BlobContainerName",
Value = blobContainer.Value!.Data.Name
}
}
}
// ... Other properties
}
);

return functionProvisionResponse.Value;
}

So we can clearly see what depends on what.

Every module is isolated.

Every module will automatically run in parallel unless it is dependent on another module.

A module with a dependency can retrieve the data from another module.