Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e7fbde2
add custom certificate
Sep 4, 2025
1386631
remove print
Sep 4, 2025
1c384c7
fix error test
Sep 5, 2025
b6500fb
Adjust certificate
Sep 5, 2025
1dd0bec
format resource
Sep 5, 2025
c0d4810
Update stackit/internal/services/cdn/customdomain/resource.go
matheuspolitano Sep 9, 2025
1a02807
Update stackit/internal/services/cdn/customdomain/resource.go
matheuspolitano Sep 9, 2025
2507af2
Update stackit/internal/services/cdn/customdomain/resource.go
matheuspolitano Sep 9, 2025
5d7c83b
Update stackit/internal/services/cdn/customdomain/datasource.go
matheuspolitano Sep 9, 2025
8c60b29
improve code
Sep 9, 2025
eceae8f
Update stackit/internal/services/cdn/customdomain/resource.go
matheuspolitano Sep 10, 2025
aba7625
add update certificate
Sep 10, 2025
65a8aa6
remove dialogs
Sep 10, 2025
f8f3ecc
Update stackit/internal/services/cdn/customdomain/resource_test.go
matheuspolitano Sep 12, 2025
9aa84b6
apply code suggestion
Sep 12, 2025
d598198
remove error
Sep 12, 2025
80fe6d7
solve pr issues
Sep 15, 2025
4805b1d
add random domain name
Sep 15, 2025
e35e70e
fix make doc and lint
Sep 15, 2025
5fa5d13
Update stackit/internal/services/cdn/customdomain/resource.go
matheuspolitano Sep 15, 2025
3743e47
fix rename function and move to the top var
Sep 15, 2025
5771d3a
remove useless var
Sep 15, 2025
ebd7886
Update stackit/internal/services/cdn/customdomain/resource_test.go
matheuspolitano Sep 15, 2025
882b9ab
fix the test
Sep 15, 2025
10fc1a8
add message when the certificate and private_key is undedined
Sep 15, 2025
eb0f8f3
Update examples/resources/stackit_cdn_custom_domain/resource.tf
matheuspolitano Sep 15, 2025
94ee425
add datasource
Sep 15, 2025
e8b6f46
final code adjustment
Sep 15, 2025
f6edb73
add checj to custom domain
Sep 15, 2025
e6e6032
update doc
Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/data-sources/cdn_custom_domain.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,19 @@ data "stackit_cdn_custom_domain" "example" {
- `name` (String)
- `project_id` (String) STACKIT project ID associated with the distribution

### Optional

- `certificate` (Attributes) The TLS certificate for the custom domain. If omitted, a managed certificate will be used. If the block is specified, a custom certificate is used. (see [below for nested schema](#nestedatt--certificate))

### Read-Only

- `errors` (List of String) List of distribution errors
- `id` (String) Terraform's internal resource identifier. It is structured as "`project_id`,`distribution_id`".
- `status` (String) Status of the distribution

<a id="nestedatt--certificate"></a>
### Nested Schema for `certificate`

Read-Only:

- `version` (Number) A version identifier for the certificate. Required for custom certificates. The certificate will be updated if this field is changed.
20 changes: 20 additions & 0 deletions docs/resources/cdn_custom_domain.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ resource "stackit_cdn_custom_domain" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
distribution_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "https://xxx.xxx"
certificate = {
certificate = "-----BEGIN CERTIFICATE-----\nY2VydGlmaWNhdGVfZGF0YQ==\n-----END CERTIFICATE---"
private_key = "-----BEGIN RSA PRIVATE KEY-----\nY2VydGlmaWNhdGVfZGF0YQ==\n-----END RSA PRIVATE KEY---"
}
}

# Only use the import statement, if you want to import an existing cdn custom domain
Expand All @@ -38,8 +42,24 @@ import {
- `name` (String)
- `project_id` (String) STACKIT project ID associated with the distribution

### Optional

- `certificate` (Attributes) The TLS certificate for the custom domain. If omitted, a managed certificate will be used. If the block is specified, a custom certificate is used. (see [below for nested schema](#nestedatt--certificate))

### Read-Only

- `errors` (List of String) List of distribution errors
- `id` (String) Terraform's internal resource identifier. It is structured as "`project_id`,`distribution_id`".
- `status` (String) Status of the distribution

<a id="nestedatt--certificate"></a>
### Nested Schema for `certificate`

Optional:

- `certificate` (String, Sensitive) The PEM-encoded TLS certificate. Required for custom certificates.
- `private_key` (String, Sensitive) The PEM-encoded private key for the certificate. Required for custom certificates. The certificate will be updated if this field is changed.

Read-Only:

- `version` (Number) A version identifier for the certificate. Required for custom certificates. The certificate will be updated if this field is changed.
6 changes: 5 additions & 1 deletion examples/resources/stackit_cdn_custom_domain/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ resource "stackit_cdn_custom_domain" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
distribution_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "https://xxx.xxx"
certificate = {
certificate = "-----BEGIN CERTIFICATE-----\nY2VydGlmaWNhdGVfZGF0YQ==\n-----END CERTIFICATE---"
private_key = "-----BEGIN RSA PRIVATE KEY-----\nY2VydGlmaWNhdGVfZGF0YQ==\n-----END RSA PRIVATE KEY---"
}
}

# Only use the import statement, if you want to import an existing cdn custom domain
import {
to = stackit_cdn_custom_domain.import-example
id = "${var.project_id},${var.distribution_id},${var.custom_domain_name}"
}
}
106 changes: 83 additions & 23 deletions stackit/internal/services/cdn/cdn_acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ package cdn_test

import (
"context"
cryptoRand "crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
"strings"
"testing"
Expand All @@ -26,6 +32,7 @@ var instanceResource = map[string]string{
"config_regions_updated": "\"EU\", \"US\", \"ASIA\"",
"blocked_countries": "\"CU\", \"AQ\"", // Do NOT use DE or AT here, because the request might be blocked by bunny at the time of creation - don't lock yourself out
"custom_domain_prefix": uuid.NewString(), // we use a different domain prefix each test run due to inconsistent upstream release of domains, which might impair consecutive test runs
"dns_name": fmt.Sprintf("tf-acc-%s.stackit.gg", strings.Split(uuid.NewString(), "-")[0]),
}

func configResources(regions string) string {
Expand All @@ -51,7 +58,7 @@ func configResources(regions string) string {
resource "stackit_dns_zone" "dns_zone" {
project_id = "%s"
name = "cdn_acc_test_zone"
dns_name = "cdntestzone.stackit.gg"
dns_name = "%s"
contact_email = "[email protected]"
type = "primary"
default_ttl = 3600
Expand All @@ -64,40 +71,87 @@ func configResources(regions string) string {
records = ["${stackit_cdn_distribution.distribution.domains[0].name}."]
}
`, testutil.CdnProviderConfig(), testutil.ProjectId, instanceResource["config_backend_origin_url"],
regions, instanceResource["blocked_countries"], testutil.ProjectId,
regions, instanceResource["blocked_countries"], testutil.ProjectId, instanceResource["dns_name"],
testutil.ProjectId, instanceResource["custom_domain_prefix"])
}

func configCustomDomainResources(regions string) string {
func configCustomDomainResources(regions, cert, key string) string {
return fmt.Sprintf(`
%s

resource "stackit_cdn_custom_domain" "custom_domain" {
project_id = stackit_cdn_distribution.distribution.project_id
distribution_id = stackit_cdn_distribution.distribution.distribution_id
name = "${stackit_dns_record_set.dns_record.name}.cdntestzone.stackit.gg"
name = "${stackit_dns_record_set.dns_record.name}.${stackit_dns_zone.dns_zone.dns_name}"
certificate = {
certificate = %q
private_key = %q
}
}
`, configResources(regions))
`, configResources(regions), cert, key)
}

func configDatasources(regions string) string {
func configDatasources(regions, cert, key string) string {
return fmt.Sprintf(`
%s
%s

data "stackit_cdn_distribution" "distribution" {
data "stackit_cdn_distribution" "distribution" {
project_id = stackit_cdn_distribution.distribution.project_id
distribution_id = stackit_cdn_distribution.distribution.distribution_id
}
data "stackit_cdn_custom_domain" "custom_domain" {
distribution_id = stackit_cdn_distribution.distribution.distribution_id
}
data "stackit_cdn_custom_domain" "custom_domain" {
project_id = stackit_cdn_custom_domain.custom_domain.project_id
distribution_id = stackit_cdn_custom_domain.custom_domain.distribution_id
name = stackit_cdn_custom_domain.custom_domain.name
}
`, configCustomDomainResources(regions))

}
`, configCustomDomainResources(regions, cert, key))
}
func makeCertAndKey(t *testing.T, organization string) (cert, key []byte) {
privateKey, err := rsa.GenerateKey(cryptoRand.Reader, 2048)
if err != nil {
t.Fatalf("failed to generate key: %s", err.Error())
}
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Issuer: pkix.Name{CommonName: organization},
Subject: pkix.Name{
Organization: []string{organization},
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour),

KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
cert, err = x509.CreateCertificate(
cryptoRand.Reader,
&template,
&template,
&privateKey.PublicKey,
privateKey,
)
if err != nil {
t.Fatalf("failed to generate cert: %s", err.Error())
}

return pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: cert,
}), pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
})
}
func TestAccCDNDistributionResource(t *testing.T) {
fullDomainName := fmt.Sprintf("%s.%s", instanceResource["custom_domain_prefix"], instanceResource["dns_name"])
organization := fmt.Sprintf("organization-%s", uuid.NewString())
cert, key := makeCertAndKey(t, organization)

organization_updated := fmt.Sprintf("organization-updated-%s", uuid.NewString())
cert_updated, key_updated := makeCertAndKey(t, organization_updated)
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckCDNDistributionDestroy,
Expand Down Expand Up @@ -128,16 +182,16 @@ func TestAccCDNDistributionResource(t *testing.T) {
{
Config: configResources(instanceResource["config_regions"]),
Check: func(_ *terraform.State) error {
_, err := blockUntilDomainResolves(instanceResource["custom_domain_prefix"] + ".cdntestzone.stackit.gg")
_, err := blockUntilDomainResolves(fullDomainName)
return err
},
},
// Custom Domain Create
{
Config: configCustomDomainResources(instanceResource["config_regions"]),
Config: configCustomDomainResources(instanceResource["config_regions"], string(cert), string(key)),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "status", "ACTIVE"),
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "name", instanceResource["custom_domain_prefix"]+".cdntestzone.stackit.gg"),
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "name", fullDomainName),
resource.TestCheckResourceAttrPair("stackit_cdn_distribution.distribution", "distribution_id", "stackit_cdn_custom_domain.custom_domain", "distribution_id"),
resource.TestCheckResourceAttrPair("stackit_cdn_distribution.distribution", "project_id", "stackit_cdn_custom_domain.custom_domain", "project_id"),
),
Expand Down Expand Up @@ -181,17 +235,21 @@ func TestAccCDNDistributionResource(t *testing.T) {
},
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"certificate.certificate",
"certificate.private_key",
},
},
// Data Source
{
Config: configDatasources(instanceResource["config_regions"]),
Config: configDatasources(instanceResource["config_regions"], string(cert), string(key)),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("data.stackit_cdn_distribution.distribution", "distribution_id"),
resource.TestCheckResourceAttrSet("data.stackit_cdn_distribution.distribution", "created_at"),
resource.TestCheckResourceAttrSet("data.stackit_cdn_distribution.distribution", "updated_at"),
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "domains.#", "2"),
resource.TestCheckResourceAttrSet("data.stackit_cdn_distribution.distribution", "domains.0.name"),
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "domains.1.name", instanceResource["custom_domain_prefix"]+".cdntestzone.stackit.gg"),
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "domains.1.name", fullDomainName),
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "domains.1.status", "ACTIVE"),
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "domains.0.type", "managed"),
Expand All @@ -206,20 +264,21 @@ func TestAccCDNDistributionResource(t *testing.T) {
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
resource.TestCheckResourceAttr("data.stackit_cdn_distribution.distribution", "status", "ACTIVE"),
resource.TestCheckResourceAttr("data.stackit_cdn_custom_domain.custom_domain", "status", "ACTIVE"),
resource.TestCheckResourceAttr("data.stackit_cdn_custom_domain.custom_domain", "name", instanceResource["custom_domain_prefix"]+".cdntestzone.stackit.gg"),
resource.TestCheckResourceAttr("data.stackit_cdn_custom_domain.custom_domain", "certificate.version", "1"),
resource.TestCheckResourceAttr("data.stackit_cdn_custom_domain.custom_domain", "name", fullDomainName),
resource.TestCheckResourceAttrPair("stackit_cdn_distribution.distribution", "distribution_id", "stackit_cdn_custom_domain.custom_domain", "distribution_id"),
),
},
// Update
{
Config: configCustomDomainResources(instanceResource["config_regions_updated"]),
Config: configCustomDomainResources(instanceResource["config_regions_updated"], string(cert_updated), string(key_updated)),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "distribution_id"),
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "created_at"),
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "updated_at"),
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.#", "2"),
resource.TestCheckResourceAttrSet("stackit_cdn_distribution.distribution", "domains.0.name"),
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.1.name", instanceResource["custom_domain_prefix"]+".cdntestzone.stackit.gg"),
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.1.name", fullDomainName),
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.status", "ACTIVE"),
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.1.status", "ACTIVE"),
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "domains.0.type", "managed"),
Expand All @@ -235,7 +294,8 @@ func TestAccCDNDistributionResource(t *testing.T) {
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "project_id", testutil.ProjectId),
resource.TestCheckResourceAttr("stackit_cdn_distribution.distribution", "status", "ACTIVE"),
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "status", "ACTIVE"),
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "name", instanceResource["custom_domain_prefix"]+".cdntestzone.stackit.gg"),
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "certificate.version", "2"),
resource.TestCheckResourceAttr("stackit_cdn_custom_domain.custom_domain", "name", fullDomainName),
resource.TestCheckResourceAttrPair("stackit_cdn_distribution.distribution", "distribution_id", "stackit_cdn_custom_domain.custom_domain", "distribution_id"),
resource.TestCheckResourceAttrPair("stackit_cdn_distribution.distribution", "project_id", "stackit_cdn_custom_domain.custom_domain", "project_id"),
),
Expand Down
Loading
Loading