Shopping Cart DevOps Demo

"develop" build status

Something (simple) you can demonstrate to showcase the Microsoft Azure DevSecOps ecosystem.

Features:

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