diff --git a/atlantis/Dockerfile b/atlantis/Dockerfile new file mode 100644 index 000000000..284cb084e --- /dev/null +++ b/atlantis/Dockerfile @@ -0,0 +1,12 @@ +FROM runatlantis/atlantis:v0.16.1 +ENV DEFAULT_TERRASCAN_VERSION=1.5.1 +ENV PLANFILE tfplan +ADD setup.sh terrascan.sh launch-atlantis.sh entrypoint.sh /usr/local/bin/ +RUN mkdir -p /etc/atlantis/ && \ + chmod +x /usr/local/bin/*.sh && \ + /usr/local/bin/setup.sh +ADD terrascan-workflow.yaml /etc/atlantis/workflow.yaml +USER atlantis +RUN terrascan init +ENTRYPOINT ["/bin/bash", "entrypoint.sh"] +CMD ["server"] diff --git a/atlantis/data/terrascan-workflow.yaml b/atlantis/data/terrascan-workflow.yaml new file mode 100644 index 000000000..20e3394cf --- /dev/null +++ b/atlantis/data/terrascan-workflow.yaml @@ -0,0 +1,26 @@ +# Copyright (C) 2020 Accurics, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +repos: +- id: "/.*/" + workflow: terrascan +workflows: + terrascan: + plan: + steps: + - run: terraform init -input=false -no-color + - run: terraform workspace select -no-color $WORKSPACE + - run: terraform plan -input=false -refresh -no-color -out $PLANFILE + - run: terraform show -no-color -json $PLANFILE > ${PLANFILE}.json + - run: terrascan.sh diff --git a/atlantis/entrypoint.sh b/atlantis/entrypoint.sh new file mode 100755 index 000000000..e97337285 --- /dev/null +++ b/atlantis/entrypoint.sh @@ -0,0 +1,50 @@ +# Copyright (C) 2020 Accurics, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash +set -e +count=1 +declare config_file +declare copy +function fetch_configfile() { + for i in "${@:1}" + do + if [[ "$i" == "-c"* ]]; then + if [[ $i =~ -c=(.+) ]]; then + eval config_file="${BASH_REMATCH[1]}" + copy=${@/"$i"} + elif [[ $i =~ -c(.+) ]]; then + echo "unacceptable argument : $i" + exit 1 + else + eval var='$'$(( count + 1 )) + eval config_file="$var" + copy=$(echo "$@" | sed "s/ -c//") + copy=${copy/$config_file} + fi + fi + (( count += 1 )) + done +} + +fetch_configfile "$@" +if [[ ! -z $config_file ]]; then + export TERRASCAN_CONFIG=$config_file +fi + +if [[ -z $copy ]]; then + launch-atlantis.sh $@ +else + launch-atlantis.sh $copy +fi diff --git a/atlantis/launch-atlantis.sh b/atlantis/launch-atlantis.sh new file mode 100755 index 000000000..3b06f2e9c --- /dev/null +++ b/atlantis/launch-atlantis.sh @@ -0,0 +1,81 @@ +# Copyright (C) 2020 Accurics, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash +set -e + +declare flag + +function lookup_repo_config_flag() { + for i in "$@" + do + if [[ "$i" == "--repo-config"* ]]; then + flag="true" + fi + done +} + +# Modified: https://github.com/hashicorp/docker-consul/blob/2c2873f9d619220d1eef0bc46ec78443f55a10b5/0.X/docker-entrypoint.sh + +# If the user is trying to run atlantis directly with some arguments, then +# pass them to atlantis. +if [ "${1:0:1}" = '-' ]; then + set -- atlantis "$@" +fi + +# If the user is running an atlantis subcommand (ex. server) then we want to prepend +# atlantis as the first arg to exec. To detect if they're running a subcommand +# we take the potential subcommand and run it through atlantis help {subcommand}. +# If the output contains "atlantis subcommand" then we know it's a subcommand +# since the help output contains that string. For anything else (ex. sh) +# it won't contain that string. +# NOTE: We use grep instead of the exit code since help always returns 0. +if atlantis help "$1" 2>&1 | grep -q "atlantis $1"; then + # We can't use the return code to check for the existence of a subcommand, so + # we have to use grep to look for a pattern in the help output. + set -- atlantis "$@" +fi + +# If the current uid running does not have a user create one in /etc/passwd +if ! whoami &> /dev/null; then + if [ -w /etc/passwd ]; then + echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default} user:/home/atlantis:/sbin/nologin" >> /etc/passwd + fi +fi + +# If we're running as root and we're trying to execute atlantis then we use +# gosu to step down from root and run as the atlantis user. +# In OpenShift, containers are run as a random users so we don't need to use gosu. +if [[ $(id -u) == 0 ]] && [[ "$1" = 'atlantis' ]]; then + # If requested, set the capability to bind to privileged ports before + # we drop to the non-root user. Note that this doesn't work with all + # storage drivers (it won't work with AUFS). + if [ ! -z ${ATLANTIS_ALLOW_PRIVILEGED_PORTS+x} ]; then + setcap "cap_net_bind_service=+ep" /bin/atlantis + fi + + set -- gosu atlantis "$@" +fi + +to_exec="" + +lookup_repo_config_flag $@ + +if [[ $flag != "true" ]] && [[ "$@" == *"atlantis"* ]] && [[ "$@" == *"server"* ]] && [[ -f /etc/atlantis/workflow.yaml ]]; then + to_exec="$@ --repo-config=/etc/atlantis/workflow.yaml" +else + to_exec="$@" +fi + +exec $to_exec diff --git a/atlantis/setup.sh b/atlantis/setup.sh new file mode 100755 index 000000000..b30485dc0 --- /dev/null +++ b/atlantis/setup.sh @@ -0,0 +1,31 @@ +# Copyright (C) 2020 Accurics, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash +set -ex + +if [[ -z "${TERRASCAN_VERSION}" ]]; then + TERRASCAN_VERSION=${DEFAULT_TERRASCAN_VERSION} +fi + +VERSION=${TERRASCAN_VERSION} + +curl -LOs https://github.com/accurics/terrascan/releases/download/v${VERSION}/terrascan_${VERSION}_Linux_x86_64.tar.gz +mkdir /usr/local/bin/terrascan_${VERSION} +tar -C /usr/local/bin/terrascan_${VERSION} -xzf terrascan_${VERSION}_Linux_x86_64.tar.gz + +mv /usr/local/bin/terrascan_${VERSION}/terrascan /usr/local/bin/terrascan + +rm terrascan_${VERSION}_Linux_x86_64.tar.gz +rm -rf /usr/local/bin/terrascan_${VERSION}/ diff --git a/atlantis/terrascan-workflow.yaml b/atlantis/terrascan-workflow.yaml new file mode 100644 index 000000000..20e3394cf --- /dev/null +++ b/atlantis/terrascan-workflow.yaml @@ -0,0 +1,26 @@ +# Copyright (C) 2020 Accurics, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +repos: +- id: "/.*/" + workflow: terrascan +workflows: + terrascan: + plan: + steps: + - run: terraform init -input=false -no-color + - run: terraform workspace select -no-color $WORKSPACE + - run: terraform plan -input=false -refresh -no-color -out $PLANFILE + - run: terraform show -no-color -json $PLANFILE > ${PLANFILE}.json + - run: terrascan.sh diff --git a/atlantis/terrascan.sh b/atlantis/terrascan.sh new file mode 100644 index 000000000..f10921a71 --- /dev/null +++ b/atlantis/terrascan.sh @@ -0,0 +1,36 @@ +# Copyright (C) 2020 Accurics, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash + +terrascan scan -i tfplan --iac-version v1 -f ${PLANFILE}.json -l error > output +exitcode=$? + +if [[ ! $exitcode -eq 0 ]]; then + echo + echo '- Terrascan identified IAC policy violations:' + echo + echo 'Scan Results:' + cat output + echo + echo '```' + echo '' + echo '

Further atlantis details below:

' + echo '
' + echo + echo '```diff' + echo +fi + +exit $exitcode diff --git a/docs/integrations/atlantis-integration.md b/docs/integrations/atlantis-integration.md index 9e3ed7fac..9bec343bc 100644 --- a/docs/integrations/atlantis-integration.md +++ b/docs/integrations/atlantis-integration.md @@ -11,7 +11,6 @@ In either scenario, the configuration of Atlantis is a diverse topic which will Through this method, you will modify or create a custom workflow for atlantis so your repositories will be scanned by terrascan as part of the pull request automation. **Requirements** - * The atlantis server must have TCP connectivity to where the terrascan server is running. * The `curl` command needs to be installed on the system so the `terrascan-remote-scan.sh` script can make the scan request. Atlantis's [docker image](https://hub.docker.com/r/runatlantis/atlantis/) has curl preinstalled. @@ -74,6 +73,48 @@ terrascan server Once the systems are running, when atlantis is called via pull request, or a comment of `atlantis plan`, terrascan will be called as part of the atlantis plan flow. Scan results will be placed in a comment on the pull request, and if issues are found the test will be marked as failed. -## Custom Atlantis Contaier -(coming soon...) +## Custom Atlantis Container + +We have come up with a custom container built on top of the official atlantis container image, that will allow users to +run IaC scans with terrascan, besides the usual atlantis usage. There's a default atlantis workflow setup inside in the +container to be used. Users may also override that default workflow using the --repo-config flag. + +### Usage + +On the code repository's end, usage is exactly the same as atlantis, you comment `atlantis plan` and `atlantis plan` on +your Pull Requests to trigger the custom atlantis-terrascan workflow. + +##### To use our container image: +``` +docker pull accurics/terrascan_atlantis +``` + +##### To build your own container image: +``` +docker build ./atlantis -t +``` + +###### Running the container: + +```bash +docker run \ +--env-file=<.env-file> \ +-p 4141:4141 \ +-v /config_data/:/etc/terrascan/ \ +accurics/terrascan_atlantis server \ +--gh-user="$USERNAME" --gh-token="$TOKEN" --gh-webhook-secret="$SECRET" \ +--repo-allowlist="$REPO_ALLOWLIST" \ +-c /etc/terrascan/config.toml +``` + +The syntax of the atlantis server command here is same as in [atlantis docs](https://www.runatlantis.io/docs/), +except for an optional `-c` flag which can be used to pass in the toml config filepath for terrascan. +Another way to provide the toml config filepath would be the TERRASCAN_CONFIG environment variable. + +You need to provide all the environment variables that terraform requires to operate with your respective cloud providers. +It's a good practice to use a [specific tag](https://hub.docker.com/r/accurics/terrascan_atlantis/tags) of the container +image rather than the latest tag. +The default workflow.yaml file used is the `atlantis/workflow.yaml` in this repo. You can override the default workflow +using the `--repo-config` flag. It will be up to you how you want to trigger `terrascan` for your usage. You can do +something along the lines of `atlantis/workflow.yaml` and `atlantis/terrascan.sh` itself.