[Yandex Cloud documentation](../../../index.md) > [Yandex Container Registry](../../index.md) > [Tutorials](../index.md) > [Automatic Docker image scan on push](index.md) > Management console, CLI, and API

# Automatic Docker image scans on push using the management console, CLI, and API


{% note info %}

You can enable auto [scans](../../concepts/vulnerability-scanner.md) of [Docker images](../../concepts/docker-image.md) for vulnerabilities on push to [Yandex Container Registry](../../index.md) in the [vulnerability scanner settings](../../operations/scanning-docker-image.md#automatically) without creating any [Yandex Cloud Functions](../../../functions/index.md) [functions](../../../functions/concepts/function.md) and [triggers](../../../functions/concepts/trigger/index.md).

{% endnote %}

To configure automatic vulnerability [scans](../../concepts/vulnerability-scanner.md) of [Docker images](index.md) on push to [Yandex Container Registry](../../index.md):

1. [Get your cloud ready](#before-you-begin).
1. [Set up your environment](#prepare).
1. [Create a function](#create-function).
1. [Create a trigger](#create-trigger).
1. [Push the Docker image](#download-image).
1. [Check the result](#check-result).

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 storing a Docker image in the [registry](../../concepts/registry.md), a vulnerability scanner, and outgoing traffic (see [Yandex Container Registry pricing](../../pricing.md)).
* Fee for [function](../../../functions/concepts/function.md) calls (see [Yandex Cloud Functions pricing](../../../functions/pricing.md)).

## Set up your environment {#prepare}

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

1. [Install and configure](../../operations/configure-docker.md) Docker.
1. Create a registry to push a Docker image to.

   {% 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) to create a registry in.
     1. In the list of services, select **Container Registry**.
     1. Click **Create registry**.
     1. Specify a name for the registry.
     1. Click **Create registry**.

   - CLI {#cli}

     Run this command:

     ```bash
     yc container registry create --name my-reg
     ```

     Result:

     ```text
     done
     id: crpd50616s9a********
     folder_id: b1g88tflru0e********
     name: my-reg
     status: ACTIVE
     created_at: "2019-01-09T14:34:06.601Z"
     ```

   - API {#api}

     Use the [create](../../api-ref/Registry/create.md) method for the [Registry](../../api-ref/Registry/index.md) resource.

   {% endlist %}

1. Create a [service account](../../../iam/concepts/users/service-accounts.md) named `scanner` and assign it the `container-registry.images.scanner` [role](../../../iam/concepts/access-control/roles.md) for the [folder](../../../resource-manager/concepts/resources-hierarchy.md#folder) where you created the registry.

   {% list tabs group=instructions %}

   - Management console {#console}

     1. In the [management console](https://console.yandex.cloud), select the relevant folder.
     1. Navigate to **Identity and Access Management**.
     1. Click **Create service account**.
     1. Enter a name for the [service account](../../../iam/concepts/users/service-accounts.md).
     1. Click ![image](../../../_assets/console-icons/plus.svg) **Add role** and select `container-registry.images.scanner`.
     1. Click **Create**.

   - CLI {#cli}

     1. Create a service account:

        ```bash
        yc iam service-account create --name service-acc
        ```

        Result:

        ```text
        id: ajelabcde12f********
        folder_id: b0g12ga82bcv********
        created_at: "2021-05-17T14:32:18.900092Z"
        name: service-acc
        ```

     1. Assign the role to the service account:

        ```bash
        yc resource-manager folder add-access-binding <folder_ID> \
          --role container-registry.images.scanner \
          --subject serviceAccount:<service_account_ID>
        ```

   - API {#api}

     Use the [create](../../../iam/api-ref/ServiceAccount/create.md) method for the [ServiceAccount](../../../iam/api-ref/ServiceAccount/index.md) resource and [updateAccessBindings](../../../resource-manager/api-ref/Folder/updateAccessBindings.md) for [Folder](../../../resource-manager/api-ref/Folder/index.md).

   {% endlist %}

1. Repeat the steps to create a service account named `invoker` and assign it the `functions.functionInvoker` role for the folder where you created the registry.

## Create a function {#create-function}

In Cloud Functions, create a function named `scan-on-push` that will run the Docker image scan:

{% 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. Select **Cloud Functions**.
  1. Click **Create function**.
  1. Enter a name, e.g., `scan-on-push`, and description for the function.
  1. Click **Create**.
  1. Go to **Editor** and create a version of the function:
     1. Under **Function code**:
        * Select the `Bash` runtime environment and click **Continue**.
        * Select how you want to edit the function: `Code editor`.
        * In the function edit window, click **Create file**. In the window that opens, enter `handler.sh` as the file name and click **Create**.
        * Paste the following code to the `handler.sh` file:

          ```bash
          DATA=$(cat | jq -sr '.[0].messages[0].details')
          ID=$(echo $DATA | jq -r '.image_id')
          NAME=$(echo $DATA | jq -r '.repository_name')
          TAG=$(echo $DATA | jq -r '.tag')
          yc container image scan --id ${ID} --async 1>&2
          ```

        * Specify the entry point: `handler.sh`.
     1. Under **Parameters**, specify:
        * **Timeout**: `60`.
        * **Memory**: `128 MB`.
        * **Service account**: `scanner`.
     1. Click **Save changes**.

- CLI {#cli}

  1. Create a function named `scan-on-push`:

     ```bash
     yc serverless function create --name=scan-on-push
     ```

     Result:

     ```text
     id: d4ejb1799eko********
     folder_id: aoek49ghmknn********
     created_at: "2021-17-05T14:07:32.134Z"
     name: scan-on-push
     log_group_id: eolm8aoq9vcp********
     http_invoke_url: https://functions.yandexcloud.net/d4ejb1799eko********
     status: ACTIVE
     ```

  1. Create the `handler.sh` file and paste the following code to it:

     ```bash
     DATA=$(cat | jq -sr '.[0].messages[0].details')
     ID=$(echo $DATA | jq -r '.image_id')
     NAME=$(echo $DATA | jq -r '.repository_name')
     TAG=$(echo $DATA | jq -r '.tag')
     yc container image scan --id ${ID} --async 1>&2
     ```

  1. Create a version of the `scan-on-push` function:

     ```bash
     yc serverless function version create \
       --function-name=scan-on-push \
       --runtime bash \
       --entrypoint handler.sh \
       --memory 128m \
       --execution-timeout 60s \
       --source-path handler.sh \
       --service-account-id <service_account_ID>
     ```

     Where:
     * `--function-name`: Name of the function whose version you want to create.
     * `--runtime`: Runtime.
     * `--entrypoint`: Entry point in `<function_file_name>.<handler_name>` format.
     * `--memory`: Amount of RAM.
     * `--execution-timeout`: Maximum function execution time before timeout.
     * `--source-path`: File with the function code.
     * `--service-account-id`: Service account ID.

     Result:

     ```text
     done (1s)
     id: d4egi3pmsd1q********
     function_id: d4e275oj7jtp********
     ...
     tags:
     - $latest
     log_group_id: ckg6nb0c7uf1********
     ```

- API {#api}

  Use the [create](../../../functions/functions/api-ref/Function/create.md) and the [createVersion](../../../functions/functions/api-ref/Function/createVersion.md) methods for the [Function](../../../functions/functions/api-ref/Function/index.md) resource.

{% endlist %}

## Create a trigger {#create-trigger}

Create a trigger that will invoke your function when creating a Docker image [tag](../../concepts/docker-image.md#version).

{% 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. Select **Cloud Functions**.
  1. Navigate to the **Triggers** tab.
  1. Click **Create trigger**.
  1. Under **Basic settings**:
     * Enter a name and description for the trigger.
     * In the **Type** field, select `Container Registry`.
  1. Under **Container Registry settings**:
     * In the **Registry** field, select the registry to push the Docker image to.
     * In the **Event types** field, select the [event `Create Docker image tag`](../../../functions/concepts/trigger/cr-trigger.md#event).
  1. Under **Function settings**:
     * Select the `scan-on-push` function.
     * Specify the `$latest` [function version tag](../../../functions/concepts/function.md#tag).
     * Specify the `invoker` service account which will invoke the function.
  1. Click **Create trigger**.

- CLI {#cli}

  To create a trigger, run this command:

  ```bash
  yc serverless trigger create container-registry \
    --name <trigger_name> \
    --registry-id <registry_ID> \
    --events 'create-image-tag' \
    --invoke-function-id <function_ID> \
    --invoke-function-service-account-id <service_account_ID>
  ```

  Where:
  * `--name`: Trigger name.
  * `--registry-id`: [ID of the registry](../../operations/registry/registry-list.md) to push the Docker image to.
  * `--events`: [Events](../../../functions/concepts/trigger/cr-trigger.md#event) to set off the trigger.
  * `--invoke-function-id`: Function ID.
  * `--invoke-function-service-account-id`: ID of the service account with permissions to invoke the function.

  Result:

  ```text
  id: a1spt834cjmk********
  folder_id: b1g86q4m5vej********
  created_at: "2021-05-18T20:42:54.898949653Z"
  ...
        function_tag: $latest
        service_account_id: aje1insoe23e********
  status: ACTIVE
  ```

- API {#api}

  Use the [Create](../../../functions/triggers/api-ref/Trigger/create.md) method for the [Trigger](../../../functions/triggers/api-ref/Trigger/index.md) resource.

{% endlist %}

## Push the Docker image {#download-image}

1. Run Docker Desktop.
1. Log in to the registry under your username with:

   {% list tabs group=registry_auth %}

   - Docker credential helper {#docker}

     1. Configure Docker to use `docker-credential-yc`:

        ```bash
        yc container registry configure-docker
        ```

        Result:

        ```text
        Credential helper is configured in '/home/<user>/.docker/config.json'
        ```

        The current user’s profile stores the settings.

        {% note warning %}
        
        The credential helper only works if you use Docker without `sudo`. To learn how to configure Docker to run on behalf of the current user without `sudo`, see [this Docker guide](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user).
        
        {% endnote %}

     1. Make sure Docker is configured.

        The `/home/<user>/.docker/config.json` configuration file should now contain this line:

        ```json
        "cr.yandex": "yc"
        ```

     1. You can now use Docker, e.g., to [push Docker images](../../operations/docker-image/docker-image-push.md). You do not need to run the `docker login` command for that.

   - OAuth token {#oauth-token}

     {% note info "OAuth token authentication is deprecated" %}
     
     This authentication method will no longer be supported. Consider using [IAM tokens](../../../iam/concepts/authorization/iam-token.md) or [API keys](../../../iam/concepts/authorization/api-key.md).
     
     {% endnote %}

     1. If you do not have an [OAuth token](../../../iam/concepts/authorization/oauth-token.md) yet, get one at [this link](https://oauth.yandex.com/authorize?response_type=token&client_id=1a6990aa636648e9b2ef855fa7bec2fb).
     1. Run this command:

        ```bash
        echo <OAuth_token> | docker login --username oauth --password-stdin cr.yandex
        ```
 
        Result:

        ```text
        Login Succeeded
        ```

   - IAM token {#iam-token}

     {% note info %}

     The IAM token has a short [lifetime](../../../iam/concepts/authorization/iam-token.md#lifetime) of up to 12 hours. This makes it a good method for applications that automatically request an IAM token.

     {% endnote %}

     1. [Get](../../../iam/operations/iam-token/create.md) an [IAM token](../../../iam/concepts/authorization/iam-token.md).
     1. Run this command:

        ```bash
        yc iam create-token | docker login --username iam --password-stdin cr.yandex
        ```

        Result:

        ```text
        Login Succeeded
        ```

   {% endlist %}

1. Pull a Docker image from [Docker Hub](https://hub.docker.com/):

   ```bash
   docker pull ubuntu:20.04
   ```

   Result:

   ```text
   20.04: Pulling from library/ubuntu
   Digest: sha256:cf31af331f38d1d7158470e095b132acd126a7180a54f263d386da88********
   Status: Image is up to date for ubuntu:20.04
   docker.io/library/ubuntu:20.04
   ```

1. Assign a tag to the Docker image:

   ```bash
   docker tag ubuntu:20.04 cr.yandex/<registry_ID>/ubuntu:20.04
   ```

1. Push the Docker image to Container Registry:

   ```bash
   docker push cr.yandex/<registry_ID>/ubuntu:20.04
   ```

   Result:

   ```text
   The push refers to repository [cr.yandex/crpu20rpdc2f********/ubuntu]
   2f140462f3bc: Layer already exists
   63c99163f472: Layer already exists
   ccdbb80308cc: Layer already exists
   20.04: digest: sha256:86ac87f73641c920fb42cc9612d4fb57b5626b56ea2a19b894d0673f******** size: 943
   ```

## Check the result {#check-result}

1. View the logs of the `scan-on-push` function and make sure it has executed.

   {% list tabs group=instructions %}

   - Management console {#console}

     1. In the [management console](https://console.yandex.cloud), select **Cloud Functions**.
     1. Go to the **Functions** section and select the `scan-on-push` function.
     1. In the window that opens, go to **Logs** and specify the time period. The default time period is one hour.

   - CLI {#cli}

     To find out the name or ID of a function, [get](../../../functions/operations/function/function-list.md) the list of functions in the folder.

     View the function execution log:

     ```bash
     yc serverless function logs scan-on-push
     ```

     Result:

     ```text
     2021-05-18 09:27:43  START RequestID: 34dc9533-ed6e-4468-b9f2-2aa0******** Version: b09i2s85a0c1********
     2021-05-18 09:27:43  END RequestID: 34dc9533-ed6e-4468-b9f2-2aa0********
     2021-05-18 09:27:43  REPORT RequestID: 34dc9533-ed6e-4468-b9f2-2aa0******** Duration: 538.610 ms Billed Duration: 538.700 ms Memory Size: 128 MB Max Memory Used: 13 MB
     2021-05-18 09:29:25  START RequestID: 5b6a3779-dcc8-44ec-8ee2-2e7f******** Version: b09i2s85a0c1********
     2021-05-18 09:29:26  END RequestID: 5b6a3779-dcc8-44ec-8ee2-2e7f********
     2021-05-18 09:29:26  REPORT RequestID: 5b6a3779-dcc8-44ec-8ee2-2e7f******** Duration: 554.904 ms Billed Duration: 555.000 ms Memory Size: 128 MB Max Memory Used: 13 MB
     ...
     ```

   {% endlist %}

1. Make sure that a new scan started when you pushed the Docker image.

   {% list tabs group=instructions %}

   - Management console {#console}

     1. In the [management console](https://console.yandex.cloud), select the parent folder of the registry containing the Docker image.
     1. Select **Container Registry**.
     1. Select the registry where you pushed your Docker image.
     1. Open the repository with the Docker image.
     1. Select the relevant Docker image and check the **Date of last scan** parameter value.

   - CLI {#cli}

     To view scans by Docker image, run the command:

     ```bash
     yc container image list-scan-results --repository-name=<registry_ID>/<Docker_image_name>
     ```

     Result:

     ```text
     +----------------------+----------------------+---------------------+--------+--------------------------------+
     |          ID          |        IMAGE         |     SCANNED AT      | STATUS |        VULNERABILITIES         |
     +----------------------+----------------------+---------------------+--------+--------------------------------+
     | crpu20rpdc2f******** | crpqmsqp5mtb******** | 2021-05-18 14:34:02 | READY  | medium:6, low:13, negligible:3 |
     +----------------------+----------------------+---------------------+--------+--------------------------------+
     ```

   {% endlist %}

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

To stop paying for the resources you created:
1. [Delete the Docker image](../../operations/docker-image/docker-image-delete.md) stored in [Yandex Container Solution](../../../cos/index.md), as well as the [registry](../../operations/registry/registry-delete.md).
1. [Delete](../../../functions/operations/function/function-delete.md) the function in Cloud Functions.
1. [Delete](../../../functions/operations/function/function-delete.md) the Cloud Functions trigger.

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

* [Automatic Docker image scan on push using Terraform](terraform.md)