Shopping Cart DevOps Demo
Something (simple) you can demonstrate to showcase the Microsoft Azure DevSecOps ecosystem.
Features:
- Integration layer with Azure API Management
- Integration tests
- OpenID authentication with a Progressive Web App app
- SAST tests with GitHub Advanced Security
- Unit tests
- 0 trust (= no static credentials, only managed identities by Azure AD)
- Chaos engineering with Azure Chaos Studio
- DAST tests
- DevOps integration with Microsoft 365 and Azure ecosystems
- SAST security tests with Semgrep
- SBOM history & audit with OWASP Dependency Track, accessible at this adrress with user/password demo/demo
- Serverless architecture
- Stress tests with Azure Load Testing
General
Pre-requisites
Make sure you have installed:
Setup
Defender for Containers
Make sure the option is enabled from the web interface.
Azure Container Registry
# Create the Azure Container Registry
az acr create \
--location westeurope \
--name shoppingcartdevopsdemo \
--resource-group shopping-cart-devops-demo \
--sku Basic \
--workspace shopping-cart-devops-demo
Kubernetes
Create the Azure Kubernetes Service documentation):
# TBD
Install the Ingress, Traefik:
helm repo add traefik https://traefik.github.io/charts
helm repo update
kubectl create ns traefik
helm upgrade \
--atomic \
--install \
--namespace=traefik \
--version=20.8.0 \
traefik \
traefik/traefik
Enable Defender for Cloud inside Azure Kubernetes Service:
az feature register \
--namespace Microsoft.ContainerService \
--name AKS-AzureDefender
az aks update \
--enable-defender \
--name shoppingcartdevopsdemo \
--resource-group shopping-cart-devops-demo
Install Chaos Mesh (Chaos Mesh documentation, Azure Chaos Studio documentation) for Kubernetes:
kubectl create ns chaos-testing
helm install chaos-mesh chaos-mesh/chaos-mesh \
--namespace=chaos-testing \
--set chaosDaemon.runtime=containerd \
--set chaosDaemon.socketPath=/run/containerd/containerd.sock \
--version 2.5.1
az role assignment create --role "Cosmos DB Operator" --assignee-object-id $EXPERIMENT_PRINCIPAL_ID --scope $RESOURCE_ID
Enable Workload Identity to the Kubernetes cluster:
az feature register --namespace "Microsoft.ContainerService" --name "EnableWorkloadIdentityPreview"
az provider register --namespace Microsoft.ContainerService
az aks update \
--name shoppingcartdevopsdemo \
--resource-group shopping-cart-devops-demo \
--enable-oidc-issuer \
--enable-workload-identity
USER_ASSIGNED_IDENTITY_NAME="shopping-cart-devops-demo"
AKS_OIDC_ISSUER="$(az aks show --name shoppingcartdevopsdemo --resource-group shopping-cart-devops-demo --query "oidcIssuerProfile.issuerUrl" -otsv)"
USER_ASSIGNED_CLIENT_ID="$(az identity show --resource-group shopping-cart-devops-demo --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -otsv)"
SERVICE_ACCOUNT_NAME="workload-identity-sa"
SERVICE_ACCOUNT_NAMESPACE="dev"
# You can repeat this step for all your namespaces (ex: dev, preprod, prod)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: "${USER_ASSIGNED_CLIENT_ID}"
labels:
azure.workload.identity/use: "true"
name: "${SERVICE_ACCOUNT_NAME}"
namespace: "${SERVICE_ACCOUNT_NAMESPACE}"
EOF
az identity federated-credential create \
--name "sa-k8s-${USER_ASSIGNED_IDENTITY_NAME}-${SERVICE_ACCOUNT_NAMESPACE}-${SERVICE_ACCOUNT_NAME}" \
--identity-name "${USER_ASSIGNED_IDENTITY_NAME}" \
--resource-group "shopping-cart-devops-demo" \
--issuer "${AKS_OIDC_ISSUER}" \
--subject system:serviceaccount:"${SERVICE_ACCOUNT_NAMESPACE}":"${SERVICE_ACCOUNT_NAME}"
Install KEDA:
SERVICE_ACCOUNT_NAMESPACE="keda"
SERVICE_ACCOUNT_NAME="keda-operator"
az identity federated-credential create \
--name "sa-k8s-${USER_ASSIGNED_IDENTITY_NAME}-${SERVICE_ACCOUNT_NAMESPACE}-${SERVICE_ACCOUNT_NAME}" \
--identity-name "${USER_ASSIGNED_IDENTITY_NAME}" \
--resource-group "shopping-cart-devops-demo" \
--issuer "${AKS_OIDC_ISSUER}" \
--subject system:serviceaccount:"${SERVICE_ACCOUNT_NAMESPACE}":"${SERVICE_ACCOUNT_NAME}"
TENANT_ID=$(az account tenant list | jq -r '.[0].tenantId')
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
kubectl create ns keda
helm upgrade \
--install \
--namespace keda \
--set podIdentity.azureWorkload.enabled=true \
--set podIdentity.azureWorkload.tenantId=${TENANT_ID} \
--set podIdentity.azureWorkload.clientId=${USER_ASSIGNED_CLIENT_ID} \
keda \
kedacore/keda
Azure Load Testing
# ID of the Service Principal used by Azure DevOps
SERVICEPRINCIPAL_ID="da0107d7-2837-4ca1-a4c9-70f7b6d8aee1"
az role assignment create --assignee $SERVICEPRINCIPAL_ID \
--role "Load Test Contributor"
Architecture
See C4 architecture model documentation.
System context diagram
flowchart TB
%% Personas
developers(Developers)
user(End user)
%% Systems
email[Email System]
azdevops[Azure DevOps System]
teams[Microsot Teams System]
this[Shoping Cart System]
%% Relations
developers -- Checks new messages, reads messages --> email
developers -- Updates the sources --> azdevops
azdevops -- Updates the application --> this
teams -- Sends message --> developers
this -- Informs about anormal activites --> email
this -- Informs about anormal activites --> teams
Container diagram
flowchart TB
%% Personas
developers(Developers)
user(End user)
%% Systems
email[Email System]
azdevops[Azure DevOps System]
teams[Microsot Teams System]
%% This system
subgraph this[Shoping Cart System]
this_cart[Cart]
this_iam[IAM]
this_integration[Integration]
this_interface[Interface]
this_monitoring[Monitoring]
end
%% System relations
developers -- Checks new messages, reads messages --> email
developers -- Updates the sources --> azdevops
teams -- Sends message --> developers
%% This relations
azdevops -- Updates the application --> this
this_integration -- Routes to --> this_cart
this_integration -- Validates signatures --> this_iam
this_monitoring -- Informs about anormal activites --> email
this_monitoring -- Informs about anormal activites --> teams
user -- Indentify --> this_iam
user -- Loads resources --> this_interface