[Yandex Cloud documentation](../../../index.md) > [Yandex Cloud CDN](../../index.md) > [Tutorials](../index.md) > [Setting up secure content access](index.md) > Terraform

# Providing secure access to content in Cloud CDN through Terraform

To configure secure access to content in Cloud CDN:

1. [Get your cloud ready](#before-you-begin).
1. [Delegate your domain to Cloud DNS](#delegate-domain).
1. [Create your infrastructure](#deploy).
1. [Publish the webiste on the web server](#publish-website).
1. [Test secure access to files](#check).

If you no longer need the resources you created, [delete them](#clear-out).


## Get your cloud ready {#before-you-begin}

Sign up for Yandex Cloud and create a [billing account](../../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../../billing/quickstart/index.md) and [link](../../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../../resource-manager/concepts/resources-hierarchy.md).


### Required paid resources {#paid-resources}

The cost of infrastructure support for setting up secure access to Cloud CDN content includes:

* Fee for using a [public IP address](../../../vpc/concepts/address.md#public-addresses) (see [Yandex Virtual Private Cloud pricing](../../../vpc/pricing.md)).
* Fee for [VM](../../../compute/concepts/vm.md) computing resources and disks (see [Yandex Compute Cloud pricing](../../../compute/pricing.md)).
* Fee for using a public [DNS zone](../../../dns/concepts/dns-zone.md#public-zones) and public DNS requests (see [Yandex Cloud DNS pricing](../../../dns/pricing.md)).
* Fee for [data storage](../../../storage/operations/index.md) in Object Storage, [operations](../../../storage/concepts/bucket.md) with data, and outgoing traffic (see [Object Storage pricing](../../../storage/pricing.md)).
* Fee for outgoing traffic from CDN servers (see [Cloud CDN pricing](../../pricing.md)).


## Delegate your domain to Cloud DNS {#delegate-domain}

Delegate your domain to Cloud DNS. To do this, in your domain registrar's account, specify the addresses of these DNS servers in your domain settings: `ns1.yandexcloud.net` and `ns2.yandexcloud.net`.


## Create an infrastructure {#deploy}

With [Terraform](https://www.terraform.io/), you can quickly create a cloud infrastructure in Yandex Cloud and manage it using configuration files. These files store the infrastructure description written in HashiCorp Configuration Language (HCL). If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.

Terraform is distributed under the [Business Source License](https://github.com/hashicorp/terraform/blob/main/LICENSE). The [Yandex Cloud provider for Terraform](https://github.com/yandex-cloud/terraform-provider-yandex) is distributed under the [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/) license.

For more information about the provider resources, see the relevant documentation on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../../terraform/index.md).

To create an infrastructure using Terraform:

1. [Install Terraform](../../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform), [get the credentials](../../../tutorials/infrastructure-management/terraform-quickstart.md#get-credentials), and specify the source for installing the Yandex Cloud provider (see [Configure your provider](../../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider), Step 1).
1. Set up your infrastructure description files:

    {% list tabs group=infrastructure_description %}

    - Ready-made configuration {#ready}

      1. Clone the repository with configuration files.

          ```bash
          git clone https://github.com/yandex-cloud-examples/yc-cdn-protected-access
          ```

      1. Navigate to the repository directory. It should now contain the following files:

          * `yc-cdn-secure-token.tf`: New infrastructure configuration.
          * `yc-cdn-secure-token.auto.tfvars`: User data file.

    - Manually {#manual}

      1. Prepare files for uploading to the bucket:

          1. Save any image in JPEG format to the `content.jpg` file.
          1. Create a file named `index.html`:
          
              ```html
              <html>
                  <body>
                  </body>
              </html>
              ```

      1. Create a folder for configuration files.
      1. In the folder, create:

          1. `yc-cdn-secure-token.tf` configuration file:

              {% cut "yc-cdn-secure-token.tf" %}

              ```hcl
              # Declaring variables
              
              variable "folder_id" {
                type = string
              }
              
              variable "domain_name" {
                type = string
              }
              
              variable "subdomain_name" {
                type = string
              }
              
              variable "bucket_name" {
                type = string
              }
              
              variable "secure_key" {
                type = string
              }
              
              variable "ssh_key_path" {
                type = string
              }
              
              variable "index_file_path" {
                type = string
              }
              
              variable "content_file_path" {
                type = string
              }
              
              locals {
                sa_name          = "my-service-account"
                network_name     = "webserver-network"
                subnet_name      = "webserver-subnet-ru-central1-b"
                sg_name          = "webserver-sg"
                vm_name          = "mywebserver"
                domain_zone_name = "my-domain-zone"
                cert_name        = "mymanagedcert"
                origin_gp_name   = "my-origin-group"
              }
              
              # Configuring the provider
              
              terraform {
                required_providers {
                  yandex = {
                    source = "yandex-cloud/yandex"
                  }
                }
                required_version = ">= 0.13"
              }
              
              provider "yandex" {
                folder_id = var.folder_id
              }
              
              # Creating a service account
              
              resource "yandex_iam_service_account" "ig-sa" {
                name = local.sa_name
              }
              
              # Assigning roles to a service account
              
              resource "yandex_resourcemanager_folder_iam_member" "storage-editor" {
                folder_id = var.folder_id
                role      = "storage.editor"
                member    = "serviceAccount:${yandex_iam_service_account.ig-sa.id}"
              }
              
              # Creating a static access key for CA
              
              resource "yandex_iam_service_account_static_access_key" "sa-static-key" {
                service_account_id = "${yandex_iam_service_account.ig-sa.id}"
              }
              
              # Creating a network
              
              resource "yandex_vpc_network" "webserver-network" {
                name = local.network_name
              }
              
              # Creating a subnet
              
              resource "yandex_vpc_subnet" "webserver-subnet-b" {
                name           = local.subnet_name
                zone           = "ru-central1-b"
                network_id     = "${yandex_vpc_network.webserver-network.id}"
                v4_cidr_blocks = ["192.168.1.0/24"]
              }
              
              # Creating a security group
              
              resource "yandex_vpc_security_group" "webserver-sg" {
                name        = local.sg_name
                network_id  = "${yandex_vpc_network.webserver-network.id}"
              
                ingress {
                  protocol       = "TCP"
                  description    = "http"
                  v4_cidr_blocks = ["0.0.0.0/0"]
                  port           = 80
                }
              
                ingress {
                  protocol       = "TCP"
                  description    = "https"
                  v4_cidr_blocks = ["0.0.0.0/0"]
                  port           = 443
                }
              
                ingress {
                  protocol       = "TCP"
                  description    = "ssh"
                  v4_cidr_blocks = ["0.0.0.0/0"]
                  port           = 22
                }
              
                egress {
                  protocol       = "ANY"
                  description    = "any"
                  v4_cidr_blocks = ["0.0.0.0/0"]
                  from_port      = 0
                  to_port        = 65535
                }
              }
              
              # Creating a boot disk for the VM
              
              resource "yandex_compute_disk" "boot-disk" {
                type     = "network-ssd"
                zone     = "ru-central1-b"
                size     = "20"
                image_id = "fd8jtn9i7e9ha5q25niu"
              }
              
              # Creating a VM
              
              resource "yandex_compute_instance" "mywebserver" {
                name        = local.vm_name
                platform_id = "standard-v2"
                zone        = "ru-central1-b"
              
                resources {
                  cores  = "2"
                  memory = "2"
                }
              
                boot_disk {
                  disk_id = yandex_compute_disk.boot-disk.id
                }
              
                network_interface {
                  subnet_id          = "${yandex_vpc_subnet.webserver-subnet-b.id}"
                  nat                = true
                  security_group_ids = ["${yandex_vpc_security_group.webserver-sg.id}"]
                }
              
                metadata = {
                  user-data = "#cloud-config\nusers:\n  - name: yc-user\n    groups: sudo\n    shell: /bin/bash\n    sudo: 'ALL=(ALL) NOPASSWD:ALL'\n    ssh-authorized-keys:\n      - ${file("${var.ssh_key_path}")}"
                }
              }
              
              # Creating a public DNS zone
              
              resource "yandex_dns_zone" "my-domain-zone" {
                name    = local.domain_zone_name
                zone    = "${var.domain_name}."
                public  = true
              }
              
              # Creating a type A resource record for the web server
              
              resource "yandex_dns_recordset" "rsA1" {
                zone_id = yandex_dns_zone.my-domain-zone.id
                name    = "${yandex_dns_zone.my-domain-zone.zone}"
                type    = "A"
                ttl     = 600
                data    = ["${yandex_compute_instance.mywebserver.network_interface.0.nat_ip_address}"]
              }
              
              # Adding a Let's Encrypt certificate
              
              resource "yandex_cm_certificate" "le-certificate" {
                name    = local.cert_name
                domains = [var.domain_name,"${var.subdomain_name}.${var.domain_name}"]
              
                managed {
                challenge_type = "DNS_CNAME"
                challenge_count = 2
                }
              }
              
              # Creating CNAME records for domain validation when issuing a certificate
              
              resource "yandex_dns_recordset" "validation-record" {
                count   = yandex_cm_certificate.le-certificate.managed[0].challenge_count
                zone_id = yandex_dns_zone.my-domain-zone.id
                name    = yandex_cm_certificate.le-certificate.challenges[count.index].dns_name
                type    = yandex_cm_certificate.le-certificate.challenges[count.index].dns_type
                ttl     = 600
                data    = [yandex_cm_certificate.le-certificate.challenges[count.index].dns_value]
              }
              
              # Waiting for domain validation and the issue of a Let's Encrypt certificate
              
              data "yandex_cm_certificate" "example-com" {
                depends_on      = [yandex_dns_recordset.validation-record]
                certificate_id  = yandex_cm_certificate.le-certificate.id
                wait_validation = true
              }
              
              # Creating a bucket
              
              resource "yandex_storage_bucket" "cdn-source" {
                access_key = yandex_iam_service_account_static_access_key.sa-static-key.access_key
                secret_key = yandex_iam_service_account_static_access_key.sa-static-key.secret_key
                bucket     = var.bucket_name
                max_size   = 1073741824
              
                anonymous_access_flags {
                  read = true
                  list = true
                }
              
                website {
                  index_document = "index.html"
                }
              }
              
              # Uploading the website home page to the bucket
              
              resource "yandex_storage_object" "index-object" {
                access_key = yandex_iam_service_account_static_access_key.sa-static-key.access_key
                secret_key = yandex_iam_service_account_static_access_key.sa-static-key.secret_key
                bucket     = "${yandex_storage_bucket.cdn-source.bucket}"
                key        = var.index_file_path
                source     = var.index_file_path
              }
              
              # Uploading a test file to the bucket
              
              resource "yandex_storage_object" "content-object" {
                access_key = yandex_iam_service_account_static_access_key.sa-static-key.access_key
                secret_key = yandex_iam_service_account_static_access_key.sa-static-key.secret_key
                bucket     = "${yandex_storage_bucket.cdn-source.bucket}"
                key        = var.content_file_path
                source     = var.content_file_path
              }
              
              # Creating a CDN origin group
              
              resource "yandex_cdn_origin_group" "my-origin-group" {
                name = local.origin_gp_name
                origin {
                  source = "${var.bucket_name}.website.yandexcloud.net"
                }
              }
              
              # Creating a CDN resource
              
              resource "yandex_cdn_resource" "my-resource" {
                cname               = "${var.subdomain_name}.${var.domain_name}"
                active              = true
                origin_protocol     = "match"
                origin_group_id     = "${yandex_cdn_origin_group.my-origin-group.id}"
                ssl_certificate {
                  type = "certificate_manager"
                  certificate_manager_id = "${data.yandex_cm_certificate.example-com.id}"
                }
                options {
                  custom_host_header    = "${var.bucket_name}.website.yandexcloud.net"
                  secure_key            = "${var.secure_key}"
                  enable_ip_url_signing = true
                }
              }
              
              # Creating a CNAME record for the CDN resource
              
              resource "yandex_dns_recordset" "cdn-cname" {
                zone_id = yandex_dns_zone.my-domain-zone.id
                name    = "${yandex_cdn_resource.my-resource.cname}."
                type    = "CNAME"
                ttl     = 600
                data    = [yandex_cdn_resource.my-resource.provider_cname]
              }
              ```

              {% endcut %}

          1. `yc-cdn-secure-token.auto.tfvars` user data file:

              {% cut "yc-cdn-secure-token.auto.tfvars" %}

              ```hcl
              folder_id         = "<folder_ID>"
              ssh_key_path      = "<path_to_public_SSH_key_file>"
              index_file_path   = "<name_of_website_homepage_file>"
              content_file_path = "<name_of_file_with_content_to_upload_to_bucket>"
              domain_name       = "<domain_name>"
              subdomain_name    = "<CDN_resource_subdomain_prefix>"
              bucket_name       = "<bucket_name>"
              secure_key        = "<secret_key>"
              ```

              {% endcut %}

    {% endlist %}

    Learn more about the properties of Terraform resources in the relevant provider guides:

    * [Service account](../../../iam/concepts/users/service-accounts.md): [yandex_iam_service_account](../../../terraform/resources/iam_service_account.md).
    * Service account [role](../../../iam/concepts/access-control/roles.md): [yandex_resourcemanager_folder_iam_member](../../../terraform/resources/resourcemanager_folder_iam_member.md).
    * [Static access key](../../../iam/concepts/authorization/access-key.md): [yandex_iam_service_account_static_access_key](../../../terraform/resources/iam_service_account_static_access_key.md).
    * [Network](../../../vpc/concepts/network.md#network): [yandex_vpc_network](../../../terraform/resources/vpc_network.md).
    * [Subnet](../../../vpc/concepts/network.md#subnet): [yandex_vpc_subnet](../../../terraform/resources/vpc_subnet.md).
    * [Security group](../../../vpc/concepts/security-groups.md): [yandex_vpc_security_group](../../../terraform/resources/vpc_security_group.md).
    * VM [disk](../../../compute/concepts/disk.md): [yandex_compute_disk](../../../terraform/resources/compute_disk.md).
    * [VM instance](../../../compute/concepts/vm.md): [yandex_compute_instance](../../../terraform/resources/compute_instance.md).
    * [DNS zone](../../../dns/concepts/dns-zone.md): [yandex_dns_zone](../../../terraform/resources/dns_zone.md).
    * [DNS resource record](../../../dns/concepts/resource-record.md): [yandex_dns_recordset](../../../terraform/resources/dns_recordset.md).
    * [TLS certificate](../../../certificate-manager/concepts/managed-certificate.md): [yandex_cm_certificate](../../../terraform/resources/cm_certificate.md).
    * [Bucket](../../../storage/concepts/bucket.md): [yandex_storage_bucket](../../../terraform/resources/storage_bucket.md).
    * [Object](../../../storage/concepts/object.md): [yandex_storage_object](../../../terraform/resources/storage_object.md).
    * [Origin group](../../concepts/origins.md#groups): [yandex_cdn_origin_group](../../../terraform/resources/cdn_origin_group.md).
    * [CDN resource](../../concepts/resource.md): [yandex_cdn_resource](../../../terraform/resources/cdn_resource.md).

1. In the `yc-cdn-secure-token.auto.tfvars` file, set the following user-defined properties:

    * `folder_id`: [Folder ID](../../../resource-manager/operations/folder/get-id.md).
    * `ssh_key_path`: Path to the file with a public SSH key to authenticate the user on the VM. For more information, see [Creating an SSH key pair](../../../compute/operations/vm-connect/ssh.md#creating-ssh-keys).
    * `index_file_path`: Path to the website homepage file.
    * `content_file_path`: Path to the file with content for uploading to the bucket.
    * `domain_name`: Your domain name, e.g., `example.com`.
    * `subdomain_name`: Prefix of subdomain for the CDN resource, e.g., `cdn`.
    * `bucket_name`: Bucket name consistent with the [naming conventions](../../../storage/concepts/bucket.md#naming).
    * `secure_key`: Secret key that is a string of 6 to 32 characters. It is required to restrict access to a resource using [secure tokens](../../concepts/secure-tokens.md).

1. Create the resources:

    1. In the terminal, navigate to the configuration file directory.
    1. Make sure the configuration is correct using this command:
    
       ```bash
       terraform validate
       ```
    
       If the configuration is valid, you will get this message:
    
       ```bash
       Success! The configuration is valid.
       ```
    
    1. Run this command:
    
       ```bash
       terraform plan
       ```
    
       You will see a list of resources and their properties. No changes will be made at this step. Terraform will show any errors in the configuration.
    1. Apply the configuration changes:
    
       ```bash
       terraform apply
       ```
    
    1. Type `yes` and press **Enter** to confirm the changes.

It may take up to 15 minutes for the new settings of the existing resource to apply to the CDN servers. After that, we recommend [purging the resource cache](../../operations/resources/purge-cache.md).

The content on the new CDN resource will be accessible only via [signed links](../../concepts/secure-tokens.md#protected-link).


## Publish the webiste on the web server {#publish-website}

Next, you will create and publish on your web server a website that will generate signed links to content hosted on the secure CDN resource. For data transfer security, you will copy the previously created TLS certificate to the same web server and enable SSL encryption.


### Download the certificate from Certificate Manager {#export-certificate}

To use the TLS certificate created in Certificate Manager in your web server configuration, download the certificate chain and private key to the current directory:

{% list tabs group=instructions %}

- Yandex Cloud CLI {#cli}

  1. Learn the ID of the previously created TLS certificate:

      ```bash
      yc certificate-manager certificate list
      ```

      Result:

      ```text
      +----------------------+---------------+-----------------------------+---------------------+---------+--------+
      |          ID          |     NAME      |           DOMAINS           |      NOT AFTER      |  TYPE   | STATUS |
      +----------------------+---------------+-----------------------------+---------------------+---------+--------+
      | fpq90lobsh0l******** | mymanagedcert | cdn.example.com,example.com | 2024-03-22 16:42:53 | MANAGED | ISSUED |
      +----------------------+---------------+-----------------------------+---------------------+---------+--------+
      ```

      For more information about the `yc certificate-manager certificate list` command, see the [CLI reference](../../../cli/cli-ref/certificate-manager/cli-ref/certificate/list.md).

  1. Download the key and certificate by specifying the ID you got in the previous step:

      ```bash
      yc certificate-manager certificate content \
        --id <certificate_ID> \
        --chain ./certificate_full_chain.pem \
        --key ./private_key.pem
      ```

      For more information about the `yc certificate-manager certificate content` command, see the [CLI reference](../../../cli/cli-ref/certificate-manager/cli-ref/certificate/content.md).

{% endlist %}


### Configure the web server {#setup-web-server}

1. Copy the certificates and private key thus obtained to the VM hosting the web server:

    ```bash
    scp ./certificate_full_chain.pem yc-user@<VM_IP_address>:certificate_full_chain.pem \
      && scp ./private_key.pem yc-user@<VM_IP_address>:private_key.pem
    ```

    Where `<VM_IP_address>` is the public IP address of the previously created VM with a web server.

    You can find the IP address of your VM in the [management console](https://console.yandex.cloud) on the VM page under **Network** or using the `yc compute instance get mywebserver` CLI command.

    If this is your first time connecting to the VM, you will see an unknown host warning:

    ```text
    The authenticity of host '51.250.**.*** (51.250.**.***)' can't be established.
    ED25519 key fingerprint is SHA256:PpcKdcT09gjU045pkEIwIU8lAXXLpwJ6bKC********.
    This key is not known by any other names
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    ```

    Type `yes` in the terminal and press **Enter**.

1. [Connect](../../../compute/operations/vm-connect/ssh.md) to the VM with the web server:

    ```bash
    ssh yc-user@<VM_IP_address>
    ```

1. Create a directory for the certificate and move the copied files there:

    ```bash
    sudo mkdir /etc/ssl-certificates
    sudo mv certificate_full_chain.pem /etc/ssl-certificates/
    sudo mv private_key.pem /etc/ssl-certificates/
    ```

1. Create a directory for your website files and grant the required permissions for it to the `www-data` user:

    ```bash
    sudo mkdir -p /var/www/<domain_name>/public_html
    sudo chown www-data:www-data /var/www/<domain_name>/public_html
    ```

    Where `<domain_name>` is the domain name of your website, e.g., `example.com`.

1. Configure a virtual host for your website:

    1. Create a virtual host configuration file:

        ```bash
        sudo nano /etc/apache2/sites-available/mywebsite.conf
        ```

    1. Add the following configuration into the file:

        ```text
        <VirtualHost *:443>
        ServerName <domain_name>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/<domain_name>/public_html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        SSLEngine on
        SSLCertificateFile /etc/ssl-certificates/certificate_full_chain.pem
        SSLCertificateChainFile /etc/ssl-certificates/certificate_full_chain.pem
        SSLCertificateKeyFile /etc/ssl-certificates/private_key.pem
        </VirtualHost>
        ```

        Where `<domain_name>` is the domain name of your website, e.g., `example.com`.

    1. Activate the virtual host you created:

        ```bash
        sudo a2ensite mywebsite
        ```

        Result:

        ```text
        Enabling site mywebsite.
        To activate the new configuration, you need to run:
          systemctl reload apache2
        ```

    1. Enable `ssl` for the web server:

        ```bash
        sudo a2enmod ssl
        ```

        Result:

        ```text
        Considering dependency setenvif for ssl:
        Module setenvif already enabled
        Considering dependency mime for ssl:
        Module mime already enabled
        Considering dependency socache_shmcb for ssl:
        Enabling module socache_shmcb.
        Enabling module ssl.
        See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
        To activate the new configuration, you need to run:
          systemctl restart apache2
        ```

    1. Restart the web server:

        ```bash
        sudo systemctl reload apache2
        ```


### Create a website {#create-website}

1. Create the home page file for the website:

    ```bash
    sudo nano /var/www/<domain_name>/public_html/index.php
    ```

    Where `<domain_name>` is the domain name of your website, e.g., `example.com`.

1. Add the following code into the `index.php` file you created:

    ```php
    <!DOCTYPE html>
    <html>
    <head>
      <title>Secure token generator website</title>
      <meta charset="utf-8" />
    </head>
    <body>

      <h2>Secure link generator</h2>
      <p>Below, a signed link to the secure CDN resource has been generated. The link is valid for five minutes. The content at this link is available only to the user the link was generated for by the website (verified by IP address).</p>
      <br>

      <?php

        $secret = '<secret_key>';
        $ip = trim(getUserIpAddr());
        $domain_name = '<domain_name>';
        $path = '<object_key>';
        $expires = time() + 300;
        $link = "$expires$path$ip $secret";
        $md5 = md5($link, true);
        $md5 = base64_encode($md5);
        $md5 = strtr($md5, '+/', '-_');
        $md5 = str_replace('=', '', $md5);
        $url = '<a href="https://'.$domain_name.$path.'?md5='.$md5.'&expires='.$expires.'" target="_blank">Signed link to file</a>';
    
        echo "<p>Your IP address: <b>".$ip."</b></p><p>If you are using a VPN, you link may not work. For the signed link generator to work properly, disable your VPN.</p>";
        echo "<br><br>";
        echo $url;
    
        function getUserIpAddr() {

            if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
               $addr = $_SERVER['HTTP_CLIENT_IP'];
            } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
               $addr = $_SERVER['HTTP_X_FORWARDED_FOR'];
            } else {
               $addr = $_SERVER['REMOTE_ADDR'];
            }
            return $addr;
        }
      ?>

    </body>
    </html>
    ```

    Where:
    * `$secret`: Secret key created when configuring the CDN resource.
    * `$domain_name`: Domain name of the created CDN resource, e.g., `cdn.example.com`.
    * `$path`: [Key of the object](../../../storage/concepts/object.md#key) in the [source](../../concepts/origins.md) bucket, e.g., `/content.jpg`. It must contain `/`.
       The website will generate a signed link to access this object via the CDN resource.


## Test secure access to files {#check}

To test the generator of signed links to the secure CDN resource:

1. In your browser, go to the website you created, e.g., `https://example.com`.
1. Click the link that was generated.

    If everything works as it should, you will see the image hosted on the secure CDN resource.

    {% note info %}

    An active VPN may interfere with the signed link generator's operation. For the website to work correctly, disable your VPN.

    {% endnote %}

1. Open the generated link on another device that uses another IP address to access the internet, e.g., a smartphone.

    Access to content will be denied.

1. Try opening the link on the first device after the five-minute timeout expires.

    Access to content will be denied.

You have configured secure access to your content.

When generating links, you can also [specify](../../operations/resources/enable-secure-token.md) a trusted IP address, e.g., the one used for internet access in your corporate network. Thus you will restrict access to your content from outside your company’s network infrastructure.


## How to delete the resources you created {#clear-out}

To stop paying for the resources you created:

1. Open the `yc-cdn-secure-token.tf` file and delete your infrastructure description from it.
1. Apply the changes:

    1. In the terminal, navigate to the configuration file directory.
    1. Make sure the configuration is correct using this command:
    
       ```bash
       terraform validate
       ```
    
       If the configuration is valid, you will get this message:
    
       ```bash
       Success! The configuration is valid.
       ```
    
    1. Run this command:
    
       ```bash
       terraform plan
       ```
    
       You will see a list of resources and their properties. No changes will be made at this step. Terraform will show any errors in the configuration.
    1. Apply the configuration changes:
    
       ```bash
       terraform apply
       ```
    
    1. Type `yes` and press **Enter** to confirm the changes.

#### See also {#see-also}

* [Providing secure access to content in Cloud CDN using the management console, CLI, or API](console.md)