# ollionorg/automated-azure-sandbox-setup architecture

> Architecture diagram of the GitHub repository ollionorg/automated-azure-sandbox-setup, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/ollionorg/automated-azure-sandbox-setup
- Repository: https://github.com/ollionorg/automated-azure-sandbox-setup

## Overview

#### Purpose and Entry Points
This repository automates temporary Azure sandbox access: GitHub Actions provision a per-user Resource Group with Contributor access, then revoke access and delete it at expiry. The operational entry points are the provisioning and cleanup workflows: `.github/workflows/azure-provision.yml` and `.github/workflows/azure-nuke.yml`.

#### GitHub Actions Orchestration
The workflows run on a configured self-hosted GitHub runner and authenticate through an Azure app/service principal plus repository secrets. Provisioning accepts a requested user, duration, and target subscription; cleanup is separately callable and is also triggered by scheduled Azure Automation work. Slack failure notification settings are separated into `.github/config/azure_provisioning_slack.yaml` and `.github/config/azure_nuke_slack.yaml`.

Paths:
- `.github/workflows/azure-provision.yml`
- `.github/workflows/azure-nuke.yml`
- `.github/workflows/README.md`

#### Azure Provisioning Boundary
Azure is the primary control plane. The configured service principal needs subscription Contributor access plus a custom role that permits the automation/runbook operations needed for timed cleanup. Each sandbox is isolated by Resource Group, with temporary Contributor RBAC assigned to the approved user. Federated GitHub OIDC credential configuration is templated by `files/credential_sample.json`; custom Azure RBAC permissions are defined by `files/custom_role.json`.

Paths:
- `files/credential_sample.json`
- `files/custom_role.json`
- `README.md`

#### Identity Validation and Authorization
Before granting Azure access, the automation validates the requester against Google Workspace and Azure AD/Microsoft Graph. Python performs domain/user validation; shell scripting obtains or uses Google Workspace authentication context. Google service-account credentials are supplied as the `CREDENTIALS_FILE` secret rather than intended as a repository-managed plaintext credential.

Paths:
- `azure/google-workspace-validate-users.py`
- `azure/google-workspace-user.sh`
- `azure/requirements.txt`

#### Timed Deprovisioning
Provisioning creates Azure Automation runbooks/schedules that later invoke GitHub cleanup. The PowerShell scheduler stage establishes or schedules the delayed cleanup job; the trigger stage calls GitHub Actions to execute the nuke workflow. This is the key asynchronous boundary: GitHub provisions now, Azure Automation retains responsibility for invoking teardown later.

Paths:
- `azure/scheduler.ps1`
- `azure/github_trigger.ps1`
- `.github/workflows/azure-nuke.yml`

#### Runtime and Infrastructure Dependencies
Execution requires a self-hosted GitHub Actions runner on an Azure VM, Azure CLI, PowerShell, Python dependencies, and Azure Automation with a system-assigned managed identity and private webhook connectivity. External services are Azure Resource Manager/RBAC, Microsoft Graph/Azure AD, Google Workspace Admin APIs, GitHub Actions/API (PAT for triggering cleanup), and Slack webhooks for failure alerts.

Paths:
- `azure/install_prerequisites.sh`
- `azure/requirements.txt`
- `.github/config/azure_nuke_slack.yaml`

#### Credentials and Trust Model
GitHub secrets hold Azure client/tenant/subscription IDs, Microsoft Graph secret, Google service-account credential material, GitHub PAT, and Slack webhook. The Azure app is assigned broad subscription capabilities, while Azure Automation receives Automation Contributor permissions. This makes secret handling, runner isolation, least-privilege role scoping, and secure private access to Automation webhooks architecturally critical.

Main entry points: [`.github/workflows/azure-provision.yml`](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/.github/workflows/azure-provision.yml) (Provision workflow), [`azure/google-workspace-validate-users.py`](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/google-workspace-validate-users.py) (Requester validation), [`.github/workflows/azure-nuke.yml`](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/.github/workflows/azure-nuke.yml) (Cleanup workflow), [`files/credential_sample.json`](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/files/credential_sample.json) (Azure service principal)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_github["GitHub Automation"]
  node_provision["Provision workflow<br/>GitHub Actions workflow"]
  node_nuke["Cleanup workflow<br/>GitHub Actions workflow<br/>[azure-nuke.yml]"]
  node_runner["Self-hosted runner<br/>Azure VM runtime"]
  node_slack["Failure notifications<br/>Slack configuration"]
end

subgraph group_azure["Azure Control Plane"]
  node_serviceprincipal{{"Azure service principal<br/>OIDC application identity"}}
  node_customrole["Custom automation role<br/>Azure RBAC definition<br/>[custom_role.json]"]
  node_resourcegroups[("Per-user sandboxes<br/>Azure Resource Groups")]
  node_automation["Azure Automation<br/>Runbooks and schedules<br/>[scheduler.ps1]"]
  node_trigger["GitHub cleanup trigger<br/>PowerShell runbook stage<br/>[github_trigger.ps1]"]
end

subgraph group_identity["Identity Validation"]
  node_requestvalidation["Requester validation<br/>Python validator"]
  node_googleauth["Google auth context<br/>Shell integration"]
  node_runtimepackages["Python dependencies<br/>Runtime requirements<br/>[requirements.txt]"]
end

subgraph group_external["External Services"]
  node_googleworkspace(("Google Workspace Admin<br/>External identity API"))
  node_graph(("Microsoft Graph / Azure AD<br/>External identity API"))
  node_arm(("Azure Resource Manager<br/>Azure API and RBAC"))
  node_githubapi(("GitHub Actions API<br/>External GitHub service"))
  node_slackwebhook(("Slack webhook<br/>External alert endpoint"))
end

node_provision -->|"runs on"| node_runner
node_nuke -->|"runs on"| node_runner
node_provision -->|"validates requester"| node_requestvalidation
node_requestvalidation -->|"uses auth context"| node_googleauth
node_googleauth -->|"queries"| node_googleworkspace
node_requestvalidation -->|"checks user"| node_graph
node_requestvalidation -->|"requires"| node_runtimepackages
node_provision -->|"authenticates as"| node_serviceprincipal
node_serviceprincipal -->|"is granted"| node_customrole
node_serviceprincipal -->|"manages"| node_arm
node_provision -->|"creates sandbox"| node_resourcegroups
node_arm -->|"applies RBAC"| node_resourcegroups
node_provision -->|"schedules expiry"| node_automation
node_automation -->|"executes at expiry"| node_trigger
node_trigger -->|"dispatches via PAT"| node_githubapi
node_githubapi -->|"invokes"| node_nuke
node_nuke -->|"revokes and deletes"| node_resourcegroups
node_provision -.->|"uses failure settings"| node_slack
node_slack -->|"alerts"| node_slackwebhook

click node_provision "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/.github/workflows/azure-provision.yml"
click node_nuke "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/.github/workflows/azure-nuke.yml"
click node_runner "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/install_prerequisites.sh"
click node_slack "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/.github/config/azure_provisioning_slack.yaml"
click node_serviceprincipal "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/files/credential_sample.json"
click node_customrole "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/files/custom_role.json"
click node_automation "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/scheduler.ps1"
click node_trigger "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/github_trigger.ps1"
click node_requestvalidation "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/google-workspace-validate-users.py"
click node_googleauth "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/google-workspace-user.sh"
click node_runtimepackages "https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/requirements.txt"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_provision,node_nuke,node_runner,node_slack toneBlue
class node_serviceprincipal,node_customrole,node_resourcegroups,node_automation,node_trigger toneAmber
class node_requestvalidation,node_googleauth,node_runtimepackages toneMint
class node_googleworkspace,node_graph,node_arm,node_githubapi,node_slackwebhook toneRose
```

## Components

### GitHub Automation

- [Provision workflow](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/.github/workflows/azure-provision.yml): GitHub Actions workflow · Creates a time-bound user sandbox. · `.github/workflows/azure-provision.yml`
- [Cleanup workflow](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/.github/workflows/azure-nuke.yml): GitHub Actions workflow · Revokes access and deletes expired sandboxes. · `.github/workflows/azure-nuke.yml`
- [Self-hosted runner](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/install_prerequisites.sh): Azure VM runtime · Runs Azure CLI, PowerShell, and Python automation. · `azure/install_prerequisites.sh`
- [Failure notifications](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/.github/config/azure_provisioning_slack.yaml): Slack configuration · `.github/config/azure_provisioning_slack.yaml`

### Azure Control Plane

- [Azure service principal](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/files/credential_sample.json): OIDC application identity · Uses GitHub secrets and subscription-level permissions. · `files/credential_sample.json`
- [Custom automation role](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/files/custom_role.json): Azure RBAC definition · Allows required Automation and runbook operations. · `files/custom_role.json`
- **Per-user sandboxes**: Azure Resource Groups · Isolated resource groups with temporary Contributor assignments.
- [Azure Automation](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/scheduler.ps1): Runbooks and schedules · Owns delayed teardown after provisioning completes. · `azure/scheduler.ps1`
- [GitHub cleanup trigger](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/github_trigger.ps1): PowerShell runbook stage · Calls GitHub to invoke cleanup. · `azure/github_trigger.ps1`

### Identity Validation

- [Requester validation](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/google-workspace-validate-users.py): Python validator · Checks requested users before access is granted. · `azure/google-workspace-validate-users.py`
- [Google auth context](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/google-workspace-user.sh): Shell integration · Uses the CREDENTIALS_FILE secret. · `azure/google-workspace-user.sh`
- [Python dependencies](https://github.com/ollionorg/automated-azure-sandbox-setup/blob/main/azure/requirements.txt): Runtime requirements · `azure/requirements.txt`

### External Services

- **Google Workspace Admin**: External identity API
- **Microsoft Graph / Azure AD**: External identity API
- **Azure Resource Manager**: Azure API and RBAC · Creates resources and applies role assignments.
- **GitHub Actions API**: External GitHub service · Receives PAT-authenticated cleanup dispatches.
- **Slack webhook**: External alert endpoint

## Connections

- Provision workflow → Self-hosted runner: runs on
- Cleanup workflow → Self-hosted runner: runs on
- Provision workflow → Requester validation: validates requester
- Requester validation → Google auth context: uses auth context
- Google auth context → Google Workspace Admin: queries
- Requester validation → Microsoft Graph / Azure AD: checks user
- Requester validation → Python dependencies: requires
- Provision workflow → Azure service principal: authenticates as
- Azure service principal → Custom automation role: is granted
- Azure service principal → Azure Resource Manager: manages
- Provision workflow → Per-user sandboxes: creates sandbox
- Azure Resource Manager → Per-user sandboxes: applies RBAC
- Provision workflow → Azure Automation: schedules expiry
- Azure Automation → GitHub cleanup trigger: executes at expiry
- GitHub cleanup trigger → GitHub Actions API: dispatches via PAT
- GitHub Actions API → Cleanup workflow: invokes
- Cleanup workflow → Per-user sandboxes: revokes and deletes
- Provision workflow → Failure notifications: uses failure settings
- Failure notifications → Slack webhook: alerts
