Введение в безопасное управление секретами с помощью систем контроля версий

Вступление

Программное обеспечение контроля версий (VCS) является неотъемлемой частью большинства современных практик разработки программного обеспечения. Среди других преимуществ такие программы, как Git, Mercurial, Bazaar, Perforce, CVS и Subversion, позволяют разработчикам сохранять моментальные снимки истории своего проекта, улучшая совместную работу, возвращаться к предыдущим состояниям и восстанавливаться после непреднамеренных изменений кода, а также управлять несколькими версиями одной и той же версии. кодовая. Эти инструменты позволяют нескольким разработчикам безопасно работать над одним проектом и предоставляют значительные преимущества, даже если вы не планируете делиться своей работой с другими.

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

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

Проверка вашего Git-репозитория на конфиденциальные данные

Перед настройкой системы для управления вашими конфиденциальными данными рекомендуется проверить, есть ли в файлах вашего проекта какой-либо секретный материал.

Сканирование ваших проектов

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

git grep my_secret $(git rev-list --all)

Это будет искать всю историю проекта для указанной строки.

Ряд специальных инструментов может помочь раскрыть секреты в более широком смысле. Такие инструменты, какgitrob, могут сканировать каждый репозиторий в организации GitHub на предмет имен файлов, соответствующих указанным в заранее определенном списке. Проектgit-secrets может сканировать репозитории локально на предмет определенных секретов на основе шаблонов как в путях к файлам, так и в содержимом. ИнструментtruffleHog использует другой подход, ища в репозиториях строки с высокой энтропией, которые, вероятно, представляют собой сгенерированные секреты, используемые приложениями. Чтобы объединить некоторые из этих функций в один инструмент,git-all-secrets склеивает или повторно реализует вышеуказанные инструменты в едином интерфейсе.

Варианты смягчения

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

Если учетные данные зафиксированы в вашем репозитории проекта, вашим первым шагом должно быть немедленное изменение пароля или секрета для аннулирования предыдущего значения. Этот шаг должен быть выполнен независимо от того, является ли хранилище общим для нескольких пользователей по нескольким причинам. Требования к совместной работе могут меняться в течение срока действия проекта, что приводит к большей подверженности риску, чем предполагалось ранее. Даже если вы знаете, что никогда не будете преднамеренно делиться своим проектом, инциденты безопасности могут привести к утечке данных непреднамеренным сторонам, поэтому лучше быть активным в изменении текущих значений.

Несмотря на то, что вы должны повернуть свои скомпрометированные учетные данные во всех случаях, вы можете также удалить полностью пропущенные учетные данные или файл из своей истории VCS. Это особенно важно для конфиденциальных данных, которые нельзя изменить, например, для любых пользовательских данных, которые были непреднамеренно зафиксированы. Удаление данных из ваших репозиториев включает в себя переписывание истории VCS для удаления файла из предыдущих коммитов. Это можно сделатьusing native git commands or with the help of some dedicated tools. Важно отметить, что даже если вы удалите все записи данных в репозитории, любой, кто ранее скопировал кодовую базу, все же может иметь доступ к конфиденциальному материалу. Помните об этом при оценке степени воздействия.

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

Использование функций VCS для избежания секретов

Прежде чем рассматривать внешние инструменты, рекомендуется ознакомиться с некоторыми функциями и возможностями, встроенными в ваши инструменты VCS, чтобы предотвратить попадание нежелательных данных в ваше хранилище.

Игнорирование конфиденциальных файлов

Самый простой способ сохранить файлы с конфиденциальными данными в вашем хранилище - это использовать функцию игнорирования VCS с самого начала. Файлы «игнорирования» VCS (например,.gitignore) определяют шаблоны, каталоги или файлы, которые следует исключить из репозитория. Это хорошая первая линия защиты от случайного обнародования данных. Эта стратегия полезна, поскольку она не зависит от внешних инструментов, список исключенных элементов автоматически настраивается для соавторов, и ее легко настроить.

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

Использование хуков VCS для проверки файлов перед фиксацией

Большинство современных реализаций VCS включают в себя систему, называемую «ловушками» для выполнения сценариев до или после выполнения определенных действий в хранилище. Эту функциональность можно использовать для выполнения скрипта, чтобы проверить содержимое ожидающих изменений для чувствительного материала. Ранее упомянутый инструментgit-secrets может устанавливать хукиpre-commit, которые реализуют автоматическую проверку типа оцениваемого содержимого. Вы можете добавить свои собственныеcustom scripts, чтобы проверить, какие шаблоны вы хотите защитить.

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

Добавление файлов в промежуточную область явным образом

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

Хранение зашифрованных секретов в репозитории

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

Реализации

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

Проект под названиемgit-secret (не путать с упомянутым ранее инструментомgit-secrets) может шифровать содержимое секретных файлов с помощью ключей GPG доверенных соавторов. Используя существующую сеть доверия, пользователиgit-secret могут управлять доступом к файлам, указав пользователей, которые должны иметь возможность расшифровать каждый элемент. Если пользователь опубликовал свой открытый ключ на сервере ключей, вы можете предоставить ему доступ к зашифрованному содержимому, даже не запрашивая у него ключ напрямую.

Инструментgit-crypt работает аналогичноgit-secret в том смысле, что он позволяет вам шифровать и фиксировать части вашего репозитория, а также регулировать доступ для других участников, используя их ключи GPG. В качестве альтернативы проектgit-crypt может использовать шифрование с симметричным ключом, если ваша команда не использует GPG или если этот шаблон управления слишком сложен для вашего варианта использования. Кроме того,git-crypt будет автоматически шифровать во время фиксации и дешифровать при клоне с использованием фильтраgit и атрибутов diff, что упрощает управление.

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

Помимо вышеприведенных общих решений, существуют также некоторые решения, созданные для работы с определенными типами репозиториев. Например, начиная с версии 5.1, проекты Ruby on Rails могут включатьencrypted secrets within the repository, используя систему, которая устанавливает главный ключ вне репозитория.

преимущества

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

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

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

Недостатки

Как и в любом решении, у этого стиля секретного управления есть некоторые компромиссы.

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

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

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

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

Использование систем управления конфигурациями для секретного управления

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

Реализации

Chef encrypted data bags иchef-vault предоставляют некоторые интегрированные функции управления секретами для инфраструктуры, управляемой Chef. Пакеты с зашифрованными данными используются для защиты конфиденциальных значений от появления в истории изменений или на других компьютерах, использующих общие секреты. Chef-vault позволяет шифровать секреты с использованием открытого ключа целевой машины, предлагая дополнительную защиту, которая изолирует возможности расшифровки для предполагаемых получателей.

Точно так же система хранения ключей и значенийPuppet’s Hiera может использоваться сHiera eyaml для безопасного управления секретами для определенных компонентов инфраструктуры. В отличие от некоторых других систем, Hiera eyaml знает о синтаксисе и структуре YAML, формата сериализации данных, который использует Hiera, что позволяет ему шифровать только конфиденциальные значения вместо всего файла. Это позволяет работать с файлами, которые содержат зашифрованные данные, используя обычные инструменты для большинства задач. Поскольку бэкэнды являются подключаемыми, команды могут реализовать шифрование GPG, чтобы легко управлять доступом.

Saltstack используетPillars для хранения данных, предназначенных для определенных машин. Чтобы защитить эти элементы, пользователи могут зашифровать значения YAML с помощью GPG, а затем настроитьGPG renderer, чтобы позволить Salt дешифровать значения во время выполнения. Как и Hiera eyaml, эта система включает в себя шифрование только конфиденциальных данных, а не полного файла, что позволяет нормально работать обычным редакторам файлов и инструментам сравнения.

Ansible включаетAnsible Vault, систему шифрования и инструмент командной строки для шифрования конфиденциальных файлов YAML в структуре playbook. Затем Ansible может прозрачно расшифровать секретные файлы во время выполнения, чтобы объединить секретные и несекретные данные, необходимые для выполнения данных задач. Ansible Vault шифрует весь файл, а не значения, поэтому редактирование требует расшифровки, и инструменты сравнения не могут отображать точную информацию об изменениях. Однако, начиная с Ansible 2.3,single variables can be encrypted in variable files дает пользователям выбор того, как они хотят шифровать конфиденциальные значения.

преимущества

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

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

Недостатки

Тесная интеграция означает, что пользователи могут использовать свои существующие системы для управления своими секретами, но это означает, что эти решения привязаны к соответствующим инструментам управления конфигурацией. Использование большинства этих стратегий в других контекстах будет затруднено или невозможно, что означает, что вы добавляете зависимость от самих инструментов управления конфигурацией. Тесная интеграция с единой платформой также может создавать проблемы для внешних систем, требующих доступа к данным. Без внешнего API или вызываемой команды в некоторых случаях секреты могут быть эффективно «захвачены», если к ним нет доступа через систему управления конфигурацией, которая может быть ограничивающей.

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

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

Использование службы управления внешним секретом

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

Реализации

Специальные службы управления секретами, такие какHashiCorp’s Vault, предлагают большую гибкость и мощные функции для защиты конфиденциальных материалов, не жертвуя при этом удобством использования. Vault защищает данные в состоянии покоя и в пути и предназначен для использования различных «бэкэндов» для предоставления различных функций и управления сложностями шифрования, хранения и аутентификации. Несколько ключевых функций включают в себя возможность настройки динамических секретов (краткосрочные учетные данные для подключенных служб, созданные на лету), шифрование данных в качестве службы (шифрование и хранение данных из внешних служб и повторное обслуживание дешифрованного содержимого по требованию уполномоченное лицо) и секретное управление на основе аренды (предоставление доступа на определенный период времени, после которого доступ автоматически аннулируется). Подключаемая архитектура Vault означает, что серверы хранения, механизмы аутентификации и т. Д. все могут быть заменены по мере изменения потребностей бизнеса.

Система управления секретамиKeywhizот Square - еще одна специализированная услуга, используемая для обеспечения общей безопасности конфиденциальных данных. Как и Vault, Keywhiz предоставляет API-интерфейсы, которые клиенты и пользователи могут использовать для хранения и доступа к секретам. Одной из уникальных возможностей, предлагаемых Keywhiz, является возможность раскрытия секретов с помощью файловой системы FUSE, виртуальной файловой системы, которую клиенты могут монтировать для доступа к конфиденциальным данным в виде псевдофайлов. Этот механизм позволяет многим различным типам программ получать доступ к нужным им данным без помощи агента или оболочки и позволяет администраторам блокировать доступ с использованием обычных разрешений файловой системы Unix.

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

преимущества

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

С административной точки зрения секретные системы управления предоставляют множество уникальных функций, недоступных в других инструментах. Простая ротация ключей шифрования, а также основных секретов, которые они защищают, невероятно полезна для больших развертываний и сложных систем, которые требуют согласования множества различных чувствительных значений. Доступ можно легко регулировать и отменять без развертывания кода или внесения каких-либо изменений во всем автопарке. Такие функции, как динамические секреты, предоставляют секретным серверам управления доступ к внешним службам, таким как базы данных, для создания учетных данных для каждого пользователя по требованию. Краткосрочный доступ к секретам, основанный на аренде, функционирует как автоматический механизм ограничения или прекращения доступа без явного отзыва.

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

Недостатки

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

Настройка централизованной системы требует тщательного планирования, тестирования и координации перед развертыванием в производственной среде. После того, как инфраструктура запущена и работает, клиенты должны быть обновлены для запроса API-интерфейсов секретного сервера управления, или процесс агента должен быть настроен для получения секретов от имени процессов, которые этого требуют. Должны быть установлены политики, определяющие, какие приложения, инфраструктура и члены группы должны иметь доступ к каждому защищенному значению.

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

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

Завершение

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

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

Related