Ocular: A Quick Start Guide
This guide covers the fundamental operations of Ocular with simple examples. You will learn how to start a pipeline and scan a git repository.
Prerequisites
Before starting, ensure you have a working installation of Ocular and access to the cluster via kubectl. If you have not installed Ocular yet, please refer to the Ocular installation guide. This document will also use the Ocular default integrations, which the installation instructions can also be found in the installation guide.
Authentication
Since Ocular is an extension of the Kubernetes API, you will need to
authenticate using the same methods used to interact with the cluster normally.
You should still be able to use kubectl, just ensure that your role/user has full
access to all Ocular custom resources (i.e. Pipelines, Crawlers,
Profiles, Downloaders, Uploaders, Searches, CronSearches)
Scanning a git repository
We will start with a basic example of scanning a git repository, and uploading the results to a 3rd party service
NOTE: In this example we will assume we have a 3rd party service
that accepts files to upload at the web URL POST https://upload.example.com/scan-result.
Step 1: Configure Profile
Ocular centers most of the scanning configuration around the concept of a profile. A profile consists of one or more scanners, a list of the artifact files produced and zero or more uploaders
In this tutorial we will use SemGrep as our scanning,
which will write scan results to a file named semgrep.json.
We will upload semgrep.json to our 3rd party service https://upload.example.com/scan-result using the
webhook uploader.
NOTE: the webhook uploader is bundled with an install of Ocular and will post a file to a URL endpoint.
To see all available default uploaders, either running kubectl get uploaders or view the
default uploaders section in the Ocular manual.
Below is an example profile we will save to the file example-profile.yaml.
apiVersion: ocular.crashoverride.run/v1beta1
kind: Profile
metadata:
name: example-profile
# Optionally specify a specific namespace to segment scans
# If not defined will use the namespace from kubeconfig
# namespace: default
spec:
# Here we define what scanners to use
coantiners:
- name: "semgrep"
image: "semgrep/semgrep:latest"
imagePullPolicy: "IfNotPresent"
# OCULAR_RESULTS_DIR is an environment variable containing the name
# of the folder that artifacts should be collected from.
# See 'Artifacts' section of the manual for more info
command: ["/bin/sh", "-c"]
args: ["semgrep scan --json --config=auto > $OCULAR_RESULTS_DIR/semgrep.json"]
# Here we define the artifacts to be collected
artifacts:
# Artifact uploads are relative to $OCULAR_RESULTS_DIR
- semgrep.json
# Here we reference the already created uploaders
# NOTE: this is just to demo the concept of uploaders
# Feel free to leave of the last section to continue with
# the tutorial with a working profile
uploaderRefs:
- name: "webhook" # This one comes bundled with Ocular Default Integrations
# If you reference an uploader that is not created or doesn't
# exists, the creation will fail.
# Uploaders support parameters passed as env vars
# To see what parameters are accepts, view the uploader definition
# by running 'kubectl get uploader $UPLOADER_NAME'
parameters:
- name: "METHOD"
value: "POST"
- name: "URL"
value: "https://upload.example.com/scan-result"
The contents of this file will be used as the payload for our request.
In the snippet below we supply this file to kubectl apply where it
will create the resource if it doesn’t exist, or update it if it does.
kubectl apply -f example-profile.yaml
Step 2: Check Downloaders
In addition to a profile we will need to tell Ocular how we would like to download our target. In this example we would like to clone a git repository, so we can use the bundled git downloader for this. This downloader will assume the target identifier is a git clone URL and the optional target version as a git reference (if not given, will clone latest).
NOTE: To see all available default downloaders, either run kubectl get downloaders or view the
default downloaders section in the Ocular manual.
Step 3: Run a Pipeline
Now its time to trigger the pipeline and actually scan our repository. We will need to supply:
- The profile to use (in this case ‘
example-profile’, from step 1) - The target (our git repository). This example will use the Ocular repository itself ‘
https://github.com/crashappsec/ocular’ - The downloader to use, in this case the default git downloader: ‘
ocular-defaults-git’
Run the following bash in your terminal to create a new pipeline:
# we use create here so we can generate a random name for the pipeline.
# This allows us to run this multiple times with different arguments
# and not update the same pipeline
cat <<EOF | kubectl create -f -
apiVersion: ocular.crashoverride.run/v1beta1
kind: Pipeline
metadata:
generate-name: example-pipeline-
spec:
profileRef:
# reference the profile we created before
name: example-profile
downloaderRef:
# reference the default bundled git downloader
name: ocular-defaults-git
target:
identifier: "https://github.com/crashappsec/ocular"
ttlSecondsAfterFinished: 180 # Cleanup pipeline 3 minutes after finishing
EOF
The output of the following command should be something similar to the following:
pipeline.ocular.crashoverride.run/example-pipeline-NNNNN created
Checking the running pods in the namespace where the pipeline was created should reveal 2 newly created pods: one for the downloader and scanners, and another for the uploaders.
After a bit of time, we should be able to check on our 3rd party upload.example.com endpoint and see the file has been uploaded!
Configuring clone access to private repository
Ocular also supports integrating with kubernetes secrets to provide the downloaders, scanners and uploaders with sensitive data.
Downloaders can leverage this in order to authenticate
and download protected resources. The default git downloader
uses the secrets to support a custom gitconfig file.
This can be used to authenticate the git clone that is performed.
Step 1: Configuring secret access
NOTE: Currently the default downloader only supports configuration via a gitconfig. In the future we plan to support authenticating via other methods like GitHub apps installations or git credential helpers.
The ‘ocular-defaults-git’ downloader will read the git config secret from a secret key named ‘gitconfig’ located
in the secret ‘downloader-secrets’.
(you can see that yourself by running kubectl get downloader ocular-defaults-git).
To set this secret lets first create a git config to access a private GitHub repository.
We will need a GitHub token with read repository access, this can be created here.
Once generated, we should configure the git-config like so (replacing YOUR_TOKEN_HERE with your new token):
# assume this file is named 'my.gitconfig'
[url "https://YOUR_TOKEN_HERE@github.com"]
insteadOf = "https://github.com"
We can then set this secret in Kubernetes using:
kubectl create secret generic downloader-secrets --from-file=gitconfig=my.gitconfig
Step 2: Re-run scan
Now lets re-trigger our scan from before but this time with
the private repository https://github.com/my-org/private-repository:
Everything else we supply remains the same:
- The profile to use (
example-profile) - The downloader (
ocular-defaults-git). We configured this but we don’t need to change anything, when invoked it will use the secret only if it exists!
cat <<EOF | kubectl create -f -
apiVersion: ocular.crashoverride.run/v1beta1
kind: Pipeline
metadata:
generate-name: example-pipeline-
spec:
profileRef:
# reference the profile we created before
name: example-profile
downloaderRef:
# reference the default bundled git downloader
name: ocular-defaults-git
target:
identifier: "https://github.com/my-org/private-repository"
ttlSecondsAfterFinished: 180 # Cleanup pipeline 3 minutes after finishing
EOF
The output should now be:
pipeline.ocular.crashoverride.run/example-pipeline-NNNNN created
Step 3: Validate
You should now be able to check your upload result to see the repo was successfully cloned.
Debugging Issues & Viewing Logs
Ocular encourages you to view its “internals” and how it interacts with the Kubernetes cluster. Sometimes the best way to debug or troubleshoot is to use kubectl (or any kubernetes client) to investigate.
Ocular uses Kubernetes jobs to perform both pipelines and searches. For pipelines specifically, Ocular will create two jobs:
- A downloading and scanning job named ‘
[PIPELINE_NAME]-scan’, where ‘[PIPELINE_NAME]’ is the name of the pipeline. The Job will have an init container for the downloader and the main containers are the scanners from the profile. - An uploading job named named ‘
[PIPELINE_NAME]-uploader’, where ‘[PIPELINE_NAME]’ is the name of its pipeline The job will have the uploaders from the profile as the main containers.
We recommend you use kubectl when issues arise and use this knowledge to troubleshoot.
For example, viewing the logs of a pipeline can be done with:
# View logs for a pipeline
# this assumes $PIPELINE_NAME is set to the name of the pipeline
kubectl logs --all-containers --all-pods -l ocular.crashoverride.run/pipeline=$PIPELINE_NAME
This will get all pods that have the label ocular.crashoverride.run/pipeline=$PIPELINE_NAME
(which the pods from pipeline jobs do).
It should return 2 pods, one for scans and one for uploads. The logs command is then configured to
return the logs from both pods.
Summary
In this guide, you’ve learned how to:
- Run a basic pipeline
- Configure clone access to a private repository
- Debug issues via kubectl
These basic operations form the foundation for more advanced Ocular usage. As you become more familiar with Ocular, you can explore more complex configurations and customize code scanning to fit your use case
For more detailed information, refer to the Ocular manual