# Безопасное хранение секретов

Узнайте о секретах разработки программного обеспечения и о том, как их безопасно управлять.

## Что такое секрет?

В разработке программного обеспечения секрет — это часть конфиденциальной информации, которая используется для проверки подлинности или авторизации доступа к системам, службам, данным и API. Вот некоторые примеры.

* **Ключи** API и **маркеры** доступа, позволяющие взаимодействовать с внешними службами, такими как REST API GitHub. Маркеры доступа также позволяют службам, таким как GitHub Actions, выполнять задачи, необходимые для проверки подлинности, так как мы будем экспериментировать позже.
* **Учетные** данные базы данных, предоставляющие доступ к локальным и внешним базам данных и хранилищу.
* **Закрытые ключи, такие как частные ключи** SSH и PGP, которые можно использовать для доступа к другим серверам и шифрования данных.

Так как секреты предоставляют так много доступа, включая критически важные системы, мы можем понять, почему это так важно, чтобы обеспечить безопасность\*\* секретов\*\*.

### Что может произойти, когда секрет предоставляется?

* Злоумышленники могут получить **несанкционированный доступ ко** всему секрету, к которым разрешен доступ.
* Хакеры могут **украсть данные**, включая конфиденциальные пользовательские данные. Это может иметь конфиденциальность и юридические последствия и вред доверия к вам и вашему приложению.
* Предоставленные секреты могут **стоить вам деньги** , если хакеры выполняют несанкционированные рабочие нагрузки на учетных записях поставщика облачных служб.
* Хакеры могут использовать предоставленный секрет для удаления, изменения и нарушения серверов, которые могут привести **к простою и потере** данных.

Рассмотрим все доступ и способности секрет предоставляет вам и то, что хакер может сделать с ним. Например, если учетная запись personal access token для учетной записи GitHub была предоставлена, хакер может опубликовать и внести изменения в GitHub как вы.

## Рекомендации по управлению секретами

Чтобы избежать этих типов проблем, следуйте рекомендациям, чтобы предотвратить утечки и ограничить ущерб, если секрет когда-либо подвергается.

### Следуйте принципу **наименьших привилегий (PoLP)**

По возможности ограничьте то, что может сделать секрет, и сможете получить доступ только к необходимым. Например:

* Если секрет будет использоваться только для чтения данных, а не внесения изменений в данные, выберите его **только** для чтения.
* Если api, который вы используете, позволяет ограничить секрет только определенными областями или разрешениями, выберите **только те, которые вам нужны**. Например, если вам нужно создать проблемы только с секретом GitHub, нет причин для доступа к содержимому репозитория или что-либо другое.
* Если секрет предоставит злоумышленнику полный доступ к учетной записи пользователя, принадлежащей ей, **рассмотрите возможность создания учетных** записей служб, которые могут владеть секретом.

### Защита секретов в приложении

* **Никогда не закодировать секрет**. Всегда используйте **переменные среды или средства управления секретами платформы (например, переменных** данных.product.github %}секреты репозитория).
* Если вам нужно поделиться секретом с кем-то, используйте специальное средство, например диспетчер\*\* паролей\*\*. Никогда не отправлять секреты по электронной почте или мгновенному сообщению.
* Если это возможно, установите **даты** окончания срока действия и **регулярно поворачивайте секреты** . Это снижает риск использования старых секретов.
* Если приложение создает журнал, убедитесь, что **секреты будут отредактированы перед ведением** журнала. В противном случае активные секреты можно сохранить в файлах с открытым текстом.

### Ограничение ущерба, если секрет предоставляется

* Рассмотрите скомпрометированный секрет, даже если он был предоставлен только на секунду, и **немедленно** отмените секрет. Затем создайте новый секрет и сохраните его безопасно.
* Проверьте все **журналы** действий, которые могут отображать любые подозрительные действия, выполненные с скомпрометированный секрет.
* Рассмотрим, как секрет был предоставлен и внесите изменения в процессы, чтобы это не могло повториться.

## Как GitHub помогает защитить секреты

Есть много, что вы можете сделать, чтобы сохранить секреты в безопасности, но есть также много, что GitHub делает, чтобы помочь сохранить секрет секреты. Все делают ошибки, и мы здесь, чтобы помочь с функциями, которые будут перехватывать любые секреты, которые вы случайно предоставляете:

* \*\*\*\*Защита от отправки, с которой мы будем экспериментировать позже, блокирует отправку секретов в репозитории на GitHub.
* \*\*\*\* Сканирование секретов сканирует репозитории и создает оповещения при обнаружении секрета. Для некоторых секретов мы также уведомляем поставщика, чтобы они могли принять меры, такие как отмена секрета автоматически.

## Практика безопасного хранения секрета

В этом упражнении мы создадим personal access token и безопасно сохраните его, чтобы использовать его с GitHub Actions. Действие, которое мы создадим, — это простой рабочий процесс, который отвечает на проблему.

### 1. Создание репозитория практики

Начнем с создания репозитория для работы. У `new2code` учетной записи есть репозиторий шаблонов, который можно использовать для быстрого начала работы.

1. Перейдите [на новую страницу](https://github.com/new?template_owner=new2code\&template_name=secret-action) репозитория. После этой ссылки предварительно выберите шаблон в учетной `new2code` записи.
2. В разделе "Владелец" убедитесь, что выбрана учетная запись пользователя.
3. В поле "Имя репозитория" введите `secret-action`.
4. Под полем описания выберите **"Общедоступный** ", чтобы задать видимость репозитория.
5. Щелкните **Создать репозиторий**.

### 2. Фиксация фиктивного маркера

Все делают ошибки, и возможно, что вы случайно зафиксируете секрет в какой-то момент в пути написания кода. В этом упражнении мы намеренно зафиксируем поддельный **токен** , чтобы мы могли ознакомиться с оповещением, которое активируется.

1. Перейдите к только что созданному репозиторию.

2. Перейдите к файлу рабочего процесса YAML, щелкнув `.github/workflows` список файлов.

3. Откройте файл рабочего процесса, щелкнув `comment.yml` список файлов.

4. Чтобы изменить файл рабочего процесса, в правом верхнем углу щелкните <svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-pencil" aria-label="pencil icon" role="img"><path d="M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61Zm.176 4.823L9.75 4.81l-6.286 6.287a.253.253 0 0 0-.064.108l-.558 1.953 1.953-.558a.253.253 0 0 0 .108-.064Zm1.238-3.763a.25.25 0 0 0-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 0 0 0-.354Z"></path></svg>.

5. В строке 13 вставьте `GH_TOKEN: ""`этот фиктивный маркер между кавычками:

   ```text
   secret_scanning_ab85fc6f8d7638cf1c11da812da308d43_abcde
   ```

   Конечный результат должен выглядеть следующим образом:

   ```yaml
   GH_TOKEN: "secret_scanning_ab85fc6f8d7638cf1c11da812da308d43_abcde"
   ```

6. Чтобы попытаться зафиксировать изменение, в правом верхнем углу нажмите кнопку **"Зафиксировать изменения",** а затем снова нажмите кнопку **"Зафиксировать изменения** " в диалоговом окне.

7. Теперь вы должны увидеть предупреждение о защите от пуша, которое сообщает: «Секретное сканирование нашло секрет GitHub Secret Scanning на строке 13».

   ![Снимок экрана: оповещение о принудительной защите для строки 13 файла, который мы пытались зафиксировать. Кнопка "Отмена" выделена в оранжевом контуре.](/assets/images/help/security/push-protection-example.png)

   Если бы мы не экспериментировали с фиктивным маркером, это оповещало нас о том, что мы были одним шагом от предоставления маркера. Просмотрите параметры, которые можно выбрать в оповещении.

8. Чтобы остановить фиксацию и избежать предоставления секрета, нажмите кнопку **"Отмена**". В правом верхнем углу нажмите кнопку **"Отмена изменений**", а затем отмените несохраненные изменения при появлении запроса.

### 3. Создание реального токена

Теперь давайте попробуем выполнить наши рекомендации. Сначала мы создадим personal access token, что позволит действию действовать от вашего имени (создаваемый комментарий будет отображаться из учетной записи пользователя).

> \[!NOTE] Обратите внимание, что мы следуйте принципу наименьших привилегий для каждого шага конфигурации. У маркера будет самый короткий срок действия, только у него есть доступ к нужному репозиторию и минимальные разрешения, необходимые для работы.

1. Перейдите [на новую страницу](https://github.com/settings/personal-access-tokens/new) personal access token.
2. В разделе "Имя токена" укажите новое имя маркера. Вы можете использовать что-то подобное "Маркер действия".
3. В разделе "Срок действия" выберите "7 дней".
4. В разделе "Доступ к репозиторию" выберите **"Только репозитории**".
5. В раскрывающемся списке "Выбор репозиториев" выберите **только** созданный ранее репозиторий практики.
6. Справа от "Разрешения репозитория" в разделе "Разрешения" щелкните <svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-unfold" aria-label="Expand" role="img"><path d="m8.177.677 2.896 2.896a.25.25 0 0 1-.177.427H8.75v1.25a.75.75 0 0 1-1.5 0V4H5.104a.25.25 0 0 1-.177-.427L7.823.677a.25.25 0 0 1 .354 0ZM7.25 10.75a.75.75 0 0 1 1.5 0V12h2.146a.25.25 0 0 1 .177.427l-2.896 2.896a.25.25 0 0 1-.354 0l-2.896-2.896A.25.25 0 0 1 5.104 12H7.25v-1.25Zm-5-2a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM6 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 6 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM12 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 12 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5Z"></path></svg> для просмотра всех возможных разрешений.
7. Прокрутите вниз до раздела "Проблемы" и в раскрывающемся списке справа выберите "Чтение и запись".
8. В нижней части страницы нажмите кнопку **"Создать токен**". При появлении запроса подтвердите, снова нажав кнопку **"Создать маркер** ".

Важно безопасно обрабатывать полученный маркер с этого момента. Как мы будем использовать маркер вскоре, вы можете скопировать его в буфер обмена кратко.

### 4. Безопасное хранение маркера

Теперь мы можем безопасно хранить новый маркер в нашем репозитории.

1. Перейдите к репозиторию, созданному в начале упражнения.
2. Под именем репозитория щелкните **<svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-gear" aria-label="gear" role="img"><path d="M8 0a8.2 8.2 0 0 1 .701.031C9.444.095 9.99.645 10.16 1.29l.288 1.107c.018.066.079.158.212.224.231.114.454.243.668.386.123.082.233.09.299.071l1.103-.303c.644-.176 1.392.021 1.82.63.27.385.506.792.704 1.218.315.675.111 1.422-.364 1.891l-.814.806c-.049.048-.098.147-.088.294.016.257.016.515 0 .772-.01.147.038.246.088.294l.814.806c.475.469.679 1.216.364 1.891a7.977 7.977 0 0 1-.704 1.217c-.428.61-1.176.807-1.82.63l-1.102-.302c-.067-.019-.177-.011-.3.071a5.909 5.909 0 0 1-.668.386c-.133.066-.194.158-.211.224l-.29 1.106c-.168.646-.715 1.196-1.458 1.26a8.006 8.006 0 0 1-1.402 0c-.743-.064-1.289-.614-1.458-1.26l-.289-1.106c-.018-.066-.079-.158-.212-.224a5.738 5.738 0 0 1-.668-.386c-.123-.082-.233-.09-.299-.071l-1.103.303c-.644.176-1.392-.021-1.82-.63a8.12 8.12 0 0 1-.704-1.218c-.315-.675-.111-1.422.363-1.891l.815-.806c.05-.048.098-.147.088-.294a6.214 6.214 0 0 1 0-.772c.01-.147-.038-.246-.088-.294l-.815-.806C.635 6.045.431 5.298.746 4.623a7.92 7.92 0 0 1 .704-1.217c.428-.61 1.176-.807 1.82-.63l1.102.302c.067.019.177.011.3-.071.214-.143.437-.272.668-.386.133-.066.194-.158.211-.224l.29-1.106C6.009.645 6.556.095 7.299.03 7.53.01 7.764 0 8 0Zm-.571 1.525c-.036.003-.108.036-.137.146l-.289 1.105c-.147.561-.549.967-.998 1.189-.173.086-.34.183-.5.29-.417.278-.97.423-1.529.27l-1.103-.303c-.109-.03-.175.016-.195.045-.22.312-.412.644-.573.99-.014.031-.021.11.059.19l.815.806c.411.406.562.957.53 1.456a4.709 4.709 0 0 0 0 .582c.032.499-.119 1.05-.53 1.456l-.815.806c-.081.08-.073.159-.059.19.162.346.353.677.573.989.02.03.085.076.195.046l1.102-.303c.56-.153 1.113-.008 1.53.27.161.107.328.204.501.29.447.222.85.629.997 1.189l.289 1.105c.029.109.101.143.137.146a6.6 6.6 0 0 0 1.142 0c.036-.003.108-.036.137-.146l.289-1.105c.147-.561.549-.967.998-1.189.173-.086.34-.183.5-.29.417-.278.97-.423 1.529-.27l1.103.303c.109.029.175-.016.195-.045.22-.313.411-.644.573-.99.014-.031.021-.11-.059-.19l-.815-.806c-.411-.406-.562-.957-.53-1.456a4.709 4.709 0 0 0 0-.582c-.032-.499.119-1.05.53-1.456l.815-.806c.081-.08.073-.159.059-.19a6.464 6.464 0 0 0-.573-.989c-.02-.03-.085-.076-.195-.046l-1.102.303c-.56.153-1.113.008-1.53-.27a4.44 4.44 0 0 0-.501-.29c-.447-.222-.85-.629-.997-1.189l-.289-1.105c-.029-.11-.101-.143-.137-.146a6.6 6.6 0 0 0-1.142 0ZM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM9.5 8a1.5 1.5 0 1 0-3.001.001A1.5 1.5 0 0 0 9.5 8Z"></path></svg> Settings**. Если вкладка "Параметры" не отображается, выберите **раскрывающееся меню <svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-kebab-horizontal" aria-label="More" role="img"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg>** и нажмите кнопку **"Параметры**".

   ![Снимок экрана: заголовок репозитория с вкладками. Вкладка "Параметры" выделена темно-оранжевым контуром.](/assets/images/help/repository/repo-actions-settings.png)
3. Под именем репозитория щелкните **<svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-gear" aria-label="gear" role="img"><path d="M8 0a8.2 8.2 0 0 1 .701.031C9.444.095 9.99.645 10.16 1.29l.288 1.107c.018.066.079.158.212.224.231.114.454.243.668.386.123.082.233.09.299.071l1.103-.303c.644-.176 1.392.021 1.82.63.27.385.506.792.704 1.218.315.675.111 1.422-.364 1.891l-.814.806c-.049.048-.098.147-.088.294.016.257.016.515 0 .772-.01.147.038.246.088.294l.814.806c.475.469.679 1.216.364 1.891a7.977 7.977 0 0 1-.704 1.217c-.428.61-1.176.807-1.82.63l-1.102-.302c-.067-.019-.177-.011-.3.071a5.909 5.909 0 0 1-.668.386c-.133.066-.194.158-.211.224l-.29 1.106c-.168.646-.715 1.196-1.458 1.26a8.006 8.006 0 0 1-1.402 0c-.743-.064-1.289-.614-1.458-1.26l-.289-1.106c-.018-.066-.079-.158-.212-.224a5.738 5.738 0 0 1-.668-.386c-.123-.082-.233-.09-.299-.071l-1.103.303c-.644.176-1.392-.021-1.82-.63a8.12 8.12 0 0 1-.704-1.218c-.315-.675-.111-1.422.363-1.891l.815-.806c.05-.048.098-.147.088-.294a6.214 6.214 0 0 1 0-.772c.01-.147-.038-.246-.088-.294l-.815-.806C.635 6.045.431 5.298.746 4.623a7.92 7.92 0 0 1 .704-1.217c.428-.61 1.176-.807 1.82-.63l1.102.302c.067.019.177.011.3-.071.214-.143.437-.272.668-.386.133-.066.194-.158.211-.224l.29-1.106C6.009.645 6.556.095 7.299.03 7.53.01 7.764 0 8 0Zm-.571 1.525c-.036.003-.108.036-.137.146l-.289 1.105c-.147.561-.549.967-.998 1.189-.173.086-.34.183-.5.29-.417.278-.97.423-1.529.27l-1.103-.303c-.109-.03-.175.016-.195.045-.22.312-.412.644-.573.99-.014.031-.021.11.059.19l.815.806c.411.406.562.957.53 1.456a4.709 4.709 0 0 0 0 .582c.032.499-.119 1.05-.53 1.456l-.815.806c-.081.08-.073.159-.059.19.162.346.353.677.573.989.02.03.085.076.195.046l1.102-.303c.56-.153 1.113-.008 1.53.27.161.107.328.204.501.29.447.222.85.629.997 1.189l.289 1.105c.029.109.101.143.137.146a6.6 6.6 0 0 0 1.142 0c.036-.003.108-.036.137-.146l.289-1.105c.147-.561.549-.967.998-1.189.173-.086.34-.183.5-.29.417-.278.97-.423 1.529-.27l1.103.303c.109.029.175-.016.195-.045.22-.313.411-.644.573-.99.014-.031.021-.11-.059-.19l-.815-.806c-.411-.406-.562-.957-.53-1.456a4.709 4.709 0 0 0 0-.582c-.032-.499.119-1.05.53-1.456l.815-.806c.081-.08.073-.159.059-.19a6.464 6.464 0 0 0-.573-.989c-.02-.03-.085-.076-.195-.046l-1.102.303c-.56.153-1.113.008-1.53-.27a4.44 4.44 0 0 0-.501-.29c-.447-.222-.85-.629-.997-1.189l-.289-1.105c-.029-.11-.101-.143-.137-.146a6.6 6.6 0 0 0-1.142 0ZM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM9.5 8a1.5 1.5 0 1 0-3.001.001A1.5 1.5 0 0 0 9.5 8Z"></path></svg> Settings**. Если вкладка "Параметры" не отображается, выберите **раскрывающееся меню <svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-kebab-horizontal" aria-label="More" role="img"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg>** и нажмите кнопку **"Параметры**".

   ![Снимок экрана: заголовок репозитория с вкладками. Вкладка "Параметры" выделена темно-оранжевым контуром.](/assets/images/help/repository/repo-actions-settings.png)
4. В разделе "Секреты репозитория" щелкните **"Создать секрет** репозитория".
5. **В поле "Имя"** введите имя секрета. Для этого упражнения мы будем использовать `MY_TOKEN`.
6. В поле "Секрет"\*\* вставьте созданные \*\*ранее данные personal access token.
7. Щелкните **Добавить секрет**.

Ваш секрет теперь безопасно зашифрован и готов к использованию!

### 5. Ссылка на маркер в нашем действии

Теперь мы можем обновить файл рабочего процесса YAML, чтобы использовать маркер и проверить его работу.

1. Вернитесь к репозиторию. Если вы находитесь в параметрах репозитория, вы можете щелкнуть **<svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-code" aria-label="code" role="img"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg> Code** под именем репозитория.

2. Перейдите к файлу рабочего процесса YAML, щелкнув `.github/workflows` список файлов.

3. Откройте файл рабочего процесса, щелкнув `comment.yml` список файлов.

4. Чтобы начать редактирование файла рабочего процесса, в правом верхнем углу щелкните <svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-pencil" aria-label="pencil icon" role="img"><path d="M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61Zm.176 4.823L9.75 4.81l-6.286 6.287a.253.253 0 0 0-.064.108l-.558 1.953 1.953-.558a.253.253 0 0 0 .108-.064Zm1.238-3.763a.25.25 0 0 0-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 0 0 0-.354Z"></path></svg>.

5. В строке 13 `GH_TOKEN: ""`замените пустые кавычки `${{ secrets.MY_TOKEN }}`на . Это будет ссылаться на секрет репозитория, который мы добавили ранее.

   ```yaml
   GH_TOKEN: ${{ secrets.MY_TOKEN }}
   ```

6. Чтобы зафиксировать изменение, в правом верхнем углу нажмите кнопку **"Зафиксировать изменения".**

7. В диалоговом окне "Фиксация изменений" измените "Зафиксировать сообщение", чтобы отразить внесенные изменения. Например, можно ввести "Обновление рабочего процесса для использования секрета репозитория".

8. Убедитесь, что выбран параметр "Зафиксировать непосредственно в `main` ветви".

9. Щелкните **Зафиксировать изменения**.

### 6. Тестирование маркера и рабочего процесса

Мы должны быть все настроены сейчас! Давайте пройдем и протестируем рабочий процесс.

personal access token 1. Щелкните **Новая проблема**.

1. В разделе "Добавить название" можно ввести любой нужный заголовок.
2. В разделе "Добавить описание" в текстовой области введите `Hello`.
3. Под текстовой областью нажмите кнопку **"Создать**".

После завершения рабочего процесса появится новый комментарий. Комментарий будет создан самостоятельно, так как мы используем ваш токен и содержат приветствие в ответ.

## Следующие шаги

Для более подробного изучения защиты от сканирования секретов и принудительной отправки можно выполнить [курс "Введение в проверку секретов](https://github.com/skills/introduction-to-secret-scanning/tree/main) " в GitHub Skills.

Еще одной важной частью безопасности кода является определение уязвимостей кода и исправление уязвимостей в проектах. См [. раздел AUTOTITLE](/ru/get-started/learning-to-code/finding-and-fixing-your-first-code-vulnerability).