Environment Setup
Environment Setup
Complete these steps before starting the exercises. Estimated setup time: ~15 minutes.
This workshop builds on trust boundaries (WS1) and code guardrails (WS2). If you havenβt completed those, see the Quick Foundation Setup at the end of this page.
4.1 Verify Trust Boundary & GHAS (from WS1-2)
Use the verify-or-skip pattern: check that WS1-2 outcomes are in place; if not, set them up quickly.
If continuing from WS1-2, verify these are active:
- Organization exists on GHE.com (Japan data residency region)
- Repository is org-owned (not personal fork)
- GitHub Advanced Security (GHAS) is enabled on the repository
- Branch protection rules are active on
main(require PR reviews, status checks)
# Verify GHAS is enabled
gh api repos/{owner}/{repo} --jq '.security_and_analysis'
# Verify branch protection
gh api repos/{owner}/{repo}/branches/main/protection --jq '.required_status_checks'
If starting fresh, see the Quick Foundation Setup below.
4.2 Create Sample Container Application
Our sample application is a minimal Node.js HTTP server. It exists solely as an artifact to build, sign, deploy, and trace.
Project structure:
.
βββ src/
β βββ index.js # Minimal HTTP server
β βββ package.json # Node.js dependencies
βββ Dockerfile # Multi-stage container build
βββ .github/
β βββ workflows/
β βββ build-deploy.yml # BEFORE: static secrets
β βββ build-deploy-oidc.yml # AFTER: OIDC + attestation
βββ THREAT-MODEL.md # Updated in Exercise 2
Build and test locally:
# Build the container image
docker build -t supply-chain-demo:local .
# Run it
docker run -p 3000:3000 supply-chain-demo:local
# Verify (in another terminal)
curl http://localhost:3000
# Expected: {"message":"Hello from Supply Chain Demo!","version":"1.0.0"}
If you see the JSON response, your application is ready.
4.3 Create CI/CD Workflow (BEFORE β Static Secrets)
The file .github/workflows/build-deploy.yml is the deliberately insecure βBEFOREβ version of our CI/CD pipeline. It uses a long-lived static secret (secrets.AZURE_CREDENTIALS) for Azure authentication.
β οΈ Warning: This workflow uses static credentials on purpose β to demonstrate the security risk. We will replace it with OIDC in Exercise 1.
Review the workflow and note where secrets.AZURE_CREDENTIALS is used:
cat .github/workflows/build-deploy.yml
Key problem: If AZURE_CREDENTIALS is leaked (log exposure, compromised runner, insider threat), an attacker can deploy anything to your cluster β indefinitely β until the credential is manually rotated.
4.4 Configure Cloud Provider (Azure)
Set up the Azure resources needed for the exercises.
Step 1: Create resource group and container registry
# Set variables
RESOURCE_GROUP="rg-devsecops-ws3"
LOCATION="japaneast"
ACR_NAME="acrdevsecopsws3${RANDOM}"
AKS_NAME="aks-devsecops-ws3"
# Create resource group
az group create --name $RESOURCE_GROUP --location $LOCATION
# Create Azure Container Registry
az acr create --resource-group $RESOURCE_GROUP --name $ACR_NAME --sku Basic
# Create AKS cluster (small, for testing only)
az aks create \
--resource-group $RESOURCE_GROUP \
--name $AKS_NAME \
--node-count 1 \
--node-vm-size Standard_B2s \
--attach-acr $ACR_NAME \
--generate-ssh-keys
Step 2: Create a service principal (the βold wayβ β for the BEFORE workflow)
# Create service principal with Contributor role scoped to the resource group
az ad sp create-for-rbac \
--name "sp-devsecops-ws3-deploy" \
--role contributor \
--scopes /subscriptions/{subscription-id}/resourceGroups/$RESOURCE_GROUP \
--sdk-auth
Step 3: Store as repository secret
# Copy the JSON output from above and store it as a GitHub secret
gh secret set AZURE_CREDENTIALS < credentials.json
β οΈ Important: We are deliberately storing a long-lived static credential. This is the pattern we will eliminate in Exercise 1 with OIDC. Note: in a real environment, delete
credentials.jsonimmediately after storing the secret.
4.5 Set Up Defender for Cloud
Step 1: Enable Defender for Containers
# Enable Defender for Containers on your subscription
az security pricing create \
--name Containers \
--tier Standard
Step 2: Enable code-to-runtime correlation
- Navigate to Azure Portal β Microsoft Defender for Cloud β Environment settings
- Select your subscription β Defender plans
- Under Containers, ensure Agentless discovery and Runtime visibility are enabled
- Under DevOps security, click Connect β select GitHub β authorize access to your repository
Step 3: Verify connection
# Check Defender for Cloud status
az security pricing show --name Containers --query "pricingTier"
# Expected: "Standard"
Note: GHAS integration with Defender for Cloud is in preview. It currently supports container workloads. Code-to-runtime mapping may take several minutes to populate after initial setup.
4.6 Verify THREAT-MODEL.md (from WS2)
If continuing from WS2, verify that THREAT-MODEL.md exists with rows 1-3 filled:
cat THREAT-MODEL.md
You should see a table like this:
| # | Attack Vector | Target Asset | Threat Actor | Current Control | Gap? |
|---|---|---|---|---|---|
| 1 | Secret leaked in commit | A2 β Secrets | T2 β Insider | β Secret scanning + push protection | Covered (WS1) |
| 2 | Insecure code pattern (SQL injection) | A1 β Source Code | T2 β Insider | β Code scanning + Copilot Autofix | Covered (WS2) |
| 3 | Vulnerable dependency | A1 β Source Code | T1 β External | β Dependabot + dependency review | Covered (WS2) |
| 4 | Build artifact tampered with | A3 β Container Images | T3 β CI/CD | ? | ? |
| 5 | Deployment artifact doesnβt match reviewed code | A4 β Deployed App | T3 β CI/CD | ? | ? |
Rows 4-5 still show β?β β we will fill these during Exercise 2.
If starting fresh, create THREAT-MODEL.md with the table above (rows 1-3 pre-filled, rows 4-5 with placeholders). See the Quick Foundation Setup below.
Tip: Run
scripts/verify-setup.shafter completing all setup steps to confirm your environment is ready.
Quick Foundation Setup
For participants who did not complete Workshops 1 and 2. This condensed setup (~5 min) establishes the minimum prerequisites.
A.1 Organization & Repository
# If you don't have an org-owned repository, create one:
gh repo create {org}/agentic-devsecops-supplychain-integrity --private --clone
cd agentic-devsecops-supplychain-integrity
A.2 Enable GHAS
- Navigate to Repository β Settings β Code security and analysis
- Enable: Dependency graph, Dependabot alerts, Code scanning (default setup), Secret scanning
A.3 Branch Protection
gh api repos/{owner}/{repo}/branches/main/protection \
--method PUT \
--input - <<'EOF'
{
"required_status_checks": { "strict": true, "contexts": [] },
"enforce_admins": true,
"required_pull_request_reviews": { "required_approving_review_count": 1 },
"restrictions": null
}
EOF
A.4 Create THREAT-MODEL.md (Pre-filled Rows 1-3)
Create THREAT-MODEL.md with the following content:
# Threat Model β Agentic DevSecOps Workshop Series
| # | Attack Vector | Target Asset | Threat Actor | Current Control | Gap? |
|---|--------------|--------------|--------------|----------------|------|
| 1 | Secret leaked in commit | A2 β Secrets | T2 β Insider | β
Secret scanning + push protection | Covered (WS1) |
| 2 | Insecure code pattern (SQL injection) | A1 β Source Code | T2 β Insider | β
Code scanning + Copilot Autofix | Covered (WS2) |
| 3 | Vulnerable dependency | A1 β Source Code | T1 β External | β
Dependabot + dependency review | Covered (WS2) |
| 4 | Build artifact tampered with | A3 β Container Images | T3 β CI/CD | ? | ? |
| 5 | Deployment artifact doesn't match reviewed code | A4 β Deployed App | T3 β CI/CD | ? | ? |
Youβre now ready to begin Section 4.2.