diff --git a/docs/data-sources/cdn_distribution.md b/docs/data-sources/cdn_distribution.md index c81d09ad3..32a3e2786 100644 --- a/docs/data-sources/cdn_distribution.md +++ b/docs/data-sources/cdn_distribution.md @@ -46,6 +46,8 @@ data "stackit_cdn_distribution" "example" { Optional: - `blocked_countries` (List of String) The configured countries where distribution of content is blocked +- `forward_host_header` (Boolean) Enable this allows the 'Host' header to be passed through to the origin. +- `strip_response_cookies` (Boolean) Enable this to prevent origin-level cookies from being forwarded to the end user. Read-Only: @@ -53,6 +55,7 @@ Read-Only: - `optimizer` (Attributes) Configuration for the Image Optimizer. This is a paid feature that automatically optimizes images to reduce their file size for faster delivery, leading to improved website performance and a better user experience. (see [below for nested schema](#nestedatt--config--optimizer)) - `redirects` (Attributes) A wrapper for a list of redirect rules that allows for redirect settings on a distribution (see [below for nested schema](#nestedatt--config--redirects)) - `regions` (List of String) The configured regions where content will be hosted +- `tls` (Attributes) Configuration for TLS protocol versions. Note: Enabling older TLS versions (1.0, 1.1) is generally discouraged for security reasons. (see [below for nested schema](#nestedatt--config--tls)) - `waf` (Attributes) Configures the Web Application Firewall (WAF) for the distribution. If this block is undefined or removed from your configuration, the WAF mode will default to DISABLED and the type to FREE. All other WAF properties will retain their last known state in the API; if they were never defined, the API will apply its default settings. (see [below for nested schema](#nestedatt--config--waf)) @@ -106,6 +109,15 @@ Read-Only: + +### Nested Schema for `config.tls` + +Read-Only: + +- `enable_tls_10` (Boolean) If set to true, the distribution will accept connections using TLS 1.1. +- `enable_tls_11` (Boolean) If set to true, the distribution will accept connections using TLS 1.0. + + ### Nested Schema for `config.waf` diff --git a/docs/resources/cdn_distribution.md b/docs/resources/cdn_distribution.md index 046eeffae..0ec70a3b8 100644 --- a/docs/resources/cdn_distribution.md +++ b/docs/resources/cdn_distribution.md @@ -146,8 +146,11 @@ Required: Optional: - `blocked_countries` (List of String) The configured countries where distribution of content is blocked +- `forward_host_header` (Boolean) Enable this allows the 'Host' header to be passed through to the origin. - `optimizer` (Attributes) Configuration for the Image Optimizer. This is a paid feature that automatically optimizes images to reduce their file size for faster delivery, leading to improved website performance and a better user experience. (see [below for nested schema](#nestedatt--config--optimizer)) - `redirects` (Attributes) A wrapper for a list of redirect rules that allows for redirect settings on a distribution (see [below for nested schema](#nestedatt--config--redirects)) +- `strip_response_cookies` (Boolean) Enable this to prevent origin-level cookies from being forwarded to the end user. +- `tls` (Attributes) Configuration for TLS protocol versions. Note: Enabling older TLS versions (1.0, 1.1) is generally discouraged for security reasons. (see [below for nested schema](#nestedatt--config--tls)) - `waf` (Attributes) Configures the Web Application Firewall (WAF) for the distribution. If this block is undefined or removed from your configuration, the WAF mode will default to DISABLED and the type to FREE. All other WAF properties will retain their last known state in the API; if they were never defined, the API will apply its default settings. (see [below for nested schema](#nestedatt--config--waf)) @@ -220,6 +223,15 @@ Optional: + +### Nested Schema for `config.tls` + +Optional: + +- `enable_tls_10` (Boolean) If set to true, the distribution will accept connections using TLS 1.1. +- `enable_tls_11` (Boolean) If set to true, the distribution will accept connections using TLS 1.0. + + ### Nested Schema for `config.waf` diff --git a/examples/resources/stackit_cdn_distribution/resource.tf b/examples/resources/stackit_cdn_distribution/resource.tf index afeabecc6..4475b8854 100644 --- a/examples/resources/stackit_cdn_distribution/resource.tf +++ b/examples/resources/stackit_cdn_distribution/resource.tf @@ -57,6 +57,13 @@ resource "stackit_cdn_distribution" "example_bucket_distribution" { ] } + tls = { + enable_tls_10 = true + enable_tls_11 = true + } + strip_response_cookies = true + forward_host_header = true + # WAF Configuration # # Precedence Hierarchy: Specific Rules > Groups > Collections diff --git a/stackit/internal/services/cdn/cdn_acc_test.go b/stackit/internal/services/cdn/cdn_acc_test.go index 369f23c5e..f66d4f2eb 100644 --- a/stackit/internal/services/cdn/cdn_acc_test.go +++ b/stackit/internal/services/cdn/cdn_acc_test.go @@ -122,6 +122,10 @@ var testConfigVarsHttp = config.Variables{ "waf_log_only_rule_ids_0": config.StringVariable(wafRule3), "waf_log_only_rule_group_ids_0": config.StringVariable(wafRule3), "waf_log_only_rule_collection_ids_0": config.StringVariable(wafRule3), + "tls_enable_tls_10": config.BoolVariable(true), + "tls_enable_tls_11": config.BoolVariable(true), + "strip_response_cookies": config.BoolVariable(false), + "forward_host_header": config.BoolVariable(true), } func configVarsHttpUpdated() config.Variables { @@ -137,6 +141,21 @@ func configVarsHttpUpdated() config.Variables { updatedConfig["waf_allowed_http_versions_0"] = config.StringVariable("HTTP/1.1") updatedConfig["waf_paranoia_level"] = config.StringVariable("L3") + // Update TLS + updatedConfig["tls_enable_tls_10"] = config.BoolVariable(false) + updatedConfig["tls_enable_tls_11"] = config.BoolVariable(false) + + // Update small features + updatedConfig["strip_response_cookies"] = config.BoolVariable(true) + updatedConfig["forward_host_header"] = config.BoolVariable(false) + + // Update WAF rules + updatedConfig["waf_disabled_rule_ids_0"] = config.StringVariable(wafRule3) + updatedConfig["waf_disabled_rule_group_ids_0"] = config.StringVariable(wafRule3) + updatedConfig["waf_disabled_rule_collection_ids_0"] = config.StringVariable(wafRule3) + + updatedConfig["waf_enabled_rule_ids_0"] = config.StringVariable(wafRule1) + updatedConfig["waf_enabled_rule_ids_0"] = config.StringVariable(wafRule2) updatedConfig["waf_enabled_rule_group_ids_0"] = config.StringVariable(wafRule2) updatedConfig["waf_enabled_rule_collection_ids_0"] = config.StringVariable(wafRule2) @@ -234,6 +253,12 @@ func TestAccCDNDistributionHttp(t *testing.T) { ), resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.optimizer.enabled", testutil.ConvertConfigVariable(testConfigVarsHttp["optimizer"])), + // TLS Checks + resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.tls.enable_tls_10", testutil.ConvertConfigVariable(testConfigVarsHttp["tls_enable_tls_10"])), + resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.tls.enable_tls_11", testutil.ConvertConfigVariable(testConfigVarsHttp["tls_enable_tls_11"])), + resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.forward_host_header", testutil.ConvertConfigVariable(testConfigVarsHttp["forward_host_header"])), + resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.strip_response_cookies", testutil.ConvertConfigVariable(testConfigVarsHttp["strip_response_cookies"])), + // WAF Checks resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.waf.mode", testutil.ConvertConfigVariable(testConfigVarsHttp["waf_mode"])), resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.waf.type", testutil.ConvertConfigVariable(testConfigVarsHttp["waf_type"])), @@ -371,6 +396,12 @@ func TestAccCDNDistributionHttp(t *testing.T) { resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.blocked_countries.0", "CU"), resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.optimizer.enabled", testutil.ConvertConfigVariable(testConfigVarsHttp["optimizer"])), + // TLS Checks inside Data Source + resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.tls.enable_tls_10", testutil.ConvertConfigVariable(testConfigVarsHttp["tls_enable_tls_10"])), + resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.tls.enable_tls_11", testutil.ConvertConfigVariable(testConfigVarsHttp["tls_enable_tls_11"])), + resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.forward_host_header", testutil.ConvertConfigVariable(testConfigVarsHttp["forward_host_header"])), + resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.strip_response_cookies", testutil.ConvertConfigVariable(testConfigVarsHttp["strip_response_cookies"])), + // WAF Checks inside Data Source resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.waf.mode", testutil.ConvertConfigVariable(testConfigVarsHttp["waf_mode"])), resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "config.waf.type", testutil.ConvertConfigVariable(testConfigVarsHttp["waf_type"])), @@ -445,6 +476,12 @@ func TestAccCDNDistributionHttp(t *testing.T) { resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.blocked_countries.0", "CU"), resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.optimizer.enabled", testutil.ConvertConfigVariable(testConfigVarsHttp["optimizer"])), + // TLS Configuration + resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.tls.enable_tls_10", testutil.ConvertConfigVariable(configVarsHttpUpdated()["tls_enable_tls_10"])), + resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.tls.enable_tls_11", testutil.ConvertConfigVariable(configVarsHttpUpdated()["tls_enable_tls_11"])), + resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.forward_host_header", testutil.ConvertConfigVariable(configVarsHttpUpdated()["forward_host_header"])), + resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.strip_response_cookies", testutil.ConvertConfigVariable(configVarsHttpUpdated()["strip_response_cookies"])), + // Checking WAF Mutated Configurations resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.waf.mode", testutil.ConvertConfigVariable(configVarsHttpUpdated()["waf_mode"])), resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "config.waf.type", testutil.ConvertConfigVariable(configVarsHttpUpdated()["waf_type"])), diff --git a/stackit/internal/services/cdn/distribution/datasource.go b/stackit/internal/services/cdn/distribution/datasource.go index 69ac63f4a..41fd1882f 100644 --- a/stackit/internal/services/cdn/distribution/datasource.go +++ b/stackit/internal/services/cdn/distribution/datasource.go @@ -46,6 +46,11 @@ var dataSourceConfigTypes = map[string]attr.Type{ "waf": types.ObjectType{ AttrTypes: wafTypes, // Shared from resource.go }, + "tls": types.ObjectType{ + AttrTypes: tlsTypes, // Shared from resource.go + }, + "strip_response_cookies": types.BoolType, + "forward_host_header": types.BoolType, } type distributionDataSource struct { @@ -207,6 +212,30 @@ func (r *distributionDataSource) Schema(_ context.Context, _ datasource.SchemaRe }, }, }, + "strip_response_cookies": schema.BoolAttribute{ + Optional: true, + Computed: true, + Description: schemaDescriptions["config_strip_response_cookies"], + }, + "forward_host_header": schema.BoolAttribute{ + Optional: true, + Computed: true, + Description: schemaDescriptions["config_forward_host_header"], + }, + "tls": schema.SingleNestedAttribute{ + Description: schemaDescriptions["config_tls_config"], + Computed: true, + Attributes: map[string]schema.Attribute{ + "enable_tls_11": schema.BoolAttribute{ + Computed: true, + Description: schemaDescriptions["config_tls_enable_tls_10"], + }, + "enable_tls_10": schema.BoolAttribute{ + Computed: true, + Description: schemaDescriptions["config_tls_enable_tls_11"], + }, + }, + }, "redirects": schema.SingleNestedAttribute{ Computed: true, Description: schemaDescriptions["config_redirects"], @@ -641,14 +670,27 @@ func mapDataSourceFields(ctx context.Context, distribution *cdnSdk.Distribution, } } + tlsObjAttrs := map[string]attr.Value{ + "enable_tls_10": types.BoolValue(distribution.Config.Tls.EnableTls10), + "enable_tls_11": types.BoolValue(distribution.Config.Tls.EnableTls11), + } + + tlsVal, diagTls := types.ObjectValue(tlsTypes, tlsObjAttrs) + if diagTls.HasError() { + return core.DiagsToError(diagWaf) + } + // Use dataSourceConfigTypes cfg, diags := types.ObjectValue(dataSourceConfigTypes, map[string]attr.Value{ - "backend": backend, - "regions": modelRegions, - "blocked_countries": modelBlockedCountries, - "optimizer": optimizerVal, - "redirects": redirectsVal, - "waf": wafVal, + "backend": backend, + "regions": modelRegions, + "blocked_countries": modelBlockedCountries, + "optimizer": optimizerVal, + "redirects": redirectsVal, + "waf": wafVal, + "tls": tlsVal, + "strip_response_cookies": types.BoolValue(distribution.Config.StripResponseCookies), + "forward_host_header": types.BoolValue(distribution.Config.ForwardHostHeader), }) if diags.HasError() { return core.DiagsToError(diags) diff --git a/stackit/internal/services/cdn/distribution/datasource_test.go b/stackit/internal/services/cdn/distribution/datasource_test.go index 7c0effccb..96513d5ad 100644 --- a/stackit/internal/services/cdn/distribution/datasource_test.go +++ b/stackit/internal/services/cdn/distribution/datasource_test.go @@ -58,14 +58,20 @@ func TestMapDataSourceFields(t *testing.T) { "disabled_rule_collection_ids": emptyWafSet, "log_only_rule_collection_ids": emptyWafSet, }) - + defaultTls := types.ObjectValueMust(tlsTypes, map[string]attr.Value{ + "enable_tls_10": types.BoolValue(false), + "enable_tls_11": types.BoolValue(false), + }) config := types.ObjectValueMust(dataSourceConfigTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "blocked_countries": blockedCountriesFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "redirects": types.ObjectNull(redirectsTypes), - "waf": emptyWaf, + "backend": backend, + "regions": regionsFixture, + "blocked_countries": blockedCountriesFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "redirects": types.ObjectNull(redirectsTypes), + "waf": emptyWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) redirectsInput := cdnSdk.RedirectConfig{ Rules: []cdnSdk.RedirectRule{ @@ -233,12 +239,15 @@ func TestMapDataSourceFields(t *testing.T) { "happy_path_with_optimizer": { Expected: expectedModel(func(m *Model) { m.Config = types.ObjectValueMust(dataSourceConfigTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": optimizer, - "blocked_countries": blockedCountriesFixture, - "redirects": types.ObjectNull(redirectsTypes), - "waf": emptyWaf, + "backend": backend, + "regions": regionsFixture, + "optimizer": optimizer, + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsTypes), + "waf": emptyWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), Input: distributionFixture(func(d *cdnSdk.Distribution) { @@ -260,12 +269,15 @@ func TestMapDataSourceFields(t *testing.T) { }), Expected: expectedModel(func(m *Model) { m.Config = types.ObjectValueMust(dataSourceConfigTypes, map[string]attr.Value{ - "backend": bucketBackendExpected, - "regions": regionsFixture, - "blocked_countries": blockedCountriesFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "redirects": types.ObjectNull(redirectsTypes), - "waf": emptyWaf, + "backend": bucketBackendExpected, + "regions": regionsFixture, + "blocked_countries": blockedCountriesFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "redirects": types.ObjectNull(redirectsTypes), + "waf": emptyWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), IsValid: true, @@ -281,12 +293,15 @@ func TestMapDataSourceFields(t *testing.T) { "region": types.StringNull(), }) m.Config = types.ObjectValueMust(dataSourceConfigTypes, map[string]attr.Value{ - "backend": backendWithGeofencing, - "regions": regionsFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "blocked_countries": blockedCountriesFixture, - "redirects": types.ObjectNull(redirectsTypes), - "waf": emptyWaf, + "backend": backendWithGeofencing, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsTypes), + "waf": emptyWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), Input: distributionFixture(func(d *cdnSdk.Distribution) { @@ -306,12 +321,15 @@ func TestMapDataSourceFields(t *testing.T) { "happy_path_with_redirects": { Expected: expectedModel(func(m *Model) { m.Config = types.ObjectValueMust(dataSourceConfigTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "blocked_countries": blockedCountriesFixture, - "redirects": redirectsConfigExpected, - "waf": emptyWaf, + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": redirectsConfigExpected, + "waf": emptyWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), Input: distributionFixture(func(d *cdnSdk.Distribution) { @@ -322,12 +340,15 @@ func TestMapDataSourceFields(t *testing.T) { "happy_path_with_waf": { Expected: expectedModel(func(m *Model) { m.Config = types.ObjectValueMust(dataSourceConfigTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "blocked_countries": blockedCountriesFixture, - "redirects": types.ObjectNull(redirectsTypes), - "waf": populatedWaf, + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsTypes), + "waf": populatedWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), Input: distributionFixture(func(d *cdnSdk.Distribution) { @@ -368,6 +389,33 @@ func TestMapDataSourceFields(t *testing.T) { }), IsValid: true, }, + "happy_path_with_tls_and_strip_response_and_cookies_forward": { + Expected: expectedModel(func(m *Model) { + m.Config = types.ObjectValueMust(dataSourceConfigTypes, map[string]attr.Value{ + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsTypes), + "waf": emptyWaf, + "tls": types.ObjectValueMust(tlsTypes, map[string]attr.Value{ + "enable_tls_10": types.BoolValue(true), + "enable_tls_11": types.BoolValue(true), + }), + "strip_response_cookies": types.BoolValue(true), + "forward_host_header": types.BoolValue(true), + }) + }), + Input: distributionFixture(func(d *cdnSdk.Distribution) { + d.Config.Tls = cdnSdk.TlsConfig{ + EnableTls10: true, + EnableTls11: true, + } + d.Config.ForwardHostHeader = true + d.Config.StripResponseCookies = true + }), + IsValid: true, + }, "sad_path_distribution_nil": { Expected: nil, Input: nil, diff --git a/stackit/internal/services/cdn/distribution/resource.go b/stackit/internal/services/cdn/distribution/resource.go index 488acdfed..14f0a3f98 100644 --- a/stackit/internal/services/cdn/distribution/resource.go +++ b/stackit/internal/services/cdn/distribution/resource.go @@ -102,6 +102,11 @@ var schemaDescriptions = map[string]string{ "waf_enabled_rule_collection_ids": "Set of WAF Collection IDs explicitly enabled. Can be set to an empty set to clear previously set rules. Case you removed waf will retain the last known state. To view available rule collections, please consult the API documentation: https://docs.api.eu01.stackit.cloud/documentation/cdn/version/v1#tag/WAF/operation/ListWafCollections", "waf_disabled_rule_collection_ids": "Set of WAF Collection IDs explicitly disabled. Can be set to an empty set to clear previously set rules. Case you removed waf will retain the last known state. To view available rule collections, please consult the API documentation: https://docs.api.eu01.stackit.cloud/documentation/cdn/version/v1#tag/WAF/operation/ListWafCollections", "waf_log_only_rule_collection_ids": "Set of WAF Collection IDs explicitly marked as Log Only. Can be set to an empty set to clear previously set rules. Case you removed waf will retain the last known state. To view available rule collections, please consult the API documentation: https://docs.api.eu01.stackit.cloud/documentation/cdn/version/v1#tag/WAF/operation/ListWafCollections", + "config_tls_config": "Configuration for TLS protocol versions. Note: Enabling older TLS versions (1.0, 1.1) is generally discouraged for security reasons.", + "config_tls_enable_tls_10": "If set to true, the distribution will accept connections using TLS 1.0.", + "config_tls_enable_tls_11": "If set to true, the distribution will accept connections using TLS 1.1.", + "config_strip_response_cookies": "Enable this to prevent origin-level cookies from being forwarded to the end user.", + "config_forward_host_header": "Enable this allows the 'Host' header to be passed through to the origin.", } type Model struct { @@ -135,12 +140,15 @@ type redirectConfig struct { } type distributionConfig struct { - Backend backend `tfsdk:"backend"` // The backend associated with the distribution - Redirects *redirectConfig `tfsdk:"redirects"` // A wrapper for a list of redirect rules that allows for redirect settings on a distribution - Regions *[]string `tfsdk:"regions"` // The regions in which data will be cached - BlockedCountries *[]string `tfsdk:"blocked_countries"` // The countries for which content will be blocked - Optimizer types.Object `tfsdk:"optimizer"` // The optimizer configuration - Waf types.Object `tfsdk:"waf"` // The WAF configuration + Backend backend `tfsdk:"backend"` // The backend associated with the distribution + Redirects *redirectConfig `tfsdk:"redirects"` // A wrapper for a list of redirect rules that allows for redirect settings on a distribution + Regions *[]string `tfsdk:"regions"` // The regions in which data will be cached + BlockedCountries *[]string `tfsdk:"blocked_countries"` // The countries for which content will be blocked + Optimizer types.Object `tfsdk:"optimizer"` // The optimizer configuration + Waf types.Object `tfsdk:"waf"` // The WAF configuration + Tls types.Object `tfsdk:"tls"` // The TLS configuration + StripResponseCookies types.Bool `tfsdk:"strip_response_cookies"` // The Enable this to prevent origin-level cookies from being forwarded to the end user + ForwardHostHeader types.Bool `tfsdk:"forward_host_header"` // The Enable this allows the 'Host' header to be passed through to the origin. } type optimizerConfig struct { @@ -157,6 +165,11 @@ type backend struct { Credentials *backendCredentials `tfsdk:"credentials"` } +type tlsConfig struct { + EnableTls10 types.Bool `tfsdk:"enable_tls_10"` + EnableTls11 types.Bool `tfsdk:"enable_tls_11"` +} + type wafConfig struct { Mode types.String `tfsdk:"mode"` Type types.String `tfsdk:"type"` @@ -193,6 +206,11 @@ var configTypes = map[string]attr.Type{ "waf": types.ObjectType{ AttrTypes: wafTypes, }, + "tls": types.ObjectType{ + AttrTypes: tlsTypes, + }, + "strip_response_cookies": types.BoolType, + "forward_host_header": types.BoolType, } var optimizerTypes = map[string]attr.Type{ @@ -229,6 +247,11 @@ var redirectsTypes = map[string]attr.Type{ }, } +var tlsTypes = map[string]attr.Type{ + "enable_tls_10": types.BoolType, + "enable_tls_11": types.BoolType, +} + var wafTypes = map[string]attr.Type{ "mode": types.StringType, "type": types.StringType, @@ -389,6 +412,33 @@ func (r *distributionResource) Schema(_ context.Context, _ resource.SchemaReques objectvalidator.AlsoRequires(path.MatchRelative().AtName("enabled")), }, }, + "strip_response_cookies": schema.BoolAttribute{ + Optional: true, + Computed: true, + Description: schemaDescriptions["config_strip_response_cookies"], + }, + "forward_host_header": schema.BoolAttribute{ + Optional: true, + Computed: true, + Description: schemaDescriptions["config_forward_host_header"], + }, + "tls": schema.SingleNestedAttribute{ + Description: schemaDescriptions["config_tls_config"], + Optional: true, + Computed: true, + Attributes: map[string]schema.Attribute{ + "enable_tls_11": schema.BoolAttribute{ + Optional: true, + Computed: true, + Description: schemaDescriptions["config_tls_enable_tls_10"], + }, + "enable_tls_10": schema.BoolAttribute{ + Optional: true, + Computed: true, + Description: schemaDescriptions["config_tls_enable_tls_11"], + }, + }, + }, "redirects": schema.SingleNestedAttribute{ Optional: true, Description: schemaDescriptions["config_redirects"], @@ -868,6 +918,21 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe blockedCountries = tempBlockedCountries } + // tls + var tls *cdnSdk.TlsConfigPatch + if !utils.IsUndefined(configModel.Tls) { + var tlsValue tlsConfig + diags = configModel.Tls.As(ctx, &tlsValue, basetypes.ObjectAsOptions{}) + if diags.HasError() { + core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", "Error mapping TLS config") + return + } + tls = &cdnSdk.TlsConfigPatch{ + EnableTls10: new(tlsValue.EnableTls10.ValueBool()), + EnableTls11: new(tlsValue.EnableTls11.ValueBool()), + } + } + // redirects redirectsConfig := convertRedirectconfig(configModel.Redirects) @@ -917,6 +982,16 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe Regions: regions, BlockedCountries: blockedCountries, Redirects: redirectsConfig, + Tls: tls, + } + + // forwardHostHeader + if !utils.IsUndefined(configModel.ForwardHostHeader) { + configPatch.ForwardHostHeader = new(configModel.ForwardHostHeader.ValueBool()) + } + // stripResponseCookies + if !utils.IsUndefined(configModel.StripResponseCookies) { + configPatch.StripResponseCookies = new(configModel.StripResponseCookies.ValueBool()) } configPatch.Waf = &cdnSdk.WafConfigPatch{ @@ -1360,13 +1435,27 @@ func mapFields(ctx context.Context, distribution *cdnSdk.Distribution, model *Mo } } } + + tlsObjAttrs := map[string]attr.Value{ + "enable_tls_10": types.BoolValue(distribution.Config.Tls.EnableTls10), + "enable_tls_11": types.BoolValue(distribution.Config.Tls.EnableTls11), + } + + tlsVal, diagTls := types.ObjectValue(tlsTypes, tlsObjAttrs) + if diagTls.HasError() { + return core.DiagsToError(diagWaf) + } + cfg, diags := types.ObjectValue(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": modelRegions, - "blocked_countries": modelBlockedCountries, - "optimizer": optimizerVal, - "redirects": redirectsVal, - "waf": wafVal, + "backend": backend, + "regions": modelRegions, + "blocked_countries": modelBlockedCountries, + "optimizer": optimizerVal, + "redirects": redirectsVal, + "waf": wafVal, + "tls": tlsVal, + "strip_response_cookies": types.BoolValue(distribution.Config.StripResponseCookies), + "forward_host_header": types.BoolValue(distribution.Config.ForwardHostHeader), }) if diags.HasError() { return core.DiagsToError(diags) @@ -1438,6 +1527,11 @@ func toCreatePayload(ctx context.Context, model *Model) (*cdnSdk.CreateDistribut optimizer = cdnSdk.NewOptimizer(cfg.Optimizer.GetEnabled()) } + var tls *cdnSdk.TlsConfig + if !utils.IsUndefined(rawConfig.Tls) { + tls = &cfg.Tls + } + var backend *cdnSdk.CreateDistributionPayloadBackend if cfg.Backend.HttpBackend != nil { backend = &cdnSdk.CreateDistributionPayloadBackend{ @@ -1480,7 +1574,15 @@ func toCreatePayload(ctx context.Context, model *Model) (*cdnSdk.CreateDistribut BlockedCountries: cfg.BlockedCountries, Optimizer: optimizer, Redirects: cfg.Redirects, - Waf: wafPayload, // Now passes nil if omitted + Waf: wafPayload, + Tls: tls, + } + + if !utils.IsUndefined(rawConfig.ForwardHostHeader) { + payload.ForwardHostHeader = new(rawConfig.ForwardHostHeader.ValueBool()) + } + if !utils.IsUndefined(rawConfig.StripResponseCookies) { + payload.StripResponseCookies = new(rawConfig.StripResponseCookies.ValueBool()) } return payload, nil @@ -1557,6 +1659,20 @@ func convertConfig(ctx context.Context, model *Model) (*cdnSdk.Config, error) { regions = append(regions, *regionEnum) } + // tls + var tls cdnSdk.TlsConfig + if !utils.IsUndefined(configModel.Tls) { + var tlsValue tlsConfig + diags := configModel.Tls.As(ctx, &tlsValue, basetypes.ObjectAsOptions{}) + if diags.HasError() { + return nil, core.DiagsToError(diags) + } + tls = cdnSdk.TlsConfig{ + EnableTls10: tlsValue.EnableTls10.ValueBool(), + EnableTls11: tlsValue.EnableTls11.ValueBool(), + } + } + // blockedCountries var blockedCountries []string if configModel.BlockedCountries != nil { @@ -1636,6 +1752,7 @@ func convertConfig(ctx context.Context, model *Model) (*cdnSdk.Config, error) { Regions: regions, BlockedCountries: blockedCountries, Redirects: redirectsConfig, + Tls: tls, } if !utils.IsUndefined(configModel.Waf) { diff --git a/stackit/internal/services/cdn/distribution/resource_test.go b/stackit/internal/services/cdn/distribution/resource_test.go index e16d5354d..7752039d3 100644 --- a/stackit/internal/services/cdn/distribution/resource_test.go +++ b/stackit/internal/services/cdn/distribution/resource_test.go @@ -77,6 +77,7 @@ func TestToCreatePayload(t *testing.T) { "disabled_rule_collection_ids": emptyWafSet, "log_only_rule_collection_ids": emptyWafSet, }) + redirectsObjType, ok := configTypes["redirects"].(basetypes.ObjectType) if !ok { t.Fatalf("configTypes[\"redirects\"] is not of type basetypes.ObjectType") @@ -84,12 +85,15 @@ func TestToCreatePayload(t *testing.T) { redirectsAttrTypes := redirectsObjType.AttrTypes config := types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "blocked_countries": blockedCountriesFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "redirects": types.ObjectNull(redirectsTypes), - "waf": defaultWaf, + "backend": backend, + "regions": regionsFixture, + "blocked_countries": blockedCountriesFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "redirects": types.ObjectNull(redirectsTypes), + "waf": defaultWaf, + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) matcherValues := types.ListValueMust(types.StringType, []attr.Value{ @@ -191,12 +195,15 @@ func TestToCreatePayload(t *testing.T) { "happy_path_with_optimizer": { Input: modelFixture(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": optimizer, - "blocked_countries": blockedCountriesFixture, - "redirects": types.ObjectNull(redirectsTypes), - "waf": defaultWaf, + "backend": backend, + "regions": regionsFixture, + "optimizer": optimizer, + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsTypes), + "waf": defaultWaf, + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) }), Expected: &cdnSdk.CreateDistributionPayload{ @@ -218,12 +225,15 @@ func TestToCreatePayload(t *testing.T) { "happy_path_with_redirects": { Input: modelFixture(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "blocked_countries": blockedCountriesFixture, - "redirects": redirectsConfigVal, - "waf": defaultWaf, + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": redirectsConfigVal, + "waf": defaultWaf, + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) }), Expected: &cdnSdk.CreateDistributionPayload{ @@ -274,12 +284,15 @@ func TestToCreatePayload(t *testing.T) { "geofencing": types.MapNull(geofencingTypes.ElemType), }) m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": bucketBackend, - "regions": regionsFixture, // reusing the existing one - "blocked_countries": blockedCountriesFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "redirects": types.ObjectNull(redirectsTypes), - "waf": defaultWaf, + "backend": bucketBackend, + "regions": regionsFixture, // reusing the existing one + "blocked_countries": blockedCountriesFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "redirects": types.ObjectNull(redirectsTypes), + "waf": defaultWaf, + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) }), Expected: &cdnSdk.CreateDistributionPayload{ @@ -301,6 +314,66 @@ func TestToCreatePayload(t *testing.T) { IsValid: true, }, "happy_path_with_waf": { + Input: modelFixture(func(m *Model) { + m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsAttrTypes), + "waf": populatedWaf, + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), + }) + }), + Expected: &cdnSdk.CreateDistributionPayload{ + Regions: []cdnSdk.Region{"EU", "US"}, + BlockedCountries: []string{"XX", "YY", "ZZ"}, + Waf: &expectedWafConfig, + Backend: cdnSdk.CreateDistributionPayloadBackend{ + HttpBackendCreate: &cdnSdk.HttpBackendCreate{ + Geofencing: &map[string][]string{"https://de.mycoolapp.com": {"DE", "FR"}}, + OriginRequestHeaders: &map[string]string{"testHeader0": "testHeaderValue0", "testHeader1": "testHeaderValue1"}, + OriginUrl: "https://www.mycoolapp.com", + Type: "http", + }, + }, + }, + IsValid: true, + }, + "happy_path_with_strip_response_and_cookies_forward": { + Input: modelFixture(func(m *Model) { + m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsAttrTypes), + "waf": types.ObjectNull(wafTypes), + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolValue(true), + "forward_host_header": types.BoolValue(true), + }) + }), + Expected: &cdnSdk.CreateDistributionPayload{ + Regions: []cdnSdk.Region{"EU", "US"}, + BlockedCountries: []string{"XX", "YY", "ZZ"}, + Waf: nil, + StripResponseCookies: new(true), + ForwardHostHeader: new(true), + Backend: cdnSdk.CreateDistributionPayloadBackend{ + HttpBackendCreate: &cdnSdk.HttpBackendCreate{ + Geofencing: &map[string][]string{"https://de.mycoolapp.com": {"DE", "FR"}}, + OriginRequestHeaders: &map[string]string{"testHeader0": "testHeaderValue0", "testHeader1": "testHeaderValue1"}, + OriginUrl: "https://www.mycoolapp.com", + Type: "http", + }, + }, + }, + IsValid: true, + }, + "happy_path_with_tls": { Input: modelFixture(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ "backend": backend, @@ -308,13 +381,23 @@ func TestToCreatePayload(t *testing.T) { "optimizer": types.ObjectNull(optimizerTypes), "blocked_countries": blockedCountriesFixture, "redirects": types.ObjectNull(redirectsAttrTypes), - "waf": populatedWaf, + "waf": types.ObjectNull(wafTypes), + "tls": types.ObjectValueMust(tlsTypes, map[string]attr.Value{ + "enable_tls_10": types.BoolValue(true), + "enable_tls_11": types.BoolValue(true), + }), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) }), Expected: &cdnSdk.CreateDistributionPayload{ Regions: []cdnSdk.Region{"EU", "US"}, BlockedCountries: []string{"XX", "YY", "ZZ"}, - Waf: &expectedWafConfig, + Waf: nil, + Tls: &cdnSdk.TlsConfig{ + EnableTls10: true, + EnableTls11: true, + }, Backend: cdnSdk.CreateDistributionPayloadBackend{ HttpBackendCreate: &cdnSdk.HttpBackendCreate{ Geofencing: &map[string][]string{"https://de.mycoolapp.com": {"DE", "FR"}}, @@ -390,12 +473,15 @@ func TestConvertConfig(t *testing.T) { optimizer := types.ObjectValueMust(optimizerTypes, map[string]attr.Value{"enabled": types.BoolValue(true)}) config := types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "blocked_countries": blockedCountriesFixture, - "redirects": types.ObjectNull(redirectsTypes), - "waf": types.ObjectNull(wafTypes), + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsTypes), + "waf": types.ObjectNull(wafTypes), + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) matcherValues := types.ListValueMust(types.StringType, []attr.Value{ @@ -502,12 +588,15 @@ func TestConvertConfig(t *testing.T) { "happy_path_with_optimizer": { Input: modelFixture(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": optimizer, - "blocked_countries": blockedCountriesFixture, - "redirects": types.ObjectNull(redirectsTypes), - "waf": types.ObjectNull(wafTypes), + "backend": backend, + "regions": regionsFixture, + "optimizer": optimizer, + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsTypes), + "waf": types.ObjectNull(wafTypes), + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) }), Expected: &cdnSdk.Config{ @@ -529,7 +618,8 @@ func TestConvertConfig(t *testing.T) { BlockedCountries: []string{"XX", "YY", "ZZ"}, }, IsValid: true, - }, "happy_path_with_waf": { + }, + "happy_path_with_tls": { Input: modelFixture(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ "backend": backend, @@ -537,7 +627,50 @@ func TestConvertConfig(t *testing.T) { "optimizer": types.ObjectNull(optimizerTypes), "blocked_countries": blockedCountriesFixture, "redirects": types.ObjectNull(redirectsTypes), - "waf": populatedWaf, + "waf": types.ObjectNull(wafTypes), + "tls": types.ObjectValueMust(tlsTypes, map[string]attr.Value{ + "enable_tls_10": types.BoolValue(true), + "enable_tls_11": types.BoolValue(true), + }), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), + }) + }), + Expected: &cdnSdk.Config{ + Backend: cdnSdk.ConfigBackend{ + HttpBackend: &cdnSdk.HttpBackend{ + OriginRequestHeaders: map[string]string{ + "testHeader0": "testHeaderValue0", + "testHeader1": "testHeaderValue1", + }, + OriginUrl: "https://www.mycoolapp.com", + Type: "http", + Geofencing: map[string][]string{ + "https://de.mycoolapp.com": {"DE", "FR"}, + }, + }, + }, + Regions: []cdnSdk.Region{"EU", "US"}, + BlockedCountries: []string{"XX", "YY", "ZZ"}, + Tls: cdnSdk.TlsConfig{ + EnableTls10: true, + EnableTls11: true, + }, + }, + IsValid: true, + }, + "happy_path_with_waf": { + Input: modelFixture(func(m *Model) { + m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsTypes), + "waf": populatedWaf, + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) }), Expected: &cdnSdk.Config{ @@ -563,12 +696,15 @@ func TestConvertConfig(t *testing.T) { "happy_path_with_redirects": { Input: modelFixture(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "blocked_countries": blockedCountriesFixture, - "redirects": redirectsConfigVal, - "waf": types.ObjectNull(wafTypes), + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": redirectsConfigVal, + "waf": types.ObjectNull(wafTypes), + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) }), Expected: &cdnSdk.Config{ @@ -623,12 +759,15 @@ func TestConvertConfig(t *testing.T) { "geofencing": types.MapNull(geofencingTypes.ElemType), }) m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": bucketBackend, - "regions": regionsFixture, - "blocked_countries": blockedCountriesFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "redirects": types.ObjectNull(redirectsTypes), - "waf": types.ObjectNull(wafTypes), + "backend": bucketBackend, + "regions": regionsFixture, + "blocked_countries": blockedCountriesFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "redirects": types.ObjectNull(redirectsTypes), + "waf": types.ObjectNull(wafTypes), + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) }), Expected: &cdnSdk.Config{ @@ -778,13 +917,21 @@ func TestMapFields(t *testing.T) { "disabled_rule_collection_ids": types.SetNull(types.StringType), "log_only_rule_collection_ids": types.SetNull(types.StringType), }) + + defaultTls := types.ObjectValueMust(tlsTypes, map[string]attr.Value{ + "enable_tls_10": types.BoolValue(false), + "enable_tls_11": types.BoolValue(false), + }) config := types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "blocked_countries": blockedCountriesFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "redirects": types.ObjectNull(redirectsAttrTypes), - "waf": defaultWaf, + "backend": backend, + "regions": regionsFixture, + "blocked_countries": blockedCountriesFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "redirects": types.ObjectNull(redirectsAttrTypes), + "waf": defaultWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) redirectsInput := &cdnSdk.RedirectConfig{ @@ -873,6 +1020,10 @@ func TestMapFields(t *testing.T) { Mode: cdnSdk.WAFMODE_DISABLED, Type: cdnSdk.WAFTYPE_FREE, }, + Tls: cdnSdk.TlsConfig{ + EnableTls10: false, + EnableTls11: false, + }, }, CreatedAt: createdAt, Domains: []cdnSdk.Domain{ @@ -907,12 +1058,15 @@ func TestMapFields(t *testing.T) { "geofencing": types.MapNull(geofencingTypes.ElemType), }) configOld := types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": bucketBackendOld, - "regions": regionsFixture, - "blocked_countries": blockedCountriesFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "redirects": types.ObjectNull(redirectsAttrTypes), - "waf": types.ObjectNull(wafTypes), + "backend": bucketBackendOld, + "regions": regionsFixture, + "blocked_countries": blockedCountriesFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "redirects": types.ObjectNull(redirectsAttrTypes), + "waf": types.ObjectNull(wafTypes), + "tls": types.ObjectNull(tlsTypes), + "strip_response_cookies": types.BoolUnknown(), + "forward_host_header": types.BoolUnknown(), }) tests := map[string]struct { Input *cdnSdk.Distribution @@ -928,12 +1082,15 @@ func TestMapFields(t *testing.T) { "happy_path_with_optimizer": { Expected: expectedModel(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": optimizer, - "blocked_countries": blockedCountriesFixture, - "redirects": types.ObjectNull(redirectsAttrTypes), - "waf": defaultWaf, + "backend": backend, + "regions": regionsFixture, + "optimizer": optimizer, + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsAttrTypes), + "waf": defaultWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), Input: distributionFixture(func(d *cdnSdk.Distribution) { @@ -955,12 +1112,15 @@ func TestMapFields(t *testing.T) { "credentials": types.ObjectNull(backendCredentialsTypes), }) m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backendWithGeofencing, - "regions": regionsFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "blocked_countries": blockedCountriesFixture, - "redirects": types.ObjectNull(redirectsAttrTypes), - "waf": defaultWaf, + "backend": backendWithGeofencing, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsAttrTypes), + "waf": defaultWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), Input: distributionFixture(func(d *cdnSdk.Distribution) { @@ -971,12 +1131,15 @@ func TestMapFields(t *testing.T) { "happy_path_with_redirects": { Expected: expectedModel(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": backend, - "regions": regionsFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "blocked_countries": blockedCountriesFixture, - "redirects": redirectsConfigExpected, - "waf": defaultWaf, + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": redirectsConfigExpected, + "waf": defaultWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), Input: distributionFixture(func(d *cdnSdk.Distribution) { @@ -992,7 +1155,27 @@ func TestMapFields(t *testing.T) { d.Status = "ERROR" }), IsValid: true, - }, "happy_path_with_waf": { + }, + "happy_path_with_waf": { + Expected: expectedModel(func(m *Model) { + m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ + "backend": backend, + "regions": regionsFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "blocked_countries": blockedCountriesFixture, + "redirects": types.ObjectNull(redirectsAttrTypes), + "waf": populatedWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), + }) + }), + Input: distributionFixture(func(d *cdnSdk.Distribution) { + d.Config.Waf = expectedWafConfig + }), + IsValid: true, + }, + "happy_path_with_tls_and_strip_response_and_cookies_forward": { Expected: expectedModel(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ "backend": backend, @@ -1000,11 +1183,22 @@ func TestMapFields(t *testing.T) { "optimizer": types.ObjectNull(optimizerTypes), "blocked_countries": blockedCountriesFixture, "redirects": types.ObjectNull(redirectsAttrTypes), - "waf": populatedWaf, + "waf": defaultWaf, + "tls": types.ObjectValueMust(tlsTypes, map[string]attr.Value{ + "enable_tls_10": types.BoolValue(true), + "enable_tls_11": types.BoolValue(true), + }), + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), Input: distributionFixture(func(d *cdnSdk.Distribution) { - d.Config.Waf = expectedWafConfig + d.Config.Tls = cdnSdk.TlsConfig{ + EnableTls10: true, + EnableTls11: true, + } + d.Config.ForwardHostHeader = false + d.Config.StripResponseCookies = false }), IsValid: true, }, @@ -1056,12 +1250,15 @@ func TestMapFields(t *testing.T) { }), Expected: expectedModel(func(m *Model) { m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{ - "backend": bucketBackendOld, - "regions": regionsFixture, - "blocked_countries": blockedCountriesFixture, - "optimizer": types.ObjectNull(optimizerTypes), - "redirects": types.ObjectNull(redirectsAttrTypes), - "waf": defaultWaf, + "backend": bucketBackendOld, + "regions": regionsFixture, + "blocked_countries": blockedCountriesFixture, + "optimizer": types.ObjectNull(optimizerTypes), + "redirects": types.ObjectNull(redirectsAttrTypes), + "waf": defaultWaf, + "tls": defaultTls, + "strip_response_cookies": types.BoolValue(false), + "forward_host_header": types.BoolValue(false), }) }), IsValid: true, diff --git a/stackit/internal/services/cdn/testdata/resource-http-base.tf b/stackit/internal/services/cdn/testdata/resource-http-base.tf index 9373493c9..08ff46e09 100644 --- a/stackit/internal/services/cdn/testdata/resource-http-base.tf +++ b/stackit/internal/services/cdn/testdata/resource-http-base.tf @@ -31,6 +31,10 @@ variable "waf_log_only_rule_group_ids_0" {} variable "waf_enabled_rule_collection_ids_0" {} variable "waf_disabled_rule_collection_ids_0" {} variable "waf_log_only_rule_collection_ids_0" {} +variable "tls_enable_tls_10" {} +variable "tls_enable_tls_11" {} +variable "strip_response_cookies" {} +variable "forward_host_header" {} # dns variable "dns_zone_name" {} @@ -78,6 +82,12 @@ resource "stackit_cdn_distribution" "distribution" { } ] } + tls = { + enable_tls_10 = var.tls_enable_tls_10 + enable_tls_11 = var.tls_enable_tls_11 + } + strip_response_cookies = var.strip_response_cookies + forward_host_header = var.forward_host_header waf = { mode = var.waf_mode type = var.waf_type