k8s-and-chill/rendered/envs/minikube/traefik/customresourcedefinition-apiportalauths.hub.traefik.io.yaml
Felix Wolf fe51c8c1bc feat(minikube): add minikube environment with garage S3 backend
Adds a self-contained minikube environment for local development and
testing alongside the existing production env.

env: minikube
  - cluster.domain: minikube (browser DNS routes *.minikube → minikube ip)
  - tls issuer: mkcert (CA-signed via cert-manager mkcert ClusterIssuer)
  - storageClass: standard (minikube hostpath provisioner)
  - backups disabled; storagebox disabled
  - excludes argocd, forgejo, hcloud-csi (manual kubectl apply for testing)

prototypes/garage:
  - hand-rolled S3-compatible object store (single Deployment + PVC)
  - mittwald-generated rpc_secret + admin_token (hex)
  - PostSync init Job: assigns cluster layout, ensures bucket and access
    key, writes ocis-s3-credentials cross-namespace into ocis ns
  - idempotent: skips if k8s secret already populated; otherwise rotates
    the garage key (admin API only returns secretAccessKey on create)
  - cross-ns RBAC re-pinned via zz-cross-ns-rbac-fix overlay (ns.ytt.yaml
    clobbers explicit namespace fields)

ocis:
  - new admin-user-id init Job ensures secret.user-id is a valid UUID v4
    (mittwald can't generate UUIDs; ocis-settings rejects non-UUID ids)
  - mittwald no longer manages user-id; existing prod UUIDs preserved
  - insecure flag (oidcIdpInsecure / ocisHttpApiInsecure / ocmInsecure)
    parameterized; defaults to false; minikube sets true for self-signed
    OIDC issuer URL trust

other prototypes:
  - victoria-metrics-single helm values ytt-ified (storageClassName)
  - grafana admin secret now generated by mittwald (was hand-created in
    prod; manifest is no-op there since mittwald only fills empty fields)

flake.nix: minikube + docker + postgresql added to dev shell.
2026-05-03 17:23:57 +02:00

269 lines
13 KiB
YAML

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
controller-gen.kubebuilder.io/version: v0.17.1
name: apiportalauths.hub.traefik.io
namespace: traefik
spec:
group: hub.traefik.io
names:
kind: APIPortalAuth
listKind: APIPortalAuthList
plural: apiportalauths
singular: apiportalauth
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: APIPortalAuth defines the authentication configuration for an APIPortal.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: The desired behavior of this APIPortalAuth.
properties:
ldap:
description: LDAP configures the LDAP authentication.
properties:
attribute:
default: cn
description: |-
Attribute is the LDAP object attribute used to form a bind DN when sending bind queries.
The bind DN is formed as <Attribute>=<Username>,<BaseDN>.
type: string
attributes:
description: Attributes configures LDAP attribute mappings for user attributes.
properties:
company:
description: Company is the LDAP attribute for user company.
type: string
email:
description: Email is the LDAP attribute for user email.
type: string
firstname:
description: Firstname is the LDAP attribute for user first name.
type: string
lastname:
description: Lastname is the LDAP attribute for user last name.
type: string
userId:
description: UserID is the LDAP attribute for user ID mapping.
type: string
type: object
baseDn:
description: BaseDN is the base domain name that should be used for bind and search queries.
type: string
bindDn:
description: |-
BindDN is the domain name to bind to in order to authenticate to the LDAP server when running in search mode.
If empty, an anonymous bind will be done.
type: string
bindPasswordSecretName:
description: |-
BindPasswordSecretName is the name of the Kubernetes Secret containing the password for the bind DN.
The secret must contain a key named 'password'.
maxLength: 253
type: string
certificateAuthority:
description: |-
CertificateAuthority is a PEM-encoded certificate to use to establish a connection with the LDAP server if the
connection uses TLS but that the certificate was signed by a custom Certificate Authority.
type: string
groups:
description: Groups configures group extraction.
properties:
memberOfAttribute:
default: memberOf
description: MemberOfAttribute is the LDAP attribute containing group memberships (e.g., "memberOf").
type: string
type: object
insecureSkipVerify:
description: InsecureSkipVerify controls whether the server's certificate chain and host name is verified.
type: boolean
searchFilter:
description: |-
SearchFilter is used to filter LDAP search queries.
Example: (&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))
%s can be used as a placeholder for the username.
type: string
startTls:
description: StartTLS instructs the middleware to issue a StartTLS request when initializing the connection with the LDAP server.
type: boolean
syncedAttributes:
description: SyncedAttributes are the user attributes to synchronize with Hub platform.
items:
enum:
- groups
- userId
- firstname
- lastname
- email
- company
type: string
maxItems: 6
type: array
url:
description: URL is the URL of the LDAP server, including the protocol (ldap or ldaps) and the port.
type: string
x-kubernetes-validations:
- message: must be a valid LDAP URL
rule: isURL(self) && (self.startsWith('ldap://') || self.startsWith('ldaps://'))
required:
- baseDn
- url
type: object
oidc:
description: OIDC configures the OIDC authentication.
properties:
claims:
description: Claims configures JWT claim mappings for user attributes.
properties:
company:
description: Company is the JWT claim for user company.
type: string
email:
description: Email is the JWT claim for user email.
type: string
firstname:
description: Firstname is the JWT claim for user first name.
type: string
groups:
description: Groups is the JWT claim for user groups. This field is required for authorization.
type: string
lastname:
description: Lastname is the JWT claim for user last name.
type: string
userId:
description: UserID is the JWT claim for user ID mapping.
type: string
required:
- groups
type: object
issuerUrl:
description: IssuerURL is the OIDC provider issuer URL.
type: string
x-kubernetes-validations:
- message: must be a valid URL
rule: isURL(self)
scopes:
description: Scopes is a list of OAuth2 scopes.
items:
type: string
type: array
secretName:
description: SecretName is the name of the Kubernetes Secret containing clientId and clientSecret keys.
maxLength: 253
type: string
syncedAttributes:
description: SyncedAttributes are the user attributes to synchronize with Hub platform.
items:
enum:
- groups
- userId
- firstname
- lastname
- email
- company
type: string
maxItems: 6
type: array
required:
- claims
- issuerUrl
- secretName
type: object
type: object
x-kubernetes-validations:
- message: exactly one of oidc or ldap must be specified
rule: '[has(self.oidc), has(self.ldap)].filter(x, x).size() == 1'
status:
description: The current status of this APIPortalAuth.
properties:
conditions:
items:
description: Condition contains details for one aspect of the current state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
hash:
description: Hash is a hash representing the APIPortalAuth.
type: string
syncedAt:
format: date-time
type: string
version:
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}