[Yandex Cloud documentation](../../index.md) > [Tutorials](../index.md) > [Serverless technologies](index.md) > Serverless-based workflows and automation > Automatically copying objects from one Object Storage bucket to another

# Automatically copying objects from one Yandex Object Storage bucket to another


Configure automatic object copying from one Object Storage [bucket](../../storage/concepts/bucket.md) to another. Objects will be copied using a [function](../../functions/concepts/function.md) from Cloud Functions invoked by a [trigger](../../functions/concepts/trigger/os-trigger.md) when a new object is added to a bucket.

To set up object copying:

1. [Get your cloud ready](#before-begin).
1. [Create service accounts](#create-sa).
1. [Create a static key](#create-key).
1. [Create a Yandex Lockbox secret](#create-secret).
1. [Create Yandex Object Storage buckets](#create-buckets).
1. [Create a ZIP archive with the function code](#create-zip).
1. [Create a function in Yandex Cloud Functions](#create-function).
1. [Create a trigger](#create-trigger).
1. [Test the function](#test-function).

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


## Get your cloud ready {#before-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 resources includes:

* Fee for storing data in a bucket (see [Yandex Object Storage pricing](../../storage/pricing.md)).
* Fee for function invocation count, computing resources allocated for the function, and outgoing traffic (see [Yandex Cloud Functions pricing](../../functions/pricing.md)).
* Fee for storing secrets (see [Yandex Lockbox pricing](../../lockbox/pricing.md)).



## Create service accounts {#create-sa}

Create a [service account](../../iam/concepts/users/service-accounts.md) named `s3-copy-fn` with the `storage.uploader`, `storage.viewer`, and `lockbox.payloadViewer` roles for the function, and a service account named `s3-copy-trigger` with the `functions.functionInvoker` role to invoke the function.

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a service account.
  1. Navigate to **Identity and Access Management**.
  1. Click **Create service account**.
  1. Name the service account: `s3-copy-fn`.
  1. Click **Add role** and select the `storage.uploader`, `storage.viewer`, and `lockbox.payloadViewer` roles.
  1. Click **Create**.
  1. Repeat the previous steps to create a service account named `s3-copy-trigger` with the `functions.functionInvoker` role. This service account will be used to invoke the function.

- Yandex Cloud CLI {#cli}

  If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

  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.

  1. Create a service account named `s3-copy-fn`:

      ```bash
      yc iam service-account create --name s3-copy-fn
      ```

      Result:

      ```text
      id: nfersamh4sjq********
      folder_id: b1gc1t4cb638********
      created_at: "2023-03-21T10:36:29.726397755Z"
      name: s3-copy-fn
      ```

      Save the ID of the `s3-copy-fn` service account (`id`) and the ID of the folder where you created it (`folder_id`).

  1. Assign the `storage.uploader`, `storage.viewer`, and `lockbox.payloadViewer` roles to the service account:

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

      yc resource-manager folder add-access-binding <folder_ID> \
        --role storage.viewer \
        --subject serviceAccount:<service_account_ID>

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

      Result:

      ```text
      done (1s)
      ```

  1. Create a service account named `s3-copy-trigger`:

      ```bash
      yc iam service-account create --name s3-copy-trigger
      ```

      Save the ID of the `s3-copy-trigger` service account (`id`) and the ID of the folder where you created it (`folder_id`).

  1. Assign the `functions.functionInvoker` role for the folder to the service account:

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

- Terraform {#tf}

  
  If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../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, specify the service account properties:

      ```hcl
      // Service account for the function
      resource "yandex_iam_service_account" "s3-copy-fn" {
        name        = "s3-copy-fn"
        folder_id   = "<folder_ID>"
      }

      resource "yandex_resourcemanager_folder_iam_member" "uploader" {
        folder_id = "<folder_ID>"
        role      = "storage.uploader"
        member    = "serviceAccount:${yandex_iam_service_account.s3-copy-fn.id}"
      }

      resource "yandex_resourcemanager_folder_iam_member" "viewer" {
        folder_id = "<folder_ID>"
        role      = "storage.viewer"
        member    = "serviceAccount:${yandex_iam_service_account.s3-copy-fn.id}"
      }

      resource "yandex_resourcemanager_folder_iam_member" "payloadViewer" {
        folder_id = "<folder_ID>"
        role      = "lockbox.payloadViewer"
        member    = "serviceAccount:${yandex_iam_service_account.s3-copy-fn.id}"
      }

      // Service account to invoke the function
      resource "yandex_iam_service_account" "s3-copy-trigger" {
        name        = "s3-copy-trigger"
        folder_id   = "<folder_ID>"
      }

      resource "yandex_resourcemanager_folder_iam_member" "functionInvoker" {
        folder_id = "<folder_ID>"
        role      = "functions.functionInvoker"
        member    = "serviceAccount:${yandex_iam_service_account.s3-copy-trigger.id}"
      }
      ```

      Where:

      * `name`: Service account name. This is a required setting.
      * `folder_id`: [Folder ID](../../resource-manager/operations/folder/get-id.md). This is an optional setting. It defaults to the value specified in the provider settings.
      * `role`: Role to assign.

      For more information about `yandex_iam_service_account` properties in Terraform, see [this provider guide](../../terraform/resources/iam_service_account.md).

  1. Make sure the configuration files are correct.

      1. In the terminal, navigate to the directory where you created your configuration file.
      1. Run a check using this command:

          ```bash
          terraform plan
          ```

      If the configuration is correct, the terminal will display information about the service account. Otherwise, Terraform will show any detected errors. 

  1. Deploy the cloud resources.

      1. If the configuration is correct, run this command:

          ```bash
          terraform apply
          ```

      1. Confirm creating the service accounts by typing `yes` in the terminal and pressing **Enter**.

          This will create the service accounts. You can check the new service accounts using the [management console](https://console.yandex.cloud) or this [CLI](../../cli/quickstart.md) command:

          ```bash
          yc iam service-account list
          ```

- API {#api}

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

  To assign roles for a folder to a service account, use the [setAccessBindings](../../iam/api-ref/ServiceAccount/setAccessBindings.md) 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 static key {#create-key}

Create a [static access key](../../iam/concepts/authorization/access-key.md) for the `s3-copy-fn` service account.


{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select your service account folder.
  1.  Navigate to **Identity and Access Management**.
  1. In the left-hand panel, select ![FaceRobot](../../_assets/console-icons/face-robot.svg) **Service accounts** and then, the `s3-copy-fn` service account.
  1. In the top panel, click **Create new key**.
  1. Select **Create static access key**.
  1. Enter a description for the key and click **Create**.
  1. Save the ID and the secret key.

- Yandex Cloud CLI {#cli}

  1. Run this command:

      ```bash
      yc iam access-key create --service-account-name s3-copy-fn
      ```

      Result:

      ```text
      access_key:
        id: aje6t3vsbj8l********
        service_account_id: ajepg0mjt06s********
        created_at: "2023-03-21T14:37:51Z"
        key_id: 0n8X6WY6S24********
      secret: JyTRFdqw8t1kh2-OJNz4JX5ZTz9Dj1rI********
      ```

  1. Save the ID (`key_id`) and the secret key (`secret`). This is the only time you can copy this key as it will not be shown again.

- Terraform {#tf}

  1. In the configuration file, specify the key properties:

      ```hcl
      resource "yandex_iam_service_account_static_access_key" "sa-static-key" {
        service_account_id = "<service_account_ID>"
      }
      ```

      Where `service_account_id` is the `s3-copy-fn` service account ID.

      For more information about `yandex_iam_service_account_static_access_key` properties in Terraform, see [this provider guide](../../terraform/resources/iam_service_account_static_access_key.md).

  1. Make sure the configuration files are correct.

      1. In the terminal, navigate to the directory where you created your configuration file.
      1. Run a check using this command:

          ```bash
          terraform plan
          ```

      If the configuration is correct, the terminal will display a list of the resources and their settings. Otherwise, Terraform will show any detected errors.

  1. Deploy the cloud resources.

      1. If the configuration is correct, run this command:

          ```bash
          terraform apply
          ```

      1. Confirm creating the static access key by typing `yes` in the terminal and pressing **Enter**.

          If there are any errors when creating the key, Terraform will report them.
          If the key is created successfully, Terraform will store it in its state without showing it to the user. The terminal will only display the ID of the created key.

          You can verify that the service account key has been created using the [management console](https://console.yandex.cloud) or this [CLI](../../cli/quickstart.md) command:

          ```bash
          yc iam access-key list --service-account-name=s3-copy-fn
          ```

- API {#api}

  To create an access key, use the [create](../../iam/awscompatibility/api-ref/AccessKey/create.md) REST API method for the [AccessKey](../../iam/awscompatibility/api-ref/AccessKey/index.md) resource or the [AccessKeyService/Create](../../iam/awscompatibility/api-ref/grpc/AccessKey/create.md) gRPC API call.

{% endlist %}


## Create a secret {#create-secret}

Create a Yandex Lockbox [secret](../../lockbox/quickstart.md) to store your static access key.

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a secret.
  1. Navigate to **Lockbox**.
  1. Click **Create secret**.
  1. In the **Name** field, specify the secret name: `s3-static-key`.

  1. Under **Secret data**:

      1. Select the **Custom** secret type.
      1. Add the key ID value:

          * In the **Key** field, specify: `key_id`.
          * In the **Value** field, specify the key ID [you got earlier](#create-key).

      1. Click **Add key/value**.
      1. Add the secret key value:

          * In the **Key** field, specify: `secret`.
          * In the **Value** field, specify the secret key value [you got earlier](#create-key).

  1. Click **Create**.

- Yandex Cloud CLI {#cli}

  To create a secret, run this command:

  ```bash
  yc lockbox secret create --name s3-static-key \
    --payload "[{'key': 'key_id', 'text_value': '<key_ID>'},{'key': 'secret', 'text_value': '<secret_key_value>'}]"
  ```

  Result:

  ```text
  id: e6q2ad0j9b55********
  folder_id: b1gktjk2rg49********
  created_at: "2021-11-08T19:23:00.383Z"
  name: s3-static-key
  status: ACTIVE
  current_version:
    id: g6q4fn3b6okj********
    secret_id: e6e2ei4u9b55********
    created_at: "2023-03-21T19:23:00.383Z"
    status: ACTIVE
    payload_entry_keys:
      - key_id
      - secret
  ```

- Terraform {#tf}

  1. In the configuration file, specify the secret properties:

      ```hcl
      resource "yandex_lockbox_secret" "my_secret" {
        name = "s3-static-key"
      }

      resource "yandex_lockbox_secret_version" "my_version" {
        secret_id = yandex_lockbox_secret.my_secret.id
        entries {
          key        = "key_id"
          text_value = "<key_ID>"
        }
        entries {
          key        = "secret"
          text_value = "<private_key_value>"
        }
      }
      ```

      Where:

      * `name`: Secret name.
      * `key`: Key name.
      * `text_value`: Key value.

      {% 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 `yandex_lockbox_secret_version_hashed`, see the [relevant provider documentation](../../terraform/resources/lockbox_secret_version_hashed.md).
      
      {% endnote %}

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

      * [yandex_lockbox_secret](../../terraform/resources/lockbox_secret.md)
      * [yandex_lockbox_secret_version](../../terraform/resources/lockbox_secret_version.md).

  1. Make sure the configuration files are correct.

      1. In the terminal, navigate to the directory where you created your configuration file.
      1. Run a check using this command:

          ```bash
          terraform plan
          ```

      If the configuration is correct, the terminal will display a list of the resources and their settings. Otherwise, Terraform will show any detected errors.

  1. Deploy the cloud resources.

      1. If the configuration is correct, run this command:

          ```bash
          terraform apply
          ```

      1. Confirm creating the secret creation by typing `yes` in the terminal and pressing **Enter**.

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


## Create Object Storage buckets {#create-buckets}

Create two buckets: a primary bucket for storing files and a backup bucket for copying files from the primary bucket.

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you want to create your buckets.
  1.  Navigate to **Object Storage**.
  1. Create the main bucket:

      1. Click **Create bucket**.
      1. In the ** Name** field, enter a name for the main bucket.
      1. In the **Read objects**, **Read object list**, and **Read settings** fields, select `With authorization`.
      1. Click **Create bucket**.

  1. Similarly, create the backup bucket.

- AWS CLI {#cli}

  If you do not have the AWS CLI yet, [install and configure it](../../storage/tools/aws-cli.md).

  Create the main and backup buckets:

  ```bash
  aws --endpoint-url https://storage.yandexcloud.net \
    s3 mb s3://<main_bucket_name>

  aws --endpoint-url https://storage.yandexcloud.net \
    s3 mb s3://<backup_bucket_name>
  ```

  Result:

  ```text
  make_bucket: <main_bucket_name>
  make_bucket: <backup_bucket_name>
  ```

- Terraform {#tf}

  {% note info %}
  
  If you access Object Storage via Terraform under a [service account](../../iam/concepts/users/service-accounts.md), [assign](../../iam/operations/sa/assign-role-for-sa.md) to the service account the relevant [role](../../storage/security/index.md#roles-list), e.g., `storage.admin`, for the folder you are going to create the resources in.
  
  {% endnote %}

  1. Describe the properties for creating a service account and access key in the configuration file:

      ```hcl
      ...
      // Creating a service account
      resource "yandex_iam_service_account" "sa" {
        name = "<service_account_name>"
      }
      
      // Assigning a role to a service account
      resource "yandex_resourcemanager_folder_iam_member" "sa-admin" {
        folder_id = "<folder_ID>"
        role      = "storage.admin"
        member    = "serviceAccount:${yandex_iam_service_account.sa.id}"
      }
      
      // Creating a static access key
      resource "yandex_iam_service_account_static_access_key" "sa-static-key" {
        service_account_id = yandex_iam_service_account.sa.id
        description        = "static access key for object storage"
      }
      ```

  1. In the configuration file, specify the properties of the main and backup buckets:

      ```hcl
      resource "yandex_storage_bucket" "main-bucket" {
        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     = "<main_bucket_name>"
      }

      resource "yandex_storage_bucket" "reserve-bucket" {
        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     = "<backup_bucket_name>"
      }
      ```

      For more information about the `yandex_storage_bucket` resource, see [this Terraform provider guide](../../terraform/resources/storage_bucket.md).

  1. Make sure the configuration files are correct.

      1. In the terminal, navigate to the directory where you created your configuration file.
      1. Run a check using this command:

          ```bash
          terraform plan
          ```

      If the configuration is correct, the terminal will display a list of the resources and their settings. Otherwise, Terraform will show any detected errors. 

  1. Deploy the cloud resources.

      1. If the configuration is correct, run this command:

          ```bash
          terraform apply
          ```

      1. Confirm creating the buckets by typing `yes` in the terminal and pressing **Enter**.

- API {#api}

  To create a bucket, use the [create](../../storage/s3/api-ref/bucket/create.md) REST API method for the [Bucket](../../storage/api-ref/Bucket/index.md) resource or the [BucketService/Create](../../storage/api-ref/grpc/Bucket/create.md) gRPC API call.

{% endlist %}


## Create a ZIP archive with the function code {#create-zip}

1. Save the following code to a file named `handler.sh`:

    ```bash
    set -e
    (
      cat | jq -c '.messages[]' | while read message; 
      do
        SRC_BUCKET=$(echo "$message" | jq -r .details.bucket_id)
        SRC_OBJECT=$(echo "$message" | jq -r .details.object_id)
        aws --endpoint-url="$S3_ENDPOINT" s3 cp "s3://$SRC_BUCKET/$SRC_OBJECT" "s3://$DST_BUCKET/$SRC_OBJECT"
      done;
    ) 1>&2
    ```

1. Add `handler.sh` to the `handler-sh.zip` archive.


## Create a function {#create-function}

Create a function that automatically copies new [objects](../../storage/concepts/object.md) from the main bucket to the backup bucket.

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a function.
  1.  Navigate to **Cloud Functions**.
  1. Create a function:

      1. Click **Create function**.
      1. Enter the function name: `copy-function`.
      1. Click **Create**.

  1. Create a function version:

      1. Select the `Bash` runtime, disable **Add files with code examples**, and click **Continue**.
      1. Specify the `ZIP archive` upload method and select the `handler-sh.zip` archive created in the previous step.
      1. Specify the entry point: `handler.sh`.
      1. Under **Parameters**, specify:

          * **Timeout**: `600`.
          * **Memory**: `128 MB`.
          * **Service account**: `s3-copy-fn`.
          * **Environment variables**:

              * `S3_ENDPOINT`: `https://storage.yandexcloud.net`.
              * `DST_BUCKET`: Name of the backup bucket to copy objects to.

          * **Lockbox secrets**:

              * `AWS_ACCESS_KEY_ID`: `s3-static-key` secret ID, `latest` version ID, `key_id` secret key.
              * `AWS_SECRET_ACCESS_KEY`: `s3-static-key` secret ID, `latest` version ID, `secret` key.

      1. Click **Save changes**.

- Yandex Cloud CLI {#cli}

  1. Create a function named `copy-function`:

      ```bash
      yc serverless function create --name=copy-function
      ```

      Result:

      ```text
      id: b09bhaokchn9********
      folder_id: <folder_ID>
      created_at: "2024-10-21T20:40:03.451Z"
      name: copy-function
      http_invoke_url: https://functions.yandexcloud.net/b09bhaokchn9********
      status: ACTIVE
      ```

  1. Create a version of the `copy-function` function:

      ```bash
      yc serverless function version create \
        --function-name copy-function \
        --memory=128m \
        --execution-timeout=600s \
        --runtime=bash \
        --entrypoint=handler.sh \
        --service-account-id=<service_account_ID> \
        --environment DST_BUCKET=<backup_bucket_name> \
        --environment S3_ENDPOINT=https://storage.yandexcloud.net \
        --secret name=s3-static-key,key=key_id,environment-variable=AWS_ACCESS_KEY_ID \
        --secret name=s3-static-key,key=secret,environment-variable=AWS_SECRET_ACCESS_KEY \
        --source-path=./handler-sh.zip
        ```

        Where:

        * `--function-name`: Name of the function whose version you are creating.
        * `--memory`: Amount of RAM.
        * `--execution-timeout`: Maximum function execution time before timeout.
        * `--runtime`: Runtime.
        * `--entrypoint`: Entry point.
        * `--service-account-id`: `s3-copy-fn` service account ID.
        * `--environment`: Environment variables.
        * `--secret`: Secret with parts of the static access key.
        * `--source-path`: Path to the `handler-sh.zip` archive.

        Result:

        ```text
        done (1s)
        id: d4e394pt4nhf********
        function_id: d4efnkn79m7n********
        created_at: "2024-10-21T20:41:01.345Z"
        runtime: bash
        entrypoint: handler.sh
        resources:
          memory: "134217728"
        execution_timeout: 600s
        service_account_id: ajelprpohp7r********
        image_size: "4096"
        status: ACTIVE
        tags:
          - $latest
        environment:
          DST_BUCKET: <backup_bucket_name>
          S3_ENDPOINT: https://storage.yandexcloud.net
        secrets:
          - id: e6qo2oprlmgn********
            version_id: e6q6i1qt0ae8********
            key: key_id
            environment_variable: AWS_ACCESS_KEY_ID
          - id: e6qo2oprlmgn********
            version_id: e6q6i1qt0ae8********
            key: secret
            environment_variable: AWS_SECRET_ACCESS_KEY
        log_options:
          folder_id: b1g681qpemb4********
        concurrency: "1"
        ```

- Terraform {#tf}

  1. In the configuration file, define the function properties:

      ```hcl
      resource "yandex_function" "copy-function" {
        name               = "copy-functionn"
        user_hash          = "first function"
        runtime            = "bash"
        entrypoint         = "handler.sh"
        memory             = "128"
        execution_timeout  = "600"
        service_account_id = "<service_account_ID>"
        environment = {
          DST_BUCKET  = "<backup_bucket_name>"
          S3_ENDPOINT = "https://storage.yandexcloud.net"
        }
        secrets {
          id                   = "<secret_ID>"
          version_id           = "<secret_version_ID>"
          key                  = "key_id"
          environment_variable = "AWS_ACCESS_KEY_ID"
        }
        secrets {
          id                   = "<secret_ID>"
          version_id           = "<secret_version_ID>"
          key                  = "secret"
          environment_variable = "AWS_SECRET_ACCESS_KEY"
        }
        content {
          zip_filename = "./handler-sh.zip"
        }
      }
      ```

      Where:

      * `name`: Function name.
      * `user_hash`: Any string to identify the function version.
      * `runtime`: Function [runtime](../../functions/concepts/runtime/index.md).
      * `entrypoint`: Entry point.
      * `memory`: Amount of memory allocated for the function, in MB.
      * `execution_timeout`: Function execution timeout.
      * `service_account_id`: `s3-copy-fn` service account ID.
      * `environment`: Environment variables.
      * `secrets`: Secret with parts of the static access key.
      * `content`: Path to the `handler-sh.zip` archive with the function source code.

      For more information about `yandex_function` properties, see [this provider guide](../../terraform/resources/function.md).

  1. Make sure the configuration files are correct.

      1. In the terminal, navigate to the directory where you created your configuration file.
      1. Run a check using this command:

          ```bash
          terraform plan
          ```

      If the configuration is correct, the terminal will display a list of the resources and their settings. Otherwise, Terraform will show any detected errors.

  1. Deploy the cloud resources.

      1. If the configuration is correct, run this command:

          ```bash
          terraform apply
          ```

      1. To confirm the function creation, type `yes` in the terminal and press **Enter**.

- API {#api}

  To create a function, use the [create](../../functions/functions/api-ref/Function/create.md) REST API method for the [Function](../../functions/functions/api-ref/Function/index.md) resource or the [FunctionService/Create](../../functions/functions/api-ref/grpc/Function/create.md) gRPC API call.

  To create a function version, use the [createVersion](../../functions/functions/api-ref/Function/createVersion.md) REST API method for the [Function](../../functions/functions/api-ref/Function/index.md) resource or the [FunctionService/CreateVersion](../../functions/functions/api-ref/grpc/Function/createVersion.md) gRPC API call.

{% endlist %}


## Create a trigger {#create-trigger}

Create a trigger for Object Storage that invokes `copy-function` when you create a new object in the main bucket.

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a trigger.
  1. Navigate to **Cloud Functions**.
  1. In the left-hand panel, select ![image](../../_assets/console-icons/gear-play.svg) **Triggers**.
  1. Click **Create trigger**.
  1. Under **Basic settings**:

      * Specify the trigger name: `bucket-to-bucket-copying`.
      * In the **Type** field, select `Object Storage`.
      * In the **Launched resource** field, select `Function`.

  1. Under **Object Storage settings**:

      * In the **Bucket** field, select the main bucket.
      * In the **Event types** field, select `Create object`.

  1. Under **Function settings**:

      * In the **Function** field, select `copy-function`.
      * In the **Service account** field, select `s3-copy-trigger`.

  1. Click **Create trigger**.

- Yandex Cloud CLI {#cli}

  Run this command:

  ```bash
  yc serverless trigger create object-storage \
    --name bucket-to-bucket-copying \
    --bucket-id <main_bucket_name> \
    --events 'create-object' \
    --invoke-function-name copy-function \
    --invoke-function-service-account-name s3-copy-trigger
  ```

  Where:

  * `--name`: Trigger name.
  * `--bucket-id`: Name of the main bucket.
  * `--events`: [Events](../../functions/concepts/trigger/os-trigger.md#event) that set off the trigger.
  * `--invoke-function-name`: Name of the function being invoked.
  * `--invoke-function-service-account-name`: Name of the service account to use for invoking the function.

  Result:

  ```text
  id: a1s92agr8mpg********
  folder_id: b1g88tflru0e********
  created_at: "2024-10-21T21:04:01.866959640Z"
  name: bucket-to-bucket-copying
  rule:
    object_storage:
      event_type:
        - OBJECT_STORAGE_EVENT_TYPE_CREATE_OBJECT
      bucket_id: <main_bucket_name>
      batch_settings:
        size: "1"
        cutoff: 1s
      invoke_function:
        function_id: d4eofc7n0m03********
        function_tag: $latest
        service_account_id: aje3932acd0c********
  status: ACTIVE
  ```

- Terraform {#tf}

  1. In the configuration file, specify the trigger properties:

      ```hcl
      resource "yandex_function_trigger" "my_trigger" {
        name        = "bucket-to-bucket-copying"
        object_storage {
            bucket_id = "<main_bucket_name>"
            create    = true
        }
        function {
          id                 = "<function_ID>"
          service_account_id = "<service_account_ID>"
        }
      }
      ```

      Where:

      * `name`: Trigger name.
      * `object_storage`: Storage settings:
          * `bucket_id`: Name of the main bucket.
          * `create`: Trigger will invoke the function when a new object is created in the storage.
      * `function`: Settings of the function the trigger will invoke:
          * `id`: `copy-function` ID.
          * `service_account_id`: `s3-copy-trigger` service account ID.

      For more information about resource properties in Terraform, see [this provider guide](../../terraform/resources/function_trigger.md).

  1. Make sure the configuration files are correct.

      1. In the terminal, navigate to the directory where you created your configuration file.
      1. Run a check using this command:

          ```bash
          terraform plan
          ```

      If the configuration is correct, the terminal will display a list of the resources and their settings. Otherwise, Terraform will show any detected errors.

  1. Deploy the cloud resources.

      1. If the configuration is correct, run this command:

          ```bash
          terraform apply
          ```

      1. Confirm creating the trigger by typing `yes` in the terminal and pressing **Enter**.

- API {#api}

  To create a trigger for Object Storage, use the [create](../../functions/triggers/api-ref/Trigger/create.md) method for the [Trigger](../../functions/triggers/api-ref/Trigger/index.md) resource or the [TriggerService/Create](../../functions/triggers/api-ref/grpc/Trigger/create.md) gRPC API call.

{% endlist %}


## Test the function {#test-function}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder containing your main bucket.
  1. Navigate to **Object Storage**.
  1. Click the name of the main bucket.
  1. In the top-right corner, click **Upload**.
  1. In the window that opens, select the files and click **Open**.
  1. The management console will display all objects selected for upload. Click **Upload**.
  1. Refresh the page.
  1. Navigate to the backup bucket and make sure it contains the files you added.

{% endlist %}


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


To stop paying for the resources you created:

1. [Delete](../../storage/operations/objects/delete-all.md) all objects from the the buckets.
1. [Delete](../../storage/operations/buckets/delete.md) the buckets.
1. [Delete](../../functions/operations/trigger/trigger-delete.md) the `bucket-to-bucket-copying` trigger.
1. [Delete](../../functions/operations/function/function-delete.md) `copy-function`.