Enhance emulator setup with Caddy support and update documentation
- Added Caddyfile example for HTTPS configuration. - Updated README to include Caddy as an optional component. - Modified make-certs.sh to use dynamic account names for certificate generation. - Improved add-account.sh to handle missing accounts.env file gracefully. - Enhanced run-server.sh to support Caddy integration and OAuth options.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
storage
|
||||
test
|
||||
Caddyfile
|
||||
|
||||
17
Caddyfile.example
Normal file
17
Caddyfile.example
Normal file
@@ -0,0 +1,17 @@
|
||||
# Caddyfile for Azure Storage Emulator
|
||||
# It uses /etc/hosts entries to route requests to the emulator
|
||||
# Replace "devstoreaccount1" with a desired storage account name if needed
|
||||
devstoreaccount1.blob.core.windows.net {
|
||||
tls storage/server_cert.pem storage/server_key.pem
|
||||
reverse_proxy localhost:10000
|
||||
}
|
||||
|
||||
devstoreaccount1.queue.core.windows.net {
|
||||
tls storage/server_cert.pem storage/server_key.pem
|
||||
reverse_proxy localhost:10001
|
||||
}
|
||||
|
||||
devstoreaccount1.table.core.windows.net {
|
||||
tls storage/server_cert.pem storage/server_key.pem
|
||||
reverse_proxy localhost:10002
|
||||
}
|
||||
23
README.md
23
README.md
@@ -8,6 +8,7 @@ This is a simple guide that will help you set up and run the Azure Storage Emula
|
||||
- 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
|
||||
|
||||
@@ -52,10 +53,14 @@ There are two ways to run the Azure Storage Emulator: as a development server ex
|
||||
|
||||
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.
|
||||
|
||||
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 `terraform.blob.core.windows.net`. You can change that. You will also need to map that name to `127.0.0.1` in your hosts file.
|
||||
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
|
||||
./make-certs.sh myaccount
|
||||
```
|
||||
|
||||
```
|
||||
127.0.0.1 terraform.blob.core.windows.net
|
||||
127.0.0.1 devstoreaccount1.blob.core.windows.net devstoreaccount1.queue.core.windows.net devstoreaccount1.table.core.windows.net
|
||||
```
|
||||
|
||||
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:
|
||||
@@ -66,4 +71,16 @@ AZURITE_ACCOUNTS="account1:key1,key2;account2:key1,key2;..."
|
||||
|
||||
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.
|
||||
|
||||
Finally, run the emulator using the `run-emulator.sh` script.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Use `--no-caddy` to disable Caddy even if it is installed. It is required to test Entra ID Authentication simulation.
|
||||
|
||||
## Reference
|
||||
|
||||
- [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)
|
||||
- [Caddy Server](https://caddyserver.com)
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ -z "$1" ]]; then
|
||||
echo "Usage: $0 <account-name> [ password ]"
|
||||
exit 1
|
||||
echo "Usage: $0 <account-name> [ password ]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$2" ]]; then
|
||||
PASSWORD=$(openssl rand -base64 32)
|
||||
PASSWORD=$(openssl rand -base64 32)
|
||||
else
|
||||
PASSWORD=$(echo -n "$2" | base64)
|
||||
PASSWORD=$(echo -n "$2" | base64)
|
||||
fi
|
||||
|
||||
AZURITE_DIR="storage"
|
||||
mkdir -p "$AZURITE_DIR"
|
||||
|
||||
AZURITE_ACCOUNTS_FILE="$AZURITE_DIR/accounts.env"
|
||||
. $AZURITE_ACCOUNTS_FILE
|
||||
|
||||
STORAGE_ACCOUNTS=($(echo "$AZURITE_ACCOUNTS" | tr ';' ' '))
|
||||
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"
|
||||
|
||||
@@ -4,6 +4,8 @@ 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..."
|
||||
@@ -29,11 +31,11 @@ if [[ ! -f "$CERT_DIR/server_cert.pem" || ! -f "$CERT_DIR/server_key.pem" ]]; th
|
||||
-newkey rsa:4096 \
|
||||
-keyout "$CERT_DIR/server_key.pem" \
|
||||
-nodes \
|
||||
-subj "/CN=terraform.blob.core.windows.net" \
|
||||
-subj "/CN=${ACCOUNT_NAME}.blob.core.windows.net" \
|
||||
-addext "basicConstraints=critical,CA:FALSE" \
|
||||
-addext "keyUsage=digitalSignature,keyEncipherment" \
|
||||
-addext "extendedKeyUsage=serverAuth,clientAuth" \
|
||||
-addext "subjectAltName=DNS:terraform.blob.core.windows.net,DNS:localhost,IP:127.0.0.1" \
|
||||
-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" \
|
||||
@@ -47,4 +49,3 @@ if [[ ! -f "$CERT_DIR/server_cert.pem" || ! -f "$CERT_DIR/server_key.pem" ]]; th
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -7,20 +7,60 @@ if [[ ! -d "$AZURITE_DIR" ]]; then
|
||||
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
|
||||
fi
|
||||
|
||||
if command -v caddy &> /dev/null; then
|
||||
CADDY=true
|
||||
else
|
||||
CADDY=""
|
||||
fi
|
||||
|
||||
OAUTH_ARGS=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--oauth)
|
||||
OAUTH_ARGS=("--oauth" "basic")
|
||||
shift
|
||||
;;
|
||||
--no-caddy)
|
||||
CADDY=""
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
AZURITE_ACCOUNTS_FILE="$AZURITE_DIR/accounts.env"
|
||||
set -a
|
||||
. $AZURITE_ACCOUNTS_FILE
|
||||
set +a
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
azurite \
|
||||
--disableTelemetry \
|
||||
--location "$AZURITE_DIR" \
|
||||
--key "$AZURITE_DIR/server_key.pem" \
|
||||
--cert "$AZURITE_DIR/server_cert.pem" \
|
||||
--blobHost 0.0.0.0 \
|
||||
--blobPort 443
|
||||
"${CERT_ARGS[@]}" \
|
||||
"${BLOB_ARGS[@]}" \
|
||||
"${OAUTH_ARGS[@]}"
|
||||
|
||||
Reference in New Issue
Block a user