This commit is contained in:
2023-10-01 09:45:28 +02:00
parent a374fe5e66
commit f15202de63
13 changed files with 785 additions and 57 deletions

View File

@@ -1,17 +1,17 @@
locals { locals {
annotations = { annotations = {
"vynil.solidite.fr/meta" = var.component "vynil.solidite.fr/meta" = var.component
"vynil.solidite.fr/name" = "${var.namespace}-auth" "vynil.solidite.fr/name" = "${var.namespace}-auth"
"vynil.solidite.fr/domain" = var.domain-name "vynil.solidite.fr/domain" = var.domain-name
"vynil.solidite.fr/issuer" = var.issuer "vynil.solidite.fr/issuer" = var.issuer
"vynil.solidite.fr/ingress" = var.ingress-class "vynil.solidite.fr/ingress" = var.ingress-class
} }
global = { global = {
"domain" = var.namespace "domain" = var.namespace
"domain-name" = var.domain-name "domain-name" = var.domain-name
"issuer" = var.issuer "issuer" = var.issuer
"ingress-class" = var.ingress-class "ingress-class" = var.ingress-class
"backups" = var.backups "backups" = var.backups
} }
authentik = { for k, v in var.authentik : k => v if k!="enable" } authentik = { for k, v in var.authentik : k => v if k!="enable" }
authentik-ldap = { for k, v in var.authentik-ldap : k => v if k!="enable" } authentik-ldap = { for k, v in var.authentik-ldap : k => v if k!="enable" }

View File

@@ -0,0 +1,117 @@
locals {
sorted-div-clients-names = reverse(distinct(sort([
for div in var.clients.divisions: div.name
])))
sorted-div-clients = flatten([
for name in local.sorted-div-clients-names: [
for div in var.clients.divisions:
div if div.name == name
]
])
sorted-div-employes-names = reverse(distinct(sort([
for div in var.employes.divisions: div.name
])))
sorted-div-employes = flatten([
for name in local.sorted-div-employes-names: [
for div in var.employes.divisions:
div if div.name == name
]
])
sorted-div-fournisseurs-names = reverse(distinct(sort([
for div in var.fournisseurs.divisions: div.name
])))
sorted-div-fournisseurs = flatten([
for name in local.sorted-div-fournisseurs-names: [
for div in var.fournisseurs.divisions:
div if div.name == name
]
])
}
resource "kubectl_manifest" "accounts-management" {
count = var.authentik.enable && var.employes.enable ? 1 : 0
depends_on = [kubernetes_namespace_v1.auth-ns]
yaml_body = <<-EOF
apiVersion: "vynil.solidite.fr/v1"
kind: "Install"
metadata:
name: "accounts-management"
namespace: "${var.namespace}-auth"
labels: ${jsonencode(local.common-labels)}
spec:
distrib: "${var.distributions.domain}"
category: "share"
component: "accounts-management"
options: ${jsonencode(merge(local.global, {
clients = var.clients
employes = var.employes
fournisseurs = var.fournisseurs
}))}
EOF
}
resource "kubectl_manifest" "employes-divisions" {
count = var.authentik.enable && var.employes.enable ? length(local.sorted-div-employes) : 0
depends_on = [kubernetes_namespace_v1.auth-ns,kubectl_manifest.accounts-management]
yaml_body = <<-EOF
apiVersion: "vynil.solidite.fr/v1"
kind: "Install"
metadata:
name: "employes-${local.sorted-div-employes[count.index].name}"
namespace: "${var.namespace}-auth"
labels: ${jsonencode(local.common-labels)}
spec:
distrib: "${var.distributions.domain}"
category: "share"
component: "division"
options: ${jsonencode(merge(local.global, {
parent = "employes"
apps = local.sorted-div-employes[count.index].apps
teams = local.sorted-div-employes[count.index].teams
}))}
EOF
}
resource "kubectl_manifest" "clients-divisions" {
count = var.authentik.enable && var.employes.enable && var.clients.enable ? length(local.sorted-div-clients) : 0
depends_on = [kubernetes_namespace_v1.auth-ns,kubectl_manifest.accounts-management]
yaml_body = <<-EOF
apiVersion: "vynil.solidite.fr/v1"
kind: "Install"
metadata:
name: "clients-${local.sorted-div-clients[count.index].name}"
namespace: "${var.namespace}-auth"
labels: ${jsonencode(local.common-labels)}
spec:
distrib: "${var.distributions.domain}"
category: "share"
component: "division"
options: ${jsonencode(merge(local.global, {
parent = "clients"
apps = local.sorted-div-clients[count.index].apps
teams = local.sorted-div-clients[count.index].teams
}))}
EOF
}
resource "kubectl_manifest" "fournisseurs-divisions" {
count = var.authentik.enable && var.employes.enable && var.fournisseurs.enable ? length(local.sorted-div-fournisseurs) : 0
depends_on = [kubernetes_namespace_v1.auth-ns,kubectl_manifest.accounts-management]
yaml_body = <<-EOF
apiVersion: "vynil.solidite.fr/v1"
kind: "Install"
metadata:
name: "fournisseurs-${local.sorted-div-fournisseurs[count.index].name}"
namespace: "${var.namespace}-auth"
labels: ${jsonencode(local.common-labels)}
spec:
distrib: "${var.distributions.domain}"
category: "share"
component: "division"
options: ${jsonencode(merge(local.global, {
parent = "fournisseurs"
apps = local.sorted-div-fournisseurs[count.index].apps
teams = local.sorted-div-fournisseurs[count.index].teams
}))}
EOF
}

View File

@@ -6,51 +6,6 @@ metadata:
name: domain-auth name: domain-auth
description: null description: null
options: options:
distributions:
default:
core: core
domain: domain
examples:
- core: core
domain: domain
properties:
core:
default: core
type: string
domain:
default: domain
type: string
type: object
authentik-forward:
default:
enable: false
examples:
- enable: false
properties:
enable:
default: false
type: boolean
type: object
issuer:
default: letsencrypt-prod
examples:
- letsencrypt-prod
type: string
authentik:
default:
enable: true
examples:
- enable: true
properties:
enable:
default: true
type: boolean
type: object
domain-name:
default: your_company.com
examples:
- your_company.com
type: string
authentik-ldap: authentik-ldap:
default: default:
enable: false enable: false
@@ -61,6 +16,30 @@ options:
default: false default: false
type: boolean type: boolean
type: object type: object
employes:
properties:
apps:
items:
type: string
type: array
divisions:
items:
properties:
apps:
items:
type: string
type: array
name:
type: string
teams:
items:
type: object
type: array
type: object
type: array
enable:
default: true
type: boolean
backups: backups:
default: default:
enable: false enable: false
@@ -91,11 +70,45 @@ options:
default: backup-settings default: backup-settings
type: string type: string
type: object type: object
ingress-class: distributions:
default: traefik default:
core: core
domain: domain
examples: examples:
- traefik - core: core
type: string domain: domain
properties:
core:
default: core
type: string
domain:
default: domain
type: string
type: object
clients:
properties:
apps:
items:
type: string
type: array
divisions:
items:
properties:
apps:
items:
type: string
type: array
name:
type: string
teams:
items:
type: object
type: array
type: object
type: array
enable:
default: false
type: boolean
storage-classes: storage-classes:
default: default:
BlockReadWriteMany: '' BlockReadWriteMany: ''
@@ -121,11 +134,70 @@ options:
default: '' default: ''
type: string type: string
type: object type: object
domain-name:
default: your_company.com
examples:
- your_company.com
type: string
fournisseurs:
properties:
apps:
items:
type: string
type: array
divisions:
items:
properties:
apps:
items:
type: string
type: array
name:
type: string
teams:
items:
type: object
type: array
type: object
type: array
enable:
default: false
type: boolean
ingress-class:
default: traefik
examples:
- traefik
type: string
authentik:
default:
enable: true
examples:
- enable: true
properties:
enable:
default: true
type: boolean
type: object
issuer:
default: letsencrypt-prod
examples:
- letsencrypt-prod
type: string
domain: domain:
default: your-company default: your-company
examples: examples:
- your-company - your-company
type: string type: string
authentik-forward:
default:
enable: false
examples:
- enable: false
properties:
enable:
default: false
type: boolean
type: object
dependencies: [] dependencies: []
providers: providers:
kubernetes: true kubernetes: true

View 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.namespace
}
}
data "kustomization_overlay" "data" {
resources = []
}

View File

@@ -0,0 +1,16 @@
resource "authentik_group" "employes" {
name = "employes"
attributes = jsonencode(merge([for app in var.employes.apps: {"${app}" = true}]))
}
resource "authentik_group" "fournisseurs" {
count = var.fournisseurs.enable ? 1 : 0
name = "fournisseurs"
attributes = jsonencode(merge([for app in var.fournisseurs.apps: {"${app}" = true}]))
}
resource "authentik_group" "clients" {
count = var.clients.enable ? 1 : 0
name = "clients"
attributes = jsonencode(merge([for app in var.clients.apps: {"${app}" = true}]))
}

View File

@@ -0,0 +1,49 @@
---
apiVersion: vinyl.solidite.fr/v1beta1
kind: Component
category: share
metadata:
name: accounts-management
description: null
options:
domain:
default: your-company
examples:
- your-company
type: string
employes:
properties:
apps:
items:
type: string
type: array
fournisseurs:
properties:
apps:
items:
type: string
type: array
enable:
default: false
type: boolean
clients:
properties:
apps:
items:
type: string
type: array
enable:
default: false
type: boolean
dependencies:
- dist: null
category: share
component: authentik
providers:
kubernetes: true
authentik: true
kubectl: true
postgresql: null
restapi: null
http: true
tfaddtype: null

View File

@@ -0,0 +1,69 @@
data "kubernetes_secret_v1" "postgresql_password" {
depends_on = [ kubectl_manifest.prj_pg ]
metadata {
name = "${var.instance}-${var.component}-superuser"
namespace = "${var.namespace}"
}
}
locals {
pg-username = data.kubernetes_secret_v1.postgresql_password.data["username"]
pg-password = data.kubernetes_secret_v1.postgresql_password.data["password"]
pg-host = "${var.db-source.name}-pg-rw.${var.db-source.namespace}.svc"
sorted-db-name = reverse(distinct(sort([
for db in var.databases: db.name
])))
sorted-dbs = flatten([
for name in local.sorted-db-name: [
for db in var.databases:
db if db.name == name
]
])
}
resource "kubectl_manifest" "db_secret" {
ignore_fields = ["metadata.annotations"]
count = length(local.sorted-dbs)
yaml_body = <<-EOF
apiVersion: "secretgenerator.mittwald.de/v1alpha1"
kind: "StringSecret"
metadata:
name: "${var.instance}-${var.component}-${local.sorted-dbs[count.index].name}"
namespace: "${var.namespace}"
labels: ${jsonencode(merge(local.common-labels, {"app.kubernetes.io/component" = local.sorted-dbs[count.index].name}))}
spec:
forceRegenerate: false
data:
POSGRESQL_USERNAME: "${local.sorted-dbs[count.index].name}"
fields:
- fieldName: "POSGRESQL_PASSWORD"
length: "32"
EOF
}
data "kubernetes_secret_v1" "password_get" {
depends_on = [ kubectl_manifest.db_secret ]
count = length(local.sorted-dbs)
metadata {
name = "${var.instance}-${var.component}-${local.sorted-dbs[count.index].name}"
namespace = "${var.namespace}"
}
}
resource "postgresql_role" "owner" {
depends_on = [ kubectl_manifest.prj_pg ]
count = length(local.sorted-dbs)
name = "${local.sorted-dbs[count.index].name}"
login = true
password = data.kubernetes_secret_v1.password_get[count.index].data["POSGRESQL_PASSWORD"]
}
resource "postgresql_database" "my_db" {
depends_on = [ postgresql_role.owner ]
count = length(local.sorted-dbs)
name = "${local.sorted-dbs[count.index].name}"
owner = "${postgresql_role.owner[count.index].name}"
connection_limit = -1
allow_connections = true
}

164
share/dataset-pg/index.yaml Normal file
View File

@@ -0,0 +1,164 @@
---
apiVersion: vinyl.solidite.fr/v1beta1
kind: Component
category: share
metadata:
name: dataset-pg
description: null
options:
domain:
default: your-company
examples:
- your-company
type: string
replicas:
default: 1
examples:
- 1
type: integer
backups:
default:
enable: false
endpoint: ''
key-id-key: s3-id
retention:
db: 30d
schedule:
db: 0 3 * * *
secret-key: s3-secret
secret-name: backup-settings
examples:
- enable: false
endpoint: ''
key-id-key: s3-id
retention:
db: 30d
schedule:
db: 0 3 * * *
secret-key: s3-secret
secret-name: backup-settings
properties:
enable:
default: false
type: boolean
endpoint:
default: ''
type: string
key-id-key:
default: s3-id
type: string
retention:
default:
db: 30d
properties:
db:
default: 30d
type: string
type: object
schedule:
default:
db: 0 3 * * *
properties:
db:
default: 0 3 * * *
type: string
type: object
secret-key:
default: s3-secret
type: string
secret-name:
default: backup-settings
type: string
type: object
storage:
default: 8Gi
examples:
- 8Gi
type: string
images:
default:
operator:
pullPolicy: IfNotPresent
registry: docker.io
repository: to-be/defined
tag: v1.0.0
examples:
- operator:
pullPolicy: IfNotPresent
registry: docker.io
repository: to-be/defined
tag: v1.0.0
properties:
operator:
default:
pullPolicy: IfNotPresent
registry: docker.io
repository: to-be/defined
tag: v1.0.0
properties:
pullPolicy:
default: IfNotPresent
enum:
- Always
- Never
- IfNotPresent
type: string
registry:
default: docker.io
type: string
repository:
default: to-be/defined
type: string
tag:
default: v1.0.0
type: string
type: object
type: object
roles:
default: []
items:
type: string
type: array
issuer:
default: letsencrypt-prod
examples:
- letsencrypt-prod
type: string
version:
default: '14'
examples:
- '14'
type: string
sub-domain:
default: to-be-set
examples:
- to-be-set
type: string
ingress-class:
default: traefik
examples:
- traefik
type: string
databases:
default: []
items:
properties:
name:
default: db
type: string
type: object
type: array
domain-name:
default: your_company.com
examples:
- your_company.com
type: string
dependencies: []
providers:
kubernetes: true
authentik: null
kubectl: true
postgresql: true
restapi: null
http: null
tfaddtype: null

View File

@@ -0,0 +1,79 @@
locals {
pg-labels = merge(local.common-labels, {
"app.kubernetes.io/component" = "postgresql"
})
pool-labels = merge(local.common-labels, {
"app.kubernetes.io/component" = "pg-pool"
})
}
resource "kubectl_manifest" "prj_pg" {
yaml_body = join("", concat([<<-EOF
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: "${var.instance}-${var.component}"
namespace: "${var.namespace}"
labels: ${jsonencode(local.pg-labels)}
spec:
instances: ${var.replicas}
storage:
size: "${var.storage}"
monitoring:
enablePodMonitor: true
EOF
], var.backups.enable?[<<-EOF
backup:
barmanObjectStore:
destinationPath: "s3://${var.instance}-${var.namespace}/"
endpointURL: "${var.backups.endpoint}/barman"
s3Credentials:
accessKeyId:
name: "${var.backups.secret-name}"
key: "${var.backups.key-id-key}"
secretAccessKey:
name: "${var.backups.secret-name}"
key: "${var.backups.secret-key}"
EOF
]:[""]))
}
resource "kubectl_manifest" "prj_pg_backup" {
count = var.backups.enable ? 1:0
yaml_body = <<-EOF
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: "${var.instance}-${var.component}"
namespace: "${var.namespace}"
labels: ${jsonencode(local.pg-labels)}
spec:
schedule: "${var.backups.schedule.db}"
backupOwnerReference: self
cluster:
name: "${var.instance}-${var.component}"
EOF
}
resource "kubectl_manifest" "prj_pg_pool" {
count = var.pool.enable ? 1:0
depends_on = [kubectl_manifest.prj_pg]
yaml_body = <<-EOF
apiVersion: postgresql.cnpg.io/v1
kind: Pooler
metadata:
name: "${var.instance}-${var.component}-pool"
namespace: "${var.namespace}"
labels: ${jsonencode(local.pool-labels)}
spec:
cluster:
name: "${var.instance}-${var.component}"
instances: 1
type: rw
pgbouncer:
poolMode: session
parameters:
max_client_conn: "1000"
default_pool_size: "10"
EOF
}

41
share/dataset-pg/roles.tf Normal file
View File

@@ -0,0 +1,41 @@
locals {
sorted-roles = reverse(distinct(sort(var.roles)))
}
resource "kubectl_manifest" "db_secret" {
ignore_fields = ["metadata.annotations"]
count = length(local.sorted-roles)
yaml_body = <<-EOF
apiVersion: "secretgenerator.mittwald.de/v1alpha1"
kind: "StringSecret"
metadata:
name: "${var.instance}-${var.component}-role-${local.sorted-roles[count.index]}"
namespace: "${var.namespace}"
labels: ${jsonencode(merge(local.common-labels, {"app.kubernetes.io/component" = local.sorted-roles[count.index]}))}
spec:
forceRegenerate: false
data:
POSGRESQL_USERNAME: "${local.sorted-roles[count.index]}"
fields:
- fieldName: "POSGRESQL_PASSWORD"
length: "32"
EOF
}
data "kubernetes_secret_v1" "password_get" {
depends_on = [ kubectl_manifest.db_secret ]
count = length(local.sorted-roles)
metadata {
name = "${var.instance}-${var.component}-role-${local.sorted-roles[count.index]}"
namespace = "${var.namespace}"
}
}
resource "postgresql_role" "role" {
depends_on = [ kubectl_manifest.prj_pg ]
count = length(local.sorted-roles)
name = "${local.sorted-roles[count.index]}"
login = true
password = data.kubernetes_secret_v1.password_get[count.index].data["POSGRESQL_PASSWORD"]
}

22
share/division/datas.tf Normal file
View 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.namespace
}
}
data "kustomization_overlay" "data" {
resources = []
}

24
share/division/groups.tf Normal file
View File

@@ -0,0 +1,24 @@
locals {
sorted-team-names = reverse(distinct(sort([
for team in var.teams: team.name
])))
sorted-teams = flatten([
for name in local.sorted-team-names: [
for team in var.teams:
team if team.name == name
]
])
}
resource "authentik_group" "division" {
name = "div-${var.instance}"
parent = var.parent
attributes = jsonencode(merge([for app in var.apps: {"${app}" = true}]))
}
resource "authentik_group" "teams" {
count = length(local.sorted-teams)
name = "team-${var.instance}-${local.sorted-teams[count.index].name}"
parent = "div-${var.instance}"
attributes = jsonencode(merge([for app in local.sorted-teams[count.index].apps: {"${app}" = true}]))
}

53
share/division/index.yaml Normal file
View File

@@ -0,0 +1,53 @@
---
apiVersion: vinyl.solidite.fr/v1beta1
kind: Component
category: share
metadata:
name: division
description: null
options:
parent:
default: employes
enum:
- employes
- clients
- fournisseurs
examples:
- employes
type: string
teams:
default: []
items:
properties:
apps:
default: []
items:
type: string
type: array
name:
default: ''
type: string
type: object
type: array
domain:
default: your-company
examples:
- your-company
type: string
apps:
default: []
items:
type: string
type: array
dependencies:
- dist: null
category: share
component: accounts-management
providers:
kubernetes: true
authentik: true
kubectl: true
postgresql: null
restapi: null
http: true
tfaddtype: null