-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathavm
More file actions
executable file
·213 lines (187 loc) · 8.01 KB
/
avm
File metadata and controls
executable file
·213 lines (187 loc) · 8.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#!/usr/bin/env bash
set -e
usage () {
echo "Usage: avm <make target>"
}
# We need to do this because bash doesn't like it when a script is updated in place.
if [ -z "${AVM_SCRIPT_FORKED}" ]; then
# If AVM_SCRIPT_FORKED is not set, we are running the script from the original repository
# Set AVM_SCRIPT_FORKED to true to avoid running this block again
export AVM_SCRIPT_FORKED=true
# Make a copy of this script in the current directory
# and run that copy.
cp "$0" .avm
chmod +x .avm
exec ./.avm "$@"
fi
# Default values for environment variables
CONTAINER_RUNTIME=${CONTAINER_RUNTIME:-"docker"}
CONTAINER_IMAGE=${CONTAINER_IMAGE:-"mcr.microsoft.com/azterraform:avm-latest"}
CONTAINER_PULL_POLICY=${CONTAINER_PULL_POLICY:-"always"}
AVM_MAKEFILE_REF=${AVM_MAKEFILE_REF:-"main"}
AVM_PORCH_REF=${AVM_PORCH_REF:-"main"}
if [ ! "$(command -v "${CONTAINER_RUNTIME}")" ] && [ -z "${AVM_IN_CONTAINER}" ]; then
echo "Error: ${CONTAINER_RUNTIME} is not installed. Please install ${CONTAINER_RUNTIME} first."
exit 1
fi
if [ -z "$1" ]; then
echo "Error: Please provide a make target. See https://github.com/Azure/avm-terraform-governance/blob/main/Makefile for available targets."
echo
usage
exit 1
fi
# Check if AZURE_CONFIG_DIR is set, if not, set it to ~/.azure
if [ -z "${AZURE_CONFIG_DIR}" ]; then
AZURE_CONFIG_DIR="${HOME}/.azure"
fi
# Check if AZURE_CONFIG_DIR exists, if it does, mount it to the container
if [ -d "${AZURE_CONFIG_DIR}" ]; then
AZURE_CONFIG_MOUNT="-v ${AZURE_CONFIG_DIR}:/home/runtimeuser/.azure"
fi
# Check if AVM_TMP_DIR is set, if so mount it to /tmp
if [ -z "${AVM_TMP_DIR}" ] && [ -n "${RUNNER_TEMP}" ]; then
AVM_TMP_DIR="${RUNNER_TEMP}"
fi
if [ -n "${AVM_TMP_DIR}" ]; then
TMP_MOUNT="-v ${AVM_TMP_DIR}:/tmp"
fi
# If the host Docker socket exists, mount it into the container so the container can talk to the host docker daemon
if [ -S /var/run/docker.sock ]; then
DOCKER_SOCK_MOUNT="-v /var/run/docker.sock:/var/run/docker.sock"
fi
# SSL certificate handling:
# The script builds a combined CA bundle and mounts it into the container when any of the
# following are detected:
#
# 1. Customer-provided certificates (AVM_SSL_CERT_FILE):
# Set AVM_SSL_CERT_FILE to the path of a PEM-encoded CA certificate or bundle on the host.
# This is intended for private TLS inspection environments where outbound traffic is
# intercepted by a corporate proxy using a custom CA. The file will be appended to the
# system CA bundle and mounted into the container.
#
# 2. GitHub Copilot Coding Agent (automatic detection):
# The coding agent installs a TLS-inspecting firewall that uses mkcert-generated certificates.
# These are trusted on the host via NODE_EXTRA_CA_CERTS / CAROOT, but not inside the Docker
# container. Detected via COPILOT_AGENT_ACTION or CAROOT/NODE_EXTRA_CA_CERTS in GITHUB_ACTIONS.
SSL_CERT_MOUNTS=""
# Detect coding agent environment:
# - COPILOT_AGENT_ACTION is set when running inside GitHub Copilot Coding Agent
# - CAROOT or NODE_EXTRA_CA_CERTS being set alongside GITHUB_ACTIONS indicates mkcert is in use
IN_CODING_AGENT=false
if [ -n "${COPILOT_AGENT_ACTION}" ]; then
IN_CODING_AGENT=true
elif [ -n "${GITHUB_ACTIONS}" ] && ([ -n "${CAROOT}" ] || [ -n "${NODE_EXTRA_CA_CERTS}" ]); then
IN_CODING_AGENT=true
fi
# Build a combined cert bundle if we need to inject any additional CA certificates.
# This happens when customer certs are provided (AVM_SSL_CERT_FILE) or we are in the coding agent.
if [ -n "${AVM_SSL_CERT_FILE}" ] || [ "${IN_CODING_AGENT}" = "true" ]; then
# Validate customer-provided cert file if set
if [ -n "${AVM_SSL_CERT_FILE}" ] && [ ! -f "${AVM_SSL_CERT_FILE}" ]; then
echo "Warning: AVM_SSL_CERT_FILE is set but the file does not exist: ${AVM_SSL_CERT_FILE}"
fi
# Create a temporary directory for the combined cert bundle.
# This directory is cleaned up automatically when the script exits.
AVM_CERT_TMP_DIR=$(mktemp -d)
trap 'rm -rf "${AVM_CERT_TMP_DIR}"' EXIT
AVM_CERT_BUNDLE="${AVM_CERT_TMP_DIR}/ca-bundle.crt"
# Ensure the bundle file exists even if the system CA bundle is missing
touch "${AVM_CERT_BUNDLE}"
# Start with the system CA bundle
if [ -f "/etc/ssl/certs/ca-certificates.crt" ]; then
cat "/etc/ssl/certs/ca-certificates.crt" > "${AVM_CERT_BUNDLE}"
fi
# Append the mkcert root CA if in the coding agent environment (used for TLS inspection firewall).
# NODE_EXTRA_CA_CERTS takes priority over CAROOT/rootCA.pem.
if [ "${IN_CODING_AGENT}" = "true" ]; then
if [ -n "${NODE_EXTRA_CA_CERTS}" ] && [ -f "${NODE_EXTRA_CA_CERTS}" ]; then
echo "" >> "${AVM_CERT_BUNDLE}"
cat "${NODE_EXTRA_CA_CERTS}" >> "${AVM_CERT_BUNDLE}"
elif [ -n "${CAROOT}" ] && [ -f "${CAROOT}/rootCA.pem" ]; then
echo "" >> "${AVM_CERT_BUNDLE}"
cat "${CAROOT}/rootCA.pem" >> "${AVM_CERT_BUNDLE}"
fi
fi
# Append customer-provided CA certificate(s) for private TLS inspection environments.
if [ -n "${AVM_SSL_CERT_FILE}" ] && [ -f "${AVM_SSL_CERT_FILE}" ]; then
echo "" >> "${AVM_CERT_BUNDLE}"
cat "${AVM_SSL_CERT_FILE}" >> "${AVM_CERT_BUNDLE}"
fi
# Mount the combined cert bundle to the container's expected CA certificate paths
SSL_CERT_MOUNTS="-v ${AVM_CERT_BUNDLE}:/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem:ro"
SSL_CERT_MOUNTS="${SSL_CERT_MOUNTS} -v ${AVM_CERT_BUNDLE}:/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt:ro"
SSL_CERT_MOUNTS="${SSL_CERT_MOUNTS} -v ${AVM_CERT_BUNDLE}:/etc/ssl/certs/ca-certificates.crt:ro"
fi
# New: allow overriding TUI behavior with PORCH_FORCE_TUI and PORCH_NO_TUI environment variables.
# - If PORCH_FORCE_TUI is set, force TUI and interactive mode (even in GH Actions).
# - If PORCH_NO_TUI is set, explicitly disable TUI.
# - Otherwise, fallback to previous behavior: enable TUI only when not in GitHub Actions and NO_COLOR is not set.
if [ -n "${PORCH_FORCE_TUI}" ]; then
TUI="--tui"
DOCKER_INTERACTIVE="-it"
export FORCE_COLOR=1
elif [ -n "${PORCH_NO_TUI}" ]; then
# Explicitly disable TUI and interactive flags
TUI=""
DOCKER_INTERACTIVE=""
else
# If we are not in GitHub Actions and NO_COLOR is not set, we want to use TUI and interactive mode
if [ -z "${GITHUB_RUN_ID}" ] && [ -z "${NO_COLOR}" ]; then
TUI="--tui"
DOCKER_INTERACTIVE="-it"
export FORCE_COLOR=1
fi
fi
# if AVM_PORCH_BASE_URL is set, we want to add it to the make command
if [ -n "${AVM_PORCH_BASE_URL}" ]; then
PORCH_BASE_URL_MAKE_ADD="PORCH_BASE_URL=${AVM_PORCH_BASE_URL}"
fi
# Get the repo specific environment variables from avm.config if it exists
LOCAL_ENVIRONMENT_VARIABLES=""
if [ -f "avm.config.json" ]; then
declare -A variables
eval "$(cat "avm.config.json" | jq -r 'to_entries[] | @sh "variables[\(.key|tostring)]=\(.value|tostring)"')"
for key in "${!variables[@]}"; do
export "$key"="${variables[$key]}"
LOCAL_ENVIRONMENT_VARIABLES="${LOCAL_ENVIRONMENT_VARIABLES}-e $key "
echo "Set environment variable: $key"="${variables[$key]}"
done
fi
# Check if we are running in a container
# If we are then just run make directly
if [ -z "${AVM_IN_CONTAINER}" ]; then
${CONTAINER_RUNTIME} run \
--pull "${CONTAINER_PULL_POLICY}" \
--user "$(id -u):$(id -g)" \
--rm \
${DOCKER_INTERACTIVE} \
-v "$(pwd)":/src \
${AZURE_CONFIG_MOUNT:-} \
${DOCKER_SOCK_MOUNT:-} \
${SSL_CERT_MOUNTS:-} \
${TMP_MOUNT:-} \
-e ARM_CLIENT_ID \
-e ARM_OIDC_REQUEST_TOKEN \
-e ARM_OIDC_REQUEST_URL \
-e ARM_SUBSCRIPTION_ID \
-e ARM_TENANT_ID \
-e ARM_USE_OIDC \
-e FORCE_COLOR \
-e GITHUB_TOKEN \
-e NO_COLOR \
-e PORCH_LOG_LEVEL \
-e TF_IN_AUTOMATION=1 \
${LOCAL_ENVIRONMENT_VARIABLES} \
--env-file <(env | grep '^TF_VAR_') \
--env-file <(env | grep '^AVM_') \
"${CONTAINER_IMAGE}" \
make \
TUI="${TUI}" \
AVM_PORCH_STDOUT="${AVM_PORCH_STDOUT}" \
AVM_MAKEFILE_REF="${AVM_MAKEFILE_REF}" \
"${PORCH_BASE_URL_MAKE_ADD}" \
AVM_PORCH_REF="${AVM_PORCH_REF}" \
"$1"
else
make TUI="${TUI}" AVM_MAKEFILE_REF="${AVM_MAKEFILE_REF}" ${PORCH_BASE_URL_MAKE_ADD} AVM_PORCH_REF="${AVM_PORCH_REF}" "$1"
fi