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
2 changes: 2 additions & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ jobs:
target: renderer
- name: solar-discovery
target: discovery
- name: solar-ui
target: ui
permissions:
contents: read
packages: write
Expand Down
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ COPY api/ api/
COPY client-go/ client-go/
COPY cmd/ cmd/
COPY pkg/ pkg/
COPY web/ web/

ARG TARGETOS
ARG TARGETARCH
Expand Down
31 changes: 31 additions & 0 deletions charts/solar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,37 @@ helm uninstall solar --namespace solar-system
| renderer.image.repository | string | `"ghcr.io/opendefensecloud/solar-renderer"` | |
| renderer.image.tag | string | `""` | |
| renderer.imagePullSecrets | list | `[]` | Image pull secrets for the renderer Pod. Use the Kubernetes shape `[{name: my-secret}]` (matches `apiserver.imagePullSecrets` etc.). Each referenced Secret must exist (type `kubernetes.io/dockerconfigjson`) in every namespace where Targets/RenderTasks are created — the renderer Pod runs in the RenderTask's namespace, so cross-namespace references don't work. Merged with `global.imagePullSecrets`. See the chart README for the recommended External Secrets Operator pattern that distributes a single source-of-truth credential to every namespace. |
| ui.affinity | object | `{}` | Affinity for pod assignment |
| ui.args.authMode | string | `"token"` | How the user's OIDC identity reaches the K8s API: "token" forwards the id_token, "impersonate" makes the BFF's ServiceAccount impersonate the user (and grants it impersonate RBAC). |
| ui.command | list | `["/solar-ui"]` | Command to run in the container |
| ui.enabled | bool | `false` | Enable UI deployment. Off by default: the UI needs an OIDC issuer to authenticate against, which is site-specific. |
| ui.extraArgs | object | `{}` | Additional command-line arguments as key-value pairs |
| ui.extraEnv | list | `[]` | Additional environment variables |
| ui.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
| ui.image.repository | string | `"ghcr.io/opendefensecloud/solar-ui"` | UI image repository |
| ui.image.tag | string | `""` | UI image tag (defaults to chart appVersion if not set) |
| ui.imagePullSecrets | list | `[]` | Image pull secrets for UI |
| ui.livenessProbe | object | `{"httpGet":{"path":"/","port":"http"},"initialDelaySeconds":15,"periodSeconds":20}` | Liveness probe configuration |
| ui.nodeSelector | object | `{}` | Node selector for pod assignment |
| ui.oidc.clientID | string | `"solar-ui"` | OIDC client ID |
| ui.oidc.existingSecret | string | `""` | Name of an existing Secret holding the OIDC client secret. Left empty for public clients (no client secret). |
| ui.oidc.existingSecretKey | string | `"client-secret"` | Key within `existingSecret` holding the client secret |
| ui.oidc.issuer | string | `""` | OIDC issuer URL, e.g. https://dex.example.com. Required when ui.enabled=true. |
| ui.oidc.redirectURL | string | `""` | OIDC redirect URL — the externally reachable /api/auth/callback of this UI, e.g. https://solar.example.com/api/auth/callback. Required when ui.enabled=true. |
| ui.podAnnotations | object | `{}` | Pod annotations |
| ui.podLabels | object | `{}` | Pod labels |
| ui.podSecurityContext | object | `{"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Pod security context |
| ui.readinessProbe | object | `{"httpGet":{"path":"/","port":"http"},"initialDelaySeconds":5,"periodSeconds":10}` | Readiness probe configuration |
| ui.replicaCount | int | `1` | Number of UI replicas. Keep at 1 unless a session key is pinned: the BFF generates one per process, so a second replica cannot read the first one's session cookies. |
| ui.resources | object | `{"limits":{"cpu":"300m","memory":"128Mi"},"requests":{"cpu":"100m","memory":"64Mi"}}` | Resource limits and requests |
| ui.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}}` | Container security context |
| ui.service.annotations | object | `{}` | UI service annotations |
| ui.service.port | int | `8090` | UI service port. Also the port the BFF listens on. |
| ui.service.type | string | `"ClusterIP"` | UI service type |
| ui.serviceAccount.annotations | object | `{}` | Service account annotations |
| ui.serviceAccount.create | bool | `true` | Create service account |
| ui.serviceAccount.name | string | `""` | Service account name (auto-generated if not set) |
| ui.tolerations | list | `[]` | Tolerations for pod assignment |
<!-- End Auto generated by helm-docs -->

## Contributing
Expand Down
50 changes: 50 additions & 0 deletions charts/solar/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,48 @@ Controller service account name
{{- end }}
{{- end }}

{{/*
UI fullname
*/}}
{{- define "solar.ui.fullname" -}}
{{- printf "%s-ui" (include "solar.fullname" .) | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
UI component labels
*/}}
{{- define "solar.ui.labels" -}}
{{ include "solar.labels" . }}
app.kubernetes.io/component: ui
app.kubernetes.io/part-of: solar
{{- end }}

{{/*
UI selector labels
*/}}
{{- define "solar.ui.selectorLabels" -}}
{{ include "solar.selectorLabels" . }}
app.kubernetes.io/component: ui
{{- end }}

{{/*
UI service account name
*/}}
{{- define "solar.ui.serviceAccountName" -}}
{{- if .Values.ui.serviceAccount.create }}
{{- default (include "solar.ui.fullname" .) .Values.ui.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.ui.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
UI service name
*/}}
{{- define "solar.ui.serviceName" -}}
{{- include "solar.ui.fullname" . }}
{{- end }}

{{/*
etcd fullname
*/}}
Expand Down Expand Up @@ -216,6 +258,14 @@ etcd image
{{- printf "%s:%s" .Values.etcd.image.repository .Values.etcd.image.tag }}
{{- end }}

{{/*
UI image
*/}}
{{- define "solar.ui.image" -}}
{{- $tag := .Values.ui.image.tag | default .Chart.AppVersion }}
{{- printf "%s:%s" .Values.ui.image.repository $tag }}
{{- end }}

{{/*
Renderer image
*/}}
Expand Down
22 changes: 22 additions & 0 deletions charts/solar/templates/ui/clusterrole.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{- if and .Values.ui.enabled .Values.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "solar.ui.fullname" . }}
labels:
{{- include "solar.ui.labels" . | nindent 4 }}
rules:
# The BFF enumerates namespaces with its own identity and then filters them
# per user via SelfSubjectRulesReview, so users need no namespace RBAC of
# their own (see pkg/ui/api.Handler.HandleListNamespaces).
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list"]
{{- if eq .Values.ui.args.authMode "impersonate" }}
# In impersonate mode the BFF, not the user's id_token, talks to the API
# server on the user's behalf.
- apiGroups: [""]
resources: ["users", "groups"]
verbs: ["impersonate"]
{{- end }}
{{- end }}
16 changes: 16 additions & 0 deletions charts/solar/templates/ui/clusterrolebinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{{- if and .Values.ui.enabled .Values.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "solar.ui.fullname" . }}
labels:
{{- include "solar.ui.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "solar.ui.fullname" . }}
subjects:
- kind: ServiceAccount
name: {{ include "solar.ui.serviceAccountName" . }}
namespace: {{ include "solar.namespace" . }}
{{- end }}
121 changes: 121 additions & 0 deletions charts/solar/templates/ui/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
{{- if .Values.ui.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "solar.ui.fullname" . }}
namespace: {{ include "solar.namespace" . }}
labels:
{{- include "solar.ui.labels" . | nindent 4 }}
{{- with .Values.commonAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.ui.replicaCount }}
selector:
matchLabels:
{{- include "solar.ui.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: ui
{{- with .Values.ui.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "solar.ui.selectorLabels" . | nindent 8 }}
{{- with .Values.ui.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.ui.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.global.imagePullSecrets }}
{{- if not $.Values.ui.imagePullSecrets }}
imagePullSecrets:
{{- end }}
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "solar.ui.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.ui.podSecurityContext | nindent 8 }}
containers:
- name: ui
image: {{ include "solar.ui.image" . }}
imagePullPolicy: {{ .Values.ui.image.pullPolicy }}
{{- with .Values.ui.command }}
command:
{{- toYaml . | nindent 12 }}
{{- end }}
args:
- --listen=0.0.0.0:{{ .Values.ui.service.port }}
- --oidc-issuer={{ required "ui.oidc.issuer is required when ui.enabled=true" .Values.ui.oidc.issuer }}
- --oidc-client-id={{ .Values.ui.oidc.clientID }}
- --oidc-redirect-url={{ required "ui.oidc.redirectURL is required when ui.enabled=true" .Values.ui.oidc.redirectURL }}
{{- if .Values.ui.oidc.existingSecret }}
- --oidc-client-secret=$(SOLAR_UI_OIDC_CLIENT_SECRET)
{{- end }}
- --auth-mode={{ .Values.ui.args.authMode }}
{{- range $key, $value := .Values.ui.extraArgs }}
- --{{ $key }}={{ $value }}
{{- end }}
{{- if or .Values.ui.oidc.existingSecret .Values.ui.extraEnv .Values.caBundle.enabled }}
env:
{{- if .Values.ui.oidc.existingSecret }}
- name: SOLAR_UI_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: {{ .Values.ui.oidc.existingSecret }}
key: {{ .Values.ui.oidc.existingSecretKey }}
{{- end }}
{{- with .Values.ui.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.caBundle.enabled }}
- name: SSL_CERT_FILE
value: /etc/ssl/certs/ca-bundle.pem
{{- end }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.ui.service.port }}
protocol: TCP
securityContext:
{{- toYaml .Values.ui.securityContext | nindent 12 }}
livenessProbe:
{{- toYaml .Values.ui.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.ui.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.ui.resources | nindent 12 }}
{{- if .Values.caBundle.enabled }}
volumeMounts:
- name: ca-bundle
mountPath: /etc/ssl/certs
readOnly: true
{{- end }}
{{- if .Values.caBundle.enabled }}
volumes:
- name: ca-bundle
configMap:
name: {{ required "caBundle.configMapName must be set when caBundle.enabled=true" .Values.caBundle.configMapName }}
items:
- key: {{ required "caBundle.key must be set when caBundle.enabled=true" .Values.caBundle.key }}
path: ca-bundle.pem
{{- end }}
{{- with .Values.ui.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.ui.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.ui.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
terminationGracePeriodSeconds: 10
{{- end }}
22 changes: 22 additions & 0 deletions charts/solar/templates/ui/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{- if .Values.ui.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "solar.ui.serviceName" . }}
namespace: {{ include "solar.namespace" . }}
labels:
{{- include "solar.ui.labels" . | nindent 4 }}
{{- with .Values.ui.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.ui.service.type }}
ports:
- port: {{ .Values.ui.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "solar.ui.selectorLabels" . | nindent 4 }}
{{- end }}
13 changes: 13 additions & 0 deletions charts/solar/templates/ui/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{- if and .Values.ui.enabled .Values.ui.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "solar.ui.serviceAccountName" . }}
namespace: {{ include "solar.namespace" . }}
labels:
{{- include "solar.ui.labels" . | nindent 4 }}
{{- with .Values.ui.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
Loading
Loading