Skip to content

Commit 049e111

Browse files
authored
feat: Added support for using external-secrets with kratos (#48)
* feat: Added support for using external-secrets with kratos * fix: Switched to a more generic form for supplying the external secret source. Changed vars so that JWKS content is passed in instead of secret name. * fix: Allow user-auth to be used without external-secrets * chore: Remove brackets around conditional
1 parent 10bed88 commit 049e111

3 files changed

Lines changed: 61 additions & 14 deletions

File tree

modules/user_auth/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ No requirements.
2222

2323
| Name | Version |
2424
|------|---------|
25-
| aws | n/a |
2625
| helm | n/a |
2726
| kubernetes | n/a |
2827
| null | n/a |
@@ -34,12 +33,15 @@ No requirements.
3433
|------|-------------|------|---------|:--------:|
3534
| auth\_namespace | Namespace to use for auth resources | `string` | `"user-auth"` | no |
3635
| backend\_service\_domain | Domain of the backend service | `string` | n/a | yes |
37-
| cookie\_sigining\_secret\_key | Default secret key for signing cookies | `string` | n/a | yes |
36+
| cookie\_signing\_secret\_key | Default secret key for signing cookies | `string` | n/a | yes |
3837
| create\_namespace | Whether to create the auth namespace(defaults to true), otherwise just references the namespace | `bool` | `true` | no |
38+
| external\_secret\_backend | The backend external-secrets will pull secret data from to create a corresponding secret in kubernetes. If empty, external-secrets will not be used. You'll need to make sure the secret is created manually. | `string` | `"secretsManager"` | no |
39+
| external\_secret\_name | Name of a secret in an external secrets backend that contains the content to pull into a kubernetes secret for Kratos to use | `string` | n/a | yes |
3940
| frontend\_service\_domain | Domain of the frontend | `string` | n/a | yes |
40-
| jwks\_secret\_name | The name of a secret in the auth namespace containing a JWKS file for Oathkeeper | `string` | n/a | yes |
41+
| jwks\_content | The content of a JWKS file for Oathkeeper | `string` | n/a | yes |
4142
| k8s\_local\_exec\_context | Custom resource (Oathkeeper Rules are created using local-exec with kubectl), if not specified it will target your current context from kubeconfig | `string` | `""` | no |
4243
| kratos\_secret\_name | Secret name for kratos to access Database credentials, created from pre-k8s script | `string` | n/a | yes |
44+
| kubectl\_extra\_args | Arguments that will be passed to kubectl when using the local executor in cases where the terraform k8s support is not enough | `string` | n/a | yes |
4345
| name | The name to create user-auth components(kratos/oathkeeper), must be unique in the cluster for helm-resources | `string` | n/a | yes |
4446
| user\_auth\_mail\_from\_address | Mail from the user management system will come from this address | `string` | `""` | no |
4547
| whitelisted\_return\_urls | URLs that can be redirected to after completing a flow initialized with the return\_to parameter | `list(string)` | `[]` | no |

modules/user_auth/main.tf

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
## Get generated JWKS content from secret
2-
data "aws_secretsmanager_secret" "jwks_content" {
3-
name = var.jwks_secret_name
4-
}
5-
data "aws_secretsmanager_secret_version" "jwks_content" {
1+
locals {
2+
# Kubernetes manifest to configure a custom resource that tells external-secrets where to pull secret data from
3+
external_secret_definition = {
4+
apiVersion : "kubernetes-client.io/v1"
5+
kind : "ExternalSecret"
6+
7+
metadata : {
8+
name : var.kratos_secret_name
9+
namespace : var.auth_namespace
10+
}
11+
spec : {
12+
backendType : var.external_secret_backend
13+
dataFrom : [var.external_secret_name]
14+
}
15+
}
16+
617

7-
secret_id = data.aws_secretsmanager_secret.jwks_content.id
818
}
919

1020
resource "kubernetes_namespace" "user_auth" {
@@ -14,19 +24,36 @@ resource "kubernetes_namespace" "user_auth" {
1424
}
1525
}
1626

27+
# Use local exec here because we are creating a custom resource which is not yet supported by the terraform kubernetes provider
28+
resource "null_resource" "external_secret_custom_resource" {
29+
count = var.external_secret_backend == "" ? 0 : 1
30+
31+
triggers = {
32+
manifest_sha1 = sha1(jsonencode(local.external_secret_definition))
33+
}
34+
35+
provisioner "local-exec" {
36+
command = "kubectl apply ${var.kubectl_extra_args} -n ${var.auth_namespace} -f - <<EOF\n${jsonencode(local.external_secret_definition)}\nEOF"
37+
}
38+
39+
depends_on = [kubernetes_namespace.user_auth]
40+
}
41+
1742
resource "helm_release" "kratos" {
1843

1944
name = "kratos-${var.name}"
2045
repository = "https://k8s.ory.sh/helm/charts"
2146
chart = "kratos"
2247
version = "0.4.11"
2348
namespace = var.auth_namespace
49+
depends_on = [kubernetes_namespace.user_auth]
2450

2551
values = [
2652
file("${path.module}/files/kratos-values.yml"),
2753
]
2854

2955
# This secret contains db credentials created during the initial zero apply command
56+
# The kubernetes secret will be created automatically by external-secrets based on the content of a secret from the specified secrets source
3057
set {
3158
name = "secret.nameOverride"
3259
value = var.kratos_secret_name
@@ -46,7 +73,7 @@ resource "helm_release" "kratos" {
4673

4774
set_sensitive {
4875
name = "kratos.config.secrets.default[0]"
49-
value = var.cookie_sigining_secret_key
76+
value = var.cookie_signing_secret_key
5077
}
5178

5279
set {
@@ -168,6 +195,7 @@ resource "helm_release" "oathkeeper" {
168195
chart = "oathkeeper"
169196
version = "0.4.11"
170197
namespace = var.auth_namespace
198+
depends_on = [kubernetes_namespace.user_auth]
171199

172200
values = [
173201
file("${path.module}/files/oathkeeper-values.yml"),
@@ -186,7 +214,7 @@ resource "helm_release" "oathkeeper" {
186214
# Clean up and set the JWKS content. This will become a secret mounted into the pod
187215
set_sensitive {
188216
name = "oathkeeper.mutatorIdTokenJWKs"
189-
value = replace(jsonencode(jsondecode(data.aws_secretsmanager_secret_version.jwks_content.secret_string)), "/([,\\[\\]{}])/", "\\$1")
217+
value = replace(jsonencode(jsondecode(var.jwks_content)), "/([,\\[\\]{}])/", "\\$1")
190218
}
191219

192220
set {

modules/user_auth/variables.tf

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ variable "user_auth_mail_from_address" {
4242
default = ""
4343
}
4444

45-
variable "jwks_secret_name" {
46-
description = "The name of a secret in the auth namespace containing a JWKS file for Oathkeeper"
45+
variable "jwks_content" {
46+
description = "The content of a JWKS file for Oathkeeper"
4747
type = string
48+
sensitive = true
4849
}
4950

5051
variable "whitelisted_return_urls" {
@@ -53,8 +54,24 @@ variable "whitelisted_return_urls" {
5354
default = []
5455
}
5556

56-
variable "cookie_sigining_secret_key" {
57+
variable "cookie_signing_secret_key" {
5758
description = "Default secret key for signing cookies"
5859
type = string
5960
sensitive = true
6061
}
62+
63+
variable "kubectl_extra_args" {
64+
description = "Arguments that will be passed to kubectl when using the local executor in cases where the terraform k8s support is not enough"
65+
type = string
66+
}
67+
68+
variable "external_secret_backend" {
69+
description = "The backend external-secrets will pull secret data from to create a corresponding secret in kubernetes. If empty, external-secrets will not be used. You'll need to make sure the secret is created manually."
70+
type = string
71+
default = "secretsManager"
72+
}
73+
74+
variable "external_secret_name" {
75+
description = "Name of a secret in an external secrets backend that contains the content to pull into a kubernetes secret for Kratos to use"
76+
type = string
77+
}

0 commit comments

Comments
 (0)