Skip to content

Commit

Permalink
Merge pull request #2 from szh/main
Browse files Browse the repository at this point in the history
Add GitHub Action
  • Loading branch information
slashben authored May 21, 2024
2 parents 751d8e2 + 25843bd commit 4b19d39
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 59 deletions.
58 changes: 0 additions & 58 deletions .github/workflows/generate-vex.yaml

This file was deleted.

31 changes: 31 additions & 0 deletions .github/workflows/self-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Self test
on:
push:
branches:
- main
pull_request:
paths-ignore:
- '**/*.md'
types: [labeled, synchronize, ready_for_review, opened, reopened]

jobs:
generate_vex:
runs-on: ubuntu-latest
name: Test VEX Generation
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Checkout nginx helm chart
uses: actions/checkout@v4
with:
repository: helm/examples
path: charts/examples
ref: main

- name: Test VEX Generation
uses: ./
with:
helm-chart-path: "charts/examples/charts/hello-world"
ready-condition: "kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=hello-world --timeout=300s"
test-command: "self-test/test.sh"
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,37 @@
# generate-vex-action
# Generate VEX with Kubescape GitHub Action

This GitHub Action is designed to generate a VEX (Vulnerability Exploitability
eXchange) document using Kubescape. It does this by deploying a Helm chart to a
KinD cluster and running a test command, which should run your suite of tests
and thereby generate usage information for Kubescape. The Action will then
produce a VEX document based on the information collected and save it as an
artifact.

## Inputs

- `helm-chart-path`: (Required) The path to the Helm chart that you want to
test.
- `ready-condition`: (Optional) A condition that the action should wait for
before collecting VEX information.
- `test-command`: (Optional) The command that should be run to test the
deployment. This should be a command that runs your suite of tests. If
omitted, no tests will be run and the VEX document will likely be unreliable
as there will be no real usage information.

## Usage

To use this action in your workflow, include it in your workflow file with the required inputs:

```yaml
- uses: slashben/generate-vex-action@v1
with:
helm-chart-path: './path/to/your/chart' # Ex. './charts/hello-world'
ready-condition: 'your-condition' # Ex. `kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=hello-world --timeout=300s`
test-command: 'your-test-command' # Ex. `./ci/test_integration.sh`
```
Replace `your-org/generate-vex-with-kubescape@v1` with the actual repository and version of the action. Replace the values of `helm-chart-path`, `ready-condition`, and `test-command` with your actual values.

## Example

To see an example of this Action in use, check out the [self test](./.github/workflows/self-test.yml) workflow in this repository.
43 changes: 43 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: "Generate VEX with Kubescape"
description: "Generate VEX with Kubescape"
inputs:
helm-chart-path:
description: "Path to Helm chart to test"
required: true
ready-condition:
description: "Condition to wait for before collecting VEX info"
required: false
test-command:
description: "Command to run to test the deployment"
required: false

runs:
using: "composite"
steps:
- name: "Setup"
run: $GITHUB_ACTION_PATH/setup.sh
shell: bash

- name: "Install Helm Chart"
env:
HELM_CHART_PATH: ${{ inputs.helm-chart-path }}
READY_CONDITION: ${{ inputs.ready-condition }}
run: $GITHUB_ACTION_PATH/install.sh
shell: bash

- name: "Run tests"
env:
TEST_COMMAND: ${{ inputs.test-command }}
run: $GITHUB_ACTION_PATH/test.sh
shell: bash

- name: "Generate VEX"
run: $GITHUB_ACTION_PATH/generate.sh
shell: bash

- name: Upload VEX document
if: always()
uses: actions/upload-artifact@v4
with:
name: VEX document
path: vex.json
31 changes: 31 additions & 0 deletions generate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -x

timeout=300
start_time=$SECONDS
while [[ -z $(kubectl -n kubescape get openvulnerabilityexchangecontainers.spdx.softwarecomposition.kubescape.io) ]]; do
echo "Waiting for VEX generation..."
sleep 10
if [[ $((SECONDS - start_time)) -gt $timeout ]]; then
echo "Timeout reached. Exiting..."

# Loop through all pods in the kubescape namespace and print the logs
for pod in $(kubectl -n kubescape get pods -o jsonpath='{.items[*].metadata.name}'); do
echo "Logs for $pod:"
kubectl -n kubescape logs "$pod"
done

break
fi
done

echo "Saving VEX results..."
kubectl -n kubescape get openvulnerabilityexchangecontainer \
"$(kubectl -n kubescape get openvulnerabilityexchangecontainer -o jsonpath='{.items[0].metadata.name}')" \
-o jsonpath='{.spec}' > vex.json

echo "Affected:"
jq "." vex.json | grep -c "\"affected\""

echo "Not affected:"
jq "." vex.json | grep -c "\"not_affected\""
8 changes: 8 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -x

helm install "$HELM_CHART_PATH" --wait --timeout 300s --generate-name

if [[ -n "$READY_CONDITION" ]]; then
$READY_CONDITION
fi
17 changes: 17 additions & 0 deletions self-test/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -x

# Get the pod name and container port of the test application
POD_NAME=$(kubectl get pods -l "app.kubernetes.io/name=hello-world" -o jsonpath="{.items[0].metadata.name}")
CONTAINER_PORT=$(kubectl get pod "$POD_NAME" -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
# Expose the test app on localhost
kubectl port-forward "$POD_NAME" 8080:"$CONTAINER_PORT" &
sleep 5
# Test the application by sending a request to it a number of times
for _ in {1..10}; do
# Prints just the status code
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080
echo
done
# Stop the port-forwarding
kill %1
29 changes: 29 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -x

# Install kind and kubectl
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-$(uname)-amd64
chmod +x ./kind
./kind create cluster
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kubectl
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
# Install helm
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
sudo ./get_helm.sh
# Install Kubescape
helm repo add kubescape https://kubescape.github.io/helm-charts/
helm repo update
helm upgrade --install kubescape kubescape/kubescape-operator -n kubescape --create-namespace \
--set clusterName="$(kubectl config current-context)" \
--set capabilities.vexGeneration=enable \
--set nodeAgent.config.learningPeriod=1m \
--set nodeAgent.config.updatePeriod=1m \
--set logger.level=debug \
--wait
# Wait for the pod to be ready
sleep 5
kubectl -n kubescape wait --for=condition=ready pod -l app.kubernetes.io/name=node-agent --timeout=300s
kubectl -n kubescape wait --for=condition=ready pod -l app.kubernetes.io/name=storage --timeout=300s
echo "Kubescape is ready"
6 changes: 6 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -x

if [[ -n "$TEST_COMMAND" ]]; then
$TEST_COMMAND
fi

0 comments on commit 4b19d39

Please sign in to comment.