Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 16 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,24 @@ 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`

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.

Read-Only:

- `version` (Number) A version identifier for the certificate. 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 CERTIFICATE-----\nY2VydGlmaWNhdGVfZGF0YQ==\n-----END CERTIFICATE---"
}
}

# 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.

Read-Only:

- `version` (Number) A version identifier for the certificate. 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 CERTIFICATE-----\nY2VydGlmaWNhdGVfZGF0YQ==\n-----END CERTIFICATE---"
}
}

# 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}"
}
}
89 changes: 74 additions & 15 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 Down Expand Up @@ -51,7 +57,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 = "cdntest-zone.stackit.gg"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I run the acc tests, I get an error that this dns_name is already used. To avoid collisions, this should be (partly) a random name. You can create a var, which stores the dns name for the acc test run and reuse it everywhere. e.g.:

var dnsName = fmt.Sprintf("tf-acc-%s.stackit.gg", acctest.RandStringFromCharSet(5, acctest.CharSetAlpha))

contact_email = "[email protected]"
type = "primary"
default_ttl = 3600
Expand All @@ -68,19 +74,23 @@ func configResources(regions string) string {
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}.cdntest-zone.stackit.gg"
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

Expand All @@ -93,11 +103,54 @@ func configDatasources(regions string) string {
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) {
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 +181,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(instanceResource["custom_domain_prefix"] + ".cdntest-zone.stackit.gg")
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", instanceResource["custom_domain_prefix"]+".cdntest-zone.stackit.gg"),
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 +234,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", instanceResource["custom_domain_prefix"]+".cdntest-zone.stackit.gg"),
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 +263,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", instanceResource["custom_domain_prefix"]+".cdntest-zone.stackit.gg"),
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", instanceResource["custom_domain_prefix"]+".cdntest-zone.stackit.gg"),
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 +293,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", instanceResource["custom_domain_prefix"]+".cdntest-zone.stackit.gg"),
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
12 changes: 11 additions & 1 deletion stackit/internal/services/cdn/customdomain/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ func (r *customDomainDataSource) Schema(_ context.Context, _ datasource.SchemaRe
Computed: true,
Description: customDomainSchemaDescriptions["errors"],
},
"certificate": schema.SingleNestedAttribute{
Description: certificateSchemaDescriptions["main"],
Optional: true,
Attributes: map[string]schema.Attribute{
"version": schema.Int64Attribute{
Description: certificateSchemaDescriptions["version"],
Computed: true,
},
},
},
},
}
}
Expand Down Expand Up @@ -121,7 +131,7 @@ func (r *customDomainDataSource) Read(ctx context.Context, req datasource.ReadRe
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN custom domain", fmt.Sprintf("Calling API: %v", err))
return
}
err = mapCustomDomainFields(customDomainResp.CustomDomain, &model)
err = mapCustomDomainFields(customDomainResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN custom domain", fmt.Sprintf("Processing API payload: %v", err))
return
Expand Down
Loading