Documentation
Connect Your Cloud

OpStack queries your live cloud infrastructure to cross-reference it against your Terraform plan. This requires read-only credentials - OpStack never modifies anything in your account. Choose your cloud provider below and follow either the UI or CLI path.

Azure
Service Principal
A service principal with Reader role on your subscription. No write permissions granted.
AWS
IAM AssumeRole
A cross-account IAM role with ReadOnlyAccess. OpStack assumes it using a trusted account.
Azure
Service Principal

Create a Service Principal with Reader access on your subscription. OpStack uses this to discover resources - no write permissions are needed or granted.

Option A - Azure Portal (UI)
1
Open App Registrations
Go to Azure Portal → Microsoft Entra ID → App registrations → New registration
Name it something like opstack-reader - leave everything else as default and click Register.
2
Copy the IDs
From the app overview page, copy these two values:
Application (client) ID - this is your Client ID
Directory (tenant) ID - this is your Tenant ID
3
Create a Client Secret
Go to Certificates & secrets → New client secret. Set an expiry (24 months recommended). Click Add and copy the Value immediately - it won't be shown again.
⚠
Copy the secret Value, not the Secret ID. The value is the longer string that starts with characters like XmB8Q~...
4
Assign Reader role on your Subscription
Go to Subscriptions → your subscription → Access control (IAM) → Add role assignment
Role: Reader  |  Assign access to: User, group, or service principal  |  Search for opstack-reader and select it. Click Save.
5
Copy your Subscription ID
Go to Subscriptions and copy the Subscription ID from the list.
or
Option B - Azure CLI
1
Login and get your Subscription ID
bash
# Login to Azure az login # List subscriptions and note your Subscription ID az account list --output table
2
Create the Service Principal with Reader role
Replace YOUR_SUBSCRIPTION_ID with your actual subscription ID.
bash
az ad sp create-for-rbac \ --name "opstack-reader" \ --role "Reader" \ --scopes "/subscriptions/YOUR_SUBSCRIPTION_ID" \ --output json
◈
The output will contain appId (Client ID), password (Client Secret), and tenant (Tenant ID). Copy all three - the password won't be shown again.
Enter these values in OpStack
OpStack Field Where to find it
Subscription ID Azure Portal → Subscriptions → your subscription
Tenant ID App registration overview → Directory (tenant) ID
CLI output: tenant
Client ID App registration overview → Application (client) ID
CLI output: appId
Client Secret Certificates & secrets → Value (copy immediately after creation)
CLI output: password
Location Optional. Your Azure region slug e.g. centralindia, eastus
ℹ
After saving, use the Test Connection button on the environment page to verify OpStack can reach your subscription before running an analysis.
AWS
IAM AssumeRole

Create a cross-account IAM role in your AWS account that trusts OpStack's AWS account. OpStack will assume this role to discover your resources - read-only, no write access.

OpStack AWS Account ID 377152274613
Option A - AWS Console (UI)
1
Open IAM → Roles → Create Role
Go to AWS Console → IAM → Roles → Create role
Trusted entity type: AWS account
Select: Another AWS account
Account ID: 377152274613
Check: Require external ID → enter a unique value e.g. opstack-prod (remember this, you'll enter it in OpStack)
2
Attach ReadOnlyAccess policy
On the permissions page, search for and attach: ReadOnlyAccess (AWS managed policy).
3
Name and create the role
Role name: OpStackDiscoveryRole (or any name you prefer). Click Create role.
4
Copy the Role ARN
Open the role you just created. Copy the ARN from the top of the page. It looks like:
arn:aws:iam::YOUR_ACCOUNT_ID:role/OpStackDiscoveryRole
or
Option B - AWS CLI
1
Create the trust policy file
Save this as trust-policy.json. Replace YOUR_EXTERNAL_ID with a unique string of your choice.
json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::377152274613:root" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "YOUR_EXTERNAL_ID" } } } ] }
2
Create the role and attach ReadOnlyAccess
bash
# Create the role aws iam create-role \ --role-name OpStackDiscoveryRole \ --assume-role-policy-document file://trust-policy.json # Attach ReadOnlyAccess aws iam attach-role-policy \ --role-name OpStackDiscoveryRole \ --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess # Get the Role ARN (copy this into OpStack) aws iam get-role \ --role-name OpStackDiscoveryRole \ --query Role.Arn \ --output text
Enter these values in OpStack
OpStack Field Where to find it
Account ID AWS Console top-right → your account name → Account ID
Region The AWS region your resources are in e.g. us-east-1, ap-south-1
IAM Role ARN IAM → Roles → OpStackDiscoveryRole → ARN at the top
Format: arn:aws:iam::ACCOUNT_ID:role/OpStackDiscoveryRole
External ID The value you set in the trust policy condition above
ℹ
After saving, use the Test Connection button on the environment page to verify OpStack can assume your role before running an analysis.
◈
The External ID is a security best practice - it prevents the confused deputy problem and ensures only you can authorise OpStack to access your account. Use a unique value per environment.
CI/CD Integration
GitHub App

The OpStack GitHub App automatically detects Terraform changes in pull requests and posts a blast radius comment - no workflow files needed. Just install the app and add .opstack.yml to your repo.

GitHub App - zero config integration
1
Install the OpStack GitHub App
Select which repositories to grant access to. You can change this at any time.
2
Connect your GitHub account in OpStack
Go to your OpStack account page → click Connect GitHub. This links the app installation to your OpStack account so analyses can run.
3
Add .opstack.yml to your repo
See the config reference below. Once added, OpStack will automatically comment on every PR that touches .tf files.
or use the GitHub Action
GitHub Action - workflow-based integration
1
Generate an API key
Go to your OpStack account page → CI/CD API Key → Generate Key. Add it as a GitHub repository secret named OPSTACK_API_KEY.
2
Add your Environment ID as a variable
Find your Environment ID in the URL when viewing an environment: /environments/42 → ID is 42. Add it as a GitHub repository variable named OPSTACK_ENVIRONMENT_ID.
3
Add the workflow
yaml
name: OpStack Analysis on: pull_request: paths: ['**.tf', '**.tfvars'] jobs: opstack: runs-on: ubuntu-latest permissions: contents: read pull-requests: write statuses: write steps: - uses: actions/checkout@v4 - name: Terraform Plan run: | terraform init terraform plan -out=tfplan terraform show -json tfplan > plan.json - name: OpStack Analysis uses: opstack-in/opstack-action@v1 with: api-key: ${{ secrets.OPSTACK_API_KEY }} environment-id: ${{ vars.OPSTACK_ENVIRONMENT_ID }} plan-file: plan.json fail-on: CRITICAL env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
.opstack.yml Reference

Add .opstack.yml to your repo root to configure which OpStack environment each branch maps to.

yaml - simple format
version: 1 environments: main: 42 # branch: environment_id develop: 38 staging: 39 "*": 42 # wildcard - fallback for any other branch
yaml - detailed format
version: 1 environments: main: id: 42 fail_on: CRITICAL # CRITICAL | HIGH | MEDIUM | LOW | NONE develop: id: 38 fail_on: HIGH staging: id: 39 fail_on: MEDIUM
ℹ
Find your Environment ID in the OpStack dashboard URL when viewing an environment: /environments/42. The fail_on threshold determines which severity level fails the PR status check. Defaults to CRITICAL.
Need help connecting your cloud account?  Contact Support ↗