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
19 changes: 13 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ RUN echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes \
&& rm -rf /var/lib/apt/lists/*

# Install sudo...
# SECURITY NOTE: NOPASSWD:ALL is configured for CI/CD automation purposes.
# This allows the agent user to execute commands with sudo without password prompts.
# This is a security trade-off for CI/CD runner functionality.
RUN test "${ADD_SUDO}" = "1" || exit 0 && \
apt-get update && apt-get install -y --no-install-recommends sudo \
&& apt clean \
Expand Down Expand Up @@ -106,7 +109,9 @@ RUN test "${ADD_JQ}" = "1" || exit 0 && \

# Install latest Azure CLI https://learn.microsoft.com/cli/azure/install-azure-cli-linux
RUN test "${ADD_AZURE_CLI}" = "1" || exit 0 && \
curl -sLS "https://aka.ms/InstallAzureCLIDeb" | bash \
curl -sLS "https://aka.ms/InstallAzureCLIDeb" -o /tmp/install-azure-cli.sh \
&& bash /tmp/install-azure-cli.sh \
&& rm /tmp/install-azure-cli.sh \
Comment on lines +112 to +114

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The change from piping curl output directly to bash to first downloading the script and then executing it is a critical security improvement. This prevents potential command injection if the remote script's content were to be compromised or unexpectedly altered, as it allows for inspection before execution. This aligns with secure shell scripting practices.

    curl -sLS "https://aka.ms/InstallAzureCLIDeb" -o /tmp/install-azure-cli.sh \
    && bash /tmp/install-azure-cli.sh \
    && rm /tmp/install-azure-cli.sh

&& apt clean \
&& rm -rf /var/lib/apt/lists/* \
&& az config set extension.use_dynamic_install=yes_without_prompt \
Expand Down Expand Up @@ -175,11 +180,12 @@ RUN test "${ADD_OPENTOFU}" = "1" || exit 0 && \

# Instal Terraspace https://terraspace.cloud/docs/install/
RUN test "${ADD_TERRASPACE}" = "1" || exit 0 && \
curl -sL https://apt.boltops.com/boltops-key.public | apt-key add - \
&& echo "deb https://apt.boltops.com stable main" > /etc/apt/sources.list.d/boltops.list \
curl -sL https://apt.boltops.com/boltops-key.public | gpg --dearmor -o /usr/share/keyrings/boltops-archive-keyring.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/boltops-archive-keyring.gpg] https://apt.boltops.com stable main" > /etc/apt/sources.list.d/boltops.list \
&& apt-get update \
&& apt-get install -y terraspace \
&& apt clean
&& apt clean \
&& rm -rf /var/lib/apt/lists/*

# Install HELM https://helm.sh/docs/intro/install/
RUN test "${ADD_HELM}" = "1" || exit 0 && \
Expand All @@ -192,9 +198,10 @@ RUN test "${ADD_HELM}" = "1" || exit 0 && \

# Install Kustomize https://kubectl.docs.kubernetes.io/installation/kustomize/
RUN test "${ADD_KUSTOMIZE}" = "1" || exit 0 && \
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash \
curl -sLf "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -o /tmp/install_kustomize.sh \
&& bash /tmp/install_kustomize.sh \
&& install -o root -g root -m 0755 kustomize /usr/local/bin/kustomize \
&& rm -f kustomize
&& rm -f kustomize /tmp/install_kustomize.sh

# Install GitHub Runner
WORKDIR /runner
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ Supported `--build-arg` variables are listed below to easily configure the runne
- `ADD_TERRASPACE`: Installs `terraspace` tool
- `ADD_SUDO`: Installs and enables `sudo` for the runner user group


## Available Profiles

Pre-configured profiles are available for different use cases:

| Profile | Description | Included Tools |
|---------|-------------|----------------|
| **full** | Complete toolset with all available tools | Docker, Azure CLI, AWS CLI, PowerShell (with Azure & AWS modules), kubectl, kubelogin, kustomize, Helm, jq, yq, Terraform, OpenTofu, Terraspace |
| **minimal** | Lightweight profile with essential tools only | Docker, jq, yq |
| **k8s** | Kubernetes-focused profile | Docker, kubectl, kubelogin, kustomize, Helm, jq, yq |
| **iac** | Infrastructure as Code profile with bash-based tools | Docker, Azure CLI, AWS CLI, Terraform, OpenTofu, Terraspace, jq, yq |
| **iac-pwsh** | Infrastructure as Code profile with PowerShell support | Docker, Azure CLI, AWS CLI, PowerShell (with Azure & AWS modules), Terraform, OpenTofu, Terraspace, jq, yq |


# References


Expand Down
2 changes: 1 addition & 1 deletion ec2_monitor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ echo "Checking for EC2 spot instance termination notice..."

# Query EC2 Instance Metadata Service for spot termination notice
# Returns HTTP 404 if no termination notice is present
RESPONSE=$(curl -s -f "$METADATA_ENDPOINT" 2>/dev/null || echo "")
RESPONSE=$(curl -sf "$METADATA_ENDPOINT" 2>/dev/null || echo "")

# Check if termination notice exists
if [ -n "$RESPONSE" ]; then
Expand Down
6 changes: 5 additions & 1 deletion run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ echo "CPUs per runner: $MAX_CPU"
echo ""

# Launch runners
for R in $(seq 1 $RUNNER_COUNT); do
for R in $(seq 1 "$RUNNER_COUNT"); do
RUNNER_NAME="runner-$(hostname)-$R"
WORK_DIR="/mnt/runner${R}/_work"
CONTAINER_NAME="github-runner-$R"
Expand All @@ -92,6 +92,10 @@ for R in $(seq 1 $RUNNER_COUNT); do
fi

# Run GitHub runner container
# SECURITY NOTE: --privileged mode grants extended privileges to the container.
# This is required for Docker-in-Docker but poses security risks.
# Consider using rootless Docker or Docker socket mounting as alternatives.
# If --privileged is not needed for your use case, remove this flag.
docker run \
--privileged \
--tty \
Expand Down
6 changes: 3 additions & 3 deletions start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ if [ -z "$GITHUB_TOKEN_FILE" ]; then
fi

GITHUB_TOKEN_FILE=/runner/.token
echo -n $GITHUB_TOKEN > "$GITHUB_TOKEN_FILE"
echo -n "$GITHUB_TOKEN" > "$GITHUB_TOKEN_FILE"
fi

unset GITHUB_TOKEN
Expand All @@ -31,7 +31,7 @@ cleanup() {
# If the agent has some running jobs, the configuration removal process will fail.
# So, give it some time to finish the job.
while true; do
./config.sh remove --token $(cat "$GITHUB_TOKEN_FILE") && break
./config.sh remove --token "$(cat "$GITHUB_TOKEN_FILE")" && break

echo "Retrying in 30 seconds..."
sleep 30
Expand All @@ -53,7 +53,7 @@ print_header "1. Configuring GitHub Runner..."
./config.sh --unattended \
--name "${RUNNER_NAME:-$(hostname)}" \
--url "$GITHUB_URL" \
--token $(cat "$GITHUB_TOKEN_FILE") \
--token "$(cat "$GITHUB_TOKEN_FILE")" \
--labels "${RUNNER_LABELS:-default}" \
--work "${RUNNER_WORK_DIRECTORY:-_work}" \
--replace
Expand Down
9 changes: 6 additions & 3 deletions vmss_monitor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ STOP_SCRIPT='/opt/stop.sh'
echo "Checking for VMSS scheduled events..."

# Query Azure Instance Metadata Service for scheduled events
curl -s "$METADATA_ENDPOINT" -H 'Metadata: true' > "$EVENTS_FILE"
curl -sf "$METADATA_ENDPOINT" -H 'Metadata: true' > "$EVENTS_FILE"

# Check if termination event is scheduled
if grep -q "Terminate" "$EVENTS_FILE"; then
Expand All @@ -30,9 +30,12 @@ if grep -q "Terminate" "$EVENTS_FILE"; then
EventId=$(jq -r '.Events[] | select(.EventType == "Terminate") | .EventId' "$EVENTS_FILE")
if [ -n "$EventId" ]; then
echo "Acknowledging event: $EventId"
curl -s -X POST "$METADATA_ENDPOINT" \
# Use jq to safely construct JSON payload to handle special characters
JSON_PAYLOAD=$(jq -n --arg eventId "$EventId" '{"StartRequests": [{"EventId": $eventId}]}')
curl -sf -X POST "$METADATA_ENDPOINT" \
-H 'Metadata: true' \
-d "{\"StartRequests\": [{\"EventId\": \"${EventId}\"}]}"
-H 'Content-Type: application/json' \
-d "$JSON_PAYLOAD"
echo "Event acknowledged successfully"
fi
else
Expand Down