Skip to content

Commit

Permalink
Merge pull request #65 from gruntwork-io/bug/github-ssh-keys-63
Browse files Browse the repository at this point in the history
Updated Github ssh keys
  • Loading branch information
denis256 authored May 10, 2024
2 parents 0e1d503 + 5108459 commit 751e00d
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 72 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Dockerfile used in execution of Github Action
FROM gruntwork/terragrunt:0.2.0
LABEL maintainer "Gruntwork <info@gruntwork.io>"
LABEL maintainer="Gruntwork <info@gruntwork.io>"

ENV MISE_CONFIG_DIR=~/.config/mise
ENV MISE_STATE_DIR=~/.local/state/mise
Expand Down
19 changes: 8 additions & 11 deletions src/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,13 @@ function setup_git {

function setup_permissions {
local -r dir="${1}"
sudo chown -R $(whoami) /github/workspace
# Set permissions for the working directory
if [[ -f "${dir}" ]]; then
sudo chown -R $(whoami) "${dir}"
sudo chmod -R o+rw "${dir}"
# fetch the user id and group id under which the github action is running
local -r uid=$(stat -c "%u" "/github/workspace")
local -r gid=$(stat -c "%g" "/github/workspace")
if [[ -e "${dir}" ]]; then
sudo chown -R "$uid:$gid" "${dir}"
sudo chmod -R o+rw "${dir}"
fi
# Set permissions for the output file
if [[ -f "${GITHUB_OUTPUT}" ]]; then
sudo chown -R $(whoami) "${GITHUB_OUTPUT}"
fi
# set permissions for .terraform directories, if any
sudo find /github/workspace -name ".terraform*" -exec chmod -R 777 {} \;
}

# Run INPUT_PRE_EXEC_* environment variables as Bash code
Expand Down Expand Up @@ -219,6 +214,8 @@ function main {
fi
run_terragrunt "${tg_dir}" "${tg_arg_and_commands}"
setup_permissions "${tg_dir}"
setup_permissions "${terragrunt_log_file}"
setup_permissions "${GITHUB_OUTPUT}"
# setup permissions for the output files
setup_post_exec

Expand Down
8 changes: 4 additions & 4 deletions terragrunt/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Container to run Terragrunt and Terraform
# Contains inside mise to allow users to install custom Terraform and Terragrunt versions
FROM ubuntu:22.04
LABEL maintainer "Gruntwork <info@gruntwork.io>"
LABEL maintainer="Gruntwork <info@gruntwork.io>"

ARG MISE_VERSION_INSTALL=v2024.4.0

Expand All @@ -16,9 +16,9 @@ RUN apt-get update \
sudo \
&& rm -rf /var/lib/apt/lists/*

RUN mkdir -p /home/runner/.ssh
COPY ./known_hosts /home/runner/.ssh/known_hosts

RUN mkdir -p /root/.ssh
COPY ./known_hosts /root/.ssh/known_hosts
RUN chown -R root:root /root/.ssh
# install mise
RUN wget -q "https://github.com/jdx/mise/releases/download/${MISE_VERSION_INSTALL}/mise-${MISE_VERSION_INSTALL}-linux-x64" -O "/usr/bin/mise" \
&& chmod +x "/usr/bin/mise"
Expand Down
2 changes: 2 additions & 0 deletions terragrunt/known_hosts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.com,bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
10 changes: 7 additions & 3 deletions test/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ import (
"github.com/gruntwork-io/terratest/modules/random"
)

func buildActionImage(t *testing.T) string {
tag := "terragrunt-action:" + random.UniqueId()
func buildImage(t *testing.T, tag, path string) {
buildOptions := &docker.BuildOptions{
Tags: []string{tag},
}
docker.Build(t, "..", buildOptions)
docker.Build(t, path, buildOptions)
}

func buildActionImage(t *testing.T) string {
tag := "terragrunt-action:" + random.UniqueId()
buildImage(t, tag, "..")
return tag
}
143 changes: 90 additions & 53 deletions test/action_run_test.go
Original file line number Diff line number Diff line change
@@ -1,132 +1,169 @@
package test

import (
"fmt"
"os"
"path/filepath"
"testing"

"github.com/gruntwork-io/terratest/modules/random"

"github.com/gruntwork-io/terratest/modules/files"
"github.com/stretchr/testify/require"

"github.com/gruntwork-io/terratest/modules/docker"
"github.com/stretchr/testify/assert"
)

type ActionConfig struct {
iacName string
iacType string
iacVersion string
tgVersion string
}

func TestTerragruntAction(t *testing.T) {
t.Parallel()
tag := buildActionImage(t)
buildImage(t, "ssh-agent:local", "ssh-agent")

testCases := []struct {
iac_name string
iac_type string
iac_version string
tg_version string
}{
testCases := []ActionConfig{
{"Terraform", "TF", "1.4.6", "0.46.3"},
{"OpenTofu", "TOFU", "1.6.0", "0.53.3"},
}

for _, tc := range testCases {
tc := tc

t.Run(tc.iac_name, func(t *testing.T) {
t.Run(tc.iacName, func(t *testing.T) {
t.Parallel()
t.Run("testActionIsExecuted", func(t *testing.T) {
t.Parallel()
testActionIsExecuted(t, tc.iac_type, tc.iac_name, tc.iac_version, tc.tg_version, tag)
testActionIsExecuted(t, tc, tag)
})
t.Run("testActionIsExecutedSSHProject", func(t *testing.T) {
t.Parallel()
testActionIsExecutedSSHProject(t, tc, tag)
})
t.Run("testOutputPlanIsUsedInApply", func(t *testing.T) {
t.Parallel()
testOutputPlanIsUsedInApply(t, tc.iac_type, tc.iac_name, tc.iac_version, tc.tg_version, tag)
testOutputPlanIsUsedInApply(t, tc, tag)
})
t.Run("testRunAllIsExecute", func(t *testing.T) {
t.Parallel()
testRunAllIsExecuted(t, tc.iac_type, tc.iac_name, tc.iac_version, tc.tg_version, tag)
testRunAllIsExecuted(t, tc, tag)
})
t.Run("testAutoApproveDelete", func(t *testing.T) {
t.Parallel()
testAutoApproveDelete(t, tc.iac_type, tc.iac_name, tc.iac_version, tc.tg_version, tag)
testAutoApproveDelete(t, tc, tag)
})
})
}
}

func testActionIsExecuted(t *testing.T, iac_type string, iac_name string, iac_version string, tg_version string, tag string) {
func testActionIsExecuted(t *testing.T, actionConfig ActionConfig, tag string) {
fixturePath := prepareFixture(t, "fixture-action-execution")

outputTF := runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "plan")
assert.Contains(t, outputTF, "You can apply this plan to save these new output values to the "+iac_name)
outputTF := runAction(t, actionConfig, false, tag, fixturePath, "plan")
assert.Contains(t, outputTF, "You can apply this plan to save these new output values to the "+actionConfig.iacName)
}

func testOutputPlanIsUsedInApply(t *testing.T, iac_type string, iac_name string, iac_version string, tg_version string, tag string) {
func testActionIsExecutedSSHProject(t *testing.T, actionConfig ActionConfig, tag string) {
fixturePath := prepareFixture(t, "fixture-action-execution-ssh")

outputTF := runAction(t, actionConfig, true, tag, fixturePath, "plan")
assert.Contains(t, outputTF, "You can apply this plan to save these new output values to the "+actionConfig.iacName)
}

func testOutputPlanIsUsedInApply(t *testing.T, actionConfig ActionConfig, tag string) {
fixturePath := prepareFixture(t, "fixture-dependencies-project")

output := runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all plan -out=plan.out")
assert.Contains(t, output, "1 to add, 0 to change, 0 to destroy")
output := runAction(t, actionConfig, false, tag, fixturePath, "run-all plan -out=plan.out")
assert.Contains(t, output, "1 to add, 0 to change, 0 to destroy", actionConfig.iacName)

output = runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all apply plan.out")
assert.Contains(t, output, "1 added, 0 changed, 0 destroyed")
output = runAction(t, actionConfig, false, tag, fixturePath, "run-all apply plan.out")
assert.Contains(t, output, "1 added, 0 changed, 0 destroyed", actionConfig.iacName)
}

func testRunAllIsExecuted(t *testing.T, iac_type string, iac_name string, iac_version string, tg_version string, tag string) {
func testRunAllIsExecuted(t *testing.T, actionConfig ActionConfig, tag string) {
fixturePath := prepareFixture(t, "fixture-dependencies-project")

output := runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all plan")
assert.Contains(t, output, "1 to add, 0 to change, 0 to destroy")
output := runAction(t, actionConfig, false, tag, fixturePath, "run-all plan")
assert.Contains(t, output, "1 to add, 0 to change, 0 to destroy", actionConfig.iacName)

output = runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all apply")
assert.Contains(t, output, "1 to add, 0 to change, 0 to destroy")
output = runAction(t, actionConfig, false, tag, fixturePath, "run-all apply")
assert.Contains(t, output, "1 to add, 0 to change, 0 to destroy", actionConfig.iacName)

output = runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all destroy")
assert.Contains(t, output, "0 to add, 0 to change, 1 to destroy")
assert.Contains(t, output, "Destroy complete! Resources: 1 destroyed")
output = runAction(t, actionConfig, false, tag, fixturePath, "run-all destroy")
assert.Contains(t, output, "0 to add, 0 to change, 1 to destroy", actionConfig.iacName)
assert.Contains(t, output, "Destroy complete! Resources: 1 destroyed", actionConfig.iacName)
}

func testAutoApproveDelete(t *testing.T, iac_type string, iac_name string, iac_version string, tg_version string, tag string) {
func testAutoApproveDelete(t *testing.T, actionConfig ActionConfig, tag string) {
fixturePath := prepareFixture(t, "fixture-dependencies-project")

output := runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all plan -out=plan.out")
output := runAction(t, actionConfig, false, tag, fixturePath, "run-all plan -out=plan.out")
assert.Contains(t, output, "1 to add, 0 to change, 0 to destroy")

output = runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all apply plan.out")
assert.Contains(t, output, "1 added, 0 changed, 0 destroyed")
output = runAction(t, actionConfig, false, tag, fixturePath, "run-all apply plan.out")
assert.Contains(t, output, "1 added, 0 changed, 0 destroyed", actionConfig.iacName)

// run destroy with auto-approve
output = runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all plan -destroy -out=destroy.out")
assert.Contains(t, output, "0 to add, 0 to change, 1 to destroy")
output = runAction(t, actionConfig, false, tag, fixturePath, "run-all plan -destroy -out=destroy.out")
assert.Contains(t, output, "0 to add, 0 to change, 1 to destroy", actionConfig.iacName)

output = runAction(t, actionConfig, false, tag, fixturePath, "run-all apply -destroy destroy.out")
assert.Contains(t, output, "Resources: 0 added, 0 changed, 1 destroyed", actionConfig.iacName)

output = runAction(t, tag, fixturePath, iac_type, iac_version, tg_version, "run-all apply -destroy destroy.out")
assert.Contains(t, output, "Resources: 0 added, 0 changed, 1 destroyed")
// check that fixturePath can removed recursively
err := os.RemoveAll(fixturePath)
assert.NoError(t, err)
}

func runAction(t *testing.T, tag, fixturePath, iac_type string, iac_version string, tg_version string, command string) string {
func runAction(t *testing.T, actionConfig ActionConfig, sshAgent bool, tag, fixturePath string, command string) string {

logId := random.Random(1, 5000)
opts := &docker.RunOptions{
EnvironmentVariables: []string{
"INPUT_" + iac_type + "_VERSION=" + iac_version,
"INPUT_TG_VERSION=" + tg_version,
"INPUT_" + actionConfig.iacType + "_VERSION=" + actionConfig.iacVersion,
"INPUT_TG_VERSION=" + actionConfig.tgVersion,
"INPUT_TG_COMMAND=" + command,
"INPUT_TG_DIR=/github/workspace/code",
"GITHUB_OUTPUT=/tmp/logs",
"INPUT_TG_DIR=/github/workspace",
fmt.Sprintf("GITHUB_OUTPUT=/tmp/github-action-logs.%d", logId),
},
Volumes: []string{fixturePath + ":/github/workspace/code"},
Volumes: []string{
fixturePath + ":/github/workspace",
},
}

// start ssh-agent container with SSH keys to allow clones over SSH
if sshAgent {
homeDir, err := os.UserHomeDir()
assert.NoError(t, err)
sshPath := filepath.Join(homeDir, ".ssh")

socketId := random.Random(1, 5000)
socketPath := fmt.Sprintf("/tmp/ssh-agent.sock.%d", socketId)
sshAgentID := docker.RunAndGetID(t, "ssh-agent:local", &docker.RunOptions{
Detach: true,
Remove: true,
EnvironmentVariables: []string{
"SSH_AUTH_SOCK=" + socketPath,
},
Volumes: []string{
"/tmp:/tmp",
sshPath + ":/root/keys",
},
})
defer docker.Stop(t, []string{sshAgentID}, &docker.StopOptions{})
opts.Volumes = append(opts.Volumes, "/tmp:/tmp")
opts.EnvironmentVariables = append(opts.EnvironmentVariables, "SSH_AUTH_SOCK="+socketPath)
}
return docker.Run(t, tag, opts)
}

func prepareFixture(t *testing.T, fixtureDir string) string {
path, err := files.CopyTerraformFolderToTemp(fixtureDir, "test")
require.NoError(t, err)
// chmod recursive for docker run

err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
return os.Chmod(path, 0777)
})
require.NoError(t, err)

err = os.Chmod(path, 0777)
require.NoError(t, err)
return path
}
7 changes: 7 additions & 0 deletions test/fixture-action-execution-ssh/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
inputs = {
name = "World"
}

terraform {
source = "git@github.com:gruntwork-io/terragrunt.git//test/fixture-download/hello-world?ref=v0.9.9"
}
11 changes: 11 additions & 0 deletions test/ssh-agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM ubuntu:22.04

RUN apt-get update && \
apt-get install -y openssh-client && \
rm -rf /var/lib/apt/lists/*

RUN mkdir /ssh-agent

ENV SSH_AUTH_SOCK /tmp/ssh-agent.sock
ADD run.sh /run.sh
CMD ["/run.sh"]
27 changes: 27 additions & 0 deletions test/ssh-agent/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Script to run ssh-agent in the background and add ssh keys
set -x

cleanup() {
echo "Caught SIGTERM signal! Cleaning up..."
ssh-agent -k
exit 0
}

trap cleanup SIGTERM SIGINT

mkdir -p ~/.ssh
cp -rfv ~/keys/* ~/.ssh/
chown -R $(whoami) ~/.ssh

# delete socket if exists
if [[ -S "$SSH_AUTH_SOCK" ]]; then
rm -f "$SSH_AUTH_SOCK"
fi

eval "$(ssh-agent -s -a "$SSH_AUTH_SOCK")"
ssh-add ~/.ssh/*

echo "SSH agent running on: $SSH_AUTH_SOCK"
tail -f /dev/null

0 comments on commit 751e00d

Please sign in to comment.