zitadel / terraform-provider-zitadel Goto Github PK
View Code? Open in Web Editor NEWOfficial Terraform provider for ZITADEL
Home Page: https://zitadel.com
License: Apache License 2.0
Official Terraform provider for ZITADEL
Home Page: https://zitadel.com
License: Apache License 2.0
Zitadel provides an api to manipulate metadata on org level. The provider should also provide this feature.
Being able to configure branding on instance and organization level via Terraform would be great. With the same possbilities as in the UI.
Problem
With the latest versions of zitadel it is possible to enable/disable domain discovery in the login policy settings. However this feature is not possible to configure with zitadel.
Solution
Make it possible to also manage the domain discovery setting on the zitadel_default_login_policy
and zitadel_login_policy
resources.
default_redirect_uri
and ignore_unknown_usernames
are imported as null
.
Version: 1.0.0-alpha.10
As a developer, I want to config default password change text with Terraform.
Related API; https://zitadel.com/docs/apis/admin/admin-service-set-default-password-change-message-text
As a developer, I want to check against ready for review expectations, so that I am sure that my PR is easily reviewable and merged fast.
Acceptance Criteria
When using the ZITADEL terraform provider, some fields are unnecessary complex.
For example, when creating an OIDC application, the enum for "auth_method_type" is neither documented, nor validated.
Instead of just using the Go enum const value, I suggest using custom values to make them clear and be able to document them properly:
Possible values for auth_method_type
: "none", "jwt_profile", "basic", ... instead of "OIDC_AUTH_METHOD_TYPE_NONE", "OIDC_AUTH_METHOD_TYPE_BASIC", ...
I found a somewhat enum like definition for terraform variables:
variable "input_parameter" {
type = string
default = "a"
validation {
condition = contains(["a", "b", "c"], var.input_parameter)
error_message = "Allowed values for input_parameter are \"a\", \"b\", or \"c\"."
}
}
As a administrator, I want to use the terraform provider to manage instance level members, security settings and IDPs so that I can configure which users have permissions and which idps can be used by the organizations.
Acceptance criteria
Since JWT access token type is available by the release of zitadel/zitadel#5150, we want to set up this parameter with Terraform.
Contains:
Will be implemented if there is demand.
Relates to zitadel/zitadel#4112
After having successfully created this resource:
resource "zitadel_org_member" "org_admin_member" {
depends_on = [zitadel_org.main_org, zitadel_machine_user.admin_user]
org_id = zitadel_org.main_org.id
user_id = zitadel_machine_user.admin_user.id
roles = ["ORG_USER_MANAGER"]
}
I tried editing the roles
as such:
resource "zitadel_org_member" "org_admin_member" {
depends_on = [zitadel_org.main_org, zitadel_machine_user.admin_user]
org_id = zitadel_org.main_org.id
user_id = zitadel_machine_user.admin_user.id
roles = ["IAM_ORG_MANAGER"]
}
planning works, but I get a panic when applying:
╷
│ Error: Request cancelled
│
│ with module.cloud.module.main_configuration.zitadel_org_member.org_admin_member,
│ on main_configuration/main.tf line 79, in resource "zitadel_org_member" "org_admin_member":
│ 79: resource "zitadel_org_member" "org_admin_member" {
│
│ The plugin.(*GRPCProvider).ApplyResourceChange request was cancelled.
╵
Stack trace from the terraform-provider-zitadel_v1.0.0-alpha.8 plugin:
panic: interface conversion: interface {} is *schema.Set, not []string
goroutine 87 [running]:
github.com/zitadel/terraform-provider-zitadel/zitadel/v2/org_member.update({0x1bb61a8, 0xc0000a7860}, 0x18d48c0?, {0x186cec0?, 0xc0002dae80})
github.com/zitadel/terraform-provider-zitadel/zitadel/v2/org_member/funcs.go:53 +0x397
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).update(0xc00014dce0, {0x1bb61e0, 0xc000873800}, 0xd?, {0x186cec0, 0xc0002dae80})
github.com/hashicorp/terraform-plugin-sdk/[email protected]/helper/schema/resource.go:741 +0x12e
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).Apply(0xc00014dce0, {0x1bb61e0, 0xc000873800}, 0xc0002a3c70, 0xc000986280, {0x186cec0, 0xc0002dae80})
github.com/hashicorp/terraform-plugin-sdk/[email protected]/helper/schema/resource.go:847 +0x83a
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).ApplyResourceChange(0xc000293d70, {0x1bb6138?, 0xc0002db9c0?}, 0xc00086ab40)
github.com/hashicorp/terraform-plugin-sdk/[email protected]/helper/schema/grpc_provider.go:1021 +0xe8d
github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server.(*server).ApplyResourceChange(0xc000256460, {0x1bb61e0?, 0xc000873020?}, 0xc0008663f0)
github.com/hashicorp/[email protected]/tfprotov5/tf5server/server.go:812 +0x515
github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5._Provider_ApplyResourceChange_Handler({0x1a135e0?, 0xc000256460}, {0x1bb61e0, 0xc000873020}, 0xc000866380, 0x0)
github.com/hashicorp/[email protected]/tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go:385 +0x170
google.golang.org/grpc.(*Server).processUnaryRPC(0xc0002a4000, {0x1bb9b58, 0xc0003d16c0}, 0xc000869440, 0xc0000b3c80, 0x2282740, 0x0)
google.golang.org/[email protected]/server.go:1295 +0xb2b
google.golang.org/grpc.(*Server).handleStream(0xc0002a4000, {0x1bb9b58, 0xc0003d16c0}, 0xc000869440, 0x0)
google.golang.org/[email protected]/server.go:1636 +0xa2f
google.golang.org/grpc.(*Server).serveStreams.func1.2()
google.golang.org/[email protected]/server.go:932 +0x98
created by google.golang.org/grpc.(*Server).serveStreams.func1
google.golang.org/[email protected]/server.go:930 +0x28a
Error: The terraform-provider-zitadel_v1.0.0-alpha.8 plugin crashed!
This is always indicative of a bug within the plugin. It would be immensely
helpful if you could report the crash with the plugin's maintainers so that it
can be fixed. The output above should help diagnose the issue.
ZITADEL version: 2.3.3
As a developer, I want to config login text with Terraform.
Related API; Login Texts | ZITADEL Docs
I think we should allow users to use the zitadel resources without explicitly defining the provider.
For example with the google cloud tf provider it is solved in this way:
resource "google_cloud_run_service" "default" {
name = "cloudrun-srv"
location = "us-central1"
metadata {
namespace = "my-project-name"
}
template {
spec {
containers {
image = "us-docker.pkg.dev/cloudrun/container/hello"
}
}
}
}
Problem
There are situations such as:
where it must be possible to have a self-contained, reproducible and automated ZITADEL setup that doesn't require human interaction. For example, this setup should be able to reproduce the production setup having the same settings and architecture as well as a dummy user that can be used for local development. This should be achieved by simply running docker compose up
Possible solution
The terraform provider would be a great candidate for this, but it still requires human interaction (login, change password, create a service user with the correct memberships). Is it planned to be able to use the terraform provider in such a way?
From what I've seen it is currently not possible to create an instance of ZITADEL without human interaction, so this might be outside of the scope of this repo.
I'm self-hosting Zitadel with PostgreSQL, but creating resources by Terraform doesn't work at all;
For example, when I tried to create orgs like that;
resource "zitadel_org" "org" {
for_each = var.tenant_ids
name = each.key
}
I got this error;
$ terraform apply
module.zitadel.zitadel_org.org["bbb"]: Creating...
module.zitadel.zitadel_org.org["aaa"]: Creating...
module.zitadel.zitadel_org.org["aaa"]: Creation complete after 2s [id=199928051646111224]
╷
│ Error: rpc error: code = Internal desc = unable to create event (SQL-SBP37)
│
│ with module.zitadel.zitadel_org.org["bbb"],
│ on ../shared/modules/zitadel/org.tf line 1, in resource "zitadel_org" "org":
│ 1: resource "zitadel_org" "org" {
│
╵
Then after I re-ran terraform apply
, it failed before generating the execution plan with this error;
$ terraform apply
module.zitadel.zitadel_org.org["aaa"]: Refreshing state... [id=199928051646111224]
╷
│ Error: error while listing orgs: http status not ok: 400 Bad Request {"error":"server_error","error_description":"ID=SQL-SBP37 Message=unable to create event Parent=(ERROR: duplicate key value violates unique constraint \"previous_sequence_unique\" (SQLSTATE 23505))"}
│
│
│ with module.zitadel.zitadel_org.org["bbb"],
│ on ../shared/modules/zitadel/org.tf line 1, in resource "zitadel_org" "org":
│ 1: resource "zitadel_org" "org" {
│
╵
The error seems to be related to the issue zitadel/zitadel#4784. Something wrong could happen when putting an event in PostgreSQL.
This error is quite critical for us to set up resources with other AWS resources for each tenant. I'm thinking to use CockloachDB if it couldn't be fixed soon, but I prefer PostgreSQL since it can be managed by AWS...
Does anyone know the cause of this problem and the difficulty and priority of fixing it?
The email field is declared as optional:
terraform-provider-zitadel/zitadel/v2/user.go
Line 105 in 97b2d6c
But omitting it triggers this error:
Error: failed to create human user: rpc error: code = InvalidArgument desc = invalid AddHumanUserRequest.Email: value is required
As a administrator, I want to use the terraform provider to manage the notification policy so that I can configure which emails are send to the user on which actions.
Acceptance criteria
When new endpoints are added to ZITADELs APIs, manual work is needed to implement the changes in the Terraform provider. This adds lag to the Terrafrom provider release.
It could be useful to use tools that automatically generate Terraform resources from gRPC definitions.
Example (never used personally, but could be worth investigating): https://github.com/gravitational/protoc-gen-terraform
As an developer, I want a pipeline with semantic release and dependabot so that with a commit and semrel defined tags new versions of the zitadel provider will get released on the terraform registry and the dependencies used are held up-to-date.
Acceptance criteria
As an administrator, I want to use the terraform provider to manage IDPs with the new templated based options so that I'm able to take advantage of them.
User does not exist.
Terraform main.tf:
resource zitadel_org zitadel {
name = "ZITADEL"
}
resource zitadel_human_user dmg_admin {
depends_on = [zitadel_org.zitadel]
org_id = zitadel_org.zitadel.id
user_name = "foobar-admin"
first_name = "Foo"
last_name = "Bar"
email = "[email protected]"
is_email_verified = "true"
initial_password = "Test_1234"
}
Terraform plan and apply for creating the user.
$ terraform apply
zitadel_org.zitadel: Refreshing state... [id=176640833305486796]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
+ create
Terraform will perform the following actions:
# zitadel_human_user.dmg_admin will be created
+ resource "zitadel_human_user" "dmg_admin" {
+ email = "[email protected]"
+ first_name = "Foo"
+ id = (known after apply)
+ initial_password = "Test_1234"
+ is_email_verified = true
+ last_name = "Bar"
+ login_names = (known after apply)
+ org_id = "176640833305486796"
+ preferred_login_name = (known after apply)
+ state = (known after apply)
+ user_name = "foobar-admin"
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
zitadel_human_user.dmg_admin: Creating...
zitadel_human_user.dmg_admin: Creation complete after 2s [id=176749781777909810]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
User was created.
Afterwards the user object was not adjusted in the main.tf
file and terraform applied again. The apply fails.
$ terraform apply
zitadel_org.zitadel: Refreshing state... [id=176640833305486796]
zitadel_human_user.dmg_admin: Refreshing state... [id=176749781777909810]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
~ update in-place
Terraform will perform the following actions:
# zitadel_human_user.dmg_admin will be updated in-place
~ resource "zitadel_human_user" "dmg_admin" {
- display_name = "Foo Bar" -> null
- gender = "GENDER_UNSPECIFIED" -> null
id = "176749781777909810"
~ is_email_verified = false -> true
- preferred_language = "und" -> null
# (10 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
zitadel_human_user.dmg_admin: Modifying... [id=176749781777909810]
2022-08-30T10:11:30.788+0200 [ERROR] vertex "zitadel_human_user.dmg_admin" error: failed to update human profile: rpc error: code = InvalidArgument desc = invalid UpdateHumanProfileRequest.DisplayName: value length must be between 1 and 200 runes, inclusive
╷
│ Error: failed to update human profile: rpc error: code = InvalidArgument desc = invalid UpdateHumanProfileRequest.DisplayName: value length must be between 1 and 200 runes, inclusive
│
│ with zitadel_human_user.dmg_admin,
│ on main.tf line 13, in resource "zitadel_human_user" "dmg_admin":
│ 13: resource zitadel_human_user dmg_admin {
Terraform apply succeeds and the user is not updated because nothing changed in the terraform plan.
Currently, it seems only possible to create terraform resources. For convenience and development workflow (see #13), I would expect to get read "data" blocks to manage at least org and project.
Current, it seems required to create a service account, create keys, add iam to zitadel instance to be able to run terraform. I would expect to be able use FirstInstance token/default credentials to automatize the configuration from scratch. This is especially useful in development where instance are destroyed and recreated multiple times.
It currently is possible to configure IdPs on organization level. However the IdP stays inactive and can only be activated manually through the UI.
Add the possibility to activate/deactivate IdPs from Terraform aswell.
As a administrator, I want to use the terraform provider to manage trigger actions with the respective flow types as strings, not integers, so that it's self-explanatory what it means when you look at the terraform files.
Acceptance criteria
The default values of https://registry.terraform.io/providers/zitadel/zitadel/latest/docs/resources/default_login_policy and https://registry.terraform.io/providers/zitadel/zitadel/latest/docs/resources/login_policy do not match with
https://github.com/zitadel/zitadel/blob/47ffa52f0faef028439914b006f124dc4d465751/cmd/defaults.yaml#L417.
It looks like mfa_init_skip_lifetime
and multi_factor_check_lifetime
might have been swapped given the ranges
Add functionality for icon and logo upload to fully cover the branding with label policy, whereas the images have to be uploaded as assets, which includes some additional logic.
Instead of using a file to point to the JSON jwt profile, it would help to configure the actual JSON value. Then, in CI situations, one can use env vars directly.
So instead of
provider "zitadel" {
domain = local.zitadel_issuer
token = var.zitadel_key_path
}
provider "zitadel" {
domain = local.zitadel_issuer
token = var.zitadel_jwt_profile
}
Further, I suggest to rename the field to actually mirror the use-case:
jwt_profile_file
in this case. Then further use-cases may include:
jwt_profile_json
or personal_access_token
.
This
resource "zitadel_org" "org" {
name = "test"
}
resource "zitadel_machine_user" "machine_user" {
depends_on = [zitadel_org.org]
org_id = zitadel_org.org.id
user_name = "[email protected]"
}
returns the following error:
│ Error: failed to create machine user: rpc error: code = InvalidArgument desc = invalid AddMachineUserRequest.Name: value length must be between 1 and 200 runes, inclusive
│
│ with module.local.zitadel_machine_user.machine_user,
│ on local/main.tf line 49, in resource "zitadel_machine_user" "machine_user":
│ 49: resource "zitadel_machine_user" "machine_user" {
When using the provider to create an OIDC application, some fields are not required (as far as I understand). However, some fields are set in the terraform state which are not configured in the tf
file.
Thus, on planning the provider wants to remove certain defaulted fields and wants to create an in-place update. But, when executing the update, the ZITADEL API responds with an error that no changes are detected.
Terraform File:
resource "zitadel_application_oidc" "frontend" {
org_id = local.zitadel_org_id
project_id = zitadel_project.project.id
name = "Frontend"
redirect_uris = [
"http://localhost/signin",
"http://localhost:3000/signin",
"http://localhost:3000/oauth2-redirect.html",
"http://localhost:5000/signin",
"http://localhost:8080/signin",
]
app_type = "OIDC_APP_TYPE_WEB"
response_types = ["OIDC_RESPONSE_TYPE_CODE"]
grant_types = ["OIDC_GRANT_TYPE_AUTHORIZATION_CODE"]
auth_method_type = "OIDC_AUTH_METHOD_TYPE_NONE"
clock_skew = "0s"
dev_mode = true
}
Terraform Plan:
# zitadel_application_oidc.frontend will be updated in-place
~ resource "zitadel_application_oidc" "frontend" {
- access_token_type = "OIDC_TOKEN_TYPE_BEARER" -> null
id = "181146078928699649"
name = "Frontend"
# (16 unchanged attributes hidden)
}
Response:
Error: failed to update applicationOIDC: rpc error: code = FailedPrecondition desc = No changes (COMMAND-1m88i)
I guess it has to do with the information that is returned versus the one that is in the terraform file.
My suggestion would be to ignore "no changes" errors in the provider and just go on.
https://discord.com/channels/927474939156643850/1064586727475396709 - also logged here
I am running in Kubernetes with nginx ingress and the tls certificates self-signed certs and i get this error when running terraform apply
zitadel_org.org: Creating...
╷
│ Error: failed to start zitadel client: Get "https://k8s-ingress.my.org:443/.well-known/openid-configuration": x509: certificate signed by unknown authority
Created the following main.tf (based on https://zitadel.com/docs/guides/manage/terraform/basics)
terraform {
required_providers {
zitadel = {
source = "zitadel/zitadel"
version = "1.0.0-alpha.11"
}
}
}
provider zitadel {
#domain = "localhost"
domain = "k8s-ingress.my.org"
#insecure = "true"
port = "443"
# project = "196916685255606539"
token = "./196947965552623625.json"
}
resource zitadel_org org {
name = "terraform-test"
}
resource zitadel_human_user human_user {
depends_on = [zitadel_org.org]
org_id = zitadel_org.org.id
user_name = "[email protected]"
first_name = "firstname"
last_name = "lastname"
nick_name = "nickname"
display_name = "displayname"
preferred_language = "de"
gender = "GENDER_MALE"
phone = "+41799999999"
is_phone_verified = true
email = "[email protected]"
is_email_verified = true
initial_password = "Password1!"
}
1.0.0-alpha6
If zitadel_domain has primary flag, it will not be destroyed.
resource zitadel_org my_org {
name = "My Org Name"
}
resource zitadel_domain primary {
org_id = zitadel_org.my_org.id
name = "primary.com"
is_primary = true
}
resource zitadel_domain secondary {
org_id = zitadel_org.my_org.id
name = "secondary.com"
}
When I run terraform destroy on it, I have error.
Error: failed to delete domain: rpc error: code = FailedPrecondition desc = Primary domain must not be deleted (ORG-Sjdi3)
May be domain should be a block in zitadel_org resource?
Provider version: 1.0.0-alpha.16
Zitadel version: 2.23.1
Enums are currently not validated, the value is simply skipped and terraform apply
succeeds.
Terraform doesn't directly support it, but it should nevertheless be possible using constraints.
Being able to configure the SMTP settings so Zitadel is able to send E-Mails.
Problem
In the ui it is possible to manually verify a domain or set it also as primary domain. In terraform this feature is missing. Also if a domain is added before the validate_org_domain
setting was disabled, this domain stays unverified.
Solution
Make it possible to also set a domain as verified and/or primary with terraform.
Acceptance Criteria
Problem:
Most of the times when selecting a data source you want to select it by name and get the ID so you can reference it elsewhere and use it for other resources. At the Moment it is only possible to select data sources by ID. However if you redeploy Zitadel all IDs change but the name stays the same.
Solution:
Make it possible to select data sources by name not by ID.
For now the organization is the most relevant resource, so we will start adding the support there.
Acceptance Criteria
It would be useful to have importers.
This would:
To extend the functionality in #27, it would be helpful to authenticate with a PAT of a service account instead of a jwt profile. PATs are easier to deliver in CI environments and serve the same purpose.
provider "zitadel" {
domain = local.zitadel_issuer
personal_access_token = var.access_token
}
A validator can then check if one of the authentication methods is set.
Contains:
Will be implemented if there is demand.
Booleans should be passed as true
instead of "true"
.
Example:
Docs: https://www.terraform.io/language/expressions/types#bools
Add functionality to manage instance_members as resources to give the option to add instance-level permission to users through terraform.
As a developer, I want to be sure that the Terraform resources affected by my changes are manageable as expected, so that I’m confident my changes don’t break anything.
Acceptance Criteria
When applying a default label policy like this:
resource "zitadel_default_label_policy" "label_policy" {
primary_color = "#000000"
warn_color = "#cd3d56"
background_color = "#ffffff"
font_color = "#4a4a4a"
primary_color_dark = "#ffffff"
background_color_dark = "#111827"
warn_color_dark = "#ff3b5b"
font_color_dark = "#ffffff"
hide_login_name_suffix = true
disable_watermark = true
set_active = true
logo_hash = filemd5("../resources/logo.png")
logo_path = "../resources/logo.png"
logo_dark_hash = filemd5("../resources/logo.png")
logo_dark_path = "../resources/logo.png"
icon_hash = filemd5("../resources/icon.png")
icon_path = "../resources/icon.png"
icon_dark_hash = filemd5("../resources/icon.png")
icon_dark_path = "../resources/icon.png"
font_hash = filemd5("../resources/font.ttf")
font_path = "../resources/font.ttf"
}
it fails with the following error:
Error: failed to upload logo: [{0 either 'jwt_profile_file' or 'jwt_profile_json' is required []}]
│
│ with zitadel_default_label_policy.label_policy,
│ on main.tf line 908, in resource "zitadel_default_label_policy" "label_policy":
│ 908: resource "zitadel_default_label_policy" "label_policy" {
Despite the error, all colors, files and fonts are set as intended. However, when terraform is run again it does not recognize this and tries to apply the changes again, failing with the same error.
If I remove the files (logo, icon, fonts) from the terraform script it works.
I'm using ZITADEL with a PostgreSQL database.
As a administrator i want to use the terraform provider in CI environments and i need a way of passing the service account as value instead of a path.
Acceptance criteria
As a system admin, I want to use a stable release, so I am confident that the Terraform provider doesn't break my setup with new releases.
Acceptance Criteria
As a developer, I wan't to follow a defined process to develop, generate and test code locally, so that I can easily contribute changes.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.