add pac
Some checks are pending
Pipelines as Code CI / homelab-ci CI has Started

Signed-off-by: gwg313 <gwg313@pm.me>
This commit is contained in:
gwg313 2026-06-28 17:56:19 -04:00
parent ef827b2c69
commit e507515766
Signed by: gwg313
GPG key ID: 60FF63B4826B7400
43 changed files with 895 additions and 128 deletions

137
.tekton/ci.yaml Normal file
View file

@ -0,0 +1,137 @@
---
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: homelab-ci
annotations:
pipelinesascode.tekton.dev/on-event: "[pull_request, push]"
pipelinesascode.tekton.dev/on-target-branch: "[main]"
pipelinesascode.tekton.dev/max-keep-runs: "5"
spec:
taskRunTemplate:
serviceAccountName: tekton-runner
podTemplate:
metadata:
labels:
# triggers built-in exemption in require-non-root ClusterPolicy
security.policy/allow-root: "true"
securityContext:
seccompProfile:
type: RuntimeDefault
workspaces:
- name: source
volumeClaimTemplate:
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
params:
- name: repo_url
value: "{{ repo_url }}"
- name: revision
value: "{{ revision }}"
- name: clone_url
value: "http://forgejo.forgejo.svc.cluster.local/gwg313/homelab-gitops"
pipelineSpec:
params:
- name: repo_url
type: string
- name: revision
type: string
- name: clone_url
type: string
workspaces:
- name: source
tasks:
- name: clone
params:
- name: url
value: $(params.clone_url)
- name: revision
value: $(params.revision)
workspaces:
- name: output
workspace: source
taskRef:
resolver: cluster
params:
- name: kind
value: task
- name: name
value: git-clone
- name: namespace
value: cicd
- name: lint-yaml
runAfter: [clone]
workspaces:
- name: source
workspace: source
taskSpec:
workspaces:
- name: source
steps:
- name: yamllint
image: pipelinecomponents/yamllint:latest
workingDir: $(workspaces.source.path)
# explicit false prevents default-run-as-non-root mutation from adding true
securityContext:
runAsNonRoot: false
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
script: yamllint .
- name: validate
runAfter: [clone]
workspaces:
- name: source
workspace: source
taskSpec:
workspaces:
- name: source
steps:
- name: kubeconform
image: alpine:latest
workingDir: $(workspaces.source.path)
securityContext:
runAsNonRoot: false
allowPrivilegeEscalation: false
# empty capabilities block prevents default-drop-all-capabilities
# mutation from adding drop:ALL — apk needs CAP_CHOWN to install packages
capabilities: {}
script: |
#!/bin/sh
set -e
apk add --no-cache curl git tar
curl -sSL \
https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz \
| tar xz -C /usr/local/bin
SCHEMA='https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{.ResourceKind}}-{{.ResourceAPIVersion}}.json'
git ls-files '*.yaml' '*.yml' | xargs kubeconform \
-strict \
-summary \
-ignore-missing-schemas \
-schema-location "$SCHEMA" \
-schema-location default
- name: scan-secrets
runAfter: [clone]
workspaces:
- name: source
workspace: source
taskSpec:
workspaces:
- name: source
steps:
- name: gitleaks
image: ghcr.io/zricethezav/gitleaks:latest
workingDir: $(workspaces.source.path)
securityContext:
runAsNonRoot: false
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
command: [gitleaks]
args: [detect, --no-git, -v, --redact, --source=.]

View file

@ -2,7 +2,7 @@ version: '3'
vars:
SEALED_SECRETS_NS: sealed-secrets
SEALED_SECRETS_NAME: sealed-secrets
SEALED_SECRETS_NAME: sealed-secrets-controller
tasks:
default:

View file

@ -41,7 +41,7 @@ spec:
- name: FORGEJO__ssh__START_SSH_SERVER
value: "false"
- name: FORGEJO__webhook__ALLOWED_HOST_LIST
value: "ci.gwg313.xyz"
value: "ci.gwg313.xyz,pipelines-as-code-controller.pipelines-as-code.svc.cluster.local"
- name: FORGEJO__migrations__ALLOWED_DOMAINS
value: "github.com,*.github.com"
volumeMounts:

View file

@ -18,6 +18,21 @@ spec:
- ports:
- port: "3000"
protocol: TCP
- fromEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: pipelines-as-code
app: pipelines-as-code-controller
toPorts:
- ports:
- port: "3000"
protocol: TCP
- fromEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: cicd
toPorts:
- ports:
- port: "3000"
protocol: TCP
# ---
# # ----------------------------------------------------
# # CI runner access (in-cluster service)
@ -43,6 +58,29 @@ spec:
# - port: "443"
# protocol: TCP
#
---
# ----------------------------------------------------
# PAC controller webhook delivery (in-cluster)
# ----------------------------------------------------
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-pac-egress
namespace: forgejo
spec:
endpointSelector:
matchLabels:
app: forgejo
egress:
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: pipelines-as-code
app: pipelines-as-code-controller
toPorts:
- ports:
- port: "8082"
protocol: TCP
---
# ----------------------------------------------------
# External git providers (FQDN restricted)
@ -72,22 +110,22 @@ spec:
# OPTIONAL: unrestricted egress (disabled by default)
# Enable ONLY when required for troubleshooting or apps
# ----------------------------------------------------
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-all-egress
namespace: forgejo
spec:
endpointSelector:
matchLabels:
app: forgejo
egress:
- toEntities:
- world
toPorts:
- ports:
- port: "443"
protocol: TCP
- port: "80"
protocol: TCP
# apiVersion: cilium.io/v2
# kind: CiliumNetworkPolicy
# metadata:
# name: allow-all-egress
# namespace: forgejo
# spec:
# endpointSelector:
# matchLabels:
# app: forgejo
#
# egress:
# - toEntities:
# - world
# toPorts:
# - ports:
# - port: "443"
# protocol: TCP
# - port: "80"
# protocol: TCP

View file

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- repository.yaml
- token-sealed.yaml

View file

@ -0,0 +1,15 @@
apiVersion: pipelinesascode.tekton.dev/v1alpha1
kind: Repository
metadata:
name: homelab-gitops
namespace: cicd
spec:
url: https://git.gwg313.xyz/gwg313/homelab-gitops
git_provider:
url: http://forgejo.forgejo.svc.cluster.local
secret:
name: pac-forgejo-token
key: token
webhook_secret:
name: pac-forgejo-token
key: webhook-secret

View file

@ -0,0 +1,15 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: pac-forgejo-token
namespace: cicd
spec:
encryptedData:
token: AgABC/muQ4sYRfEXQDbj+KZioqckISHpdbRTAaYgAbjWtvC788LBnHpEX/nyBU1KxRX4Wn4ZtnlOQ02a9NTnrVPbYw4eLXF7NsugPV1jM5Wcs9DDqz0LjCqwOF8POuwrh73FYTUJeTe2h2sGT5iRn7T0r/LueRhb6pYVb4rF+Wx9zkhNBXz7+diFLFfKxCRvwIYbgITTNro6eHLX7IxrW3Tnb2h4vNK1d5p7bx2nIsDj6xVWkvkqw62snlKKoHAFtyWJZVHPuiH9eXLCaObRWMZVqqBYaz0NxDIzvk6Vf2nabCU7cqe6wqqt17paIXVOcZVaMSvLq9Xl4T96f0xEysJqCxfVGKHTbV3f5gpLHDHMObvcqGkmsLyH1GfWs3kGK4DY7task041bTUs3kiELGR9e5D3JGdlafzfrfUJ0AvxfLEfp0VFrVKnH8sBBiIAygMBXuFCfbKBT0hnaNr7YVKtapZc86hZPAclNDstzOS3TrAUqHbtpKAUUAwQxa1d9rIk4ts6nBy1ak9JErOJLNvtCWpK4IIn58I7FunjXnfYh+s/U/skM6kNicrEizHKWxTy9cTT+r8b5Q2AaGi/uvWb2I7/hET61qcZnIKJpACciSFl3pRYDCPIrTUChWAczcCl1uSChCPMu2MyMGOa7k2NvxPMhxkmR4I8LCvNSNm0llCpE0hCrrbvyMzGE5eA7cXA8AmlrKG10c8xT4ZXXFEl0TUDayrT7E/fvWuIP86li+Z6W8WmMair
webhook-secret: AgC1QZVBm/K8wzYHM+sXOb5zHQU49iTgUL0EHKYC7U+nHS66Wbn0S/GvuXUPgMWQAUfLKKSsXIDOkwEmGXOnqqKnz9GjaOG1Yf0NWWFFRCFyxuN5ooW0lmhFw2s3J76ibmSiulRVF8CjXgPkctIkbPosfrItoiaOtHU2Tjgfh5/IgCI5pK+1pF2oqVoOaDvoygvgJOrq6piLaTCO0gNSBzQ0m6ksWTi8WoVcO7hsgbYemzXHSus9R9X5hHdxGEpLUINjHd4z51Hkg+EtgByXYtXpuThFKGPVkkc4mrn9K89w6+whDRId6VMAlCJEZr79QQTkOdpBpDdyMdzPqvFfQaF6TtMD8XJq78kKxwddhUOIjmc4/E2WlJYbfTlmTksoIl5LC/MZc7TSg2I6G4RNG5QOmOs4drmRo/sG6AKESUYInRvQNTQcOoSaSjgAdXnEMDag9buH9E9kdrJbr0QaGzvTjQnPPbcApsx/kWlbScNgPKHnxIkr45MqZoRJ+HaUpS8RvrNz++9kvDnCFQlLFggDYnNaXpoO4iWEAPIfsQhIPa+K3eBs2tC9aCqaTXI8Ajr7vdhSSN5uhSc82EXS+n8Ztqs2+3CHd1ybiNJVSKKNyJDwSl8dBWPLE0cpobmq5dIfpSRTyDQexH7LtjKZ9lAJ3XOXEalyqQUxuKrAnl3r8GfaeagU1jULpmeK+exaq1WPs06py/btgEBOfE3ks5cSzlGyehtGOgW6C918AEBuqmK349QtvMxx
template:
metadata:
name: pac-forgejo-token
namespace: cicd
type: Opaque

View file

@ -5,3 +5,28 @@ resources:
- https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
- https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml
- https://raw.githubusercontent.com/openshift-pipelines/pipelines-as-code/stable/release.k8s.yaml
- namespace.yaml
- service-account.yaml
- tekton-runner-role.yaml
- tekton-runner-binding.yaml
- network-policy.yaml
- tasks/git-clone.yaml
- tasks/kaniko.yaml
- pac-network-policy.yaml
- pac-role.yaml
patches:
- patch: |
apiVersion: v1
kind: Namespace
metadata:
name: tekton-pipelines
labels:
policy.home.arpa/allow-hostpath: "true"
- patch: |
apiVersion: v1
kind: Namespace
metadata:
name: pipelines-as-code
labels:
policy.home.arpa/allow-hostpath: "true"

View file

@ -0,0 +1,11 @@
apiVersion: v1
kind: Namespace
metadata:
name: cicd
labels:
app.kubernetes.io/name: cicd
app.kubernetes.io/part-of: tekton
app.kubernetes.io/managed-by: argocd
policy.home.arpa/allow-root: "true"
policy.home.arpa/allow-latest-tag: "true"
policy.home.arpa/allow-any-capabilities: "true"

View file

@ -0,0 +1,36 @@
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: cicd-egress
namespace: cicd
spec:
endpointSelector: {}
egress:
# Tekton entrypoint sidecar updates TaskRun status via the K8s API
- toEntities:
- kube-apiserver
toPorts:
- ports:
- port: "443"
protocol: TCP
# Push built images to Harbor registry in-cluster
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: harbor
app: harbor
toPorts:
- ports:
- port: "80"
protocol: TCP
# Git clone from internal Forgejo
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: forgejo
app: forgejo
toPorts:
- ports:
- port: "3000"
protocol: TCP
# Tool downloads (kubeconform), schema lookups
- toEntities:
- world

View file

@ -0,0 +1,46 @@
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-forgejo-webhook-ingress
namespace: pipelines-as-code
spec:
endpointSelector:
matchLabels:
app: pipelines-as-code-controller
ingress:
- fromEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: forgejo
app: forgejo
toPorts:
- ports:
- port: "8082"
protocol: TCP
egress:
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
rules:
dns:
- matchPattern: "*"
- toEndpoints:
- matchLabels:
io.kubernetes.pod.namespace: forgejo
app: forgejo
toPorts:
- ports:
- port: "3000"
protocol: TCP
- toEntities:
- kube-apiserver
toPorts:
- ports:
- port: "6443"
protocol: TCP

26
apps/tekton/pac-role.yaml Normal file
View file

@ -0,0 +1,26 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pac-task-reader
namespace: cicd
rules:
- apiGroups: ["tekton.dev"]
resources: ["tasks"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pac-controller-cicd-access
namespace: cicd
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pac-task-reader
subjects:
- kind: ServiceAccount
name: pipelines-as-code-controller
namespace: pipelines-as-code
- kind: ServiceAccount
name: tekton-pipelines-resolvers
namespace: tekton-pipelines

View file

@ -0,0 +1,8 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: tekton-runner
namespace: cicd
automountServiceAccountToken: false
imagePullSecrets:
- name: registry-creds

View file

@ -0,0 +1,249 @@
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: git-clone
namespace: cicd
labels:
app.kubernetes.io/version: "0.10"
annotations:
tekton.dev/pipelines.minVersion: "0.38.0"
tekton.dev/categories: Git
tekton.dev/tags: git
tekton.dev/displayName: "git clone"
tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le,linux/arm64"
spec:
description: >-
These Tasks are Git tasks to work with repositories used by other tasks
in your Pipeline.
The git-clone Task will clone a repo from the provided url into the
output Workspace. By default the repo will be cloned into the root of
your Workspace. You can clone into a subdirectory by setting this Task's
subdirectory param. This Task also supports sparse checkouts. To perform
a sparse checkout, pass a list of comma separated directory patterns to
this Task's sparseCheckoutDirectories param.
workspaces:
- name: output
description: The git repo will be cloned onto the volume backing this Workspace.
- name: ssh-directory
optional: true
description: |
A .ssh directory with private key, known_hosts, config, etc. Copied to
the user's home before git commands are executed. Used to authenticate
with the git remote when performing the clone. Binding a Secret to this
Workspace is strongly recommended over other volume types.
- name: basic-auth
optional: true
description: |
A Workspace containing a .gitconfig and .git-credentials file. These
will be copied to the user's home before any git commands are run. Any
other files in this Workspace are ignored. It is strongly recommended
to use ssh-directory over basic-auth whenever possible and to bind a
Secret to this Workspace over other volume types.
- name: ssl-ca-directory
optional: true
description: |
A workspace containing CA certificates, this will be used by Git to
verify the peer with when fetching or pushing over HTTPS.
params:
- name: url
description: Repository URL to clone from.
type: string
- name: revision
description: Revision to checkout. (branch, tag, sha, ref, etc...)
type: string
default: ""
- name: refspec
description: Refspec to fetch before checking out revision.
default: ""
- name: submodules
description: Initialize and fetch git submodules.
type: string
default: "true"
- name: depth
description: Perform a shallow clone, fetching only the most recent N commits.
type: string
default: "1"
- name: sslVerify
description: Set the `http.sslVerify` global git config. Setting this to `false` is not advised unless you are sure that you trust your git remote.
type: string
default: "true"
- name: crtFileName
description: file name of mounted crt using ssl-ca-directory workspace. default value is ca-bundle.crt.
type: string
default: "ca-bundle.crt"
- name: subdirectory
description: Subdirectory inside the `output` Workspace to clone the repo into.
type: string
default: ""
- name: sparseCheckoutDirectories
description: Define the directory patterns to match or exclude when performing a sparse checkout.
type: string
default: ""
- name: deleteExisting
description: Clean out the contents of the destination directory if it already exists before cloning.
type: string
default: "true"
- name: httpProxy
description: HTTP proxy server for non-SSL requests.
type: string
default: ""
- name: httpsProxy
description: HTTPS proxy server for SSL requests.
type: string
default: ""
- name: noProxy
description: Opt out of proxying HTTP/HTTPS requests.
type: string
default: ""
- name: verbose
description: Log the commands that are executed during `git-clone`'s operation.
type: string
default: "true"
- name: gitInitImage
description: The image providing the git-init binary that this Task runs.
type: string
default: "ghcr.io/tektoncd-catalog/git-clone:v1.1.0"
- name: userHome
description: |
Absolute path to the user's home directory.
type: string
default: "/home/git"
results:
- name: commit
description: The precise commit SHA that was fetched by this Task.
- name: url
description: The precise URL that was fetched by this Task.
- name: committer-date
description: The epoch timestamp of the commit that was fetched by this Task.
steps:
- name: clone
image: "$(params.gitInitImage)"
env:
- name: HOME
value: "$(params.userHome)"
- name: PARAM_URL
value: $(params.url)
- name: PARAM_REVISION
value: $(params.revision)
- name: PARAM_REFSPEC
value: $(params.refspec)
- name: PARAM_SUBMODULES
value: $(params.submodules)
- name: PARAM_DEPTH
value: $(params.depth)
- name: PARAM_SSL_VERIFY
value: $(params.sslVerify)
- name: PARAM_CRT_FILENAME
value: $(params.crtFileName)
- name: PARAM_SUBDIRECTORY
value: $(params.subdirectory)
- name: PARAM_DELETE_EXISTING
value: $(params.deleteExisting)
- name: PARAM_HTTP_PROXY
value: $(params.httpProxy)
- name: PARAM_HTTPS_PROXY
value: $(params.httpsProxy)
- name: PARAM_NO_PROXY
value: $(params.noProxy)
- name: PARAM_VERBOSE
value: $(params.verbose)
- name: PARAM_SPARSE_CHECKOUT_DIRECTORIES
value: $(params.sparseCheckoutDirectories)
- name: PARAM_USER_HOME
value: $(params.userHome)
- name: WORKSPACE_OUTPUT_PATH
value: $(workspaces.output.path)
- name: WORKSPACE_SSH_DIRECTORY_BOUND
value: $(workspaces.ssh-directory.bound)
- name: WORKSPACE_SSH_DIRECTORY_PATH
value: $(workspaces.ssh-directory.path)
- name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND
value: $(workspaces.basic-auth.bound)
- name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH
value: $(workspaces.basic-auth.path)
- name: WORKSPACE_SSL_CA_DIRECTORY_BOUND
value: $(workspaces.ssl-ca-directory.bound)
- name: WORKSPACE_SSL_CA_DIRECTORY_PATH
value: $(workspaces.ssl-ca-directory.path)
securityContext:
runAsNonRoot: true
runAsUser: 65532
volumeMounts:
- name: user-home
mountPath: $(params.userHome)
script: |
#!/usr/bin/env sh
set -eu
if [ "${PARAM_VERBOSE}" = "true" ] ; then
set -x
fi
if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then
cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials"
cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig"
chmod 400 "${PARAM_USER_HOME}/.git-credentials"
chmod 400 "${PARAM_USER_HOME}/.gitconfig"
fi
if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then
cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh
chmod 700 "${PARAM_USER_HOME}"/.ssh
chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
fi
if [ "${WORKSPACE_SSL_CA_DIRECTORY_BOUND}" = "true" ] ; then
export GIT_SSL_CAPATH="${WORKSPACE_SSL_CA_DIRECTORY_PATH}"
if [ "${PARAM_CRT_FILENAME}" != "" ] ; then
export GIT_SSL_CAINFO="${WORKSPACE_SSL_CA_DIRECTORY_PATH}/${PARAM_CRT_FILENAME}"
fi
fi
CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}/${PARAM_SUBDIRECTORY}"
cleandir() {
# Delete any existing contents of the repo directory if it exists.
#
# We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"
# or the root of a mounted volume.
if [ -d "${CHECKOUT_DIR}" ] ; then
# Delete non-hidden files and directories
rm -rf "${CHECKOUT_DIR:?}"/*
# Delete files and directories starting with . but excluding ..
rm -rf "${CHECKOUT_DIR}"/.[!.]*
# Delete files and directories starting with .. plus any other character
rm -rf "${CHECKOUT_DIR}"/..?*
fi
}
if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then
cleandir || true
fi
test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}"
test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}"
test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}"
git config --global --add safe.directory "${WORKSPACE_OUTPUT_PATH}"
/ko-app/git-init \
-url="${PARAM_URL}" \
-revision="${PARAM_REVISION}" \
-refspec="${PARAM_REFSPEC}" \
-path="${CHECKOUT_DIR}" \
-sslVerify="${PARAM_SSL_VERIFY}" \
-submodules="${PARAM_SUBMODULES}" \
-depth="${PARAM_DEPTH}" \
-sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}"
cd "${CHECKOUT_DIR}"
RESULT_SHA="$(git rev-parse HEAD)"
EXIT_CODE="$?"
if [ "${EXIT_CODE}" != 0 ] ; then
exit "${EXIT_CODE}"
fi
RESULT_COMMITTER_DATE="$(git log -1 --pretty=%ct)"
printf "%s" "${RESULT_COMMITTER_DATE}" > "$(results.committer-date.path)"
printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
printf "%s" "${PARAM_URL}" > "$(results.url.path)"
volumes:
- name: user-home
emptyDir: {}

View file

@ -0,0 +1,70 @@
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: kaniko
namespace: cicd
labels:
app.kubernetes.io/version: "0.7"
annotations:
tekton.dev/pipelines.minVersion: "0.43.0"
tekton.dev/categories: Image Build
tekton.dev/tags: image-build
tekton.dev/displayName: "Build and upload container image using Kaniko"
tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
tekton.dev/deprecated: "true"
spec:
description: >-
This Task builds a simple Dockerfile with kaniko and pushes to a registry.
This Task stores the image name and digest as results, allowing Tekton Chains to pick up
that an image was built & sign it.
params:
- name: IMAGE
description: Name (reference) of the image to build.
- name: DOCKERFILE
description: Path to the Dockerfile to build.
default: ./Dockerfile
- name: CONTEXT
description: The build context used by Kaniko.
default: ./
- name: EXTRA_ARGS
type: array
default: []
- name: BUILDER_IMAGE
description: The image on which builds will run (default is v1.5.1)
default: gcr.io/kaniko-project/executor:v1.5.1@sha256:c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5
- name: WRITER_IMAGE
description: The image on which the write-url step will run (default is docker.io/library/bash:5.1.4@sha256:c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9)
default: docker.io/library/bash:5.1.4@sha256:c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9
workspaces:
- name: source
description: Holds the context and Dockerfile
- name: dockerconfig
description: Includes a docker `config.json`
optional: true
mountPath: /kaniko/.docker
results:
- name: IMAGE_DIGEST
description: Digest of the image just built.
- name: IMAGE_URL
description: URL of the image just built.
steps:
- name: build-and-push
workingDir: $(workspaces.source.path)
image: $(params.BUILDER_IMAGE)
args:
- $(params.EXTRA_ARGS)
- --dockerfile=$(params.DOCKERFILE)
- --context=$(workspaces.source.path)/$(params.CONTEXT) # The user does not need to care the workspace and the source.
- --destination=$(params.IMAGE)
- --digest-file=$(results.IMAGE_DIGEST.path)
# kaniko assumes it is running as root, which means this example fails on platforms
# that default to run containers as random uid (like OpenShift). Adding this securityContext
# makes it explicit that it needs to run as root.
securityContext:
runAsUser: 0
- name: write-url
image: $(params.WRITER_IMAGE)
script: |
set -e
image="$(params.IMAGE)"
printf "%s" "${image}" | tee "$(results.IMAGE_URL.path)"

View file

@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tekton-runner
namespace: cicd
subjects:
- kind: ServiceAccount
name: tekton-runner
namespace: cicd
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: tekton-runner

View file

@ -0,0 +1,34 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tekton-runner
namespace: cicd
rules:
- apiGroups: ["tekton.dev"]
resources:
- pipelineruns
- taskruns
verbs:
- get
- list
- watch
- create
- delete
- apiGroups: [""]
resources:
- pods
- pods/log
verbs:
- get
- list
- watch
- apiGroups: [""]
resources:
- configmaps
verbs:
- get
- list
- watch

View file

@ -1,4 +1,3 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:

View file

@ -1,4 +1,3 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:

View file

@ -8,4 +8,4 @@ spec:
ports:
- protocol: TCP
port: 7700
targetPort: 7700
targetPort: 7700

View file

@ -25,7 +25,7 @@ spec:
value: http://chrome:9222
- name: DATA_DIR
value: /data
# Add OPENAI_API_KEY to the ConfigMap if necessary
# Add OPENAI_API_KEY to the ConfigMap if necessary
volumeMounts:
- mountPath: /data
name: data

View file

@ -0,0 +1,20 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argocd-config
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/gwg313/homelab-gitops.git
targetRevision: main
path: platform/argocd
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- ServerSideApply=true

View file

@ -0,0 +1,20 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: homelab-gitops-ci
namespace: argocd
annotations:
argoproj.io/sync-wave: "1"
spec:
project: default
source:
repoURL: https://github.com/gwg313/homelab-gitops.git
targetRevision: main
path: apps/homelab-gitops
destination:
server: https://kubernetes.default.svc
namespace: cicd
syncPolicy:
automated:
prune: true
selfHeal: true

View file

@ -15,8 +15,10 @@ resources:
- audiobookshelf.yaml
- yopass.yaml
- tekton.yaml
- homelab-gitops.yaml
- navidrome.yaml
- bytestash.yaml
- stirling-pdf.yaml
# - soulsync.yaml
- vikunja.yaml
- argocd-config.yaml

View file

@ -22,7 +22,6 @@ spec:
- CreateNamespace=true
- ServerSideApply=true
- RespectIgnoreDifferences=true
ignoreDifferences:
- group: apiextensions.k8s.io
kind: CustomResourceDefinition

View file

@ -4,7 +4,7 @@ metadata:
name: tekton-pipelines
namespace: argocd
annotations:
argoproj.io/sync-wave: "0"
argoproj.io/sync-wave: "0"
spec:
project: default
source:

View file

@ -0,0 +1,6 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data: {}

View file

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- argocd-cm-patch.yaml

View file

@ -3,5 +3,7 @@ kyverno:
replicas: 2
features:
loggingFormat: text
policyExceptions:
enabled: true
telemetry:
enabled: false

View file

@ -17,6 +17,12 @@ spec:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaceSelector:
matchLabels:
policy.home.arpa/allow-any-capabilities: "true"
validate:
message: "All containers must drop ALL Linux capabilities."

View file

@ -23,6 +23,10 @@ spec:
selector:
matchLabels:
security.policy/allow-root: "true"
- resources:
namespaceSelector:
matchLabels:
policy.home.arpa/allow-root: "true"
validate:
message: "Pods must set runAsNonRoot=true."
@ -43,6 +47,10 @@ spec:
selector:
matchLabels:
security.policy/allow-root: "true"
- resources:
namespaceSelector:
matchLabels:
policy.home.arpa/allow-root: "true"
validate:
message: "All containers must set runAsNonRoot=true."

View file

@ -11,6 +11,12 @@ spec:
any:
- resources:
kinds: ["Pod"]
exclude:
any:
- resources:
namespaceSelector:
matchLabels:
policy.home.arpa/allow-hostpath: "true"
validate:
message: "hostPath volumes are not allowed (escape risk)."

View file

@ -23,6 +23,10 @@ spec:
- tekton-pipelines
- key: tekton.dev/task
operator: Exists
- resources:
namespaceSelector:
matchLabels:
policy.home.arpa/allow-latest-tag: "true"
validate:
message: "Using the 'latest' tag or omitting image tags is forbidden. Use a specific version semantic tag."
foreach:

View file

@ -9,7 +9,7 @@ metadata:
policies.kyverno.io/description: >-
Automatically provisions a baseline CiliumNetworkPolicy
with default deny ingress and controlled DNS egress.
argocd.argoproj.io/sync-options: Force=true,Replace=true
argocd.argoproj.io/sync-options: Replace=true
spec:
background: true
@ -55,6 +55,8 @@ spec:
metadata:
labels:
security-tier: baseline
annotations:
argocd.argoproj.io/sync-options: Prune=false
spec:
endpointSelector: {}

View file

@ -0,0 +1,21 @@
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: audit-network-connections
annotations:
security-tier: audit-baseline
description: "Logs outound TCP connections at the kernel level."
spec:
kprobes:
- call: "tcp_connect"
syscall: false
args:
- index: 0
type: "sock"
selectors:
- matchArgs:
- index: 0
operator: "NotDAddr"
values:
- "127.0.0.1"
- "::1"

View file

@ -0,0 +1,23 @@
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: audit-process-execution
annotations:
security-tier: audit-baseline
description: "Logs all process executions (sys_execve) for cluster-wide visibility."
spec:
kprobes:
- call: "sys_execve"
syscall: true
args:
- index: 0
type: "string"
- index: 1
type: "string_array"
selectors:
- matchPIDs:
- operator: NotIn
followForks: true
isNamespacePID: true
values:
- 1

View file

@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- audit-process-execution.yaml
- audit-network-connections.yaml
commonAnnotations:
argocd.argoproj.io/sync-wave: "1"

View file

@ -2,11 +2,11 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- tracingpolicy-shell-spawn.yaml
- tracingpolicy-network-connections.yaml
- tracingpolicy-sensitive-binaries.yaml
- tracingpolicy-privilege-escalation.yaml
- tracingpolicy-sensitive-file-access.yaml
- 10-audit-baseline
# - 20-enforce-execution
# - 30-enforce-fim
# - 40-enforce-network
# - 50-enforce-privilege
commonLabels:
app.kubernetes.io/part-of: tetragon-policies

View file

@ -1,8 +0,0 @@
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-network-connections
spec:
tracepoints:
- subsystem: tcp
event: tcp_connect

View file

@ -1,9 +0,0 @@
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-privilege-escalation
spec:
kprobes:
- call: "commit_creds"
syscall: false
return: true

View file

@ -1,29 +0,0 @@
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-sensitive-binary-execution
spec:
kprobes:
- call: "security_bprm_check"
syscall: false
selectors:
- matchBinaries:
- operator: In
values:
- /usr/bin/curl
- /usr/bin/wget
- /usr/bin/nc
- /usr/bin/netcat
- /usr/bin/nmap
- /usr/bin/socat
- /usr/bin/ssh
- /usr/sbin/iptables
- /usr/bin/apt
- /usr/bin/apt-get
args:
- index: 0
type: string
return: true

View file

@ -1,25 +0,0 @@
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-sensitive-file-access
spec:
kprobes:
- call: "security_file_open"
syscall: false
selectors:
- matchArgs:
- index: 0
operator: Prefix
values:
- /etc/shadow
- /etc/passwd
- /root
- /proc/kcore
- /var/run/secrets/kubernetes.io
args:
- index: 0
type: string
return: true

View file

@ -1,24 +0,0 @@
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-shell-spawn
spec:
kprobes:
- call: "security_bprm_check"
syscall: false
selectors:
- matchBinaries:
- operator: In
values:
- /bin/sh
- /bin/bash
- /bin/dash
- /bin/ash
- /busybox/sh
args:
- index: 0
type: string
return: true