[Yandex Cloud documentation](../../../index.md) > [Yandex Lockbox](../../index.md) > [Tutorials](../index.md) > [Secure password transmission to an initialization script](index.md) > Terraform

# Secure password transmission to an initialization script with the help of Terraform

To [create a VM while protecting sensitive information in its initialization script](index.md) using Terraform:

1. [Get your cloud ready](#before-you-begin).
1. [Create the infrastructure](#deploy).
1. [Log in to Windows](#login-windows).

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 infrastructure support cost includes:
* Fee for continuously running [VMs](../../../compute/concepts/vm.md) (see [Yandex Compute Cloud pricing](../../../compute/pricing.md)).
* Fee for using an [image](../../../compute/concepts/image.md) (depends on the image).
* Fee for using a KMS [key](../../../kms/concepts/key.md) (see [KMS pricing](../../../kms/pricing.md)).
* Fee for using a [secret](../../concepts/secret.md) (see [Yandex Lockbox pricing](../../pricing.md)).


## 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 guides on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../../terraform/index.md).

To create your infrastructure via Terraform:

1. [Install Terraform](../../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform), [obtain authentication credentials](../../../tutorials/infrastructure-management/terraform-quickstart.md#get-credentials), and specify the source for installing the Yandex Cloud provider. For details, 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 containing the configuration files.

        ```bash
        git clone https://github.com/yandex-cloud-examples/yc-secured-password.git
        ```

     1. Navigate to the repository directory. It should now contain the following files:
        * `yc-secured-password.tf`: New infrastructure configuration.
        * `script.tpl`: Script template for creating administrator and user accounts.
        * `yc-secured-password.auto.tfvars`: User data file.

   - Manually {#manual}

     1. Create a folder for configuration files.
     1. In the folder, create:
        1. `yc-secured-password.tf` configuration file:

           {% cut "yc-secured-password.tf" %}

           ```hcl
           # Configuring the provider
           
           terraform {
             required_providers {
               yandex = {
                 source  = "yandex-cloud/yandex"
                 version = ">= 0.47.0"
               }
             }
           }
           
           provider "yandex" {
             folder_id = var.folder_id
           }
           
           # Declaring variables with sensitive data
           
           variable "zone" {
             type = string
           }
           
           variable "folder_id" {
             type = string
           }
           
           variable "admin_pass" {
             type = string
             sensitive = true
           }
           
           variable "username" {
             type = string
           }
           
           variable "user_pass" {
             type = string
             sensitive = true
           }
           
           variable "image_family" {
             type = string
           }
           
           # Creating a cloud network and a subnet
           
           resource "yandex_vpc_network" "network-1" {
             name = "win-network"
           }
           
           # Creating a subnet
           
           resource "yandex_vpc_subnet" "subnet-a" {
             name           = "win-subnet"
             zone           = var.zone
             v4_cidr_blocks = ["192.168.1.0/24"]
             network_id     = yandex_vpc_network.network-1.id
           }
           
           # Creating a security group
           
           resource "yandex_vpc_security_group" "vm-sg" {
             name        = "vm_security_group"
             network_id  = yandex_vpc_network.network-1.id
             egress {
               protocol       = "ANY"
               description    = "any"
               from_port      = 0
               to_port        =  65535
               v4_cidr_blocks = ["0.0.0.0/0"]
             }
             ingress {
               protocol       = "TCP"
               description    = "ext-http"
               v4_cidr_blocks = ["0.0.0.0/0"]
               port           = 80
             } 
             ingress {
               protocol       = "TCP"
               description    = "ext-https"
               v4_cidr_blocks = ["0.0.0.0/0"]
               port           = 443
             }
           
             ingress {
               protocol       = "TCP"
               description    = "ext-https"
               v4_cidr_blocks = ["0.0.0.0/0"]
               port           = 3389
             }
           }
           
           # Creating a service account
           
           resource "yandex_iam_service_account" "my-sa" {
             name = "win-secret-sa"
           }
           
           # Assigning permissions to a service account
           
           resource "yandex_resourcemanager_folder_iam_member" "view-keys" {
             folder_id = var.folder_id
             role      = "kms.keys.encrypterDecrypter"
             member    = "serviceAccount:${yandex_iam_service_account.my-sa.id}"
           }
           
           resource "yandex_resourcemanager_folder_iam_member" "view-payload" {
             folder_id = var.folder_id
             role      = "lockbox.payloadViewer"
             member    = "serviceAccount:${yandex_iam_service_account.my-sa.id}"
           }
           
           # Creating a symmetric KMS encryption key
           
           resource "yandex_kms_symmetric_key" "key-a" {
             name                = "win-secret-key"
             default_algorithm   = "AES_128"
             rotation_period     = "8760h"
           }
           
           # Creating a secret
           
           resource "yandex_lockbox_secret" "win_secret" {
               name                = "win-secret"
               folder_id           = var.folder_id
               kms_key_id          = yandex_kms_symmetric_key.key-a.id
           }
           
           # Creating a secret version
           
           resource "yandex_lockbox_secret_version_hashed" "win_secret_version" {
             secret_id = yandex_lockbox_secret.win_secret.id
             key_1        = "Administrator"
             text_value_1 = var.admin_pass
             key_2        = var.username
             text_value_2 = var.user_pass
           }
           
           # Creating a boot disk for the VM
           
           data "yandex_compute_image" "default" {
             family = var.image_family
           }
           
           resource "yandex_compute_disk" "boot-disk" {
             type     = "network-ssd"
             zone     = var.zone
             size     = "100"
             image_id = data.yandex_compute_image.default.id
           }
           
           # Creating a VM
           
           resource "yandex_compute_instance" "my-vm" {
             name               = "win-test"
             platform_id        = "standard-v2"
             zone               = var.zone
             service_account_id = yandex_iam_service_account.my-sa.id
           
             resources {
               cores  = "2"
               memory = "4"
             }
           
             boot_disk {
               disk_id = yandex_compute_disk.boot-disk.id
             }
           
             network_interface {
               subnet_id          = yandex_vpc_subnet.subnet-a.id
               nat                = true
               security_group_ids = ["${yandex_vpc_security_group.vm-sg.id}"]
             }
           
             metadata = {
               serial-port-enable = 1
               user-data = templatefile("script.tpl", { MYSECRET_ID = yandex_lockbox_secret.win_secret.id })
             } 
           }
           ```

           {% endcut %}

        1. `script.tpl`: Script template for creating administrator and user accounts:

           {% cut "script.tpl" %}

           ```hcl
           #ps1

           # logging
           Start-Transcript -Path "$ENV:SystemDrive\provision2.txt" -IncludeInvocationHeader -Force
           "Bootstrap script started" | Write-Host

           # SECRET'S ID:
           $SecretID = "${MYSECRET_ID}"

           [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
           $SecretURL = "https://payload.lockbox.api.cloud.yandex.net/lockbox/v1/secrets/$SecretID/payload"

           "Secret ID is $SecretID"
           "Payload URL is $SecretURL"

           $YCToken = (Invoke-RestMethod -Headers @{'Metadata-Flavor'='Google'} -Uri "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token").access_token
           if (!$YCToken) {
              throw "Service Account doesn't connected to VM. Please, add Service account with roles lockbox.payloadViewer and kms.key.encryptorDecryptor to VM and try again."
           }

           # Creating parameters for REST-invokations
           $Headers = @{
              Authorization="Bearer $YCToken"
           }

           $Params = @{
              Uri = $SecretURL
              Method = "GET"
              Headers = $Headers
           }

           # Getting secret via REST invoke
           $Secret = Invoke-RestMethod @Params
           $SecretAdministratorPlainTextPassword = $Secret.entries[0].textValue

           # inserting value's from terraform
           if (-not [string]::IsNullOrEmpty($SecretAdministratorPlainTextPassword)) {
              "Set local administrator password" | Write-Host
              $SecretAdministratorPassword = $SecretAdministratorPlainTextPassword | ConvertTo-SecureString -AsPlainText -Force
              # S-1-5-21domain-500 is a well-known SID for Administrator
              # https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/security-identifiers-in-windows
              $Administrator = Get-LocalUser | Where-Object -Property "SID" -like "S-1-5-21-*-500"
              $Administrator | Set-LocalUser -Password $SecretAdministratorPassword
           }

           # Creating new users if any
           if($Secret.entries.count -gt 1) {
              foreach($User in $Secret.entries[1..($Secret.entries.count-1)]){
                 $SecretUserPassword = $User.textValue | ConvertTo-SecureString -AsPlainText -Force
                 New-LocalUser -Name $User.key -Password $SecretUserPassword -FullName $User.key
                 Add-LocalGroupMember -Group Users -Member $User.key
                 Add-LocalGroupMember -Group "Remote Desktop Users" -Member $User.key
              }
           }

           "Bootstrap script ended" | Write-Host
           ```

           {% endcut %}

        1. `yc-secured-password.auto.tfvars` user data file:

           ```hcl
           zone         = "<availability_zone>"
           folder_id    = "<folder_ID>"
           admin_pass   = "<administrator_password>"
           username     = "<username>"
           user_pass    = "<user_password>"
           image_family = "<image_family>"
           ```

   {% endlist %}

   For more information about Terraform resource properties, see the relevant provider guides:

   * [Cloud network](../../../vpc/concepts/network.md): [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).
   * [Service account](../../../iam/concepts/users/service-accounts.md): [yandex_iam_service_account](../../../terraform/resources/iam_service_account.md).
   * [Assigning permissions](../../../iam/concepts/access-control/index.md#access-bindings): [yandex_resourcemanager_folder_iam_member](../../../terraform/resources/resourcemanager_folder_iam_member.md).
   * [Symmetric encryption key](../../../kms/concepts/key.md): [yandex_kms_symmetric_key](../../../terraform/resources/kms_symmetric_key.md)
   * [Secret](../../../terraform/resources/lockbox_secret.md): [yandex_lockbox_secret](../../concepts/secret.md).
   * [Secret version](../../concepts/secret.md#version): [yandex_lockbox_secret_version_hashed](../../../terraform/resources/lockbox_secret_version_hashed.md).
   * [Image](../../../compute/concepts/image.md): [yandex_compute_image](../../../terraform/resources/compute_image.md)
   * [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).

1. In the `yc-secured-password.auto.tfvars` file, specify these custom settings:
   * `zone`: [Availability zone](../../../overview/concepts/geo-scope.md).
   * `folder_id`: [Folder ID](../../../resource-manager/operations/folder/get-id.md).
   * `admin_pass`: Admin password.

       {% note warning %}
       
       When selecting passwords, make sure to comply with mandatory password requirements.
       These password requirements are:
       
       * At least 8 characters long.
       * Does not incude the account name.
       * Must include three of the following:
          * Latin uppercase letters (A-Z)
          * Latin lowercase letters (a-z)
          * Numbers (0-9)
          * Non-alphanumeric characters (`!`, `?`, `%`, `$`, `#`, etc.)
       
       {% endnote %}

   * `username`: Username.
   * `user_pass`: Password.
   * `image_family`: Family of one of the VM [images](../../../compute/concepts/image.md) with the required OS version.

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.

After creating the infrastructure, [log in to the Windows OS](#login-windows).


## Log in to Windows {#login-windows}

To make sure the setup created user accounts from your secret, log in to Windows on your VM:

1. In the [management console](https://console.yandex.cloud), select your VM folder.
1. Navigate to **Compute Cloud**.
1. Select the `win-test` VM.
1. Navigate to the **Serial console** tab.
1. Under **Serial console**, select `COM2` and click **Connect**. You will see the command line prompt:

    ```bash
    Computer is booting, SAC started and initialized.                               
                                                                                    
    Use the "ch -?" command for information about using channels.                   
    Use the "?" command for general help.                                           
                                                                                    
                                                                                    
    SAC>                                                                            
    EVENT: The CMD command is now available.                                         
    ```

1. Show the list of open channels:

    ```bash
    SAC>ch
    Channel List

    (Use "ch -?" for information on using channels)

    # Status  Channel Name
    0 (AV)    SAC
    ```

1. Create a new channel with a shell instance, if required.

    ```bash
    SAC>cmd
    The Command Prompt session was successfully launched.
    SAC>
    EVENT:   A new channel has been created.  Use "ch -?" for channel help.
    Channel: Cmd0001
    ```

1. To switch to a channel, press **ESC** + **TAB** or run the following command:

    ```bash
    SAC>ch -sn Cmd0001
    Name:                  Cmd0001
    Description:           Command
    Type:                  VT-UTF8
    Channel GUID:          e203fb79-d80d-11ea-87e3-c2679e14957d
    Application Type GUID: 63d02271-8aa4-11d5-bccf-00b0d014a2d0

    Press <esc><tab> for next channel.
    Press <esc><tab>0 to return to the SAC channel.
    Use any other key to view this channel.
    ```

1. Press **Enter** and specify the following:

    * Username.
    * Domain, if you logged in under a domain account; otherwise, enter your host name or nothing.
    * Password.

    ```bash
    Please enter login credentials.
    Username: Administrator
    Domain  :
    Password: ***************
    ```

1. If you logged in successfully, you will see the Windows command prompt:

    ```bash
    C:\Windows\system32>
    ```

    A successful login means that the setup created user accounts from your secret.


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

To stop incurring charges for the resources you created:

1. Open the `yc-secured-password.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.


#### Useful links {#see-also}

* [Securely providing a password to an initialization script using the management console, CLI, or API](console.md)