first commit
This commit is contained in:
20
apps/code-server/configs.tf
Normal file
20
apps/code-server/configs.tf
Normal file
@@ -0,0 +1,20 @@
|
||||
resource "kubectl_manifest" "code-server-config" {
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
data:
|
||||
config.yml: |
|
||||
auth: none
|
||||
autostart.sh: |
|
||||
#!/bin/bash
|
||||
kubectl config set-cluster default --server=https://$${KUBERNETES_SERVICE_HOST}:$${KUBERNETES_SERVICE_PORT} --certificate-authority=/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
kubectl config set-credentials default --token=$(cat /run/secrets/kubernetes.io/serviceaccount/token)
|
||||
kubectl config set-context default --cluster=default --user=default
|
||||
kubectl config use-context default
|
||||
[ -e /home/coder/.bashrc ] || cp /etc/skel/.bashrc /home/coder/.bashrc
|
||||
EOF
|
||||
}
|
||||
22
apps/code-server/datas.tf
Normal file
22
apps/code-server/datas.tf
Normal file
@@ -0,0 +1,22 @@
|
||||
locals {
|
||||
common-labels = {
|
||||
"vynil.solidite.fr/owner-name" = var.instance
|
||||
"vynil.solidite.fr/owner-namespace" = var.namespace
|
||||
"vynil.solidite.fr/owner-category" = var.category
|
||||
"vynil.solidite.fr/owner-component" = var.component
|
||||
"app.kubernetes.io/managed-by" = "vynil"
|
||||
"app.kubernetes.io/name" = var.component
|
||||
"app.kubernetes.io/instance" = var.instance
|
||||
}
|
||||
}
|
||||
|
||||
data "kubernetes_secret_v1" "authentik" {
|
||||
metadata {
|
||||
name = "authentik"
|
||||
namespace = "${var.domain}-auth"
|
||||
}
|
||||
}
|
||||
|
||||
data "kustomization_overlay" "data" {
|
||||
resources = []
|
||||
}
|
||||
109
apps/code-server/deploy.tf
Normal file
109
apps/code-server/deploy.tf
Normal file
@@ -0,0 +1,109 @@
|
||||
resource "kubectl_manifest" "deploy" {
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
spec:
|
||||
replicas: 1
|
||||
hostname: "${var.component}-${var.instance}"
|
||||
subdomain: "${var.domain-name}"
|
||||
selector:
|
||||
matchLabels: ${jsonencode(local.common-labels)}
|
||||
template:
|
||||
metadata:
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
runAsGroup: 1000
|
||||
capabilities:
|
||||
add:
|
||||
- SETGID
|
||||
- SETUID
|
||||
- SYS_CHROOT
|
||||
hostname: "${var.component}-${var.instance}"
|
||||
containers:
|
||||
- name: code-server
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
privileged: true
|
||||
env:
|
||||
- name: TZ
|
||||
value: "${var.timezone}"
|
||||
- name: ENTRYPOINTD
|
||||
value: /usr/local/startup
|
||||
- name: PORT
|
||||
value: "8080"
|
||||
- name: CODE_SERVER_CONFIG
|
||||
value: /etc/code-server/config.yml
|
||||
image: "${var.images.codeserver.registry}/${var.images.codeserver.repository}:${var.images.codeserver.tag}"
|
||||
imagePullPolicy: "${var.images.codeserver.pullPolicy}"
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
scheme: HTTP
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 1
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
scheme: HTTP
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 1
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/code-server/config.yml
|
||||
subPath: config.yml
|
||||
- name: startup
|
||||
mountPath: /usr/local/startup/autostart.sh
|
||||
subPath: autostart.sh
|
||||
- name: home
|
||||
mountPath: /home/coder
|
||||
- name: run
|
||||
mountPath: /run
|
||||
restartPolicy: Always
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
serviceAccount: "${var.component}-${var.instance}"
|
||||
serviceAccountName: "${var.component}-${var.instance}"
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
defaultMode: 0420
|
||||
name: "${var.component}-${var.instance}"
|
||||
items:
|
||||
- key: config.yml
|
||||
path: config.yml
|
||||
- name: startup
|
||||
configMap:
|
||||
defaultMode: 0755
|
||||
name: "${var.component}-${var.instance}"
|
||||
items:
|
||||
- key: autostart.sh
|
||||
path: autostart.sh
|
||||
- name: home
|
||||
persistentVolumeClaim:
|
||||
claimName: "${var.component}-${var.instance}"
|
||||
- name: run
|
||||
emptyDir: {}
|
||||
EOF
|
||||
}
|
||||
122
apps/code-server/forward.tf
Normal file
122
apps/code-server/forward.tf
Normal file
@@ -0,0 +1,122 @@
|
||||
locals {
|
||||
authentik-token = data.kubernetes_secret_v1.authentik.data["AUTHENTIK_BOOTSTRAP_TOKEN"]
|
||||
request_headers = {
|
||||
"Content-Type" = "application/json"
|
||||
Authorization = "Bearer ${local.authentik-token}"
|
||||
}
|
||||
forward-outpost-providers = jsondecode(data.http.get_forward_outpost.response_body).results[0].providers
|
||||
forward-outpost-pk = jsondecode(data.http.get_forward_outpost.response_body).results[0].pk
|
||||
app-name = var.component == var.instance ? var.instance : format("%s-%s", var.component, var.instance)
|
||||
app-icon = "dashboard/statics/icons/favicon-96x96.png"
|
||||
main-group = format("%s-users", local.app-name)
|
||||
sub-groups = []
|
||||
external-url = format("https://%s", local.dns-names[0])
|
||||
access-token-validity = "hours=10" // ;minutes=10
|
||||
}
|
||||
|
||||
|
||||
data "authentik_flow" "default-authorization-flow" {
|
||||
depends_on = [authentik_group.prj_users]
|
||||
slug = "default-provider-authorization-implicit-consent"
|
||||
}
|
||||
|
||||
resource "authentik_provider_proxy" "prj_forward" {
|
||||
name = local.app-name
|
||||
external_host = local.external-url
|
||||
authorization_flow = data.authentik_flow.default-authorization-flow.id
|
||||
mode = "forward_single"
|
||||
access_token_validity = local.access-token-validity
|
||||
}
|
||||
|
||||
|
||||
resource "authentik_application" "prj_application" {
|
||||
name = local.app-name
|
||||
slug = local.app-name
|
||||
protocol_provider = authentik_provider_proxy.prj_forward.id
|
||||
meta_launch_url = local.external-url
|
||||
meta_icon = format("%s/%s", local.external-url, local.app-icon)
|
||||
}
|
||||
|
||||
resource "authentik_group" "prj_users" {
|
||||
name = local.main-group
|
||||
}
|
||||
|
||||
resource "authentik_group" "subgroup" {
|
||||
count = length(local.sub-groups)
|
||||
name = format("%s-%s", local.app-name, local.sub-groups[count.index])
|
||||
parent = authentik_group.prj_users.id
|
||||
}
|
||||
|
||||
data "authentik_group" "vynil-admin" {
|
||||
depends_on = [authentik_group.prj_users] # fake dependency so it is not evaluated at plan stage
|
||||
name = "vynil-forward-admins"
|
||||
}
|
||||
|
||||
resource "authentik_policy_binding" "prj_access_users" {
|
||||
target = authentik_application.prj_application.uuid
|
||||
group = authentik_group.prj_users.id
|
||||
order = 0
|
||||
}
|
||||
resource "authentik_policy_binding" "prj_access_vynil" {
|
||||
target = authentik_application.prj_application.uuid
|
||||
group = data.authentik_group.vynil-admin.id
|
||||
order = 1
|
||||
}
|
||||
|
||||
data "http" "get_forward_outpost" {
|
||||
depends_on = [authentik_provider_proxy.prj_forward]
|
||||
url = "http://authentik.${var.domain}-auth.svc/api/v3/outposts/instances/?name__iexact=forward"
|
||||
method = "GET"
|
||||
request_headers = local.request_headers
|
||||
lifecycle {
|
||||
postcondition {
|
||||
condition = contains([200], self.status_code)
|
||||
error_message = "Status code invalid"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "restapi" {
|
||||
uri = "http://authentik.${var.domain}-auth.svc/api/v3/"
|
||||
headers = local.request_headers
|
||||
create_method = "PATCH"
|
||||
update_method = "PATCH"
|
||||
destroy_method = "PATCH"
|
||||
write_returns_object = true
|
||||
id_attribute = "name"
|
||||
}
|
||||
|
||||
resource "restapi_object" "forward_outpost_binding" {
|
||||
path = "/outposts/instances/${local.forward-outpost-pk}/"
|
||||
data = jsonencode({
|
||||
name = "forward"
|
||||
providers = contains(local.forward-outpost-providers, authentik_provider_proxy.prj_forward.id) ? local.forward-outpost-providers : concat(local.forward-outpost-providers, [authentik_provider_proxy.prj_forward.id])
|
||||
})
|
||||
}
|
||||
|
||||
resource "kubectl_manifest" "prj_middleware" {
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: "forward-${local.app-name}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
spec:
|
||||
forwardAuth:
|
||||
address: http://ak-outpost-forward.${var.domain}-auth.svc:9000/outpost.goauthentik.io/auth/traefik
|
||||
trustForwardHeader: true
|
||||
authResponseHeaders:
|
||||
- X-authentik-username
|
||||
# - X-authentik-groups
|
||||
# - X-authentik-email
|
||||
# - X-authentik-name
|
||||
# - X-authentik-uid
|
||||
# - X-authentik-jwt
|
||||
# - X-authentik-meta-jwks
|
||||
# - X-authentik-meta-outpost
|
||||
# - X-authentik-meta-provider
|
||||
# - X-authentik-meta-app
|
||||
# - X-authentik-meta-version
|
||||
EOF
|
||||
}
|
||||
130
apps/code-server/index.yaml
Normal file
130
apps/code-server/index.yaml
Normal file
@@ -0,0 +1,130 @@
|
||||
---
|
||||
apiVersion: vinyl.solidite.fr/v1beta1
|
||||
kind: Component
|
||||
category: apps
|
||||
metadata:
|
||||
name: code-server
|
||||
description: null
|
||||
options:
|
||||
sub-domain:
|
||||
default: code
|
||||
examples:
|
||||
- code
|
||||
type: string
|
||||
issuer:
|
||||
default: letsencrypt-prod
|
||||
examples:
|
||||
- letsencrypt-prod
|
||||
type: string
|
||||
admin:
|
||||
default:
|
||||
cluster: false
|
||||
namespace: false
|
||||
examples:
|
||||
- cluster: false
|
||||
namespace: false
|
||||
properties:
|
||||
cluster:
|
||||
default: false
|
||||
type: boolean
|
||||
namespace:
|
||||
default: false
|
||||
type: boolean
|
||||
type: object
|
||||
ingress-class:
|
||||
default: traefik
|
||||
examples:
|
||||
- traefik
|
||||
type: string
|
||||
images:
|
||||
default:
|
||||
codeserver:
|
||||
pullPolicy: IfNotPresent
|
||||
registry: docker.io
|
||||
repository: sebt3/code-server
|
||||
tag: 4.13
|
||||
examples:
|
||||
- codeserver:
|
||||
pullPolicy: IfNotPresent
|
||||
registry: docker.io
|
||||
repository: sebt3/code-server
|
||||
tag: 4.13
|
||||
properties:
|
||||
codeserver:
|
||||
default:
|
||||
pullPolicy: IfNotPresent
|
||||
registry: docker.io
|
||||
repository: sebt3/code-server
|
||||
tag: 4.13
|
||||
properties:
|
||||
pullPolicy:
|
||||
default: IfNotPresent
|
||||
enum:
|
||||
- Always
|
||||
- Never
|
||||
- IfNotPresent
|
||||
type: string
|
||||
registry:
|
||||
default: docker.io
|
||||
type: string
|
||||
repository:
|
||||
default: sebt3/code-server
|
||||
type: string
|
||||
tag:
|
||||
default: 4.13
|
||||
type: number
|
||||
type: object
|
||||
type: object
|
||||
domain:
|
||||
default: your-company
|
||||
examples:
|
||||
- your-company
|
||||
type: string
|
||||
timezone:
|
||||
default: Europe/Paris
|
||||
examples:
|
||||
- Europe/Paris
|
||||
type: string
|
||||
storage:
|
||||
default:
|
||||
accessMode: ReadWriteOnce
|
||||
size: 20Gi
|
||||
type: Filesystem
|
||||
examples:
|
||||
- accessMode: ReadWriteOnce
|
||||
size: 20Gi
|
||||
type: Filesystem
|
||||
properties:
|
||||
accessMode:
|
||||
default: ReadWriteOnce
|
||||
enum:
|
||||
- ReadWriteOnce
|
||||
- ReadOnlyMany
|
||||
- ReadWriteMany
|
||||
type: string
|
||||
size:
|
||||
default: 20Gi
|
||||
type: string
|
||||
type:
|
||||
default: Filesystem
|
||||
enum:
|
||||
- Filesystem
|
||||
- block
|
||||
type: string
|
||||
type: object
|
||||
domain-name:
|
||||
default: your_company.com
|
||||
examples:
|
||||
- your_company.com
|
||||
type: string
|
||||
dependencies:
|
||||
- dist: null
|
||||
category: share
|
||||
component: authentik-forward
|
||||
providers:
|
||||
kubernetes: true
|
||||
authentik: true
|
||||
kubectl: true
|
||||
postgresql: null
|
||||
restapi: true
|
||||
http: true
|
||||
76
apps/code-server/ingress.tf
Normal file
76
apps/code-server/ingress.tf
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
locals {
|
||||
dns-names = ["${var.instance}.${var.sub-domain}.${var.domain-name}"]
|
||||
middlewares = ["${var.instance}-https", "forward-${local.app-name}"]
|
||||
service = {
|
||||
"name" = "${var.component}-${var.instance}"
|
||||
"port" = {
|
||||
"number" = 80
|
||||
}
|
||||
}
|
||||
rules = [ for v in local.dns-names : {
|
||||
"host" = "${v}"
|
||||
"http" = {
|
||||
"paths" = [{
|
||||
"backend" = {
|
||||
"service" = local.service
|
||||
}
|
||||
"path" = "/"
|
||||
"pathType" = "Prefix"
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
resource "kubectl_manifest" "prj_certificate" {
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: "cert-manager.io/v1"
|
||||
kind: "Certificate"
|
||||
metadata:
|
||||
name: "${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
spec:
|
||||
secretName: "${var.instance}-cert"
|
||||
dnsNames: ${jsonencode(local.dns-names)}
|
||||
issuerRef:
|
||||
name: "${var.issuer}"
|
||||
kind: "ClusterIssuer"
|
||||
group: "cert-manager.io"
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "kubectl_manifest" "prj_https_redirect" {
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: "traefik.containo.us/v1alpha1"
|
||||
kind: "Middleware"
|
||||
metadata:
|
||||
name: "${var.instance}-https"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
spec:
|
||||
redirectScheme:
|
||||
scheme: "https"
|
||||
permanent: true
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "kubectl_manifest" "prj_ingress" {
|
||||
force_conflicts = true
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: "networking.k8s.io/v1"
|
||||
kind: "Ingress"
|
||||
metadata:
|
||||
name: "${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
annotations:
|
||||
"traefik.ingress.kubernetes.io/router.middlewares": "${join(",", [for m in local.middlewares : format("%s-%s@kubernetescrd", var.namespace, m)])}"
|
||||
spec:
|
||||
ingressClassName: "${var.ingress-class}"
|
||||
rules: ${jsonencode(local.rules)}
|
||||
tls:
|
||||
- hosts: ${jsonencode(local.dns-names)}
|
||||
secretName: "${var.instance}-cert"
|
||||
EOF
|
||||
}
|
||||
17
apps/code-server/pvc.tf
Normal file
17
apps/code-server/pvc.tf
Normal file
@@ -0,0 +1,17 @@
|
||||
resource "kubectl_manifest" "pvc" {
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
spec:
|
||||
accessModes:
|
||||
- "${var.storage.accessMode}"
|
||||
resources:
|
||||
requests:
|
||||
storage: "${var.storage.size}"
|
||||
volumeMode: "${var.storage.type}"
|
||||
EOF
|
||||
}
|
||||
78
apps/code-server/rbac.tf
Normal file
78
apps/code-server/rbac.tf
Normal file
@@ -0,0 +1,78 @@
|
||||
resource "kubectl_manifest" "sa" {
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "kubectl_manifest" "role" {
|
||||
count = var.admin.namespace?1:0
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
rules:
|
||||
- apiGroups: ['*']
|
||||
resources: ['*']
|
||||
verbs: ['*']
|
||||
EOF
|
||||
}
|
||||
resource "kubectl_manifest" "rb" {
|
||||
count = var.admin.namespace?1:0
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
namespace: "${var.namespace}"
|
||||
name: "${var.component}-${var.instance}"
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
EOF
|
||||
}
|
||||
resource "kubectl_manifest" "clusterrole" {
|
||||
count = var.admin.cluster?1:0
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: "${var.component}-${var.namespace}-${var.instance}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
rules:
|
||||
- apiGroups: ['*']
|
||||
resources: ['*']
|
||||
verbs: ['*']
|
||||
EOF
|
||||
}
|
||||
resource "kubectl_manifest" "crb" {
|
||||
count = var.admin.cluster?1:0
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: "${var.component}-${var.namespace}-${var.instance}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: "${var.component}-${var.namespace}-${var.instance}"
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
EOF
|
||||
}
|
||||
18
apps/code-server/svc.tf
Normal file
18
apps/code-server/svc.tf
Normal file
@@ -0,0 +1,18 @@
|
||||
resource "kubectl_manifest" "service" {
|
||||
yaml_body = <<-EOF
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: "${var.component}-${var.instance}"
|
||||
namespace: "${var.namespace}"
|
||||
labels: ${jsonencode(local.common-labels)}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
selector: ${jsonencode(local.common-labels)}
|
||||
EOF
|
||||
}
|
||||
Reference in New Issue
Block a user