Skip to content

Commit 656b4d8

Browse files
committed
Add preliminary support for TDE
1 parent f5e3b0d commit 656b4d8

14 files changed

+283
-1
lines changed

docs/resources/service.md

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ resource "clickhouse_service" "service" {
5959
- `encryption_assumed_role_identifier` (String) Custom role identifier ARN.
6060
- `encryption_key` (String) Custom encryption key ARN.
6161
- `endpoints` (Attributes) Allow to enable and configure additional endpoints (read protocols) to expose on the ClickHouse service. (see [below for nested schema](#nestedatt--endpoints))
62+
- `has_transparent_data_encryption` (Boolean) If true, the Transparent Data Encryption (TDE) feature is enabled in the service. Only supported in AWS and GCP. Requires an organization with the Enterprise plan.
6263
- `idle_scaling` (Boolean) When set to true the service is allowed to scale down to zero when idle.
6364
- `idle_timeout_minutes` (Number) Set minimum idling timeout (in minutes). Must be greater than or equal to 5 minutes. Must be set if idle_scaling is enabled.
6465
- `max_replica_memory_gb` (Number) Maximum memory of a single replica during auto-scaling in Gb. Must be a multiple of 8. `max_replica_memory_gb` x `num_replicas` (default 3) must be lower than 360 for non paid services or 720 for paid services.

examples/full/tde/aws/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## AWS Basic example
2+
3+
The Terraform code deploys following resources:
4+
- 1 ClickHouse service on AWS
5+
6+
WARNING: this example requires an organization with the Enterprise plan to run.
7+
8+
## How to run
9+
10+
- Rename `variables.tfvars.sample` to `variables.tfvars` and fill in all needed data.
11+
- Run `terraform init`
12+
- Run `terraform <plan|apply> -var-file=variables.tfvars`

examples/full/tde/aws/main.tf

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
variable "organization_id" {
2+
type = string
3+
}
4+
5+
variable "token_key" {
6+
type = string
7+
}
8+
9+
variable "token_secret" {
10+
type = string
11+
}
12+
13+
variable "service_name" {
14+
type = string
15+
default = "My Terraform Service"
16+
}
17+
18+
variable "region" {
19+
type = string
20+
default = "us-east-2"
21+
}
22+
23+
variable "release_channel" {
24+
type = string
25+
default = "default"
26+
validation {
27+
condition = var.release_channel == "default" || var.release_channel == "fast"
28+
error_message = "Release channel can be either 'default' or 'fast'."
29+
}
30+
}
31+
32+
data "clickhouse_api_key_id" "self" {
33+
}
34+
35+
resource "clickhouse_service" "service" {
36+
name = var.service_name
37+
cloud_provider = "aws"
38+
region = var.region
39+
release_channel = var.release_channel
40+
idle_scaling = true
41+
idle_timeout_minutes = 5
42+
password_hash = "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=" # base64 encoded sha256 hash of "test"
43+
44+
ip_access = [
45+
{
46+
source = "0.0.0.0"
47+
description = "Anywhere"
48+
}
49+
]
50+
51+
endpoints = {
52+
mysql = {
53+
enabled = true
54+
}
55+
}
56+
57+
query_api_endpoints = {
58+
api_key_ids = [
59+
data.clickhouse_api_key_id.self.id,
60+
]
61+
roles = [
62+
"sql_console_admin"
63+
]
64+
allowed_origins = null
65+
}
66+
67+
min_replica_memory_gb = 8
68+
max_replica_memory_gb = 120
69+
70+
backup_configuration = {
71+
backup_period_in_hours = 24
72+
backup_retention_period_in_hours = 24
73+
backup_start_time = null
74+
}
75+
76+
has_transparent_data_encryption = true
77+
}
78+
79+
output "service_endpoints" {
80+
value = clickhouse_service.service.endpoints
81+
}
82+
83+
output "service_iam" {
84+
value = clickhouse_service.service.iam_role
85+
}

examples/full/tde/aws/provider.tf

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# This file is generated automatically please do not edit
2+
terraform {
3+
required_providers {
4+
clickhouse = {
5+
version = "3.0.0"
6+
source = "ClickHouse/clickhouse"
7+
}
8+
}
9+
}
10+
11+
provider "clickhouse" {
12+
organization_id = var.organization_id
13+
token_key = var.token_key
14+
token_secret = var.token_secret
15+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
terraform {
2+
required_providers {
3+
clickhouse = {
4+
version = "${CLICKHOUSE_TERRAFORM_PROVIDER_VERSION}"
5+
source = "ClickHouse/clickhouse"
6+
}
7+
}
8+
}
9+
10+
provider "clickhouse" {
11+
organization_id = var.organization_id
12+
token_key = var.token_key
13+
token_secret = var.token_secret
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# these keys are for example only and won't work when pointed to a deployed ClickHouse OpenAPI server
2+
organization_id = "aee076c1-3f83-4637-95b1-ad5a0a825b71"
3+
token_key = "avhj1U5QCdWAE9CA9"
4+
token_secret = "4b1dROiHQEuSXJHlV8zHFd0S7WQj7CGxz5kGJeJnca"

examples/full/tde/gcp/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## AWS Basic example
2+
3+
The Terraform code deploys following resources:
4+
- 1 ClickHouse service on GCP with TDE feature enabled
5+
6+
WARNING: this example requires an organization with the Enterprise plan to run.
7+
8+
## How to run
9+
10+
- Rename `variables.tfvars.sample` to `variables.tfvars` and fill in all needed data.
11+
- Run `terraform init`
12+
- Run `terraform <plan|apply> -var-file=variables.tfvars`

examples/full/tde/gcp/main.tf

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
variable "organization_id" {
2+
type = string
3+
}
4+
5+
variable "token_key" {
6+
type = string
7+
}
8+
9+
variable "token_secret" {
10+
type = string
11+
}
12+
13+
variable "service_name" {
14+
type = string
15+
default = "My Terraform Service"
16+
}
17+
18+
variable "region" {
19+
type = string
20+
default = "europe-west4"
21+
}
22+
23+
variable "release_channel" {
24+
type = string
25+
default = "default"
26+
validation {
27+
condition = var.release_channel == "default" || var.release_channel == "fast"
28+
error_message = "Release channel can be either 'default' or 'fast'."
29+
}
30+
}
31+
32+
data "clickhouse_api_key_id" "self" {
33+
}
34+
35+
resource "clickhouse_service" "service" {
36+
name = var.service_name
37+
cloud_provider = "gcp"
38+
region = var.region
39+
release_channel = var.release_channel
40+
idle_scaling = true
41+
idle_timeout_minutes = 5
42+
password_hash = "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=" # base64 encoded sha256 hash of "test"
43+
44+
ip_access = [
45+
{
46+
source = "0.0.0.0"
47+
description = "Anywhere"
48+
}
49+
]
50+
51+
endpoints = {
52+
mysql = {
53+
enabled = true
54+
}
55+
}
56+
57+
query_api_endpoints = {
58+
api_key_ids = [
59+
data.clickhouse_api_key_id.self.id,
60+
]
61+
roles = [
62+
"sql_console_admin"
63+
]
64+
allowed_origins = null
65+
}
66+
67+
min_replica_memory_gb = 8
68+
max_replica_memory_gb = 120
69+
70+
backup_configuration = {
71+
backup_retention_period_in_hours = 48
72+
}
73+
74+
has_transparent_data_encryption = true
75+
}
76+
77+
output "service_endpoints" {
78+
value = clickhouse_service.service.endpoints
79+
}
80+
81+
output "service_iam" {
82+
value = clickhouse_service.service.iam_role
83+
}

examples/full/tde/gcp/provider.tf

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# This file is generated automatically please do not edit
2+
terraform {
3+
required_providers {
4+
clickhouse = {
5+
version = "3.0.0"
6+
source = "ClickHouse/clickhouse"
7+
}
8+
}
9+
}
10+
11+
provider "clickhouse" {
12+
organization_id = var.organization_id
13+
token_key = var.token_key
14+
token_secret = var.token_secret
15+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
terraform {
2+
required_providers {
3+
clickhouse = {
4+
version = "${CLICKHOUSE_TERRAFORM_PROVIDER_VERSION}"
5+
source = "ClickHouse/clickhouse"
6+
}
7+
}
8+
}
9+
10+
provider "clickhouse" {
11+
organization_id = var.organization_id
12+
token_key = var.token_key
13+
token_secret = var.token_secret
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# these keys are for example only and won't work when pointed to a deployed ClickHouse OpenAPI server
2+
organization_id = "aee076c1-3f83-4637-95b1-ad5a0a825b71"
3+
token_key = "avhj1U5QCdWAE9CA9"
4+
token_secret = "4b1dROiHQEuSXJHlV8zHFd0S7WQj7CGxz5kGJeJnca"

pkg/internal/api/models.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ type Service struct {
6262
PrivateEndpointIds []string `json:"privateEndpointIds,omitempty"`
6363
EncryptionKey string `json:"encryptionKey,omitempty"`
6464
EncryptionAssumedRoleIdentifier string `json:"encryptionAssumedRoleIdentifier,omitempty"`
65+
HasTransparentDataEncryption *bool `json:"hasTransparentDataEncryption,omitempty"`
6566
BackupConfiguration *BackupConfiguration `json:"backupConfiguration,omitempty"`
6667
ReleaseChannel string `json:"releaseChannel,omitempty"`
6768
QueryAPIEndpoints *ServiceQueryEndpoint `json:"-"`
68-
HasTransparentDataEncryption bool `json:"hasTransparentDataEncryption,omitempty"`
6969
}
7070

7171
type ServiceUpdate struct {

pkg/resource/models/service_resource.go

+2
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ type ServiceResourceModel struct {
208208
PrivateEndpointConfig types.Object `tfsdk:"private_endpoint_config"`
209209
EncryptionKey types.String `tfsdk:"encryption_key"`
210210
EncryptionAssumedRoleIdentifier types.String `tfsdk:"encryption_assumed_role_identifier"`
211+
HasTransparentDataEncryption types.Bool `tfsdk:"has_transparent_data_encryption"`
211212
QueryAPIEndpoints types.Object `tfsdk:"query_api_endpoints"`
212213
BackupConfiguration types.Object `tfsdk:"backup_configuration"`
213214
HasTransparentDataEncryption types.Bool `tfsdk:"has_transparent_data_encryption"`
@@ -237,6 +238,7 @@ func (m *ServiceResourceModel) Equals(b ServiceResourceModel) bool {
237238
!m.PrivateEndpointConfig.Equal(b.PrivateEndpointConfig) ||
238239
!m.EncryptionKey.Equal(b.EncryptionKey) ||
239240
!m.EncryptionAssumedRoleIdentifier.Equal(b.EncryptionAssumedRoleIdentifier) ||
241+
!m.HasTransparentDataEncryption.Equal(b.HasTransparentDataEncryption) ||
240242
!m.IpAccessList.Equal(b.IpAccessList) ||
241243
!m.QueryAPIEndpoints.Equal(b.QueryAPIEndpoints) ||
242244
!m.BackupConfiguration.Equal(b.BackupConfiguration) ||

pkg/resource/service.go

+21
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,15 @@ func (r *ServiceResource) Schema(_ context.Context, _ resource.SchemaRequest, re
338338
Description: "Custom role identifier ARN.",
339339
Optional: true,
340340
},
341+
"has_transparent_data_encryption": schema.BoolAttribute{
342+
Description: "If true, the Transparent Data Encryption (TDE) feature is enabled in the service. Only supported in AWS and GCP. Requires an organization with the Enterprise plan.",
343+
Optional: true,
344+
Computed: true,
345+
PlanModifiers: []planmodifier.Bool{
346+
boolplanmodifier.UseStateForUnknown(),
347+
boolplanmodifier.RequiresReplace(),
348+
},
349+
},
341350
"query_api_endpoints": schema.SingleNestedAttribute{
342351
Description: "Configuration of the query API endpoints feature.",
343352
Optional: true,
@@ -768,6 +777,12 @@ func (r *ServiceResource) Create(ctx context.Context, req resource.CreateRequest
768777
}
769778
}
770779

780+
if service.Tier == api.TierPPv2 {
781+
if !plan.HasTransparentDataEncryption.IsUnknown() && !plan.HasTransparentDataEncryption.IsNull() {
782+
service.HasTransparentDataEncryption = plan.HasTransparentDataEncryption.ValueBoolPointer()
783+
}
784+
}
785+
771786
service.IdleScaling = plan.IdleScaling.ValueBool()
772787
if !plan.IdleTimeoutMinutes.IsNull() {
773788
idleTimeoutMinutes := int(plan.IdleTimeoutMinutes.ValueInt64())
@@ -1794,6 +1809,12 @@ func (r *ServiceResource) syncServiceState(ctx context.Context, state *models.Se
17941809
state.EncryptionAssumedRoleIdentifier = types.StringNull()
17951810
}
17961811

1812+
if service.HasTransparentDataEncryption != nil {
1813+
state.HasTransparentDataEncryption = types.BoolValue(*service.HasTransparentDataEncryption)
1814+
} else {
1815+
state.HasTransparentDataEncryption = types.BoolNull()
1816+
}
1817+
17971818
if service.QueryAPIEndpoints != nil {
17981819
queryApiEndpoint := models.QueryAPIEndpoints{}
17991820

0 commit comments

Comments
 (0)