Skip to content

Commit

Permalink
Add image scanner
Browse files Browse the repository at this point in the history
Signed-off-by: Pete Wall <pete.wall@grafana.com>
  • Loading branch information
petewall committed Oct 30, 2024
1 parent 0e4f3f5 commit 5150565
Show file tree
Hide file tree
Showing 9 changed files with 6,730 additions and 0 deletions.
60 changes: 60 additions & 0 deletions .github/workflows/security-scans.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
name: Security Scans

on:

Check failure on line 4 in .github/workflows/security-scans.yml

View workflow job for this annotation

GitHub Actions / runner / yamllint

[yamllint] reported by reviewdog 🐶 [warning] truthy value should be one of [false, true] (truthy) Raw Output: ./.github/workflows/security-scans.yml:4:1: [warning] truthy value should be one of [false, true] (truthy)
push:
branches: ["main"]
paths:
- 'charts/k8s-monitoring/docs/examples/features/all-features/output.yaml'
pull_request:
paths:
- 'charts/k8s-monitoring/docs/examples/features/all-features/output.yaml'
workflow_dispatch:

jobs:
list-container-images:
name: List Container Images
runs-on: ubuntu-latest
outputs:
images: ${{ steps.list_images.outputs.images }}
steps:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'
check-latest: true

- name: Install yq
run: pip install yq

- name: List Container Images
id: list_images
run: |

Check failure on line 32 in .github/workflows/security-scans.yml

View workflow job for this annotation

GitHub Actions / runner / actionlint

[actionlint] reported by reviewdog 🐶 shellcheck reported issue in this script: SC2002:style:7:20: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead [shellcheck] Raw Output: .github/workflows/security-scans.yml:32:9: shellcheck reported issue in this script: SC2002:style:7:20: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead [shellcheck]
file=charts/k8s-monitoring/docs/examples/features/all-features/output.yaml
yq -r -o json '. | select(.kind=="DaemonSet") | .spec.template.spec.containers[].image' "${file}" > images.txt
yq -r -o json '. | select(.kind=="Deployment") | .spec.template.spec.containers[].image' "${file}" > images.txt
yq -r -o json '. | select(.kind=="Job") | .spec.template.spec.containers[].image' "${file}" > images.txt
yq -r -o json '. | select(.kind=="Pod") | .spec.containers[].image' "${file}" > images.txt
yq -r -o json '. | select(.kind=="StatefulSet") | .spec.template.spec.containers[].image' "${file}" > images.txt
echo "images=$(cat images.txt | sort --unique | jq --raw-input --slurp --compact-output 'split("\n") | map(select(. != ""))')" >> "${GITHUB_OUTPUT}"
scan-container-images:
name: Scan Container Images
needs: list-container-images
runs-on: ubuntu-latest
strategy:
matrix:
image: ${{ fromJson(needs.list-container-images.outputs.images) }}
fail-fast: false
steps:
- name: Run Trivy
uses: aquasecurity/trivy-action

Check failure on line 51 in .github/workflows/security-scans.yml

View workflow job for this annotation

GitHub Actions / runner / actionlint

[actionlint] reported by reviewdog 🐶 specifying action "aquasecurity/trivy-action" in invalid format because ref is missing. available formats are "{owner}/{repo}@{ref}" or "{owner}/{repo}/{path}@{ref}" [action] Raw Output: .github/workflows/security-scans.yml:51:15: specifying action "aquasecurity/trivy-action" in invalid format because ref is missing. available formats are "{owner}/{repo}@{ref}" or "{owner}/{repo}/{path}@{ref}" [action]
with:
image-ref: ${{ matrix.image }}
format: sarif
output: trivy-results.sarif

- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<!--
(NOTE: Do not edit README.md directly. It is a generated file!)
( To make changes, please modify values.yaml or description.txt and run `make examples`)
-->
# Example: features/all-features/values.yaml

## Values

```yaml
---
cluster:
name: all-features-cluster

destinations:
- name: otlpGateway
type: otlp
url: https://otlp.example.com:4317/v1/traces
auth:
type: basic
username: "my-username"
password: "my-password"
metrics: { enabled: true }
logs: { enabled: true }
traces: { enabled: true }
- name: pyroscope
type: pyroscope
url: http://pyroscope.example.com

# Features
clusterMetrics:
enabled: true
kepler: { enabled: true }
clusterEvents: { enabled: true }

podLogs: { enabled: true }
applicationObservability:
enabled: true
receivers:
grpc:
enabled: true
annotationAutodiscovery: { enabled: true }
prometheusOperatorObjects: { enabled: true }
profiling: { enabled: true }
integrations:
alloy:
instances:
- name: alloy

# Collectors
alloy-metrics: { enabled: true }

alloy-logs: { enabled: true }

alloy-singleton: { enabled: true }
alloy-receiver:
enabled: true
alloy:
extraPorts:
- name: otlp-grpc
port: 4317
targetPort: 4317
protocol: TCP
alloy-profiles: { enabled: true }```
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// Destination: otlpGateway (otlp)
otelcol.receiver.prometheus "otlpgateway" {
output {
metrics = [otelcol.processor.transform.otlpgateway.input]
}
}
otelcol.receiver.loki "otlpgateway" {
output {
logs = [otelcol.processor.transform.otlpgateway.input]
}
}
otelcol.auth.basic "otlpgateway" {
username = nonsensitive(remote.kubernetes.secret.otlpgateway.data["username"])
password = remote.kubernetes.secret.otlpgateway.data["password"]
}

otelcol.processor.transform "otlpgateway" {
error_mode = "ignore"
metric_statements {
context = "resource"
statements = ["set(attributes[\"k8s.cluster.name\"], \"all-features-cluster\") where attributes[\"k8s.cluster.name\"] == nil"]
}
log_statements {
context = "resource"
statements = ["set(attributes[\"k8s.cluster.name\"], \"all-features-cluster\") where attributes[\"k8s.cluster.name\"] == nil"]
}
trace_statements {
context = "resource"
statements = ["set(attributes[\"k8s.cluster.name\"], \"all-features-cluster\") where attributes[\"k8s.cluster.name\"] == nil"]
}

output {
metrics = [otelcol.exporter.otlp.otlpgateway.input]
logs = [otelcol.exporter.otlp.otlpgateway.input]
traces = [otelcol.exporter.otlp.otlpgateway.input]
}
}
otelcol.exporter.otlp "otlpgateway" {
client {
endpoint = "https://otlp.example.com:4317/v1/traces"
headers = {
"X-Scope-OrgID" = nonsensitive(remote.kubernetes.secret.otlpgateway.data["tenantId"]),
}
tls {
insecure = false
insecure_skip_verify = false
ca_pem = nonsensitive(remote.kubernetes.secret.otlpgateway.data["ca"])
cert_pem = nonsensitive(remote.kubernetes.secret.otlpgateway.data["cert"])
key_pem = remote.kubernetes.secret.otlpgateway.data["key"]
}
}
}

remote.kubernetes.secret "otlpgateway" {
name = "otlpgateway-ko-k8s-monitoring"
namespace = "default"
}

// Feature: Pod Logs
declare "pod_logs" {
argument "logs_destinations" {
comment = "Must be a list of log destinations where collected logs should be forwarded to"
}

discovery.relabel "filtered_pods" {
targets = discovery.kubernetes.pods.targets
rule {
source_labels = ["__meta_kubernetes_namespace"]
action = "replace"
target_label = "namespace"
}
rule {
source_labels = ["__meta_kubernetes_pod_name"]
action = "replace"
target_label = "pod"
}
rule {
source_labels = ["__meta_kubernetes_pod_container_name"]
action = "replace"
target_label = "container"
}
rule {
source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
separator = "/"
action = "replace"
replacement = "$1"
target_label = "job"
}

// set the container runtime as a label
rule {
action = "replace"
source_labels = ["__meta_kubernetes_pod_container_id"]
regex = "^(\\S+):\\/\\/.+$"
replacement = "$1"
target_label = "tmp_container_runtime"
}
}

discovery.kubernetes "pods" {
role = "pod"
selectors {
role = "pod"
field = "spec.nodeName=" + env("HOSTNAME")
}
}

discovery.relabel "filtered_pods_with_paths" {
targets = discovery.relabel.filtered_pods.output

rule {
source_labels = ["__meta_kubernetes_pod_uid", "__meta_kubernetes_pod_container_name"]
separator = "/"
action = "replace"
replacement = "/var/log/pods/*$1/*.log"
target_label = "__path__"
}
}

local.file_match "pod_logs" {
path_targets = discovery.relabel.filtered_pods_with_paths.output
}

loki.source.file "pod_logs" {
targets = local.file_match.pod_logs.targets
forward_to = [loki.process.pod_logs.receiver]
}

loki.process "pod_logs" {
stage.match {
selector = "{tmp_container_runtime=~\"containerd|cri-o\"}"
// the cri processing stage extracts the following k/v pairs: log, stream, time, flags
stage.cri {}

// Set the extract flags and stream values as labels
stage.labels {
values = {
flags = "",
stream = "",
}
}
}

stage.match {
selector = "{tmp_container_runtime=\"docker\"}"
// the docker processing stage extracts the following k/v pairs: log, stream, time
stage.docker {}

// Set the extract stream value as a label
stage.labels {
values = {
stream = "",
}
}
}

// Drop the filename label, since it's not really useful in the context of Kubernetes, where we already have cluster,
// namespace, pod, and container labels. Drop any structured metadata. Also drop the temporary
// container runtime label as it is no longer needed.
stage.label_drop {
values = [
"filename",
"tmp_container_runtime",
]
}
forward_to = argument.logs_destinations.value
}
}
pod_logs "feature" {
logs_destinations = [
otelcol.receiver.loki.otlpgateway.receiver,
]
}
Loading

0 comments on commit 5150565

Please sign in to comment.