Сохранение вашего кода в целости и сохранности

Внедрение секретов в конвейеры CI/CD

Краткое руководство по репозиториям GitHub, Azure DevOps и App Center.

Как вы, надеюсь, уже знаете, никогда не следует включать секреты (например, ключи API, симметричные ключи, сертификаты и т. д.) в свои репозитории. Даже не в частных.

Недавно мне пришлось использовать секреты для личного проекта и для проекта заказчика. Мне нужно было придумать элегантное решение для моих .NET-проектов, и я решил поделиться с вами своими знаниями и лучшими практиками.

Вообще говоря, есть два подхода к реализации секретов в ваших проектах .NET:

Секреты пользователя

Вы включаете секреты в секретный файл. Приложение .NET загрузит их для вас во время выполнения. В рабочей среде вы указываете секреты с помощью других средств (таких как Key Vault и т. д.). Обычно это работает для проектов ASP.NET Core и рабочих служб.

Константы

Вы указываете типизированные секреты в статическом классе и ссылаетесь на класс в своих проектах. Обычно это используется для приложений и тестовых проектов.

В этой статье я сосредоточусь на последнем сценарии для проектов на основе .NET:

  • В моем личном проекте мне пришлось добавлять секреты в свое приложение UWP с помощью App Center и GitHub.
  • В коммерческом проекте я выбрал TDD так естественно, что мне пришлось предоставить некоторые секреты для моих интеграционных тестов, не перебарщивая, потому что я хотел сохранить KISS. Для этого я использовал Azure DevOps.

Без дальнейших церемоний, поехали.

Первоначальные соображения по проекту

Теперь то, как именно вы включаете секреты, зависит исключительно от вашего проекта. В моем случае я создал частичный статический класс с именем Constants.cs, в котором я определяю необходимые свойства, и еще один частичный класс Constants.Secret.cs, содержащий распространяемые значения:

Чтобы дать вам представление, вот как выглядят оба файла:

// Constants.cs
public static partial class Constants
{
    public static string ApiKey { get; set; }
}
// Constants.Secret.cs
public static partial class Constants
{
    static Constants()
    {
        ApiKey = "verysecretkey!123"
    }
}

Компилятор Rosyln автоматически разрешает оба файла. Чтобы использовать класс, не требуется специальной настройки, и вы можете просто ссылаться на свойство Constants.ApiKey из любого места.

Теперь, прежде чем что-либо коммитить в Git, убедитесь, что вы добавили секретный файл в свой файл .gitignore:

Constants.Secret.cs

Это будет игнорировать все файлы, которые соответствуют имени в вашем репозитории, поэтому они никогда не будут проверены в вашем удаленном репозитории. Очень удобно, если в вашем решении много разных проектов, у которых есть свой набор секретов.

Давай, предоставьте хорошее сообщение о коммите и нажмите его. После того, как вы это сделаете, мы можем заняться аспектами CI/CD.

CI/CD

Нам требуется некоторая настройка CI/CD, потому что на данный момент все сборки будут просто терпеть неудачу, поскольку компилятор не может найти файл Constants.Secret.cs в репозитории — в первую очередь потому, что на него есть ссылка в нашем решении, но его нельзя найти в рабочем каталоге удаленного репозитория.

Чтобы решить эту проблему, я покажу три варианта, которые должны работать в большинстве сценариев: GitHub, Azure DevOps и App Center.

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

Гитхаб

GitHub позволяет хранить секреты в вашем репозитории. Затем на эти секреты можно ссылаться из ваших действий GitHub.

Чтобы управлять своими секретами, перейдите в свой репозиторий и нажмите Настройки › Секреты.

Там создайте новый секрет репозитория и включите в него содержимое файла Constants.Secret.cs. Дайте ему запоминающееся имя (с этого момента я буду называть его <CONSTANTS>. Вы должны использовать другое имя) и сохраните секрет.

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

Скрипт может выглядеть так: он просто запишет содержимое секрета в файл.

steps:
- uses: actions/checkout@v2
- name: Create Constants
  run: echo ${{secrets.<CONSTANTS>}} > "./<PATH>/Constants.Secret.cs"
# ...

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

Зафиксируйте обновленный файл действий, и ваша сборка должна завершиться успешно.

Azure DevOps

Azure DevOps позволяет загружать защищенные файлы. Защищенные файлы — хорошее решение для управления вашими секретными файлами в ваших пайплайнах. Это позволяет вам управлять тем, кто может получить доступ к защищенным файлам и какие конвейеры могут их использовать.

Чтобы управлять всеми своими секретами, убедитесь, что вы включили Pipelines для своего проекта. Затем перейдите в раздел Конвейеры › Библиотека. Библиотека позволяет повторно использовать переменные и хранить защищенные файлы.

Там перейдите на вкладку Защищенные файлы, загрузите свой секретный класс констант (Constants.Secret.cs) и убедитесь, что вы дали ему хорошее имя — такое, которое позволит вам отличать константные классы друг от друга. в случае, если у вас есть более чем один из них.

После этого пришло время добавить наш защищенный файл в конвейер сборки. Для использования защищенных файлов используется задача SecureFile. В качестве входных данных требуется имя задачи и имя защищенного файла. имя задачи позволяет ссылаться на файл на всех последовательных шагах сборки:

steps:
- task: DownloadSecureFile@1
  name: constantsFile
  displayName: 'Download Constants for Integration Tests'
  inputs:
    secureFile: 'Constants.Secret.cs'

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

- script: cp $(constantsFile.secureFilePath) <PATH>/Constants.Secret.cs
  displayName: Copy constants

И вы сделали! Этот шаг теперь скопирует защищенный файл в место назначения.

Сохраните определение сборки и запустите его. Ваша сборка должна быть успешной.

Центр приложений

Центр приложений позволяет запускать пользовательские сценарии на определенных этапах. Подробнее об этом можно прочитать в Документации App Center.

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

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

Если вы планируете использовать App Center только для целей CI, все будет в порядке. Однако, если вы планируете распространять пакет своего приложения среди тестировщиков, вам нужно будет найти способы распространения ваших констант.

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

Я создал приложение UWP, и мне пришлось распространить в нем несколько констант. Чтобы добавить сценарий пост-клонирования, добавьте файл сценария в корневой путь вашего репозитория.

Для сборок на основе Windows, таких как UWP(appcenter-post-clone.ps1)

"namespace <PLACEHOLDER>
{
    public static partial class Constants
    {
        static Constants() { }
    }
}" | Out-File -FilePath ".\\<PATH>\\Constants.Secret.cs

Для сборок на базе Mac (appcenter-post-clone.sh)

echo "namespace <PLACEHOLDER>\
{\
    public static partial class Constants\
    {\
        static Constants() { } \
    }\
}" > "<PATH>/Constants.Secret.cs.cs"

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

Надеюсь, эта статья поможет и вдохновит вас. Дайте мне знать, что вы думаете.

Недавно я стал студенческим послом Microsoft Learn. Если вы хотите, чтобы я публиковал больше статей в будущем, подписывайтесь на меня в Medium и Twitter. Также обратите внимание на другие мои статьи!

Привет, и спасибо за чтение!