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
1 change: 1 addition & 0 deletions azure-pipelines/new-scan-engine/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
love/love
47 changes: 47 additions & 0 deletions azure-pipelines/new-scan-engine/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Azure Pipelines Demo

In this demo we will use Azure Pipelines to build, scan and push a container image.

NOTE: This example uses the [new Sysdig scanning engine](https://docs.sysdig.com/en/docs/sysdig-secure/scanning/new-scanning-engine/)

The workflow is as follows:

1. Build the container image and store it locally
2. Download the sysdig-cli-scanner cli if needed
3. Perform the scan
4. Push the container image to a remote registry

The workflow leverages Azure Pipeline actions cache to avoid downloading the binary,
the databases and the container images if they are available.

## Setup

### Variables

It is required to create a TOKEN pipeline variable containing the Sysdig API token in order
to be able to perform the scan. See [the official documentation](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/set-secret-variables)
for instructions on how to do it, but basically:

* Edit the pipeline
* Select "Variables"
* Add a new TOKEN variable with the proper content

### Registry access

It is required to create a Docker registry "Service Connections" to be able to push images to the registry.
See [the official documentation](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#docker-hub-or-others)
for instructions on how to do it, but basically:

* Select Project settings > Service connections
* Select + New service connection, select the "Docker Registry", and then select Next
* Add the registry url, user & password and a Service connection name (it will be used as REGISTRY_CONNECTION)

Then, modify the variables on the [azure-pipelines.yml](azure-pipelines.yml) file to fit your needs:

```
SYSDIG_SECURE_ENDPOINT: "https://eu1.app.sysdig.com"
REGISTRY_HOST: "quay.io"
IMAGE_NAME: "e_minguez/my-example-app"
IMAGE_TAG: "latest"
REGISTRY_CONNECTION: "quayio-e_minguez"
```
86 changes: 86 additions & 0 deletions azure-pipelines/new-scan-engine/azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
trigger:
- main

pool:
vmImage: ubuntu-latest

variables:
CACHE_FOLDER: $(Pipeline.Workspace)/cache/
SYSDIG_SECURE_ENDPOINT: "https://eu1.app.sysdig.com"
REGISTRY_HOST: "quay.io"
IMAGE_NAME: "e_minguez/my-example-app"
IMAGE_TAG: "latest"
REGISTRY_CONNECTION: "quayio-e_minguez"

steps:

- task: Cache@2
inputs:
key: |
sysdig-cli-scanner-cache | "$(Agent.OS)" | "$(CACHE_FOLDER)/sysdig-cli-scanner" | "$(CACHE_FOLDER)/latest_version.txt" | "$(CACHE_FOLDER)/db/main.db.meta.json" | "$(CACHE_FOLDER)/scanner-cache/inlineScannerCache.db"
restoreKeys: |
sysdig-cli-scanner-cache | "$(Agent.OS)"
sysdig-cli-scanner-cache
path: $(CACHE_FOLDER)
displayName: Cache sysdig-cli-scanner and databases

- task: Cache@2
displayName: Docker cache
inputs:
key: 'docker | "$(Agent.OS)" | cache'
path: $(Pipeline.Workspace)/docker
cacheHitVar: CACHE_RESTORED

- script: |
docker load -i $(Pipeline.Workspace)/docker/cache.tar
displayName: Docker restore
condition: and(not(canceled()), eq(variables.CACHE_RESTORED, 'true'))

- task: Docker@2
inputs:
command: 'build'
Dockerfile: 'love/Containerfile'
buildContext: 'love/'
repository: $(REGISTRY_HOST)/$(IMAGE_NAME)
tags: $(IMAGE_TAG)
addPipelineData: false
addBaseImageData: false

- script: |
curl -sLO https://download.sysdig.com/scanning/sysdig-cli-scanner/latest_version.txt
mkdir -p $(CACHE_FOLDER)/db/
if [ ! -f $(CACHE_FOLDER)/latest_version.txt ] || [ $(cat ./latest_version.txt) != $(cat $(CACHE_FOLDER)/latest_version.txt) ]; then
cp ./latest_version.txt $(CACHE_FOLDER)/latest_version.txt
curl -sL -o $(CACHE_FOLDER)/sysdig-cli-scanner "https://download.sysdig.com/scanning/bin/sysdig-cli-scanner/$(cat $(CACHE_FOLDER)/latest_version.txt)/linux/amd64/sysdig-cli-scanner"
chmod +x $(CACHE_FOLDER)/sysdig-cli-scanner
else
echo "sysdig-cli-scanner latest version already downloaded"
fi
displayName: Download the sysdig-cli-scanner if needed

- script: |
$(CACHE_FOLDER)/sysdig-cli-scanner \
--apiurl $(SYSDIG_SECURE_ENDPOINT) \
--console-log \
--dbpath=$(CACHE_FOLDER)/db/ \
--cachepath=$(CACHE_FOLDER)/scanner-cache/ \
docker://$(REGISTRY_HOST)/$(IMAGE_NAME):$(IMAGE_TAG) \
displayName: Run the sysdig-cli-scanner
env:
SECURE_API_TOKEN: $(TOKEN)

- task: Docker@2
displayName: Push the container image
inputs:
containerRegistry: $(REGISTRY_CONNECTION)
repository: $(IMAGE_NAME)
command: push
tags: $(IMAGE_TAG)
addPipelineData: false
addBaseImageData: false

- script: |
mkdir -p $(Pipeline.Workspace)/docker
docker save $(docker images -q) -o $(Pipeline.Workspace)/docker/cache.tar
displayName: Docker save
condition: and(not(canceled()), or(failed(), ne(variables.CACHE_RESTORED, 'true')))
10 changes: 10 additions & 0 deletions azure-pipelines/new-scan-engine/love/Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM golang:1.18-alpine as builder
WORKDIR /app
COPY . .
RUN go mod download
RUN go build -o /love

FROM alpine
COPY --from=builder /love /love
EXPOSE 8080
ENTRYPOINT [ "/love" ]
3 changes: 3 additions & 0 deletions azure-pipelines/new-scan-engine/love/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module love

go 1.18
16 changes: 16 additions & 0 deletions azure-pipelines/new-scan-engine/love/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import (
"fmt"
"log"
"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "I love %s!\n", r.URL.Path[1:])
}

func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ The `no_proxy` variable can be used to define a list of hosts that don't use the

In this [repository](https://github.com/sysdiglabs/secure-inline-scan-examples/) you can find the following examples in alphabetical order:

* [AWS Codebuild](https://github.com/sysdiglabs/secure-inline-scan-examples/tree/main/new-scan-engine/aws-codebuild)
* [Azure Pipelines (New scan engine)](https://github.com/sysdiglabs/secure-inline-scan-examples/tree/main/azure-pipelines)
* [Google Cloud Build](https://github.com/sysdiglabs/secure-inline-scan-examples/tree/main/google-cloud-build)
* [Jenkins](https://github.com/sysdiglabs/secure-inline-scan-examples/tree/main/jenkins)
* [Scan from repository](https://github.com/sysdiglabs/secure-inline-scan-examples/tree/main/jenkins/jenkins-scan-from-repo)
Expand Down