From 0888b8bd6dcc90928a7588cc772b8b5bcb383dd8 Mon Sep 17 00:00:00 2001 From: Jarvis Date: Tue, 21 Apr 2026 20:15:20 -0500 Subject: [PATCH] feat(mosaic-portainer): add PORTAINER_INSECURE flag for self-signed TLS Self-signed Portainer instances (e.g. internal LAN at 10.1.1.43:9443) caused all wrapper calls to fail silently with HTTP 000. Setting PORTAINER_INSECURE=1 passes -k to curl, bypassing certificate verification and unblocking API calls to such instances. Co-Authored-By: Claude Sonnet 4.6 --- packages/mosaic/framework/tools/portainer/README.md | 8 ++++++++ .../framework/tools/portainer/endpoint-list.sh | 8 +++++++- .../mosaic/framework/tools/portainer/stack-list.sh | 8 +++++++- .../mosaic/framework/tools/portainer/stack-logs.sh | 12 +++++++++--- .../framework/tools/portainer/stack-redeploy.sh | 8 +++++++- .../mosaic/framework/tools/portainer/stack-start.sh | 8 +++++++- .../mosaic/framework/tools/portainer/stack-status.sh | 8 +++++++- .../mosaic/framework/tools/portainer/stack-stop.sh | 8 +++++++- 8 files changed, 59 insertions(+), 9 deletions(-) diff --git a/packages/mosaic/framework/tools/portainer/README.md b/packages/mosaic/framework/tools/portainer/README.md index 58a8bd7..d1cd796 100644 --- a/packages/mosaic/framework/tools/portainer/README.md +++ b/packages/mosaic/framework/tools/portainer/README.md @@ -13,6 +13,14 @@ export PORTAINER_URL="https://portainer.example.com:9443" export PORTAINER_API_KEY="your-api-key-here" ``` +If your Portainer instance uses a self-signed TLS certificate (e.g. internal LAN), set: + +```bash +export PORTAINER_INSECURE=1 +``` + +This passes `-k` to all curl calls, bypassing certificate verification. Do not set this against public/production instances. + You can add these to your shell profile (`~/.bashrc`, `~/.zshrc`) or use a `.env` file. ### Creating an API Key diff --git a/packages/mosaic/framework/tools/portainer/endpoint-list.sh b/packages/mosaic/framework/tools/portainer/endpoint-list.sh index 4ff6505..b294e5d 100755 --- a/packages/mosaic/framework/tools/portainer/endpoint-list.sh +++ b/packages/mosaic/framework/tools/portainer/endpoint-list.sh @@ -46,8 +46,14 @@ fi # Remove trailing slash from URL PORTAINER_URL="${PORTAINER_URL%/}" +# TLS options +CURL_OPTS=() +if [ "${PORTAINER_INSECURE:-0}" = "1" ]; then + CURL_OPTS+=(-k) +fi + # Fetch endpoints -response=$(curl -s -w "\n%{http_code}" \ +response=$(curl -s "${CURL_OPTS[@]}" -w "\n%{http_code}" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \ "${PORTAINER_URL}/api/endpoints") diff --git a/packages/mosaic/framework/tools/portainer/stack-list.sh b/packages/mosaic/framework/tools/portainer/stack-list.sh index 45acc96..43f3f54 100755 --- a/packages/mosaic/framework/tools/portainer/stack-list.sh +++ b/packages/mosaic/framework/tools/portainer/stack-list.sh @@ -52,8 +52,14 @@ fi # Remove trailing slash from URL PORTAINER_URL="${PORTAINER_URL%/}" +# TLS options +CURL_OPTS=() +if [ "${PORTAINER_INSECURE:-0}" = "1" ]; then + CURL_OPTS+=(-k) +fi + # Fetch stacks -response=$(curl -s -w "\n%{http_code}" \ +response=$(curl -s "${CURL_OPTS[@]}" -w "\n%{http_code}" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \ "${PORTAINER_URL}/api/stacks") diff --git a/packages/mosaic/framework/tools/portainer/stack-logs.sh b/packages/mosaic/framework/tools/portainer/stack-logs.sh index d0c24db..07ecf60 100755 --- a/packages/mosaic/framework/tools/portainer/stack-logs.sh +++ b/packages/mosaic/framework/tools/portainer/stack-logs.sh @@ -64,12 +64,18 @@ fi # Remove trailing slash from URL PORTAINER_URL="${PORTAINER_URL%/}" +# TLS options +CURL_OPTS=() +if [ "${PORTAINER_INSECURE:-0}" = "1" ]; then + CURL_OPTS+=(-k) +fi + # Function to make API requests api_request() { local method="$1" local endpoint="$2" - curl -s -w "\n%{http_code}" -X "$method" \ + curl -s "${CURL_OPTS[@]}" -w "\n%{http_code}" -X "$method" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \ "${PORTAINER_URL}${endpoint}" } @@ -165,7 +171,7 @@ fi # Note: Docker API returns raw log stream, not JSON if [[ "$FOLLOW" == "true" ]]; then # Stream logs - curl -s -N \ + curl -s "${CURL_OPTS[@]}" -N \ -H "X-API-Key: ${PORTAINER_API_KEY}" \ "${PORTAINER_URL}/api/endpoints/${ENDPOINT_ID}/docker/containers/${CONTAINER_ID}/logs?${params}" | \ # Docker log format has 8-byte header per line, strip it @@ -175,7 +181,7 @@ if [[ "$FOLLOW" == "true" ]]; then done else # Get logs (non-streaming) - curl -s \ + curl -s "${CURL_OPTS[@]}" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \ "${PORTAINER_URL}/api/endpoints/${ENDPOINT_ID}/docker/containers/${CONTAINER_ID}/logs?${params}" | \ # Docker log format has 8-byte header per line, attempt to strip it diff --git a/packages/mosaic/framework/tools/portainer/stack-redeploy.sh b/packages/mosaic/framework/tools/portainer/stack-redeploy.sh index 8be4aab..fd6bd03 100755 --- a/packages/mosaic/framework/tools/portainer/stack-redeploy.sh +++ b/packages/mosaic/framework/tools/portainer/stack-redeploy.sh @@ -63,13 +63,19 @@ fi # Remove trailing slash from URL PORTAINER_URL="${PORTAINER_URL%/}" +# TLS options +CURL_OPTS=() +if [ "${PORTAINER_INSECURE:-0}" = "1" ]; then + CURL_OPTS+=(-k) +fi + # Function to make API requests api_request() { local method="$1" local endpoint="$2" local data="${3:-}" - local args=(-s -w "\n%{http_code}" -X "$method" -H "X-API-Key: ${PORTAINER_API_KEY}") + local args=(-s "${CURL_OPTS[@]}" -w "\n%{http_code}" -X "$method" -H "X-API-Key: ${PORTAINER_API_KEY}") if [[ -n "$data" ]]; then args+=(-H "Content-Type: application/json" -d "$data") diff --git a/packages/mosaic/framework/tools/portainer/stack-start.sh b/packages/mosaic/framework/tools/portainer/stack-start.sh index b90939d..33f94f6 100755 --- a/packages/mosaic/framework/tools/portainer/stack-start.sh +++ b/packages/mosaic/framework/tools/portainer/stack-start.sh @@ -54,12 +54,18 @@ fi # Remove trailing slash from URL PORTAINER_URL="${PORTAINER_URL%/}" +# TLS options +CURL_OPTS=() +if [ "${PORTAINER_INSECURE:-0}" = "1" ]; then + CURL_OPTS+=(-k) +fi + # Function to make API requests api_request() { local method="$1" local endpoint="$2" - curl -s -w "\n%{http_code}" -X "$method" \ + curl -s "${CURL_OPTS[@]}" -w "\n%{http_code}" -X "$method" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \ "${PORTAINER_URL}${endpoint}" } diff --git a/packages/mosaic/framework/tools/portainer/stack-status.sh b/packages/mosaic/framework/tools/portainer/stack-status.sh index d607184..1fda6a3 100755 --- a/packages/mosaic/framework/tools/portainer/stack-status.sh +++ b/packages/mosaic/framework/tools/portainer/stack-status.sh @@ -57,12 +57,18 @@ fi # Remove trailing slash from URL PORTAINER_URL="${PORTAINER_URL%/}" +# TLS options +CURL_OPTS=() +if [ "${PORTAINER_INSECURE:-0}" = "1" ]; then + CURL_OPTS+=(-k) +fi + # Function to make API requests api_request() { local method="$1" local endpoint="$2" - curl -s -w "\n%{http_code}" -X "$method" \ + curl -s "${CURL_OPTS[@]}" -w "\n%{http_code}" -X "$method" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \ "${PORTAINER_URL}${endpoint}" } diff --git a/packages/mosaic/framework/tools/portainer/stack-stop.sh b/packages/mosaic/framework/tools/portainer/stack-stop.sh index 899b4b3..7640197 100755 --- a/packages/mosaic/framework/tools/portainer/stack-stop.sh +++ b/packages/mosaic/framework/tools/portainer/stack-stop.sh @@ -54,12 +54,18 @@ fi # Remove trailing slash from URL PORTAINER_URL="${PORTAINER_URL%/}" +# TLS options +CURL_OPTS=() +if [ "${PORTAINER_INSECURE:-0}" = "1" ]; then + CURL_OPTS+=(-k) +fi + # Function to make API requests api_request() { local method="$1" local endpoint="$2" - curl -s -w "\n%{http_code}" -X "$method" \ + curl -s "${CURL_OPTS[@]}" -w "\n%{http_code}" -X "$method" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \ "${PORTAINER_URL}${endpoint}" }