Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/lint_workflows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Lint GitHub Actions workflows

# Lints the repo's own GitHub Actions workflows:
# - actionlint: workflow syntax, expression and runner-label checks, plus shellcheck on run: blocks
# - zizmor: workflow security (also enforced locally via the pre-commit hook)

on:
push:
branches:
- main
paths:
- '.github/workflows/**'
pull_request:
paths:
- '.github/workflows/**'

permissions: {}

jobs:
lint_workflows:
name: "Run linters"
runs-on: ubuntu-latest
permissions:
contents: read
actions: read

steps:
- name: Check out repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Run actionlint
uses: raven-actions/actionlint@205b530c5d9fa8f44ae9ed59f341a0db994aa6f8 # v2.1.2

- name: Run zizmor
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
with:
# Don't integrate with GitHub Advanced Security
advanced-security: false
32 changes: 32 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Pre-commit Checks

on:
pull_request:
branches: [ main ]
workflow_dispatch:

permissions:
contents: read

jobs:
pre-commit:
name: Run pre-commit hooks
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: '3.12'
cache: 'pip'

- name: Install pre-commit
run: pip install pre-commit

- name: Run pre-commit
run: pre-commit run --all-files --show-diff-on-failure
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ activemq-data/
.env
.envrc
.venv
# Deployment options generated by samples/web-app-file-storage/scripts/01-deploy-resources.sh
.deploy-options.env
env/
venv/
ENV/
Expand Down
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
repos:
- repo: https://github.com/zizmorcore/zizmor-pre-commit
rev: v1.25.2
hooks:
- id: zizmor

- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaks
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 LocalStack Samples

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
48 changes: 45 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ This repository contains a set of end-to-end samples that show how to deploy an
Every sample deploys the same Vacation Planner web app, a small Python [Flask](https://flask.palletsprojects.com/) single-page application, and only differs in the Azure data service used to persist the activity data behind it:

- [Azure SQL Database](https://learn.microsoft.com/en-us/azure/azure-sql/database/sql-database-paas-overview?view=azuresql)
- [Azure Database DB for PostgreSQL flexible server](https://learn.microsoft.com/en-us/azure/postgresql/overview)
- [Azure Database for MySQL flexible server](https://learn.microsoft.com/en-us/azure/mysql/flexible-server/overview)
- [Azure Database for PostgreSQL flexible server](https://learn.microsoft.com/en-us/azure/postgresql/overview)
- An in-cluster [PostgreSQL](https://www.postgresql.org/) database deployed as a Kubernetes [StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/)
- [Azure Cosmos DB for MongoDB](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/overview)
- [Azure Cosmos DB for NoSQL](https://learn.microsoft.com/en-us/azure/cosmos-db/overview)
- [Azure Blob Storage](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- [Azure Files](https://learn.microsoft.com/en-us/azure/storage/files/storage-files-introduction), mounted into the pods over SMB or NFS by the [Azure Files CSI driver](https://learn.microsoft.com/en-us/azure/aks/azure-files-csi)

This makes it easy to compare how the same application is wired up against different backing stores.

Expand All @@ -23,8 +25,47 @@ This makes it easy to compare how the same application is wired up against diffe
- [kubectl](https://kubernetes.io/docs/tasks/tools/) to manage the cluster.
- [yq](https://github.com/mikefarah/yq), and (depending on the sample) `sqlcmd` or `psql` on the host machine.
- An SSH key pair at `~/.ssh/id_rsa.pub` (used to provision the AKS node pools).
- For local deployments only: the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/), which routes Azure CLI calls to the emulator with [`lstk az`](https://docs.localstack.cloud/azure/integrations/az/).

> Running on LocalStack? Point the Azure CLI at the emulator endpoint (typically `http://localhost:4566`) and run the same scripts unchanged. The Azure resource model is emulated locally, so you can iterate on the full deployment without incurring cloud costs.
## Run against LocalStack

Every sample and tutorial in this repository runs unchanged against [LocalStack for Azure](https://docs.localstack.cloud/azure/), which emulates the Azure resource model locally, so you can iterate on a full deployment without incurring cloud costs.

Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/), which routes Azure CLI calls to the emulator:

```bash
brew install localstack/tap/lstk
```

```bash
npm install -g @localstack/lstk
```

Alternatively, download a pre-built binary from the [lstk releases page](https://github.com/localstack/lstk/releases).

Start the emulator and point the Azure CLI at it:

```bash
# Set your LocalStack auth token
export LOCALSTACK_AUTH_TOKEN=<your_auth_token>

# Start the LocalStack Azure emulator
IMAGE_NAME=localstack/localstack-azure localstack start -d
localstack wait -t 60

# Route all Azure CLI calls to the emulator
lstk az start-interception
```

From here on, run the scripts exactly as documented: `az`, `kubectl`, `terraform` and Bicep all talk to the emulator. To send Azure CLI calls back to Azure:

```bash
lstk az stop-interception
```

For more information, see [Azure CLI interception](https://docs.localstack.cloud/azure/integrations/az/), the [lstk CLI documentation](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and the [lstk GitHub repository](https://github.com/localstack/lstk).

> The first deployment against the emulator downloads and builds container images, which takes a few minutes. Later deployments reuse them and are much faster.

## Create an Azure Kubernetes Service (AKS) cluster

Expand Down Expand Up @@ -75,7 +116,8 @@ All samples implement the same Vacation Planner web app. They only vary the unde
| [web-app-in-cluster-postgresql](samples/web-app-in-cluster-postgresql/) | Stores activities in an in-cluster [PostgreSQL](https://www.postgresql.org/) database deployed as a Kubernetes [StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) (a primary with two streaming-replica standbys), instead of a managed Azure data service. |
| [web-app-cosmosdb-mongodb-api](samples/web-app-cosmosdb-mongodb-api/) | Stores activities in a collection of an [Azure Cosmos DB for MongoDB](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/introduction) account. |
| [web-app-cosmosdb-nosql-api](samples/web-app-cosmosdb-nosql-api/) | Stores activities in a container of an [Azure Cosmos DB for NoSQL](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/) account. |
| [web-app-storage-account](samples/web-app-storage-account/) | Stores activities in an [Azure Blob Storage](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction) container, using a connection string. |
| [web-app-blob-storage](samples/web-app-blob-storage/) | Stores activities in an [Azure Blob Storage](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction) container, using a connection string. |
| [web-app-file-storage](samples/web-app-file-storage/) | Stores activities as text files on an [Azure Files](https://learn.microsoft.com/en-us/azure/storage/files/storage-files-introduction) share mounted into the pods by the [Azure Files CSI driver](https://learn.microsoft.com/en-us/azure/aks/azure-files-csi), over either SMB or NFS, with either a pre-created share or one provisioned on demand. The only sample whose app uses no Azure SDK at all. |
| [web-app-managed-identity](samples/web-app-managed-identity/) | Stores activities in an Azure Blob Storage container, authenticating with [Microsoft Entra Workload ID](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview) (federated credential plus workload identity) instead of a secret, and optionally exposes the app through the Gateway API with a managed TLS certificate. |

Each sample folder follows the same layout:
Expand Down
18 changes: 18 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Security Policy

## Scope

This repository contains **sample code**: end-to-end demonstrations of how to deploy an [Azure Kubernetes Service (AKS)](https://learn.microsoft.com/en-us/azure/aks/what-is-aks) cluster and run a workload on it, against Azure or against the [LocalStack for Azure](https://docs.localstack.cloud/azure/) emulator. It is written to be read and adapted, not to be deployed as-is into production.

Two consequences worth stating plainly:

- **The credentials in these samples are throwaway demo values.** Database passwords, admin logins and Flask secret keys are hardcoded so a sample runs with a single command. They protect resources you create in your own subscription for the duration of a demo. Change them before you keep anything around, and never reuse them.
- **Security trade-offs are chosen for clarity.** Public network access, permissive mount options and secrets passed through environment variables all make a sample easier to follow and are called out in the sample's README where they matter. Harden them for real workloads.

## Reporting a vulnerability

If you find a vulnerability in this repository, for example a real credential committed by mistake, a script that exfiltrates data, or a dependency with a known exploit, report it privately through GitHub's [private vulnerability reporting](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability): open the **Security** tab of this repository and choose **Report a vulnerability**.

Please do not open a public issue for something exploitable.

For a vulnerability in LocalStack itself rather than in these samples, see the [LocalStack documentation](https://docs.localstack.cloud/) for the current support channels.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Before installing the sample, make sure to create an [Azure Kubernetes Service (

All commands below are run from this sample's `scripts/` folder.

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../README.md#run-against-localstack) for the full setup.

## Architecture

The following diagram illustrates the architecture of the solution:
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions samples/web-app-cosmosdb-mongodb-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Before installing the sample, make sure to create an [Azure Kubernetes Service (

All commands below are run from this sample's `scripts/` folder.

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../README.md#run-against-localstack) for the full setup.

## Architecture

The following diagram illustrates the architecture of the solution:
Expand Down
2 changes: 2 additions & 0 deletions samples/web-app-cosmosdb-nosql-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ All commands below are run from this sample's `scripts/` folder.

> LocalStack note: when running against the emulator, the `LOCALSTACK_URL` variable in [`00-variables.sh`](scripts/00-variables.sh) triggers installation of the LocalStack root CA so the app trusts the emulated endpoint. Set it to an empty value when targeting real Azure.

> **Running on LocalStack?** Install the [lstk CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/) and run `lstk az start-interception` to route Azure CLI calls to the emulator. See [Run against LocalStack](../../README.md#run-against-localstack) for the full setup.

## Architecture

The following diagram illustrates the architecture of the solution:
Expand Down
Loading