Station is a Terraform module that lets you quickly spin up new workload environments in Azure and Terraform Cloud. Station gives you a high level of automation for workload environment provisioning.
- Station is maintained by the DevOps team at blinQ (https://blinq.no).
- See the terraform-docs.md file for
terraform-docs
generated documentation. - Check out our Design Decision document here.
To quickly enable users to deploy workload environments in Azure. Isolating Entra ID and Azure Subscription interactions from the actual workload environment. Station consists of three parts; bootstrap, deployments and workload environment.
- Bootstrap: setting up a Station for your Azure subscription(s) and tenant. (Administrator with permissions on Subscription and Entra ID/Azure AD)
- Deployments: Where workload environments are defined and deployed. (Application Team/DevOps/SRE/Platform Engineer/Cloud Engineer)
- Workload Environment: The workload environment where infrastructure is deployed to. (Application Team)
Station was designed with isolation in mind. We want our environments to work with least-privilege principle. That's why your workload identity is restricted to permissions inside its own resource group(s). The module is highly flexible and also support Cloud Adoption Framework-like modularization. See our COMING! examples folder for more!
Station is used primarily in context of application development and hosting; DevOps, GitOps, SRE's or Platform Engineers. There is nothing wrong with using Station in operations; we encourage it!
- Terraform Cloud account
- Permission to create Team Token
- Azure- Tenant and Subscription
- Global Administrator on Azure AD
- Owner on Subscription
The following example deploys a workload environment for common resources, in this environment we would deploy Container Registries for example.
Consider the following file structure:
common.tf
github_repositories.tf
tags.tf
variables.tf
# filename: common.tf
module "common" {
source = "git::https://github.com/blinqas/station.git?ref=1.3.0"
tenant_id = var.tenant_id
subscription_id = var.subscription_id
environment_name = "prod"
resource_group_name = "common"
tags = local.tags.common
tfe = {
organization_name = "my-tfc-organization"
project_name = "Azure"
workspace_name = "common"
workspace_description = "Common resources which are shared between workloads."
vcs_repo = {
identifier = github_repository.repos["common"].full_name
branch = "trunk"
oauth_token_id = var.vcs_repo_oauth_token_id
}
}
}
This file would provision the following:
- Resource Group
- Managed Identity
- Service Principal is assigned Owner on Resource Group
- Federated Credential (OIDC to authenticate Terraform Cloud runners)
- Terraform Cloud (TFC) Workspace
- Configured to run on commits to trunk branch
- Configured to authenticate to VCS with token already in Terraform Cloud
- TFC Environment Variables for OIDC authentication with Managed Identity
- Kim Iversen | [email protected]
- Sander Blomvågnes | [email protected]
- Erik Hansen | [email protected]
MIT
Name | Description | Type | Default | Required |
---|---|---|---|---|
app_role_assignments | (Optional) A set of azuread_app_role_assignment resources to assign to the workload identity. Only built-in application roles are supported. Example: hcl |
set(string) |
[] |
no |
applications | Map of applications to create. The body of each object is more or less identical to azuread_application with the exception of map usage instead of blocks (as blocks are impossible to define with HCL) |
map(object({ |
{} |
no |
default_location | The name of the default location to deploy workload resources to. | string |
"norwayeast" |
no |
environment_name | The name of the deployment environment for the workload. Ex: dev/staging/production | string |
"dev" |
no |
federated_identity_credential_config | Map of Federated Credentials to create on the workload identity | map(object({ |
{} |
no |
group_membership | Map of group object ids the workload identity should be member of. Example: group_membership = { "Kubernetes Administrators" = azuread_group.k8s_admins.object_id } |
map(string) |
{} |
no |
groups | (Optional) Map of Entra ID (Azure AD) groups to create Note: The workload identity is automatically assigned the App Role "User.ReadBasic.All" and "Group.Read.All" because being "Owner" of the group is not sufficient to add principals and then list them after an add or delete operation. |
map(object({ |
{} |
no |
managed_identity_name | The name of the managed identity (identity provided to the workload) that is created. The final name is prefixed with mi- .If a value is not provided, Station will set the name to mi-var.tfe.workspace_name-var.environment_name |
string |
null |
no |
resource_group_name | The name of the workload resource group. The final name is prefixed with rg- .If a value is not provided, Station will set the name to rg-var.tfe.workspace_name-var.environment_name |
string |
null |
no |
resource_groups | Map of resource groups to create | map(object({ |
{} |
no |
role_assignment | Map of role_assignments to create. Be careful of who is allowed to provision role_assignments, you might want to consider Sentinel policies in TFC. - assign_to_workload_principal assigns the role to the workload identity. Can not be used with principal_id. |
map(object({ |
{} |
no |
role_definition_name_on_workload_rg | The name of an in-built role to assign the workload identity on the workload resource group | string |
"Owner" |
no |
subscription_id | (Required) The Azure subscription ID used by the caller. | string |
n/a | yes |
tags | Tags to merge with the default tags configured by Station. Station configures the following map in tags.tf: { "station-id" = random_id.workload.hex "environment" = var.environment_name } |
map(string) |
{} |
no |
tenant_id | (Required) The Entra ID tenant ID used by the caller. | string |
n/a | yes |
tfe | Terraform Cloud configuration for the workload environment - tfe.create_federated_identity_credential configures Federated Credentials on the workload identity for plan and apply phases. - Either of tfe.vcs_repo.(oauth_token_id|github_app_installation_id) must be provided, both can not be used at the same time. - tfe.workspace_env_vars lets you configure Environment Variables for the Terraform Cloud runtime environment - tfe.workspace_vars lets you configure Terraform variables - tfe.module_outputs_to_workspace_var.(groups|applications|user_assigned_identities) sets output from the respective resource into respective Terraform variables on the Terraform Cloud workspace. Useful when you need group object ids for the groups Station Deployments provisioned in your workload environment. - tfe.workspace_settings lets you configure the workspace settings like agent_pool_id and execution_mode. If agent_pool_id is provided, execution_mode must be set to "agent". |
object({ |
null |
no |
user_assigned_identities | User Assigned Identities to create." Example: user_assigned_identities = { my_app = { name = "uai-my-identity" resource_group_name = "rg-name" location = "norwayeast" app_role_assignments = ["IdentityRiskEvent.ReadWrite.All"] group_memberships = { "Kubernetes Administrators" = azuread_group.k8s_admins.object_id } } } |
map(object({ |
{} |
no |
Name | Description |
---|---|
applications | n/a |
client_id | n/a |
groups | n/a |
resource_group | n/a |
resource_groups_user_specified | n/a |
subscription_id | n/a |
tenant_id | n/a |
tfe | n/a |
user_assigned_identities | n/a |
workload_resource_group_name | n/a |
workload_service_principal_object_id | n/a |