CLI for CI

Introduction

This document provides instructions on how to integrate Prancer CLI for Infrastructure as Code (IaC) static code analysis (SCA) into Continuous Integration (CI) pipelines to scan the infrastructure as code for security purposes. Prerequisites for installing Prancer CLI include the installation of Prancer CLI, OPA binary, and HELM binary on the CI machine. To install Prancer CLI, users can run a specific command or follow the installation instructions provided in the link. Users can create a new collection from the Configuration Wizard for the git repository they want to scan for security. To run Prancer CLI in the pipeline, users need to define variables in the CI tool, including Prancer API token and GitHub token. The document provides sample GitHub Actions files and instructions on how to run Prancer basic pipeline scripts and Prancer basic inside a docker image pipeline script.

Prancer CLI for Infrastructure as Code (IaC) static code analysis (SCA) can be integrated into all Continuous Integration (CI) pipelines to security scan the infrastructure as code. For example, GitHub can be configured with Prancer CLI if you are using GitHub Actions.

Prerequisites

make sure the following binaries are installed on your CI machine:

How to Install Prancer CLI

To Install Prancer CLI, you can run the following command: pip3 install -U prancer-basic

To make sure prancer is installed successfully, you can run this command:

  $ prancer --version
  Prancer 2.0.21

For the complete installation description, you can visit the following URL: Prancer Installation

Setup on Prancer SaaS solution

New collection

Create a new collection from the Configuration Wizard for the git repository you want to do the security scan. To understand how to use the Configuration Wizard, you can review this post

CI Variables

Defining variables in CI tool to run Prancer CLI in your pipeline, you need to define some variables.

Prancer API token

Generate a user access token from Prancer SaaS solution How to generate token in Prancer SaaS

You should define this variable as APITOKEN in your CI tool. Add this as a secret.

Github token

you need to generate a new personal access token for prancer with the following permissions: Repo permission / User permission You should define this variable as GITTOKEN in your CI tool. Add this as a secret as well.

How to run

To integrate Prancer CLI into your CI tool, you need to have the base structure and run the appropriate commands.

-> The easiest way is to clone the following repo for the base structure files Sample GitHub Actions file

Run the following command:

    collection_name="the name of the collection from prancer saas"
    company_name="the name of your company in prancer tenant."

    prancer $collection_name --db REMOTE --company $company_name

Link to the repo with the base structure: Prancer Armof

Link to the sample GitHub Actions pipeline: Sample GitHub Actions file

# This is a basic workflow to help you get started with Actions

name: Prancer CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      # Runs a set of commands using the runners shell  
      - name: Install Prancer
        run: |
          pip3 install -U prancer-basic

      - name: Install opa 
        run: |
          echo "opa and helm binariees required, helm is packaged with ubuntu, install opa only"
          curl -L -o /usr/local/bin/opa https://openpolicyagent.org/downloads/v0.36.1/opa_linux_amd64_static
          chmod 755 /usr/local/bin/opa
          echo "opa binary path..."
          which opa
          echo "helm binary path..."
          which helm

      - name: Run Prancer
        run: |
          export APITOKEN=${{ secrets.APITOKEN }}
          export GITTOKEN=${{ secrets.GITTOKEN }}
          prancer --db REMOTE --company prancer-liquware armof

Running prancer-basic pipeline script

trigger:
  - master

resources:
  - repo: self

stages:
  - stage: prancer_static_code_analysis_for_iac
    displayName: "Prancer Static Code Analysis for IaC"
    jobs:
      - job: prancer_basic
        displayName: "prancer basic install in agent"
        pool: "Default"
        steps:
          - bash: |
              echo "Setup start"

              binary="pip3"
              ispresent=`which $binary`
              if [ -z $ispresent ]; then
              apt-get -y install python3-pip
              else
              echo "using existing pip3 path: $ispresent"
              fi

              pip3 install -U prancer-basic
              binary="opa"
              ispresent=`which $binary`
              if [ -z $ispresent ]; then
              curl -L -o /usr/local/bin/opa https://openpolicyagent.org/downloads/v0.36.1/opa_linux_amd64_static
              chmod 755 /usr/local/bin/opa
              else
              echo "using existing opa binary path: $ispresent"
              fi

              binary="helm"
              ispresent=`which $binary`
              if [ -z $ispresent ]; then
              snap install helm --classic
              else
              echo "using existing helm binary path: $ispresent"
              fi

              export APITOKEN=${APITOKEN}
              export GITTOKEN=${GITTOKEN}
              prancer --db REMOTE --company liquware --apitoken "${APITOKEN}" --gittoken "${GITTOKEN}" scenario_aws_githubEntNon
            env:
              GITTOKEN: $(GITTOKEN)
              APITOKEN: $(APITOKEN)

Running prancer-basic inside a docker image pipeline script

trigger:
  - master

resources:
  - repo: self

stages:
  - stage: prancer_basic_setup_pipeline
    displayName: "Prancer basic setup in pipeline"
    jobs:
      - job: prancer_basic
        displayName: "prancer basic install in agent"
        pool: "Default"
        steps:
          - bash: |
              echo "Setup start"

              # Creating Working Directory
              mkdir prancer
              cd prancer

              # Downloading setup.py from prancer-basic to find latest version
              curl -L -o setup.py https://raw.githubusercontent.com/prancer-io/cloud-validation-framework/master/setup.py
              version=`cat setup.py  | grep -i 'version=' | sed -e "s/version='//" | sed -e "s/',//" | sed -e 's/ //g'`

              echo $version

              # Creating temp dir for opa and helm
              mkdir helmdir opadir

              # Download opa binary
              curl -L -o opadir/opa https://openpolicyagent.org/downloads/v0.36.1/opa_linux_amd64_static
              chmod 755 opadir/opa

              # Download helm binary
              curl -L -o helmdir/helm-v3.8.1-linux-amd64.tar.gz https://get.helm.sh/helm-v3.8.1-linux-amd64.tar.gz
              tar -zxvf helmdir/helm-v3.8.1-linux-amd64.tar.gz -C helmdir
              chmod 755 helmdir/linux-amd64/helm

              # Creating Docker File

              cat << EOF >> Dockerfile
              FROM python:3.9-alpine3.15
              ENV APP_VERSION=$version
              RUN apk update     && apk upgrade     && apk add git build-base libffi-dev openssl-dev
              COPY opadir/opa /usr/local/bin/opa
              RUN chmod +x /usr/local/bin/opa
              COPY helmdir/linux-amd64/helm /usr/local/bin/helm
              RUN chmod +x /usr/local/bin/helm
              RUN pip install ply    
              RUN pip install prancer-basic==$version
              EOF

              # Building Docker image with prancer-basic as per version
              docker build -t prancer-basic:${version} -f Dockerfile .

              # Running Prancer-basic docker image with remote for scenario_aws_githubEntNon collection
              docker container run prancer-basic:${version} prancer --db REMOTE --company liquware --env QA --apitoken "${APITOKEN}" --gittoken "${GITTOKEN}" scenario_aws_githubEntNon
            env:
              GITTOKEN: $(GITTOKEN)
              APITOKEN: $(APITOKEN)