Azure-Samples / AzureSubscriptionBuilder

The Azure Subscription Builder project allows an Enterprise Account owner to quickly deploy secure, policy compliant, Azure Subscriptions. The solution consists of a Front End HTTP trigger, a Logic App Workflow, Azure Automation Account/Runbooks, Blueprints, and CosmosDB. The front end passes variables to the Logic App workflow URI via HTTP Post, details are covered in a dedicated section below. Currently, a sample static web front end is defined as an option in this project. Since the solution leverages a RESTful HTTP trigger, you can bring your own front end such as a PowerApp or a Github Action. The Logic App then takes the variables and passes them as parameters when invoking a set of Azure Automation Runbooks. The first runbook called create-mgmt-group creates a management group (if it already does not exist) to place the subscriptions under. The second runbook called create-subscription creates the subscriptions and places them under the previously created management group. The last runbook called assign-blueprintassigns the desired blueprint to the newly created subscriptions. This helps to ensure that proper policy and governance is enforced on new subscriptions at the time of build
MIT License
24 stars 19 forks source link

page_type: sample languages:

Azure Subscription Builder

The Azure Subscription Builder project allows an Enterprise Account owner to quickly deploy secure, policy compliant, Azure Subscriptions. The solution consists of a Front End HTTP trigger, a Logic App Workflow, Azure Automation Account/Runbooks, Blueprints, and CosmosDB. The front end passes variables to the Logic App workflow URI via HTTP Post, details are covered in a dedicated section below. Currently, a sample static web front end is defined as an option in this project. Since the solution leverages a RESTful HTTP trigger, you can bring your own front end such as a PowerApp or a Github Action. The Logic App then takes the variables and passes them as parameters when invoking a set of Azure Automation Runbooks. The first runbook called create-mgmt-group creates a management group (if it already does not exist) to place the subscriptions under. The second runbook called create-subscription creates the subscriptions and places them under the previously created management group. The last runbook called assign-blueprint assigns the desired blueprint to the newly created subscriptions. This helps to ensure that proper policy and governance is enforced on new subscriptions at the time of build.

Contents

File/folder Description
blueprints/ A sample blueprint for deployment. You can bring your own.
images/ Architecture design, example screenshots, and images for optional web frontend.
infra_templates/ ARM templates for infrastructure deployment.
runbooks/ Azure Automation Runbooks leveraged by the tool.
Webserver/ Optional webserver frontend.
deploy.ps1 PowerShell script to deploy tool.
deployParams.json Deployment parameters used by deploy.ps1 and teardown.ps1.
teardown.ps1 PowerShell script to decommission the tool. Makes testing and experimentation easy.
.gitignore Define what to ignore at commit time.
CHANGELOG.md List of changes to the sample.
CONTRIBUTING.md Guidelines for contributing to the sample.
README.md This README file.
LICENSE The license for the sample.

Prerequisites

To successfully deploy this project, it requires the user have the following:

Setup

Creating a self signed certificate

As part of this project you will need to have access to a certificate in PFX format. Below are examples on how to generate a self signed certificate with openssl (Mac) and PowerShell (Windows)

With OpenSSL This is an example using openssl to create a private key and public certificate, good for 1 year. Those components can then be used to build the PFX file:

$ openssl req -x509 -newkey rsa:4096 -keyout privateKey.pem -out publicCert.pem -days 365
Generating a 4096 bit RSA private key
...............................................++
.......................++
writing new private key to 'privateKey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:US
State or Province Name (full name) []:Washington
Locality Name (eg, city) []:Seattle
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:automationCert
Email Address []:EXAMPLE@EMAIL.COM

$ openssl pkcs12 -export -out Cert.pfx -inkey privateKey.pem -in publicCert.pem 
Enter pass phrase for privateKey.pem:
Enter Export Password:
Verifying - Enter Export Password:

With PowerShell PKI module This is an example using PowerShell PKI module to create a private key and public certificate, good for 1 year. Those components can then be used to build the PFX file.

If you are running WindowsPowershell (v5.x)

Simply install the PKI Client module and use the New-SelfSignedCertificate cmdlet to generate your self signed certificate:

PS C:\Users\jdoe> Install-Module PKI

PS C:\Users\jdoe> $cert = New-SelfSignedCertificate -CertStoreLocation Cert:\CurrentUser\My\ -Subject MyCertificate -KeySpec KeyExchange

PS C:\Users\jdoe>$pw = ConvertTo-SecureString -String "p@ssw0rd!" -Force -AsPlainText

PS C:\Users\jdoe>Export-PfxCertificate -cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" -Password $pw -FilePath C:\temp\MyCertificate.pfx

If you are running PowerShell Core

You'll need to install the Windows Compatibility module in order to then install the PKI Client Module. Once that's done, all steps are the same.

C:\Users\jdoe> Install-Module WindowsCompatibility -Scope CurrentUser

C:\Users\jdoe> Import-WinModule PKI

C:\Users\jdoe> $cert = New-SelfSignedCertificate....

Deployment variables

The variables necessary to deploy this infrastructure are located in deployParams.json file. Fill in the key value pairs and save before running deploy.ps1.

Example Parameters:

{
    "Name": "subbuilder",
    "location": "westus2",
    "rootManagementGroup": "GlobalRootGroup",
    "pfxCertPath": "/Users/jdoe/temp/test.pfx",
    "certPass": "passw0rd!",
    "webserverSshKey": "ssh-rsa XjY586.......",
    "webserverAdminCidr": "50.1.1.1/32"
}   

Running the sample

Steps to deploy infrastructure:

Steps to tear down the deployment:

How to invoke the Logic App workflow

The Logic App trigger will accept an HTTP Post to the Logic App URL with the following payload schema:

{
    "method": "POST",
    "schema": {
        "properties": {
            "blueprintName": {
                "type": "string"
            },
            "businessUnit": {
                "type": "string"
            },
            "location": {
                "type": "string"
            },
            "devTestSubCount": {
                "type": "string"
            },
            "prodSubCount": {
                "type": "string"
            }
        },
        "type": "object"
    }
}

If you were to test with cURL or Postman, An example payload would look like the following:

[
    {
        "blueprintName": "myblueprint",
        "businessUnit": "mybusinessunit,
        "location": "westus2",
        "devTestSubCount": "3",
        "prodSubCount": "2"
    }
]

NOTE: IF YOU CHOOSE NOT TO DEPLOY ONE OF THE SUBSCRIPTION OFFER TYPES (DEV/TEST OR PROD) YOU NEED TO ENTER 0 FOR THE VALUE

Optional Web Server - hosted on Ubuntu VM

We realize that some Subscription Builder users will want to bring their own front end trigger, allowing for endless customization and integrations. For those individuals, please continue on to the next section which covers the expected format for the body of the HTTP POST API call.

For the individuals that are looking for a simpler solution we decided to include the option to create a web based front end trigger as part of the Subscription Builder deployment process. When running the deploy.ps1 script, the user is asked if they would like to also deploy the optional Web Server (default is 'No'). If the user chooses '(Y)es', the Subscription Builder Web Server will be deployed and configured as part of the infrastructure deployment into it's own resource group. If the user chooses '(N)o', then the deployment continues and no front end is configured. The optional front end is built on an Ubuntu VM LAMP Stack using the installDynamic.sh script orchestrated by the Linux Custom Script Extension. The Subscription Builder website consists of 3 files, those being:

We dynamically generate the webFormDynamic.html file and the installDynamic.sh, connect the HTTP Trigger to the Logic App URL, and upload all 3 files to the Storage Account. This web server presents a form for users to input the variables required to run the Subscription Builder service. The user then will click on the Submit button, and they will be asked to verify their selections. If the user would like to continue, they will click on the BUILD button at which time the server will POST the required JSON payload to the Logic App endpoint.

Step By Step Instructions for Front End

Step 1

Step 2

Step 3

Step 4

Successful Trigger

Failed Trigger

Key concepts

So, what does this solution actually deploy?

The included deploy script, deploy.ps1, will build the following infrastructure:

Architecture and workflow

Azure Subscription Builder Architecture Azure Subscription Builder Workflow

Service Principal credential expiration

Until all Azure Services support Managed Identities we do have to worry about expiring credentials for Service Principals. The deploy script deploy.ps1 sets the expiration date for the certificate and password for 6 months after the creation date. You can see in the example below:

## Create new Azure Service Principal
Write-Output "Creating new Azure Service Principal"
$now = [System.DateTime]::Now
$6mofrmnow = $now.AddMonths(6) 
$sp = New-AzADServicePrincipal `
-DisplayName "$Name" `
-CertValue $Base64Value `
-StartDate $now `
-EndDate $6mofrmnow

## Add client Secret to SP
Write-Output "Creating Azure Service Principal client secret"
New-AzADAppCredential `
-DisplayName $sp.DisplayName `
-Password $certPass `
-StartDate $now `
-EndDate $6mofrmnow

You can alter the expiration date to suit your specific needs by modifying the $6mofrmnow variable. This automation will stop working if the credentials on the Service Principal expire.

Security considerations

For the purpose of this proof of concept we have not integrated security into the Logic App being deployed as part of this workflow. The HTTP trigger is unauthenticated in this example, which is not secure and only recommended for testing. To use this service in a production deployment it is recommended to use one or more of the following methods to secure your Logic App endpoint:

The following documentation from Azure walks though best practices on securing the HTTP Trigger: Securing Logic Apps

IT IS RECOMMENDED TO USE AVAILABLE SECURITY CONTROLS IN A PRODUCTION DEPLOYMENT

FAQ

Why would I use Subscription Builder?

Subscription Builder enables EA customers to provision secure and compliant Azure Subscriptions quickly and repeatably, all while maintaining control over the underlying environments. The best part is that it can be easily customized to support any organizations individual needs! Unlocking the possibility of quickly deploying anything from greenfield Azure landing zones to a single, policy compliant, Azure subscription.

What does the roadmap for Subscription Builder look like?

The goal for Subscription Builder is to become the de facto standard for Subscription deployments in Azure. We want to provide CAF Compliant infrastructure on demand, allowing for endless customization for our customers. Eventually, the goal is for this project to become a single Blueprint that you apply to a management group and have this all automagically deployed for you. Here is what is top of mind for us:

Who are the awesome people that built this??

Tyler, Harvey, and Chris are just some PNW computer nerds with our heads always in the clouds!

Want to know more about Azure Subscription Builder??

Please make sure to to check out the official Azure Subscription Builder presentation available here:

Also, feel free to reach out to subscriptionbuilder@microsoft.com with any questions or feedback!

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.