Compare commits

..

68 Commits

Author SHA1 Message Date
3755329fe6 fix: standardize note formatting in README.md for consistency 2026-03-24 11:56:42 +01:00
6a1f332372 fix: standardize note formatting in README.md for clarity 2026-03-24 11:55:41 +01:00
8d967d7ad7 fix: remove --oauth command from azurite service in compose.yaml and enhance error handling in run-server.sh 2026-03-24 11:29:12 +01:00
f825835744 fix: remove azurite deployment and service configuration from Kubernetes manifests 2026-03-24 11:28:45 +01:00
ea6277ba3b update: refactor run-server.sh to match Docker version. 2026-03-24 11:17:10 +01:00
8800154d37 fix: update image handling in build script to use AZURITE_IMAGE variable consistently 2026-03-24 10:23:32 +01:00
8c454fa2fc fix: update Caddyfile generation and add /etc/hosts entries for emulator endpoints 2026-03-24 09:58:35 +01:00
149f8a30eb fix: enhance argument handling in start-azurite script to support container configuration 2026-03-24 09:47:14 +01:00
2631d4ff85 fix: allow unknown arguments in start-azurite script to be passed as container arguments 2026-03-24 09:45:44 +01:00
b342be88f3 fix: update start-azurite script to improve error handling and streamline container arguments 2026-03-24 09:43:40 +01:00
795e1c6740 fix: improve error messaging and correct NO_CADDY condition in entrypoint.sh 2026-03-24 09:43:29 +01:00
a19036f10d fix: simplify AZURITE_ACCOUNTS check by removing default account generation 2026-03-24 09:38:52 +01:00
4c66ee38ba fix: move account name lookup above certificate check in entrypoint.sh 2026-03-24 09:31:46 +01:00
7f1027c6e0 fix: add check for existence of account certificate and key in entrypoint.sh 2026-03-24 09:18:28 +01:00
9d1546a1bc fix: update Dockerfile to copy the correct Caddyfile template and remove unused cert-functions.sh 2026-03-24 08:30:09 +01:00
00459cbb1c refactor: remove unused certificate generation functions and streamline entrypoint.sh 2026-03-24 08:29:01 +01:00
2af06a3bbf fix: update CA_DIR default value to use ./storage instead of ./ca 2026-03-24 08:28:47 +01:00
b092c00e27 fix: update .gitignore to remove duplicate entry for storage 2026-03-24 08:28:37 +01:00
32bbc40979 Renamed Caddyfile template to a correct name. 2026-03-24 08:25:18 +01:00
58d0a96bfe update: change reverse proxy URLs to use localhost instead of account names 2026-03-24 08:24:41 +01:00
12b14460e9 refactor: remove cert-functions.sh as its functionality is no longer needed 2026-03-24 07:54:50 +01:00
c3c078fa7f fix: remove unnecessary echo statement when creating CA certificate and key 2026-03-24 07:43:19 +01:00
47efc09d18 fix: ensure CA certificate and key are created only if they do not exist 2026-03-24 07:42:37 +01:00
5a840f6577 update: ensure CA directory is created before generating certificates 2026-03-24 07:39:09 +01:00
8fdbce7fb4 update: make CA_DIR, CA_NAME, and STORAGE_ACCOUNT_NAME configurable 2026-03-24 07:38:36 +01:00
4f1d78f174 feat: add make-cert.sh script for generating self-signed CA and server certificates 2026-03-24 07:37:58 +01:00
b17d34ae2b fix: add 'ca' to .gitignore to prevent tracking of certificate authority files 2026-03-24 07:02:39 +01:00
d5cddbdd8c fix: correct command check for Docker daemon in start-azurite script 2026-03-23 22:59:27 +01:00
abbb0842fc Fixed incorrect AI autocomplete. 2026-03-22 10:17:22 +01:00
eac8adbcfa fix: include CA name in certificate generation for improved clarity 2026-03-21 19:01:35 +01:00
d7ad25c4d6 fix: add resource limits to container run command for azurite 2026-03-21 19:01:07 +01:00
241f70cb22 feat: add VSCode settings for shell script association with start-azurite 2026-03-21 19:01:00 +01:00
6822c65a7a fix: update subject in server certificate generation to use the full subject name 2026-03-03 13:23:33 +01:00
fb7ec2ac9e fix: improve feedback during PFX file generation and secure password handling 2026-03-03 12:40:17 +01:00
76c812794c fix: correct parameter name from '-passout' to '-password' in make_pfx function 2026-03-03 12:24:57 +01:00
3b9c295a35 feat: enhance certificate generation functions and add make_account_cert for streamlined server cert creation 2026-03-03 11:54:47 +01:00
3a068149a7 fix: update init.sh to use correct path for accounts.env file 2026-03-02 11:52:38 +01:00
ea7905d7c7 feat: add Kubernetes manifest for Azurite deployment 2026-03-02 07:34:00 +01:00
d5a715fcfc update: revise installation instructions in README and adjust Azurite image in docker-compose 2026-03-02 07:08:55 +01:00
815278e918 feat: add docker-compose configuration for Azurite service 2026-03-02 06:45:36 +01:00
58c31e73bf fix: update Caddyfile.example to use __AZURITE_STORAGE__ for certificate and key paths 2026-02-28 20:39:52 +01:00
1a66e46615 update: rename run.sh to start-azurite and enhance documentation for environment variables 2026-02-28 20:13:35 +01:00
93fb89446d fix: use variable for AZURITE_IMAGE in docker run commands 2026-02-28 19:52:02 +01:00
c8ac9ddebf update: rename run.sh to start-azurite. 2026-02-28 19:46:51 +01:00
ffdfc2697b fix: update run.sh to use current directory for AZURITE_DIR and correct env-file paths 2026-02-28 19:45:10 +01:00
b698521720 fix: update entrypoint.sh to source accounts from accounts.env and improve Caddy handling 2026-02-28 19:45:00 +01:00
8813a4d5ed update: change docker run options from interactive to detached mode in run.sh 2026-02-28 19:27:20 +01:00
b8f6c2dccf chore: remove obsolete list-accounts.sh script 2026-02-28 11:58:40 +01:00
199346b48f fix: correct minor grammatical errors and improve clarity in README.md 2026-02-28 11:45:25 +01:00
8d30246ea0 chore: remove incomplete section on Let's Encrypt certificates from README.md 2026-02-28 11:17:47 +01:00
050986ff87 fix: update storage directory variable in run.sh for consistency 2026-02-28 11:15:21 +01:00
aa9274aca3 feat: enhance build and entrypoint scripts with improved argument handling and host entry management 2026-02-28 10:36:36 +01:00
ae7542100b Refactored scripts to focues on compatibility with the real product. 2026-02-28 09:34:52 +01:00
c65c347ca5 feat: add Terraform configuration and initialization scripts for Azure backend 2026-02-27 22:48:31 +01:00
8be0eb7d90 update: streamlined run-server.sh with entrypoint.sh. 2026-02-27 22:41:55 +01:00
f336039cd8 fix: update oauth flag handling to support shorthand option 2026-02-27 21:24:24 +01:00
901477ef5a fix: add error handling for unknown arguments in run script 2026-02-27 21:02:48 +01:00
103df98c0f fix: update port exposure logic and enhance OAuth handling in run script 2026-02-27 20:47:10 +01:00
32a438dee2 fix: refactor port exposure functions and improve --oauth flag handling in run script 2026-02-27 14:49:24 +01:00
790f779572 fix: update port mappings for blob, queue, and table hosts in entrypoint script 2026-02-27 14:39:27 +01:00
60f3fcfa60 fix: update entrypoint to specify blob, queue, and table host addresses 2026-02-27 13:54:36 +01:00
1b22711071 fix: remove unnecessary port exposure for HTTPS in Dockerfile 2026-02-27 13:46:39 +01:00
5483f22f6f fix: correct exposed port mapping in run script 2026-02-27 13:45:03 +01:00
0862cad994 fix: prevent multiple --oauth flag usage in run script 2026-02-27 13:43:02 +01:00
2393a281c3 fix: streamline port exposure handling in run script 2026-02-27 13:33:21 +01:00
ddc8fe8241 fix: enable SSL when OAuth is used in entrypoint script 2026-02-27 13:14:30 +01:00
241ee9f645 fix: add container name to run commands in run.sh 2026-02-27 12:21:50 +01:00
f23d36ecd8 fix: update script permissions. 2026-02-27 11:24:50 +01:00
19 changed files with 585 additions and 330 deletions

4
.gitignore vendored
View File

@@ -1,4 +1,6 @@
storage storage
test **/.terraform
**/.terraform.lock.hcl
Caddyfile Caddyfile
*.env *.env
storage

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"start-azurite": "shellscript"
}
}

View File

@@ -1,17 +0,0 @@
# Caddyfile for Azure Storage Emulator
# It uses /etc/hosts entries to route requests to the emulator
# Replace "__ACCOUNT_NAME__" with a desired storage account name if needed
__ACCOUNT_NAME__.blob.core.windows.net {
tls __AZURITE_DIR__/__ACCOUNT_NAME___cert.pem __AZURITE_DIR__/__ACCOUNT_NAME___key.pem
reverse_proxy localhost:10000
}
__ACCOUNT_NAME__.queue.core.windows.net {
tls __AZURITE_DIR__/__ACCOUNT_NAME___cert.pem __AZURITE_DIR__/__ACCOUNT_NAME___key.pem
reverse_proxy localhost:10001
}
__ACCOUNT_NAME__.table.core.windows.net {
tls __AZURITE_DIR__/__ACCOUNT_NAME___cert.pem __AZURITE_DIR__/__ACCOUNT_NAME___key.pem
reverse_proxy localhost:10002
}

30
Caddyfile.template Normal file
View File

@@ -0,0 +1,30 @@
# Caddyfile for Azure Storage Emulator
__ACCOUNT_NAME__.blob.core.windows.net {
tls __AZURITE_STORAGE__/__ACCOUNT_NAME___cert.pem __AZURITE_STORAGE__/__ACCOUNT_NAME___key.pem
reverse_proxy https://__ACCOUNT_NAME__.blob.core.windows.net:10000 {
transport http {
tls
tls_trust_pool file __AZURITE_STORAGE__/ca_cert.pem
}
}
}
__ACCOUNT_NAME__.queue.core.windows.net {
tls __AZURITE_STORAGE__/__ACCOUNT_NAME___cert.pem __AZURITE_STORAGE__/__ACCOUNT_NAME___key.pem
reverse_proxy https://__ACCOUNT_NAME__.queue.core.windows.net:10001 {
transport http {
tls
tls_trust_pool file __AZURITE_STORAGE__/ca_cert.pem
}
}
}
__ACCOUNT_NAME__.table.core.windows.net {
tls __AZURITE_STORAGE__/__ACCOUNT_NAME___cert.pem __AZURITE_STORAGE__/__ACCOUNT_NAME___key.pem
reverse_proxy https://__ACCOUNT_NAME__.table.core.windows.net:10002 {
transport http {
tls
tls_trust_pool file __AZURITE_STORAGE__/ca_cert.pem
}
}
}

View File

@@ -27,12 +27,7 @@ RUN npm ci --omit=dev --unsafe-perm
WORKDIR /app WORKDIR /app
COPY ./entrypoint.sh . COPY ./entrypoint.sh .
COPY ./Caddyfile.example . COPY ./Caddyfile.template .
RUN chmod +x entrypoint.sh RUN chmod +x entrypoint.sh
EXPOSE 443
EXPOSE 10000
EXPOSE 10001
EXPOSE 10002
ENTRYPOINT [ "/app/entrypoint.sh" ] ENTRYPOINT [ "/app/entrypoint.sh" ]

205
README.md
View File

@@ -1,18 +1,52 @@
# Azure Storage Emulator # Azure Storage Emulator
This is a simple guide that will help you set up and run the Azure Storage Emulator on your local machine. The Azure Storage Emulator allows you to develop and test your applications that use Azure Storage services without needing an actual Azure subscription nor Internet connection. This is a simple guide that will help you set up and run the Azure Storage Emulator on your local machine. The Azure Storage Emulator allows you to develop and test your applications that use Azure Storage services without needing an Azure subscription or an Internet connection.
## Prerequisites Review the [Documentation](#reference) for more details on how to use the emulator and its features. This document covers a scenario where you want to run the emulator as close to the real Azure Storage service as possible, which means using triple HTTPS endpoints and OAuth simulation.
- Any system that supports fairly recent versions of Node.js (LTS vesions are recommended). ## Installation
- A Bash shell (a Linux or macOS system or Windows with WSL2 installed).
- Docker Community Edition or Docker Desktop (for running the emulator in a containerized environment).
- Apple `container` command (for running the containerized version of the emulator on macOS).
- (Optional) Caddy HTTP server (for running the emulator with triple HTTPS endpoints, as it would be in Azure).
## Native Installation You can install and use the emulator in a few different ways, depending on your preferences and environment. The recommended way is to use a container runtime or Kubernetes, but you can also install it natively using Node.js and Caddy HTTP Server.
To install the Azure Storage Emulator natively on your machine, follow these steps: ### Using a container runtime
To run the Azure Storage Emulator in a container, follow these steps:
1. Ensure that a container runtime is installed. This repository supports both Docker and Apple `container` command.
2. Create a custom non-public certificate for the emulator. Use the provided `make-cert.sh` script to generate a self-signed CA certificate and a server certificate for the specified storage account name. The script will use `CA_DIR` (default: `./storage`), `CA_NAME` (default: `Azurite Emulator CA`), and `STORAGE_ACCOUNT_NAME` (default: `azuritelocal`) environment variables to determine the storage location for the certificates, the name of the CA, and the storage account name for which the server certificate will be generated. For example:
```bash
./make-cert.sh
```
or
```bash
CA_DIR=./myca CA_NAME="My Custom CA" STORAGE_ACCOUNT_NAME=myaccount ./make-cert.sh
```
You can run the script multiple times with different `STORAGE_ACCOUNT_NAME` values to generate certificates for multiple storage accounts if needed. Just make sure to use the same `CA_DIR` and `CA_NAME` for all of them (or use the defaults) to ensure they are signed by the same CA.
3. Build the emulator image using the provided Dockerfile:
```bash
./build.sh
```
or pull it from the Docker Hub registry using image name: `skoszewski/azurite:latest`.
4. Run the emulator container:
```bash
./start-azurite
```
You can also use the included example `compose.yaml` file for running it using `docker compose` (or any other compose compatible CLI).
### Using Node.js and Caddy HTTP Server
To install the Azure Storage Emulator natively on your machine, ensure you have Node.js (with npm) and Caddy HTTP Server installed, and follow these steps:
1. Clone the repository: 1. Clone the repository:
@@ -47,40 +81,163 @@ To install the Azure Storage Emulator natively on your machine, follow these ste
rm -rf azurite rm -rf azurite
``` ```
## Running the Emulator 6. Create an `accounts.env` file in the same directory as the `run-server.sh` script with the following content:
There are two ways to run the Azure Storage Emulator: as a development server exposing the API on localhost using high ports (10000-10002) or as a fake Azure Storage service. The first one is easy, just run the `azurite` command in your terminal and that's it. The second one is a bit more complex, but it allows you to use the emulator as if it were the real Azure Storage service, and connect to it applications that do not support custom endpoints (Terraform azurerm state storage backend for example). ```bash
AZURITE_ACCOUNTS=accountname:accountkey
```
Run the `make-certs.sh` script to generate a self-signed CA certificate and a server certificate signed by that CA. The server certificate will be used by the emulator to serve HTTPS traffic, and the CA certificate can be imported into your system's trusted root certificates store to avoid security warnings when connecting to the emulator. Replace `accountname` with the desired account name. Use OpenSSL to generate an account key.
The `make-certs.sh` script will create a storage directory for the emulator and place the generated PEM files there. The script will create a certificate for the `devstoreaccount1.blob.core.windows.net`. You can change that by adding you own storage account name as a single positional parameter. You will also need to map that name to `127.0.0.1` in your hosts file. ```bash
openssl rand -base64 32
```
You can also generate a deterministic account key using any string as a seed:
```bash
echo -n "your-seed-string" | base64
```
7. Add the following line to your `/etc/hosts` file to map the custom domain names to localhost:
```
127.0.0.1 <accountname>.blob.core.windows.net <accountname>.queue.core.windows.net <accountname>.table.core.windows.net
```
8. Create a certificate for the specified account name using the `make-cert.sh` as described in the container runtime installation steps.
9. Run the server:
```bash
./run-server.sh
```
## Accessing the blob storage
### RClone
RClone is a command-line program to manage files on cloud storage. You can use it to interact with the Azure Storage Emulator the same way you would with the real Azure Storage service. Edit the rclone.conf file and add the following configuration:
```ini
[azurite]
type = azureblob
account = accountname
key = accountkey
```
or, if you want to use simulated OAuth authentication:
```ini
[azurite]
type = azureblob
account = accountname
env_auth = true
```
Now, you can use rclone commands to interact with the emulator. For example, to list the containers in the blob service:
```bash ```bash
./make-certs.sh myaccount rclone ls azurite:
``` ```
``` > **Note** On modern Linux distributions and MacOS systems the `rclone.conf` file is typically located at `~/.config/rclone/rclone.conf`.
127.0.0.1 devstoreaccount1.blob.core.windows.net devstoreaccount1.queue.core.windows.net devstoreaccount1.table.core.windows.net
### Terraform
Use the following Terraform Azure RM backend configuration to use the Azure Storage Emulator as the backend for storing Terraform state:
```hcl
terraform {
backend "azurerm" {
storage_account_name = "accountname"
container_name = "tfstate"
key = "terraform.tfstate"
}
}
``` ```
Next, create an empty `accounts.env` file in the same directory. This file will be used by the emulator to retrieve the storage accounts names and access keys. You can use a single key or a pair of keys for each account. The format of the file is as follows: and initialize the module:
```shell ```bash
AZURITE_ACCOUNTS="account1:key1,key2;account2:key1,key2;..." terraform init -backend-config=access_key=__base64_encoded_account_key__
``` ```
Use `add-account.sh` script to add at least one account to the `accounts.env` file. The script will generate random key for each added account. You can use `list-accounts.sh` script to list all accounts and their keys. You can also specify a password that will be used as the value for the key. The key is always Base64 encoded, and you password will also be Base64 encoded before being stored in the `accounts.env` file. The benefit of using a password is that the account key will be deterministic, so you can easily recreate the same account with the same key if needed. > **Note** Be aware that AI Agents may generate or suggest using the `endpoint` parameter, which will not work. You have to create *fake* account FQDNs in your `/etc/hosts` file as described in the installation steps.
Finally, run the emulator using the `run-emulator.sh` script.
You can specify `--oauth` to enable simulation of Entra ID Authentication. It requires the endpoints to be directly accessed via HTTPS. You can use OAuth simulation with Terraform by adding the `use_azuread_auth` parameter to the backend configuration:
The `run-emulator.sh` will detect if Caddy HTTP server is installed on your system, and if it is, it will use it to serve the emulator on triple HTTPS endpoints (Blob, Queue and Table services) as it would be in Azure. ```hcl
terraform {
backend "azurerm" {
storage_account_name = "accountname"
container_name = "tfstate"
key = "terraform.tfstate"
use_azuread_auth = true
}
}
```
Use `--no-caddy` to disable Caddy even if it is installed. It is required to test Entra ID Authentication simulation. ## Command Reference
### `build.sh`
The script builds a container image for the Azure Storage Emulator using the provided Dockerfile. The image includes the Azurite server and Caddy HTTP server, configured to run the emulator with triple HTTPS endpoints and optional OAuth simulation. It does not require Azurite or Caddy to be installed on the host machine, as they are included in the container image.
Accepted flags:
- `--arch`: Specifies the target architecture for the container image. Supported values are `amd64` and `arm64`. If not provided, the script will build for the architecture of the host machine. It can be specified twice to build for both architectures.
- `--version`: Specifies the version tag for the built container image. The version value must correspond to a valid Azurite GitHub tag.
- `--latest`: Uses the latest released version of Azurite from GitHub as the base for the container image. This flag cannot be used together with `--version`.
- `--registry`: Specifies the container registry to which the built image will be pushed. If not provided, the image will only be built locally and not tagged with registry prefix.
Used environment variables:
- `AZURITE_IMAGE`: Overrides the default image name (`azurite:latest`) for the built container image. This can be useful if you want to use a different naming convention or push to a specific registry. The `--registry` flag will replace the registry part of the image name, but it will not override the entire name, so you can still use a custom image name with the registry prefix if needed.
### `start-azurite`
The script runs the Azure Storage Emulator using a supported container runtime (Docker or Apple `container` command). It enables OAuth and starts Caddy by defualt.
> **Remember**: Make backups of the storage directory when the container is not running.
Accepted flags:
- `--no-oauth` - disables OAuth simulation in the emulator. When this flag is set, you have to use the account key for authentication.
- `--no-caddy` - disables Caddy server and runs Azurite with its built-in HTTP server. This will result in the emulator being accessible over three HTTPS endpoints (ports: 10000, 10001, 10002). Use this flag if you want to run the emulator and proxy the endpoints yourself. Note that you have to configure your proxy to accept the certificate supplied for the emulator. Caddy uses `tls_trust_pool file <pem_cert_path>` directive.
Used environment variables:
- `AZURITE_DIR`: Specifies the directory on the host machine where the emulator will store its data. This directory will be mounted as `/storage` in the container, allowing the emulator to persist data across container restarts.
- `AZURITE_IMAGE`: Specifies the name of the container image to use when running the emulator. If not set, it defaults to `azurite:latest`, which is the default tag used by the `build.sh` script.
### `run-server.sh`
The script is the entry point for starting the Azure Storage Emulator natively. It discovers the account name and key from the `accounts.env` file, checks for the necessary SSL certificates, configures Caddy for HTTPS endpoints, and starts the Azurite server with the appropriate settings.
The script assumes that both Azurite and Caddy are installed and available in the system's PATH. It also assumes that the `accounts.env` file is properly configured with at least one account name and key, and that the `/etc/hosts` file contains the necessary entries mapped to `127.0.0.1` for the custom domain names, e.g. `accountname.blob.core.windows.net`, `accountname.queue.core.windows.net`, and `accountname.table.core.windows.net`.
The storage location is determined by the `AZURITE_DIR` environment variable. Data files are stored in the `storage` subdirectory. The directory structure pointed to by `AZURITE_DIR` will be created if it does not exist.
The script will use the certificate for the listed endpoints. Caddy will be configured to use that certificate for all HTTPS endpoints, therefore the certificate must have all the required SANs (Subject Alternative Names) for the endpoints and must be trusted by the system. The emulator will be accessible at the following endpoints:
- Blob service: `https://accountname.blob.core.windows.net`
- Queue service: `https://accountname.queue.core.windows.net`
- Table service: `https://accountname.table.core.windows.net`
For Debian-based systems, you can use the following commands to add the certificate to the trusted store:
```bash
sudo cp storage/ca_cert.pem /usr/local/share/ca-certificates/azurite_ca_cert.crt
sudo update-ca-certificates
```
For macOS, you can use the Keychain Access application to import the certificate and mark it as trusted. Windows users can use the Certificate Manager to import the certificate into the "Trusted Root Certification Authorities" store.
## Reference ## Reference
- [Azure Storage Emulator GitHub Repository](https://github.com/azure/azurite) - [Azure Storage Emulator GitHub Repository](https://github.com/azure/azurite)
- [Azure Storage Emulator Documentation](https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite) - [Azure Storage Emulator Documentation](https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite)
- [Caddy Server](https://caddyserver.com) - [Caddy Server](https://caddyserver.com)
- [RClone](https://rclone.org)

View File

@@ -1,27 +0,0 @@
#!/usr/bin/env bash
if [[ -z "$1" ]]; then
echo "Usage: $0 <account-name> [ password ]"
exit 1
fi
if [[ -z "$2" ]]; then
PASSWORD=$(openssl rand -base64 32)
else
PASSWORD=$(echo -n "$2" | base64)
fi
AZURITE_DIR="storage"
mkdir -p "$AZURITE_DIR"
AZURITE_ACCOUNTS_FILE="$AZURITE_DIR/accounts.env"
if [[ -f "$AZURITE_ACCOUNTS_FILE" ]]; then
. "$AZURITE_ACCOUNTS_FILE"
STORAGE_ACCOUNTS=($(echo "$AZURITE_ACCOUNTS" | tr ';' ' '))
else
# No accounts file, start with an empty array
STORAGE_ACCOUNTS=()
fi
STORAGE_ACCOUNTS+=("$1:$PASSWORD")
printf 'AZURITE_ACCOUNTS="%s"\n' $(IFS=';'; echo "${STORAGE_ACCOUNTS[*]}") > "$AZURITE_ACCOUNTS_FILE"

55
build.sh Normal file → Executable file
View File

@@ -1,8 +1,57 @@
#!/usr/bin/env bash #!/usr/bin/env bash
if command -v dockerd &> /dev/null; then
docker build -t azurite:latest . ARCH=()
VERSION_ARG=()
VERSION=""
REGISTRY=""
AZURITE_IMAGE="${AZURITE_IMAGE:-azurite:latest}"
while [[ $# -gt 0 ]]; do
case "$1" in
--arch|-a)
ARCH+=("--arch" "$2")
shift 2
;;
--version|-v)
VERSION="$2"
VERSION_ARG+=("--build-arg" "VERSION=$VERSION")
shift 2
;;
--latest|-l)
VERSION="latest"
LATEST_TAG=$(git ls-remote --tags --refs --sort='v:refname' https://github.com/Azure/Azurite | tail -n1 | awk -F/ '{ print $3 }')
VERSION_ARG+=("--build-arg" "VERSION=$LATEST_TAG")
shift
;;
--registry|-r)
REGISTRY="$2"
shift 2
;;
*)
echo "Unknown argument: $1" >&2
exit 1
;;
esac
done
if [[ ! -z "$REGISTRY" ]]; then
# Prepend the registry to the image name for tagging.
AZURITE_IMAGE="$REGISTRY/${AZURITE_IMAGE#*/}"
fi
if [[ -z "$VERSION" ]]; then
TAG_ARGS=("--tag" "${AZURITE_IMAGE%:*}:latest")
elif [[ "$VERSION" == "latest" ]]; then
TAG_ARGS=("--tag" "${AZURITE_IMAGE%:*}:${LATEST_TAG#v}" "--tag" "${AZURITE_IMAGE%:*}:latest")
else
TAG_ARGS=("--tag" "${AZURITE_IMAGE%:*}:${VERSION#v}")
fi
echo "Effective command line arguments:" ${ARCH[@]} ${VERSION_ARG[@]} ${TAG_ARGS[@]}
if command -v docker &> /dev/null; then
docker build "${ARCH[@]}" "${VERSION_ARG[@]}" "${TAG_ARGS[@]}" .
elif command -v container &> /dev/null; then elif command -v container &> /dev/null; then
container build -t azurite:latest . container build "${ARCH[@]}" "${VERSION_ARG[@]}" "${TAG_ARGS[@]}" .
else else
echo "Neither supported container runtime found." >&2 echo "Neither supported container runtime found." >&2
exit 1 exit 1

11
compose.yaml Normal file
View File

@@ -0,0 +1,11 @@
services:
azurite:
image: azurite:latest
container_name: azurite
ports:
- "443:443"
env_file:
- $HOME/.azurite/accounts.env
volumes:
- $HOME/.azurite/storage:/storage
restart: unless-stopped

View File

@@ -1,114 +1,33 @@
#!/bin/bash #!/bin/bash
set -e set -euo pipefail
function make_ca() {
# Use the provided directory argument or default to AZURITE_DIR if not provided
local CERT_DIR="${1:-$AZURITE_DIR}"
if [[ ! -d "$CERT_DIR" ]]; then
echo "ERROR: Certificate directory $CERT_DIR does not exist."
return 1
fi
# Generate CA certificate and key if they don't exist
if [[ ! -f "$CERT_DIR/ca_cert.pem" || ! -f "$CERT_DIR/ca_key.pem" ]]; then
echo "Generating CA certificate and key..."
if ! openssl req \
-x509 \
-newkey rsa:4096 \
-keyout "$CERT_DIR/ca_key.pem" \
-out "$CERT_DIR/ca_cert.pem" \
-days 3650 \
-nodes \
-subj "/CN=Azurite CA" \
-text \
-addext "basicConstraints=critical,CA:TRUE,pathlen:0"; then
echo "Error: Failed to generate CA certificate and key." >&2
return 1
fi
fi
}
function make_server_cert() {
local ACCOUNT_NAME="${1:-devstoreaccount1}"
local CERT_DIR="${2:-$AZURITE_DIR}"
if [[ ! -d "$CERT_DIR" ]]; then
echo "ERROR: Certificate directory $CERT_DIR does not exist."
return 1
fi
# Generate server certificate and key if they don't exist
if [[ ! -f "$CERT_DIR/${ACCOUNT_NAME}_cert.pem" || ! -f "$CERT_DIR/${ACCOUNT_NAME}_key.pem" ]]; then
echo "Generating server certificate and key..."
if ! openssl req \
-newkey rsa:4096 \
-keyout "$CERT_DIR/${ACCOUNT_NAME}_key.pem" \
-nodes \
-subj "/CN=${ACCOUNT_NAME}.blob.core.windows.net" \
-addext "basicConstraints=critical,CA:FALSE" \
-addext "keyUsage=digitalSignature,keyEncipherment" \
-addext "extendedKeyUsage=serverAuth,clientAuth" \
-addext "subjectAltName=DNS:${ACCOUNT_NAME}.blob.core.windows.net,DNS:${ACCOUNT_NAME}.queue.core.windows.net,DNS:${ACCOUNT_NAME}.table.core.windows.net,DNS:localhost,IP:127.0.0.1" \
| openssl x509 \
-req \
-CA "$CERT_DIR/ca_cert.pem" \
-CAkey "$CERT_DIR/ca_key.pem" \
-set_serial "0x$(openssl rand -hex 16)" \
-copy_extensions copyall \
-days 365 \
-text \
-out "$CERT_DIR/${ACCOUNT_NAME}_cert.pem"; then
echo "Error: Failed to generate server certificate and key." >&2
exit 1
fi
fi
}
# Setup default storage location, account name and accounts file path.
AZURITE_DIR="/storage"
# Check, if the AZURITE_ACCOUNTS variable is set # Check, if the AZURITE_ACCOUNTS variable is set
if [[ -z "$AZURITE_ACCOUNTS" ]]; then if [[ -z "$AZURITE_ACCOUNTS" ]]; then
# Generate a default account echo "[ERROR] AZURITE_ACCOUNTS variable is not set." >&2
export AZURITE_ACCOUNTS="devstoreaccount1:$(openssl rand -base64 32)" exit 1
fi fi
# Look up the account name from the AZURITE_ACCOUNTS variable, which is in the format "accountName:accountKey1:accountKey2;accountName2:accountKey1:accountKey2" # Look up the account name from the AZURITE_ACCOUNTS variable, which is in the format "accountName:accountKey1:accountKey2;accountName2:accountKey1:accountKey2"
ACCOUNT_NAME=$(echo "$AZURITE_ACCOUNTS" | cut -f 1 -d ';' | cut -f 1 -d ':') ACCOUNT_NAME=$(echo "$AZURITE_ACCOUNTS" | cut -f 1 -d ';' | cut -f 1 -d ':')
# Ensure /etc/hosts contains an entry the Azure endpoint names, # Check, if the certificate for the account exists.
# so Caddy can route requests to the correct service based on the hostname. if [[ ! -f "/storage/${ACCOUNT_NAME}_cert.pem" ]] || [[ ! -f "/storage/${ACCOUNT_NAME}_key.pem" ]]; then
if ! grep -qE "${ACCOUNT_NAME}\.blob\.core\.windows\.net" /etc/hosts || echo "[ERROR] Certificate or key for account ${ACCOUNT_NAME} not found."
! grep -qE "${ACCOUNT_NAME}\.queue\.core\.windows\.net" /etc/hosts || exit 1
! grep -qE "${ACCOUNT_NAME}\.table\.core\.windows\.net" /etc/hosts; then
echo -e "\n127.0.0.1\t${ACCOUNT_NAME}.blob.core.windows.net ${ACCOUNT_NAME}.queue.core.windows.net ${ACCOUNT_NAME}.table.core.windows.net" >> /etc/hosts
fi fi
CADDY=true OAUTH_ARGS=("--oauth" "basic")
AZURITE_SSL="" NO_CADDY=""
CERT_ARGS=()
BLOB_ARGS=()
OAUTH_ARGS=()
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--oauth) --no-oauth)
OAUTH_ARGS=("--oauth" "basic") OAUTH_ARGS=()
# Ensure Caddy is disabled when using OAuth, as Azurite does not support OAuth behind a reverse proxy.
CADDY=""
shift
;;
--ssl)
AZURITE_SSL=true
# Ensure Caddy is disabled when using Azurite's built-in SSL support.
CADDY=""
shift shift
;; ;;
--no-caddy) --no-caddy)
# Disable Caddy on request. NO_CADDY=true
CADDY=""
shift shift
;; ;;
*) *)
@@ -118,38 +37,28 @@ while [[ $# -gt 0 ]]; do
esac esac
done done
# Ensure certificates are generated before starting Azurite or Caddy. if [[ -n "$NO_CADDY" ]]; then
if [[ -n "$AZURITE_SSL" || -n "$CADDY" ]]; then HOST_ARGS=("--blobHost" "0.0.0.0" "--queueHost" "0.0.0.0" "--tableHost" "0.0.0.0")
if ! make_ca "$AZURITE_DIR"; then
echo "Error: Failed to create CA certificate and key." >&2
exit 1
fi
if ! make_server_cert "$ACCOUNT_NAME" "$AZURITE_DIR"; then
echo "Error: Failed to create server certificate and key." >&2
exit 1
fi
fi
if [[ -n "$CADDY" ]]; then
# If using Caddy, it will reverse proxy blob, queue, and table endpoints to different ports on localhost,
# allowing simultaneous access to all services on a single HTTPS port.
# Generate a Caddyfile configuration based on the account name and storage directory.
sed -E "s/__ACCOUNT_NAME__/${ACCOUNT_NAME}/g; s|__AZURITE_DIR__|${AZURITE_DIR}|g" /app/Caddyfile.example > "$AZURITE_DIR/Caddyfile"
echo "Starting Caddy server..."
caddy start --config "$AZURITE_DIR/Caddyfile" # Use start not run, start does not block the shell process.
else else
# If not using Caddy, configure Azurite to listen on all interfaces and use the generated self-signed certificate. # Create /etc/hosts entries for the emulator endpoints, so that they can be accessed via their standard Azure Storage hostnames.
# This mode does not require Caddy, but it will not allow simultaneous access to the table and queue services on the same HTTPS port. ALTNAMES=()
if [[ -n "$AZURITE_SSL" ]]; then for name in blob queue table; do
BLOB_ARGS=("--blobHost" "0.0.0.0" "--blobPort" "443") ALTNAMES+=("${ACCOUNT_NAME}.${name}.core.windows.net")
CERT_ARGS=("--key" "$AZURITE_DIR/${ACCOUNT_NAME}_key.pem" "--cert" "$AZURITE_DIR/${ACCOUNT_NAME}_cert.pem") done
fi echo "127.0.0.1 ${ALTNAMES[@]}" >> /etc/hosts
# Generate a Caddyfile configuration based on the account name and storage directory.
sed -E "s/__ACCOUNT_NAME__/${ACCOUNT_NAME}/g; s|__AZURITE_STORAGE__|/storage|g" /app/Caddyfile.template > "/storage/Caddyfile"
# Start Caddy in the background to handle HTTPS requests and route them to Azurite.
caddy start --config "/storage/Caddyfile" # Use start not run, start does not block the shell process.
HOST_ARGS=("--blobHost" "127.0.0.1" "--queueHost" "127.0.0.1" "--tableHost" "127.0.0.1")
fi fi
PORT_ARGS=("--blobPort" "10000" "--queuePort" "10001" "--tablePort" "10002")
# Start Azurite with the appropriate arguments based on the configuration.
exec node /app/azurite/src/azurite.js \ exec node /app/azurite/src/azurite.js \
--disableTelemetry \ --disableTelemetry \
--location "$AZURITE_DIR" \ --location "/storage" \
"${CERT_ARGS[@]}" \ --key "/storage/${ACCOUNT_NAME}_key.pem" --cert "/storage/${ACCOUNT_NAME}_cert.pem" \
"${BLOB_ARGS[@]}" \ "${HOST_ARGS[@]}" "${PORT_ARGS[@]}" "${OAUTH_ARGS[@]}"
"${OAUTH_ARGS[@]}"

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env bash
AZURITE_DIR="storage"
if [[ ! -d "$AZURITE_DIR" ]]; then
echo "No accounts found"
exit 0
fi
AZURITE_ACCOUNTS_FILE="$AZURITE_DIR/accounts.env"
. $AZURITE_ACCOUNTS_FILE
while IFS=';' read -ra ACCOUNTS; do
for ACCOUNT in "${ACCOUNTS[@]}"; do
IFS=':' read -ra KV <<< "$ACCOUNT"
echo "Account: ${KV[0]}"
echo "Password: $(echo -n "${KV[1]}")"
echo
done
done <<< "$AZURITE_ACCOUNTS"

49
make-cert.sh Executable file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/env bash
#
# This script creates a self-signed CA and a server certificate for the Azurite Emulator.
#
# For more sophisticated certificate management, consider using Simple CA project
# from: https://gitea.koszewscy.waw.pl/slawek/simple-ca.git
CA_DIR="${CA_DIR:-./storage}"
CA_NAME="${CA_NAME:-Azurite Emulator CA}"
STORAGE_ACCOUNT_NAME="${STORAGE_ACCOUNT_NAME:-azuritelocal}"
mkdir -p "$CA_DIR"
if [[ ! -f "${CA_DIR}/ca_cert.pem" || ! -f "${CA_DIR}/ca_key.pem" ]]; then
openssl req \
-x509 -noenc -text \
-newkey rsa:4096 \
-keyout "${CA_DIR}/ca_key.pem" \
-out "${CA_DIR}/ca_cert.pem" \
-days 3650 \
-subj "/CN=$CA_NAME" \
-addext "basicConstraints=critical,CA:TRUE,pathlen:0"
HASH=$(openssl x509 -in "${CA_DIR}/ca_cert.pem" -noout -hash 2>/dev/null)
ln -sf ca_cert.pem "${CA_DIR}/$HASH.0"
fi
ALTNAMES=()
for endpoint in blob queue table; do
ALTNAMES+=("DNS:${STORAGE_ACCOUNT_NAME}.${endpoint}.core.windows.net")
done
openssl req \
-newkey rsa:4096 \
-noenc \
-keyout "${CA_DIR}/${STORAGE_ACCOUNT_NAME}_key.pem" \
-subj "/CN=${STORAGE_ACCOUNT_NAME}.blob.core.windows.net" \
-addext "basicConstraints=critical,CA:FALSE" \
-addext "keyUsage=digitalSignature, keyEncipherment" \
-addext "extendedKeyUsage=serverAuth" \
-addext "subjectAltName=$(IFS=, ; echo "${ALTNAMES[*]}")" \
| openssl x509 \
-req -text \
-CA "${CA_DIR}/ca_cert.pem" \
-CAkey "${CA_DIR}/ca_key.pem" \
-copy_extensions copyall \
-days 365 \
-out "${CA_DIR}/${STORAGE_ACCOUNT_NAME}_cert.pem"
openssl verify -CApath "${CA_DIR}" "${CA_DIR}/${STORAGE_ACCOUNT_NAME}_cert.pem"
cat <<EOF
Add the following line to your /etc/hosts file to resolve the emulator endpoints:
127.0.0.1 $(IFS=' '; echo "${ALTNAMES[@]#DNS:}")
EOF

View File

@@ -1,51 +0,0 @@
#!/usr/bin/env bash
CERT_DIR="./storage"
mkdir -p "$CERT_DIR"
ACCOUNT_NAME="${1:-devstoreaccount1}"
# Generate CA certificate and key if they don't exist
if [[ ! -f "$CERT_DIR/ca_cert.pem" || ! -f "$CERT_DIR/ca_key.pem" ]]; then
echo "Generating CA certificate and key..."
if ! openssl req \
-x509 \
-newkey rsa:4096 \
-keyout "$CERT_DIR/ca_key.pem" \
-out "$CERT_DIR/ca_cert.pem" \
-days 3650 \
-nodes \
-subj "/CN=Azurite CA" \
-text \
-addext "basicConstraints=critical,CA:TRUE,pathlen:0"; then
echo "Error: Failed to generate CA certificate and key." >&2
exit 1
fi
fi
# Generate server certificate and key if they don't exist
if [[ ! -f "$CERT_DIR/server_cert.pem" || ! -f "$CERT_DIR/server_key.pem" ]]; then
echo "Generating server certificate and key..."
if ! openssl req \
-newkey rsa:4096 \
-keyout "$CERT_DIR/server_key.pem" \
-nodes \
-subj "/CN=${ACCOUNT_NAME}.blob.core.windows.net" \
-addext "basicConstraints=critical,CA:FALSE" \
-addext "keyUsage=digitalSignature,keyEncipherment" \
-addext "extendedKeyUsage=serverAuth,clientAuth" \
-addext "subjectAltName=DNS:${ACCOUNT_NAME}.blob.core.windows.net,DNS:${ACCOUNT_NAME}.queue.core.windows.net,DNS:${ACCOUNT_NAME}.table.core.windows.net,DNS:localhost,IP:127.0.0.1" \
| openssl x509 \
-req \
-CA "$CERT_DIR/ca_cert.pem" \
-CAkey "$CERT_DIR/ca_key.pem" \
-set_serial "0x$(openssl rand -hex 16)" \
-copy_extensions copyall \
-days 365 \
-text \
-out "$CERT_DIR/server_cert.pem"; then
echo "Error: Failed to generate server certificate and key." >&2
exit 1
fi
fi

View File

@@ -1,34 +1,53 @@
#!/usr/bin/env bash #!/usr/bin/env bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
AZURITE_DIR="$SCRIPT_DIR/storage" AZURITE_DIR="${AZURITE_DIR:-$SCRIPT_DIR}"
if [[ ! -d "$AZURITE_DIR" ]]; then if ! mkdir -p "$AZURITE_DIR/storage"; then
echo "No accounts found" echo "ERROR: Failed to create storage directory at $AZURITE_DIR/storage. Please ensure the path is correct and writable."
exit 0
fi
if ! command -v azurite &> /dev/null; then
echo "Azurite is not installed. Please install it with 'npm install -g azurite'"
exit 1 exit 1
fi fi
if command -v caddy &> /dev/null; then if [[ -z "$AZURITE_ACCOUNTS" && -f "$AZURITE_DIR/accounts.env" ]]; then
CADDY=true set -a
else source "$AZURITE_DIR/accounts.env"
CADDY="" set +a
fi fi
OAUTH_ARGS=() if [[ -z "$AZURITE_ACCOUNTS" ]]; then
echo "[ERROR] AZURITE_ACCOUNTS variable is not set." >&2
exit 1
fi
# Look up the account name from the AZURITE_ACCOUNTS variable, which is in the format "accountName:accountKey1:accountKey2;accountName2:accountKey1:accountKey2"
ACCOUNT_NAME=$(echo "$AZURITE_ACCOUNTS" | cut -f 1 -d ';' | cut -f 1 -d ':')
# Ensure /etc/hosts contains an entry the Azure endpoint names,
# so Caddy can route requests to the correct service based on the hostname.
ALTNAMES=()
for name in blob queue table; do
if ! grep -qE "${ACCOUNT_NAME}.${name}.core.windows.net" /etc/hosts; then
echo "ERROR: /etc/hosts does not contain an entry for ${ACCOUNT_NAME}.${name}.core.windows.net mapping to 127.0.0.1."
exit 1
fi
done
if ! command -v azurite &> /dev/null; then
echo "ERROR: Azurite is not installed. Please install it with 'npm install -g azurite'"
exit 1
fi
if ! command -v caddy &> /dev/null; then
echo "ERROR: Caddy is not installed. Please install it from https://caddyserver.com/docs/install or with 'brew install caddy' on macOS."
exit 1
fi
OAUTH_ARGS=("--oauth" "basic")
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--oauth) --no-oauth)
OAUTH_ARGS=("--oauth" "basic") OAUTH_ARGS=()
shift
;;
--no-caddy)
CADDY=""
shift shift
;; ;;
*) *)
@@ -38,30 +57,26 @@ while [[ $# -gt 0 ]]; do
esac esac
done done
AZURITE_ACCOUNTS_FILE="$AZURITE_DIR/accounts.env" if [[ ! -f "$AZURITE_DIR/storage/ca_cert.pem" ||
set -a ! -f "$AZURITE_DIR/storage/ca_key.pem" ||
. $AZURITE_ACCOUNTS_FILE ! -f "$AZURITE_DIR/storage/${ACCOUNT_NAME}_cert.pem" ||
set +a ! -f "$AZURITE_DIR/storage/${ACCOUNT_NAME}_key.pem" ]]; then
echo "ERROR: SSL certificate or key files not found in $AZURITE_DIR/storage. Please run 'make-cert.sh' to create the necessary certificates and keys."
if [[ -n "$CADDY" ]]; then exit 1
# If using Caddy, it will reverse proxy blob, queue, and table endpoints to different ports on localhost,
# allowing simultaneous access to all services on a single HTTPS port.
echo "Starting Caddy server..."
caddy start --config Caddyfile # Use start not run, start does not block the shell process.
trap "echo 'Stopping Caddy server...'; caddy stop" EXIT INT TERM HUP KILL STOP
CERT_ARGS=()
BLOB_ARGS=()
OAUTH_ARGS=() # Ensure OAuth is disabled when using Caddy, as Azurite does not support OAuth in reverse proxy mode.
else
# If not using Caddy, configure Azurite to listen on all interfaces and use the generated self-signed certificate.
# This mode does not require Caddy, but it will not allow simultaneous access to the table and queue services on the same HTTPS port.
BLOB_ARGS=("--blobHost" "0.0.0.0" "--blobPort" "443")
CERT_ARGS=("--key" "$AZURITE_DIR/server_key.pem" "--cert" "$AZURITE_DIR/server_cert.pem")
fi fi
# Generate a Caddyfile configuration based on the account name and storage directory.
sed -E "s|__ACCOUNT_NAME__|${ACCOUNT_NAME}|g; s|__AZURITE_STORAGE__|${AZURITE_DIR}/storage|g" "$SCRIPT_DIR/Caddyfile.template" > "$AZURITE_DIR/Caddyfile"
echo "Starting Caddy server..."
caddy start --config "$AZURITE_DIR/Caddyfile" # Use start not run, start does not block the shell process.
trap "echo 'Stopping Caddy server...'; caddy stop" EXIT INT TERM HUP KILL STOP
# Start Azurite
echo "Starting Azurite..."
azurite \ azurite \
--disableTelemetry \ --disableTelemetry \
--location "$AZURITE_DIR" \ --location "$AZURITE_DIR/storage" \
"${CERT_ARGS[@]}" \ --blobHost 127.0.0.1 --queueHost 127.0.0.1 --tableHost 127.0.0.1 \
"${BLOB_ARGS[@]}" \ --key "$AZURITE_DIR/storage/${ACCOUNT_NAME}_key.pem" --cert "$AZURITE_DIR/storage/${ACCOUNT_NAME}_cert.pem" \
"${OAUTH_ARGS[@]}" "${OAUTH_ARGS[@]}"

9
run.sh
View File

@@ -1,9 +0,0 @@
#!/usr/bin/env bash
if command -v dockerd &> /dev/null; then
docker run --rm -it --env-file accounts.env -p 443:443 -v ./storage:/storage azurite:latest
elif command -v container &> /dev/null; then
container run --rm -it --env-file accounts.env -p 443:443 --mount type=bind,source=./storage,target=/storage azurite:latest
else
echo "Neither supported container runtime found." >&2
exit 1
fi

81
start-azurite Executable file
View File

@@ -0,0 +1,81 @@
#!/usr/bin/env bash
set -euo pipefail
AZURITE_DIR="${AZURITE_DIR:-}"
CONTAINER_ARGS=()
AZURITE_IMAGE="${AZURITE_IMAGE:-azurite:latest}"
while [[ $# -gt 0 ]]; do
case "$1" in
--no-oauth|--no-caddy)
# Pass these flags to the container, so that it can configure Azurite accordingly.
CONTAINER_ARGS+=("$1")
shift
;;
-d|--azurite-dir)
if [[ -n "$2" && -d "$2" ]]; then
AZURITE_DIR="$2"
shift 2
else
echo "Error: Selected directory does not exist." >&2
exit 1
fi
;;
*)
echo "Error: Unknown argument: $1" >&2
exit 1
;;
esac
done
# Check, if the AZURITE_DIR variable is set and is a valid directory
if [[ -z "$AZURITE_DIR" || ! -d "$AZURITE_DIR" ]]; then
echo "Error: AZURITE_DIR is not set or is not a valid directory." >&2
exit 1
fi
# Check, if the accounts.env file exists in the AZURITE_DIR directory
if [[ ! -f "$AZURITE_DIR/accounts.env" ]]; then
echo "Error: accounts.env file not found in AZURITE_DIR directory." >&2
exit 1
fi
source "$AZURITE_DIR/accounts.env"
if [[ -z "$AZURITE_ACCOUNTS" ]]; then
echo "Error: AZURITE_ACCOUNTS variable is not set in accounts.env file." >&2
exit 1
fi
ACCOUNT_NAME=$(echo "$AZURITE_ACCOUNTS" | cut -f 1 -d ';' | cut -f 1 -d ':')
# Check, if the certificate for the account exists.
if [[ ! -f "$AZURITE_DIR/storage/${ACCOUNT_NAME}_cert.pem" ]] || [[ ! -f "$AZURITE_DIR/storage/${ACCOUNT_NAME}_key.pem" ]]; then
echo "Error: Certificate or key for account ${ACCOUNT_NAME} not found in AZURITE_DIR directory." >&2
exit 1
fi
if command -v docker &> /dev/null; then
docker run \
--rm \
-d \
--name azurite \
--env-file "$AZURITE_DIR/accounts.env" \
-p 443:443 \
-v "$AZURITE_DIR/storage":/storage \
"$AZURITE_IMAGE" "${CONTAINER_ARGS[@]}"
elif command -v container &> /dev/null; then
container run \
-c 2 \
-m 512M \
--rm \
-d \
--name azurite \
--env-file "$AZURITE_DIR/accounts.env" \
-p 443:443 \
--mount type=bind,source="$AZURITE_DIR/storage",target=/storage \
"$AZURITE_IMAGE" "${CONTAINER_ARGS[@]}"
else
echo "Neither supported container runtime found." >&2
exit 1
fi

3
test/backend.config Normal file
View File

@@ -0,0 +1,3 @@
storage_account_name = "terraform"
container_name = "tfstate"
key = "test.tfstate"

38
test/init.sh Executable file
View File

@@ -0,0 +1,38 @@
#!/usr/bin/env bash
AZURITE_DIR="$HOME/.azurite"
if [[ ! -d "$AZURITE_DIR" ]]; then
echo "Error: Azurite data directory not found at $AZURITE_DIR" >&2
exit 1
fi
if [[ ! -f "$AZURITE_DIR/accounts.env" ]]; then
echo "Error: accounts.env file not found at $AZURITE_DIR/accounts.env" >&2
exit 1
fi
ACCESS_KEY=""
while [[ $# -gt 0 ]]; do
case "$1" in
--key|-k)
if [[ ! -f "$AZURITE_DIR/accounts.env" ]]; then
echo "Error: accounts.env file not found at $AZURITE_DIR/accounts.env" >&2
exit 1
fi
# Load the accounts.env file to get the ACCESS_KEY variable.
source "$AZURITE_DIR/accounts.env"
ACCESS_KEY=$(echo "$AZURITE_ACCOUNTS" | cut -f 1 -d ';' | cut -f 2 -d ':')
;;
*)
echo "Unknown argument: $1"
exit 1
;;
esac
shift
done
if [[ -z "$ACCESS_KEY" ]]; then
terraform init -backend-config="backend.config" -backend-config="use_azuread_auth=true" -reconfigure
else
terraform init -backend-config="backend.config" -backend-config="access_key=$ACCESS_KEY" -reconfigure
fi

35
test/main.tf Normal file
View File

@@ -0,0 +1,35 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
}
random = {
source = "hashicorp/random"
}
}
backend "azurerm" {}
}
provider "azurerm" {
features {}
}
resource "random_password" "user1" {
length = 12
min_lower = 1
min_upper = 1
min_numeric = 1
min_special = 1
special = true
override_special = "!@#$"
}
resource "terraform_data" "password" {
input = random_password.user1.result
}
output "user1" {
value = terraform_data.password.output
}