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

# Secure password transmission to an initialization script

You can use an initialization script when creating a VM based on a Windows image. Such a script may contain system user passwords To protect sensitive data, use [Yandex Lockbox](../../lockbox/index.md) tools and Yandex Key Management Service keys instead of explicitly specifying settings in the script.

In this tutorial, you will create a Windows VM using an initialization script which retrieves usernames and passwords from Yandex Lockbox.

To create a VM while protecting sensitive information in its initialization script:

1. [Create a service account](#create-account).
1. [Create a KMS key](#create-key).
1. [Create a secret](#create-secret).
1. [Create a VM](#create-vm).
1. [Log in to Windows](#login-windows).

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

## Getting started {#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 (see [Yandex Compute Cloud pricing](../../compute/pricing.md)).
* Fee for using an image (depends on the image).
* Fee for using a KMS key (see [KMS pricing](../../kms/pricing.md)).
* Fee for using a secret (see [Yandex Lockbox pricing](../../lockbox/pricing.md)).

## Create a service account {#create-account}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create your service account.
  1. [Go](../../console/operations/select-service.md#select-service) to **Identity and Access Management**.
  1. Click **Create service account**.
  1. Enter the service account name, e.g., `win-secret-sa`.
  1. Click **Create**.

- CLI {#cli}

  The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

  To create a service account, run the command below, specifying `win-secret-sa` as the service account name:

  ```bash
  yc iam service-account create --name win-secret-sa
  ```

  Where `name` is the service account name.

  Result:

  ```text
  id: ajehr0to1g8b********
  folder_id: b1gv87ssvu49********
  created_at: "2024-03-15T09:03:11.665153755Z"
  name: win-secret-sa
  ```

- API {#api}

  To create a service account, use the [ServiceAccountService/Create](../../iam/api-ref/grpc/ServiceAccount/create.md) gRPC API call or the [create](../../iam/api-ref/ServiceAccount/create.md) REST API method for the `ServiceAccount` resource.

{% endlist %}

## Create a KMS key {#create-key}

1. Create an [encryption key](../../kms/concepts/key.md):

   {% list tabs group=instructions %}

   - Management console {#console}

     1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create a key.
     1. [Go](../../console/operations/select-service.md#select-service) to **Key Management Service**.
     1. In the left-hand panel, select ![image](../../_assets/console-icons/key.svg) **Symmetric keys**.
     1. Click **Create key** and specify its attributes:
        * **Name**: `win-secret-key`.
        * **Encryption algorithm**: `AES-256`.
        * Keep the default values for all other parameters.
     1. Click **Create**.

     This will create an encryption key and its first version; select the key in the list to open its attribute page.

   - CLI {#cli}

     Run this command:

     ```bash
     yc kms symmetric-key create \
       --name win-secret-key \
       --default-algorithm aes-256
     ```

     Where:

     * `--name`: Key name.
     * `--default-algorithm`: Encryption algorithm: `aes-128`, `aes-192`, or `aes-256`.

   - Terraform {#tf}

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

     If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
     
     
     To manage infrastructure using Terraform under a service account or user accounts (a Yandex account, a federated account, or a local user), [authenticate](../../terraform/authentication.md) using the appropriate method.

     To create a key:
     
     1. Specify the `yandex_kms_symmetric_key` resource properties in the configuration file:
     
        ```hcl
        resource "yandex_kms_symmetric_key" "key-a" {
          name                = "<key_name>"
          description         = "<key_description>"
          default_algorithm   = "AES_128"
          rotation_period     = "8760h"
          deletion_protection = true
          lifecycle {
            prevent_destroy = true
          }
        }
        ```
     
        Where:
     
        * `name`: Key name. The name format is as follows:
     
           * Length: between 3 and 63 characters.
           * It can only contain lowercase Latin letters, numbers, and hyphens.
           * It must start with a letter and cannot end with a hyphen.
     
        * `description`: Key description.
        * `default_algorithm`: Encryption algorithm. The possible values are `AES-128`, `AES-192`, or `AES-256`.
        * `rotation_period`: [Rotation](../../kms/concepts/version.md#rotate-key) period (how often to change key versions). To create a key without automatic rotation, do not specify the `rotation_period` parameter.
        * `deletion_protection`: Key deletion protection. To create a key without deletion protection, do not specify the `deletion_protection` parameter.
        * `lifecycle.prevent_destroy`: Key deletion protection when running Terraform commands. To create a key without such protection, do not specify the `lifecycle` section.
     
        {% note warning %}
     
        Deleting a KMS key destroys all data encrypted with that key: the data becomes unrecoverable after the key is deleted. The `deletion_protection` parameter and the `lifecycle` section are required to prevent the deletion of the key (e.g., with the `terraform destroy` command).
     
        {% endnote %}
     
        For more information about resource properties in Terraform, see [this provider guide](../../terraform/resources/kms_symmetric_key.md).
     
     1. Validate your configuration using this command:
     
        ```bash
        terraform validate
        ```
     
        If the configuration is valid, you will get this message:
     
        ```text
        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. Confirm the changes: type `yes` into the terminal and press **Enter**.
     
        This will create all the resources you need in the specified folder. You can check the new resources and their configuration using the [management console](https://console.yandex.cloud) or these [CLI](../../cli/quickstart.md) commands:
     
        ```bash
        yc kms symmetric-key list
        ```

   - API {#api}

     Use the [create](../../kms/api-ref/SymmetricKey/create.md) REST API method for the [SymmetricKey](../../kms/api-ref/SymmetricKey/index.md) resource or the [SymmetricKeyService/Create](../../kms/api-ref/grpc/SymmetricKey/create.md) gRPC API call.

   {% endlist %}

1. Assign the `kms.keys.encrypterDecrypter` [role](../../iam/concepts/access-control/roles.md) to the `win-secret-sa` service account:

   {% list tabs group=instructions %}

   - Management console {#console}

     1. Navigate to the **Access permissions** tab on the key page.
     1. On the **Service account access permissions** page, find the `win-secret-sa` account in the list and click ![image](../../_assets/options.svg).
     1. Click **Edit roles**.
     1. In the dialog that opens, click **Add role** and select `kms.keys.encrypterDecrypter`.

   - CLI {#cli}

     Run this command:

     ```bash
     yc resource-manager folder add-access-binding <folder_ID> \
        --role kms.keys.encrypterDecrypter \
        --subject serviceAccount:<service_account_ID>
     ```

   - API {#api}

     To assign a role for a folder to a service account, use the [setAccessBindings](../../iam/api-ref/ServiceAccount/setAccessBindings.md) REST API method for the [ServiceAccount](../../iam/api-ref/ServiceAccount/index.md) resource or the [ServiceAccountService/SetAccessBindings](../../iam/api-ref/grpc/ServiceAccount/setAccessBindings.md) gRPC API call.

   {% endlist %}

## Create a secret {#create-secret}

1. Create a Yandex Lockbox secret to store usernames and passwords of Windows user accounts:

   {% 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 %}

   {% list tabs group=instructions %}

   - Management console {#console}

     1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create your secret.
     1. [Go](../../console/operations/select-service.md#select-service) to **Lockbox**.
     1. Click **Create secret**.
     1. In the **Name** field, specify the secret name: `win-secret`.
     1. In the **KMS key** field, specify the `win-secret-key` key.
     1. In the **Key** field, specify the `Administrator` username.
     1. In the **Value**, specify the administrator password.
     1. You can add more users by clicking **Add key/value** and specifying their usernames and passwords.
     1. Click **Create**.

   - CLI {#cli}

     1. Run this command:

        ```bash
        yc lockbox secret create \
           --name win-secret \
           --kms-key-id <key_ID> \
           --payload "[{'key': 'Administrator', 'text_value': '<administrator_password>'},{'key': 'user1', 'text_value': '<user_password>'}]" \
           --cloud-id <cloud_ID> \
           --folder-id <folder_ID>
        ```

        Where:

        * `--name`: Secret name (required).
        * `--kms-key-id`: KMS key ID.
        * `--description`: Secret description. This is an optional setting.
        * `--payload`: Secret content in YAML or JSON format.
        * `--cloud-id`: [ID of the cloud](../../resource-manager/operations/cloud/get-id.md) where you want to create your secret.
        * `--folder-id`: [ID of the folder](../../resource-manager/operations/folder/get-id.md) where you want to create your secret.

   - Terraform {#tf}

     If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
     
     
     To manage infrastructure using Terraform under a service account or user accounts (a Yandex account, a federated account, or a local user), [authenticate](../../terraform/authentication.md) using the appropriate method.

     1. In the configuration file, describe the resources you want to create:

        ```hcl
        resource "yandex_lockbox_secret" "win_secret" {
           name                = "<secret_name>"
           folder_id           = "<folder_ID>"
           kms_key_id          = "<encryption_key_ID>"
        }
        resource "yandex_lockbox_secret_version" "win_secret_version" {
          secret_id = yandex_lockbox_secret.win_secret.id
          entries {
            key        = "Administrator"
            text_value = "<administrator_password>"
          }
          entries {
            key        = "user1"
            text_value = "<user_password>"
          }
        }
        ```

        Where:

        * `name`: Secret name (required).
        * `folder_id`: [ID](../../resource-manager/operations/folder/get-id.md) of the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create a secret. This is an optional setting.
        * `kms_key_id`: ID of the [Key Management Service](../../kms/concepts/key.md) encryption key used to encrypt your secret.
        * `entries`: Secret content.

        {% note info %}
        
        We recommend using `yandex_lockbox_secret_version_hashed`: it stores values in Terraform state in hashed format. We continue supporting `yandex_lockbox_secret_version`.
        
        For more information about the `yandex_lockbox_secret_version_hashed` resource, see [this provider guide](../../terraform/resources/lockbox_secret_version_hashed.md).
        
        {% endnote %}

        {% note warning %}

        For better security, instead of setting the password directly in your configuration file, use a reference to an environment variable.

        {% endnote %}

     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.

   - API {#api}

     To create a secret, use the [create](../../lockbox/api-ref/Secret/create.md) REST API method for the [Secret](../../lockbox/api-ref/Secret/index.md) resource or the [SecretService/Create](../../lockbox/api-ref/grpc/Secret/create.md) gRPC API call.

   {% endlist %}

1. Assign the `lockbox.payloadViewer` [role](../../iam/concepts/access-control/roles.md) to the `win-secret-sa` service account:

   {% list tabs group=instructions %}

   - Management console {#console}

     1. Navigate to the **Access permissions** tab on the secret page.
     1. Navigate to the **Access bindings** tab.
     1. Find the `win-secret-sa` account in the list and click ![image](../../_assets/options.svg).
     1. Click **Edit roles**.
     1. In the dialog that opens, click **Add role** and select `lockbox.payloadViewer`.

   - CLI {#cli}

     Run this command:

     ```bash
     yc resource-manager folder add-access-binding <folder_ID> \
        --role lockbox.payloadViewer \
        --subject serviceAccount:<service_account_ID>
     ```

   - API {#api}

     To assign a role for a folder to a service account, use the [setAccessBindings](../../iam/api-ref/ServiceAccount/setAccessBindings.md) REST API method for the [ServiceAccount](../../iam/api-ref/ServiceAccount/index.md) resource or the [ServiceAccountService/SetAccessBindings](../../iam/api-ref/grpc/ServiceAccount/setAccessBindings.md) gRPC API call.

   {% endlist %}

## Create a VM {#create-vm}

Create a Windows VM and add the administrator and user accounts to it.

1. Create the `init.ps1` file with the following code:

   ```text
   #ps1

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

   # SECRET'S ID:
   $$SecretID = "<secret_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
   ```

1. Replace `<secret_id>` with the ID of the secret with user account data you created in the previous step.

1. Create a VM:

   {% list tabs group=instructions %}

   - Management console {#console}

     1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create your VM.
     1. At the top right, click **Create resource** and select `Virtual machine instance`.
     1. Under **Boot disk image**, select the Windows [image](../../compute/concepts/image.md).
     1. Under **Location**, select the [availability zone](../../overview/concepts/geo-scope.md) where your VM will reside.
     1. Under **General information**, specify the VM name, e.g., `win-test`.
     1. Under **Advanced**, specify the VM access credentials:
        * Select the `win-secret-sa` [service account](../../iam/concepts/index.md#sa).
        * Grant it access to the [serial console](../../compute/operations/serial-console/index.md).
     1. Under **Metadata**:
        * In the **Key** field, specify `user-data`.
        * In the **Value** field, paste the contents of the `init.ps1` file.
     1. Click **Create VM**.

   - CLI {#cli}

     Run this command:

     ```bash
     yc compute instance create \
        --name win-test \
        --hostname windows10 \
        --zone ru-central1-a \
        --create-boot-disk image-id=<image_id> \
        --cores 2 \
        --core-fraction 100 \
        --memory 4 \
        --metadata-from-file user-data=init.ps1 \
        --network-interface subnet-name=<subnet_name>,nat-ip-version=ipv4 \
        --service-account-name win-test-sa \
        --platform standard-v3
     ```

     Where:

     * `image_id`: Windows image ID.
     * `subnet_name`: Name of the subnet where your VM will get connected.

     {% note info %}
     
     The commands [`yc compute instance create`](../../cli/cli-ref/compute/cli-ref/instance/create.md) | [`create-with-container`](../../cli/cli-ref/compute/cli-ref/instance/create-with-container.md) | [`update`](../../cli/cli-ref/compute/cli-ref/instance/update.md) | [`add-metadata`](../../cli/cli-ref/compute/cli-ref/instance/add-metadata.md) support substitution of environment variable values into VM metadata. When you execute a Yandex Cloud CLI command, these values, specified in the `user-data` key in `$<variable_name>` format, will be substituted into the VM metadata from the environment variables of the environment the command is executed in. 
     
     To change such behavior, i.e. to provide a variable name to the VM metadata in `$<variable_name>` format rather than take the variable value from the CLI command runtime environment, use the two-dollar syntax, e.g., `$$<variable_name>`.
     
     For more information, see [Specifics of providing environment variables in metadata via the CLI](../../compute/concepts/metadata/sending-metadata.md#environment-variables).
     
     {% endnote %}

   {% endlist %}


## 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. [Go](../../console/operations/select-service.md#select-service) 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
    SAC>
    ```

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 (AV)    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 paying for the resources you created:
* [Delete](../../compute/operations/vm-control/vm-delete.md) the VM.
* [Delete](../../lockbox/operations/secret-delete.md) the secret.
* [Delete](../../kms/operations/key.md#delete) the key.