Skip to content
Open
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
23 changes: 18 additions & 5 deletions .github/linters/.checkov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,21 @@ directory:
skip-path:
- tests
skip-check:
- CKV_K8S_49 # Minimize wildcard use in Roles and ClusterRoles
- CKV_K8S_155 # Minimize ClusterRoles that grant control over validating or mutating admission webhook configurations
- CKV_K8S_156 # Minimize ClusterRoles that grant permissions to approve CertificateSigningRequests
- CKV_K8S_157 # Minimize Roles and ClusterRoles that grant permissions to bind RoleBindings or ClusterRoleBindings
- CKV_K8S_158 # Minimize Roles and ClusterRoles that grant permissions to escalate Roles or ClusterRoles
# CKV_K8S_49: Minimize wildcard use in Roles and ClusterRoles
- CKV_K8S_49
# CKV_K8S_155: ClusterRoles for admission webhook configurations
- CKV_K8S_155
# CKV_K8S_156: ClusterRoles to approve CertificateSigningRequests
- CKV_K8S_156
# CKV_K8S_157: Roles/ClusterRoles to bind RoleBindings or ClusterRoleBindings
- CKV_K8S_157
# CKV_K8S_158: Roles/ClusterRoles to escalate Roles or ClusterRoles
- CKV_K8S_158
# CKV_K8S_38: S3 setup job needs SA token for oc CLI
- CKV_K8S_38
# CKV_K8S_40: Job uses OpenShift namespace default UID (high UID assigned at runtime, no anyuid needed)
- CKV_K8S_40
# CKV_K8S_43: Image digest; chart uses tag, digest is deployment-specific
- CKV_K8S_43
# CKV_SECRET_6: False positives - templates use placeholders, script refs to cluster secrets only
- CKV_SECRET_6
2 changes: 2 additions & 0 deletions .github/workflows/superlinter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ jobs:
with:
sl_env: |
VALIDATE_BIOME_FORMAT=false
# Exclude Helm chart templates (contain {{ }}; not valid YAML)
FILTER_REGEX_EXCLUDE=.*/templates/.*
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Helm template files contain {{ }} and are not plain YAML
templates/
8 changes: 8 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# AVD-KSV-0125: registry.redhat.io trusted; S3 job uses ose-cli from Red Hat
AVD-KSV-0125
# AVD-KSV-0113: S3 setup Role intentionally needs secret get/create/patch for quay config bundle
AVD-KSV-0113
# AVD-KSV-0020: Job uses OpenShift namespace default UID at runtime (high UID, no anyuid needed)
AVD-KSV-0020
# AVD-KSV-0021: Job uses OpenShift namespace default GID at runtime
AVD-KSV-0021
12 changes: 12 additions & 0 deletions .yamllint
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
extends: default
ignore:
- templates/
- templates/**
- "**/templates/**"
rules:
document-start: disable
line-length:
max: 80
brackets:
min-spaces-inside: 0
max-spaces-inside: 1
14 changes: 9 additions & 5 deletions Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
apiVersion: v2
description: A Helm chart to serve as the Validated Patterns Template
keywords:
- pattern
name: vp-template
version: 0.0.1
name: quay-registry
description: Red Hat Quay Registry Resources
type: application
version: 0.1.0
appVersion: "3.9"
home: https://github.com/validatedpatterns/quay-chart
maintainers:
- name: Zero Trust Validated Patterns Team
email: ztvp-arch-group@redhat.com
12 changes: 7 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ test: helm-lint helm-unittest ## Runs helm lint and unit tests
.PHONY: super-linter
super-linter: ## Runs super linter locally
rm -rf .mypy_cache
podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \
-e VALIDATE_BIOME_FORMAT=false \
-v $(PWD):/tmp/lint:rw,z \
-w /tmp/lint \
ghcr.io/super-linter/super-linter:slim-v8
podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \
-e VALIDATE_BIOME_FORMAT=false \
-e "FILTER_REGEX_EXCLUDE=.*/templates/.*" \
-e VALIDATE_GITHUB_ACTIONS_ZIZMOR=false \
-v $(PWD):/tmp/lint:rw,z \
-w /tmp/lint \
ghcr.io/super-linter/super-linter:slim-v8
51 changes: 48 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,58 @@
# vp-template
# quay-registry

![Version: 0.0.1](https://img.shields.io/badge/Version-0.0.1-informational?style=flat-square)
<!-- markdownlint-disable MD013 -->

A Helm chart to serve as the Validated Patterns Template
![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.9](https://img.shields.io/badge/AppVersion-3.9-informational?style=flat-square)

<!-- markdownlint-enable MD013 -->

<!-- markdownlint-disable MD013 -->

Red Hat Quay Registry Resources

<!-- markdownlint-enable MD013 -->

This chart is used to serve as the template for Validated Patterns Charts

## Notable changes

**Homepage:** <https://github.com/validatedpatterns/quay-chart>

## Maintainers

| Name | Email | Url |
| ---------------------------------- | ---------------------------- | --- |
| Zero Trust Validated Patterns Team | <ztvp-arch-group@redhat.com> | |

<!-- markdownlint-disable MD013 MD034 MD060 -->

## Values

| Key | Type | Default | Description |
| -------------------------------------------- | ------ | ---------------------------------------------- | ----------- |
| job.image | string | `"registry.redhat.io/openshift4/ose-cli:4.15"` | |
| job.resources.limits.cpu | string | `"500m"` | |
| job.resources.limits.memory | string | `"256Mi"` | |
| job.resources.requests.cpu | string | `"50m"` | |
| job.resources.requests.memory | string | `"128Mi"` | |
| objectStorage.objectBucketClaim.bucketName | string | `"quay-datastore"` | |
| objectStorage.objectBucketClaim.name | string | `"quay-bucket"` | |
| objectStorage.objectBucketClaim.storageClass | string | `"openshift-storage.noobaa.io"` | |
| quay.configBundleSecret.deploy | bool | `true` | |
| quay.configBundleSecret.name | string | `"quay-init-config-bundle-secret"` | |
| quay.namespace | string | `"quay-enterprise"` | |
| quay.setup.admin.email | string | `"quayadmin@example.com"` | |
| quay.setup.admin.name | string | `"quayadmin"` | |
| quay.setup.user.email | string | `"developer1@myorg.com"` | |
| quay.setup.user.name | string | `"developer1"` | |
| quay.storage.clairpostgres.size | string | `"50Gi"` | |
| quay.storage.postgres.size | string | `"50Gi"` | |
| quay_config.org.email | string | `"devel@myorg.com"` | |
| quay_config.org.name | string | `"devel"` | |
| quay_config.repo | string | `"example"` | |

<!-- markdownlint-enable MD013 MD034 MD060 -->

---

Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
6 changes: 6 additions & 0 deletions README.md.gotmpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
{{ template "chart.header" . }}
{{ template "chart.deprecationWarning" . }}

<!-- markdownlint-disable MD013 -->
{{ template "chart.badgesSection" . }}
<!-- markdownlint-enable MD013 -->

<!-- markdownlint-disable MD013 -->
{{ template "chart.description" . }}
<!-- markdownlint-enable MD013 -->

This chart is used to serve as the template for Validated Patterns Charts

Expand All @@ -17,6 +21,8 @@ This chart is used to serve as the template for Validated Patterns Charts

{{ template "chart.requirementsSection" . }}

<!-- markdownlint-disable MD013 MD034 MD060 -->
{{ template "chart.valuesSection" . }}
<!-- markdownlint-enable MD013 MD034 MD060 -->

{{ template "helm-docs.versionFooter" . }}
Empty file removed templates/.keep
Empty file.
11 changes: 11 additions & 0 deletions templates/object-bucket-claim.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
apiVersion: objectbucket.io/v1alpha1
kind: ObjectBucketClaim
metadata:
name: {{ .Values.objectStorage.objectBucketClaim.name }}
namespace: {{ .Values.quay.namespace }}
annotations:
argocd.argoproj.io/sync-wave: "5" # Create OBC after NooBaa system is ready
spec:
generateBucketName: {{ .Values.objectStorage.objectBucketClaim.bucketName }}
storageClassName: {{ .Values.objectStorage.objectBucketClaim.storageClass }}
45 changes: 45 additions & 0 deletions templates/quay-config-bundle-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ .Values.quay.configBundleSecret.name }}
namespace: {{ .Values.quay.namespace }}
annotations:
argocd.argoproj.io/sync-wave: "7" # Layer 1: Create base config secret (template)
type: Opaque
stringData:
config.yaml: |
FEATURE_USER_INITIALIZE: true
FEATURE_GENERAL_OCI_SUPPORT: true
BROWSER_API_CALLS_XHR_ONLY: false
SUPER_USERS:
- {{ .Values.quay.setup.admin.name }}
FEATURE_USER_CREATION: true
ALLOW_PULLS_WITHOUT_STRICT_LOGGING: false
AUTHENTICATION_TYPE: Database
DEFAULT_TAG_EXPIRATION: 2w
ENTERPRISE_LOGO_URL: /static/img/RH_Logo_Quay_Black_UX-horizontal.svg
FEATURE_BUILD_SUPPORT: false
FEATURE_DIRECT_LOGIN: true
FEATURE_MAILING: false
REGISTRY_TITLE: Red Hat Quay
REGISTRY_TITLE_SHORT: Quay
TEAM_RESYNC_STALE_TIME: 60m
TESTING: false
CREATE_NAMESPACE_ON_PUSH: true
# Proxy all storage traffic through Quay instead of direct client access
FEATURE_PROXY_STORAGE: true
# NooBaa Multicloud Object Gateway (MCG) S3-compatible storage configuration
# This is a template - actual secret with real credentials is created by quay-s3-credentials-setup job
DISTRIBUTED_STORAGE_CONFIG:
default:
- RHOCSStorage
- hostname: s3.openshift-storage.svc.cluster.local
port: 443
is_secure: true
storage_path: /datastorage/registry
access_key: PLACEHOLDER_ACCESS_KEY
secret_key: PLACEHOLDER_SECRET_KEY
bucket_name: PLACEHOLDER_BUCKET_NAME
DISTRIBUTED_STORAGE_DEFAULT_LOCATIONS: []
DISTRIBUTED_STORAGE_PREFERENCE:
- default
38 changes: 38 additions & 0 deletions templates/quay-registry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
apiVersion: quay.redhat.com/v1
kind: QuayRegistry
metadata:
name: quay-registry
namespace: {{ .Values.quay.namespace | default "quay-enterprise" }}
annotations:
argocd.argoproj.io/sync-wave: "10" # Layer 1: Deploy Quay Registry
argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true
spec:
components:
- kind: clair
managed: true
- kind: horizontalpodautoscaler
managed: true
- kind: mirror
managed: true
- kind: monitoring
managed: true
- kind: postgres
managed: true
overrides:
volumeSize: {{ .Values.quay.storage.postgres.size }}
- kind: redis
managed: true
- kind: objectstorage
managed: false
- kind: route
managed: true
- kind: tls
managed: true
- kind: quay
managed: true
- kind: clairpostgres
managed: true
overrides:
volumeSize: {{ .Values.quay.storage.clairpostgres.size }}
# Use the secret created by the S3 job (with real credentials), not the Git-managed template
configBundleSecret: quay-config-with-s3
112 changes: 112 additions & 0 deletions templates/quay-s3-credentials-job.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: quay-s3-credentials-setup
namespace: {{ .Values.quay.namespace }}
annotations:
argocd.argoproj.io/sync-wave: "8" # Layer 1: Setup S3 credentials
spec:
template:
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
serviceAccountName: quay-s3-setup
# Job needs SA token for oc CLI (CKV_K8S_38 skipped via checkov config)
automountServiceAccountToken: true
containers:
- name: setup-s3-credentials
image: {{ .Values.job.image | default "registry.redhat.io/openshift4/ose-cli:4.15" }}
imagePullPolicy: Always
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
resources:
{{- with .Values.job.resources }}
{{- toYaml . | nindent 10 }}
{{- else }}
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
{{- end }}
volumeMounts:
- name: tmp
mountPath: /tmp
command:
- /bin/bash
- -c
- |
set -e
echo "Setting up S3 credentials for Quay from NooBaa MCG ObjectBucketClaim..."

echo "Using oc for Kubernetes API access..."

# Check if ObjectBucketClaim exists and is bound
echo "Checking ObjectBucketClaim quay-bucket status..."
oc get objectbucketclaim quay-bucket -n {{ .Values.quay.namespace }}

# Wait for ObjectBucketClaim to be in Bound state
echo "Waiting for ObjectBucketClaim quay-bucket to be Bound (timeout: 10 minutes)..."
oc wait --for=jsonpath='{.status.phase}'=Bound objectbucketclaim/quay-bucket -n {{ .Values.quay.namespace }} --timeout=600s || {
echo "ERROR: ObjectBucketClaim failed to reach Bound state within timeout"
oc describe objectbucketclaim quay-bucket -n {{ .Values.quay.namespace }}
exit 1
}

# Use the actual secret and configmap names (not the objectBucketName from spec)
CONFIG_MAP="quay-bucket"
SECRET_NAME="quay-bucket"

echo "ConfigMap: $CONFIG_MAP"
echo "Secret: $SECRET_NAME"

# Extract S3 credentials from Quay namespace
ACCESS_KEY=$(oc get secret $SECRET_NAME -n {{ .Values.quay.namespace }} -o jsonpath='{.data.AWS_ACCESS_KEY_ID}' | base64 -d)
SECRET_KEY=$(oc get secret $SECRET_NAME -n {{ .Values.quay.namespace }} -o jsonpath='{.data.AWS_SECRET_ACCESS_KEY}' | base64 -d)
BUCKET_NAME=$(oc get configmap $CONFIG_MAP -n {{ .Values.quay.namespace }} -o jsonpath='{.data.BUCKET_NAME}')
S3_ENDPOINT=$(oc get configmap $CONFIG_MAP -n {{ .Values.quay.namespace }} -o jsonpath='{.data.BUCKET_HOST}')

echo "Retrieved S3 credentials successfully"
echo "Bucket: $BUCKET_NAME"
echo "Endpoint: $S3_ENDPOINT"

# With FEATURE_PROXY_STORAGE enabled, all traffic goes through Quay proxy
echo "Using RHOCSStorage with proxy mode - clients will access storage through Quay"

# Get the template config secret (with placeholders)
oc get secret {{ .Values.quay.configBundleSecret.name }} -n {{ .Values.quay.namespace }} -o jsonpath='{.data.config\.yaml}' | base64 -d > /tmp/config.yaml

# Replace placeholders with actual values using a different delimiter to handle special characters
sed -i "s|PLACEHOLDER_ACCESS_KEY|$ACCESS_KEY|g" /tmp/config.yaml
sed -i "s|PLACEHOLDER_SECRET_KEY|$SECRET_KEY|g" /tmp/config.yaml
sed -i "s|PLACEHOLDER_BUCKET_NAME|$BUCKET_NAME|g" /tmp/config.yaml

# Note: With FEATURE_PROXY_STORAGE enabled, we keep internal hostname since all traffic goes through Quay proxy

echo "Updated Quay configuration to use RHOCSStorage with proxy mode"

# Create a NEW secret with the actual credentials (not modifying the Git-managed one)
echo "Creating quay-config-with-s3 secret with real credentials..."
oc create secret generic quay-config-with-s3 \
--from-file=config.yaml=/tmp/config.yaml \
-n {{ .Values.quay.namespace }} \
--dry-run=client -o yaml | oc apply -f -

echo "Quay S3 credentials setup completed successfully"
echo "Created quay-config-with-s3 secret with real S3 credentials"
volumes:
- name: tmp
emptyDir: {}
restartPolicy: OnFailure
backoffLimit: 5
Loading