Стратегія для збереження секретної інформації, такої як ключі API, поза контролем джерела?


217

Я працюю над веб-сайтом, який дозволить користувачам входити в систему за допомогою облікових даних OAuth, подібних до Twitter, Google тощо. Для цього мені потрібно зареєструватися у цих різних провайдерів і отримати супер секретний ключ API, який у мене є захищати заставою від різних частин тіла. Якщо мій ключ зірветься, частина розірветься.

Ключ API повинен подорожувати з моїм джерелом, оскільки він використовується під час виконання для виконання запитів аутентифікації. У моєму випадку ключ повинен існувати в програмі у файлі конфігурації або в самому коді. Це не проблема, коли я створюю і публікую з однієї машини. Однак, коли ми кидаємо контроль джерел у суміш, справи ускладнюються.

Оскільки я дешевий ублюдок, я вважаю за краще скористатися послугами безкоштовного контролю джерел, такими як TFS у хмарі або GitHub. Це залишає у мене невелику головоломку:

Як я можу зберегти своє тіло недоторканим, коли в моєму коді є ключі API, а мій код доступний у загальнодоступному сховищі?

Я можу придумати кілька способів вирішити це, але жоден із них не задовольняє.

  • Я міг видалити всю приватну інформацію з коду та відредагувати її назад після розгортання. Це було б дуже сильним болем (я не буду деталізувати багато способів), і це не варіант.
  • Я міг би це зашифрувати. Але оскільки я маю це розшифрувати, кожен із джерелом міг зрозуміти, як це зробити. Безглуздо.
  • Я міг би заплатити за контроль над приватними джерелами. LOL j / k витрачати гроші? Будь ласка.
  • Я можу використовувати мовні функції для відокремлення чутливої ​​інформації від решти мого джерела і тому зберігати її від контролю джерела. Це я зараз роблю, але це можна було легко викрутити, помилково перевіривши в секретному файлі.

Я дійсно шукаю гарантований спосіб переконатися, що я не поділяюсь з приватними особами зі своїм світом (за винятком Snapchat), який буде працювати безперебійно через розробку, налагодження та розгортання, а також бути надійним. Це абсолютно нереально. То що реально я можу зробити?

Технічні деталі: VS2012, C # 4.5, управління джерелом буде або TF-послугою, або GitHub. В даний час використовується частковий клас для розділення чутливих клавіш на окремий файл .cs, який не буде додано до керування джерелом. Я думаю, що GitHub може мати перевагу, оскільки .gitignore може бути використаний, щоб переконатися, що файл часткового класу не зареєстрований, але я це вже накрутив. Я сподіваюся на "о, поширене питання, ось як ви це робите", але, можливо, мені доведеться вирішити "те, що не смокче стільки, скільки може",: /


6
Ви можете переконатися, що файл конфігурації, що містить ваш ключ API, не знаходиться в керованому джерелом каталозі, що унеможливить його перевірку в першу чергу.
Давид Сергій

22
BitBucket.org має необмежену кількість приватних сховищ. Безкоштовно. І імпортер сховища gitHub (зберігає історію)
Роб ван дер Веер

4
@Dainius Я не довіряю своїм розробникам, тому що я їх знаю. Інтимно. Насправді я принаймні інтимний із собою ... ні, я дозволю цьому брехати. Але я знаю, як легко викрутити і як важко буде вичистити історію згаданого прокручування.
Буде

15
@Dainius: Так. Я переглядаю кожного персонажа, який кодує моя команда. Серйозно. Я не маю вибору. Я не можу кодувати із зав'язаними очима. Принаймні, не надійно. Але я це роблю, бо я - моя команда. Я Я в TEAM. Є один розробник, і це я. Я його. Так. Я той хлопець, який зіб'є це, якщо він не зробить це правильно. Я.
Буде

3
Чому ви намагаєтесь в першу чергу скомпілювати ключ до коду? Зазвичай це потрібно помістити у файл конфігурації.
Стипендіати Дональ

Відповіді:


128

Не вкладайте у свій код секретну інформацію. Помістіть його у файл конфігурації, який читається вашим кодом при запуску. Файли конфігурації не повинні ставитись на контроль версій, якщо вони не є "заводськими налаштуваннями", і тоді вони не повинні мати приватної інформації.

Дивіться також питання управління версіями та особистий файл конфігурації, як зробити це добре.


8
@RobertHarvey, просто не перекладаючи його на контроль версій, додаючи правило ігнорування, коли це необхідно. Кожен, хто використовує програмне забезпечення, повинен створити власний файл конфігурації за допомогою власного ключа API.
Філіп

10
Отже, коли ви переходите до створення та створення дистрибутива свого програмного забезпечення, як ви впевнені, що воно постачається з файлом конфігурації? Якщо у вас є якийсь файл із розумними за замовчуванням, зазвичай не розумно очікувати, що ваш користувач пройде процес створення конфігураційного файла.
Томас Оуенс

4
Що ж, заводські налаштування - це одна частина, "інсталятори" або "майстри першого запуску" - ще одна
johannes

6
Якщо багато користувачів мають власну установку, чи не повинні вони створювати та використовувати власний ключ API? Кілька сайтів / установок за допомогою одного ключа, мабуть, погана ідея. Якщо це лише одна установка, то використання файлу конфігурації не є великим клопотом.
Майк Веллер

10
@ Якщо ви не зможете цього зробити через непрактичність деталей реалізації, то я б сказав, що у вас просто немає належного інструментарію для розгортання. Розгортання за допомогою некомерційного секретного конфігураційного файлу повинно бути абсолютно безболісним. Я не можу запропонувати вам конкретних порад, оскільки живу в екосистемі Рубі, а не на C #. Але люди Рубі, як правило, використовують Capistrano для автоматизованих розгортань. Я впевнений, що C # також має свій інструмент для автоматизованого розгортання, і це повинно полегшити процес.
Бен Лі

29

Ви можете розмістити всі приватні / захищені ключі як змінні системного середовища. Ваш файл конфігурації виглядатиме так:

private.key=#{systemEnvironment['PRIVATE_KEY']}

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

private.key=A_DEVELOPMENT_LONG_KEY

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

Як щодо розміщення цих змінних оточуючих середовищ на вашому сервері збірки перед відправкою в пряме середовище? Таким чином, ви будете готові до створення ресурсних / конфігураційних файлів.
Іоанніс Цикас

Сервер збирання - це машина розробки, тому я переживаю, щоб ця інформація була випадково перевірена в контролі джерел.
Буде

Проблема з цим може полягати в тому, що середовище читає кожен сервер.
JasonG

Користувачі користувача читають тільки користувач або root. (Стародавні Linux та AIX цього не робили)
Ніл МакГуйган

27

Pure Git шлях

  • .gitignore включений файл із приватними даними
  • Використовуйте місцевого відділення, в якому ви замінюєте TEMPLATEзDATA
  • Використовуйте фільтри розмазання / очищення, в яких сценарій (локального) фільтра виконує двосторонню заміну TEMPLATE<->DATA

Меркурійський шлях

  • MQ-патч (а) на верхній частині манекена коду, який замінить TEMPLATEз DATA(ревізій є відкритими, пластир приватний)
  • Розширення ключових слів зі спеціально розробленими ключовими словами (розширено лише у вашому робочому каталозі )

СКМ-агностический спосіб

  • Замініть ключові слова як частину процесу складання / розгортання

Гммм ... Порада з git хороша, а ваша агностична порада дає мені гарну ідею ... Я можу використовувати події побудови, щоб ввести файл у процес публікації, а потім видалити його, допомагаючи гарантувати, що він не буде бути випадково додані в систему управління ..
буде

7
Ні, ні і ще раз - ні! ігнорування файлів добре для додавання дуже специфічних налаштувань для складання процесу чи чогось іншого, але воно не повинно використовуватись для зберігання захищених даних. Не зберігайте захищені дані в РЕПО, навіть якщо ви їх ігноруєте.
shabunc

11
@shabunc - RTFM! Проігнорований файл не зберігається в репо
Lazy Badger

9
@LazyBadger - я добре знаю, що це ігнорується. Я також знаю, що, перебуваючи в репо, завжди є ймовірність, що хтось ніколи не помилково додасть це до репо. Деякі зовнішні конфігураційні шляхи набагато краще
shabunc

4
@shabunc - хороший момент щодо збереження конфігурації від шляху до SCM. Ось чому, наприклад, Postgres дозволяє обходити перевірку паролів, вводячи пароль у файл. Але вони вимагають, щоб файл пароля було введено у ~ / .pgpass - що, мабуть, не є місцем, яке дуже зручно перевірити в контролі джерела. Вони знають, що для автоматизації вони повинні дати тобі пістолет, але вони наполегливо працюють, щоб не застрелити себе в ногу.
Стів Мідглі

14

Я вкладаю секрети в зашифровані файли (файли), які я потім фіксую. Фраза пропуску надається під час запуску системи або вона зберігається у невеликому файлі, який я не ввожу. Приємно, що Emacs весело керує цими зашифрованими файлами. Наприклад, файл emacs init включає: (завантажувати "secrets.el.gpg"), який просто працює - підказуючи мені пароль для тих рідкісних занять, коли я запускаю редактор. Я не переживаю за те, щоб хтось порушив шифрування.


3
Це чудове рішення - я здивований, що у вас немає більше голосів. Я працюю з компанією, яка займається даними студентів, яка федерально регулюється у США, тому вони повинні бути дуже обережними з обліковими даними та секретами. Вони також є великою компанією, тому їм потрібно використовувати SCM для облікових даних, щоб ІТ могли їх знайти / керувати після того, як engr будує їх. Ваше рішення саме те, що вони роблять. Вони мають дешифрувати файли ключів, які містять ключі розшифрування для dev / staging / prod / etc (один файл для кожного). Потім всі секрети шифруються і перевіряються у файли. Файли дешифрування використовуються для отримання їх у кожному середовищі.
Стів Мідглі

7
Ну, у певному сенсі шифрування секрету (ключ API в цьому випадку) лише зміщує проблему від не введення секретних даних до не введення пропущеної фрази (яка тепер стає секретними даними ). Але, звичайно, просити його при запуску системи - хороший варіант.
siegi

Мені подобається це рішення. Тип зашифрованого файлу, який ви здійснюєте, може бути файлом KeePass. Це буде запис для кожного середовища, використовуючи notesполе для зберігання вмісту .env-файлу. Кілька місяців тому я написав інструмент, який може прочитати файл зберігання та створити .env-файл, використовуючи notesполе запису. Я думаю додати функцію, щоб я міг робити require('switchenv').env()у верхній частині програми Node.js і створювати змінні process.env на основі запису, який відповідає NODE_ENV або щось подібне. -> github.com/christiaanwesterbeek/switchenv
Крістіан Вестербек

14

Це дуже специфічно для Android / Gradle, але ви можете визначити ключі у вашому глобальному gradle.propertiesфайлі, розташованому в user home/.gradle/. Це також корисно, оскільки ви можете використовувати різні властивості залежно від buildType або смаку, тобто API для розробника та інший для випуску.

gradle.properties

MY_PRIVATE_API_KEY=12356abcefg

build.gradle

buildTypes {
        debug{
            buildConfigField("String", "GOOGLE_VERIFICATION_API_KEY", "\"" + MY_PRIVATE_API_KEY +"\"")
            minifyEnabled false
            applicationIdSuffix ".debug"
            }
        }

У коді ви посилаєтесь так

String myAPI = BuildConfig.GOOGLE_VERIFICATION_API_KEY;

BuildConfig перекладається у відповідний вихідний файл, тому проста інверсна інженерія на вашій apk розкриє всі ті ключі та секрети, які ви вкладете в BuildConfig
Дмитро Лівотов

1
Дійсно, дійсний пункт. Але питання полягало у тому, як утримати ключі api від вихідного коду, а не бінарного.
scottyab

11

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

Мобільний веб-додаток

Для Android / iPhone пристрій повинен запитувати КЛЮЧ у власної веб-служби під час першого запуску програми. Потім ключ зберігається у безпечному місці. Якщо ключ буде змінений або скасований видавцем. Ваша веб-служба може опублікувати новий ключ.

Розміщений веб-додаток

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

Опублікований вихідний код

Ви зберігаєте свій вихідний код у загальнодоступному сховищі, але не в KEY. У конфігурації файлу ви додаєте сюди рядки * клавіша місця * . Коли розробник використовує ваш вихідний код, він робить копію sample.cfgфайлу і додає свій власний ключ.

Ви не зберігаєте свій config.cfgфайл, який використовується для розробки або виробництва у сховищі.


4
Це питання задає питання, як це зробити ні, це абсолютно НЕ. Справа в тому, що ці ключі потрібно використовувати за кодом, тому до них можна отримати доступ за кодом, а це зазвичай означає через код або файли конфігурації, які, якщо вони не є у вихідному документі разом, вони принаймні близькі і можуть випадково опинитися в джерело. На жаль, розміщений веб-додаток є безглуздим. Вам не потрібно було подавати заявку на ключ api, щоб увійти в StackOverflow через ваш (гіпотетичний) facebook-акаунт. Ключовим словом тут є масштабне надмірне спрощення, яке не працюватиме в розробницьких середовищах, як описано в запитанні.
Чи буде

Я правильно відповів на питання, як і багато інших. Той факт, що ви не прийняли жоден з них, означає, що ви не розумієте, як працювати з цими ключами.
Реакційний

7
Тоді як ми захищаємо веб-службу видачі ключів? Використовуєте інший ключ?
Цзяндже Чжан

Дітто, що сказав @JianggeZhang - це небезпечна порада
Девід К. Хесс

5

Використовуйте змінні середовища для секретних речей, які змінюються для кожного сервера.

http://en.wikipedia.org/wiki/Environment_variable

Як їх використовувати, залежить мова.


3
Безпека через невідомість для багатьох не рекомендується. Чи хотіли б ви детальніше пояснити свою відповідь?

2
Це не незрозуміло, змінні середовища доступні лише тому користувачеві, який ви їх додали, тому всі ваші облікові дані мають однаковий захист контексту користувача, у якому працює ваш додаток. Я оновив відповідь, щоб включити поняття змінних середовища. Це більш зрозуміло?
Філіпе Джусті

4

Я думаю, це питання, з яким у когось виникли проблеми.

Ось я використав робочий процес, який може працювати для вас. Він використовує .gitignore з поворотом:

  1. Всі файли конфігурації переходять у спеціальну папку (без конфігураційних файлів без вибірки - необов'язково)
  2. Усі файли конфігурації включені у .gitignore, щоб вони не оприлюднили
  3. Налаштуйте сервер gitolite (або ваш улюблений сервер git) на приватній коробці
  4. Додайте репо з усіма конфігураційними файлами на приватному сервері
  5. Додайте скрипт для копіювання конфігураційних файлів у спеціальну папку в основній репортажі (необов’язково)

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

Ви все ще отримуєте всі цукерки GitHub, діліться своїм кодом зі світом, і конфіденційні дані ніколи не є головним репо, тому вони не публікуються. Вони все ще є лише потягом та копією від будь-якої системи розгортання.

Я використовую коробку 15 $ на рік для приватного сервера git, але ви також можете налаштувати його вдома, відповідно до вимоги chepskate ;-)

PS: Ви також можете використовувати підмодуль git ( http://git-scm.com/docs/git-submodule ), але я завжди забуваю команди, тому швидкі та брудні правила!


2

Використовуйте шифрування, але вкажіть головний ключ при запуску, як пароль на консолі, у файлі, який може читати лише користувач процесу, або з наданого системою сховища ключів, як брелок Mac OS або Windows Key Store.

Для безперервної доставки вам потрібно буде десь записати різні ключі. Конфігурація має бути відмежована від коду, але має сенс тримати її під контролем редагування.


1

3 стратегії, ще не згадані (?)

Під час заїзду або попередньої реєстрації VCS у гачку

  • пошук рядків з високою ентропією, приклад- виявлення-секрети
  • regex пошук добре відомих ключових шаблонів API. Приклади клавіш AKIA * AWS - приклад, git-secrets - це один із інструментів, заснований на цьому. Також імена змінних на зразок "пароль" з постійним призначенням.
  • шукати відомі секрети - ви знаєте свої секрети, шукайте їх текст. Або скористайтеся інструментом, я написав це підтвердження концепції .

Стратегії, вже згадані

  • зберігати у файлі поза вихідного дерева
  • є у вихідному дереві, але скажіть VCS ігнорувати його
  • змінні середовища - це варіація зберігання даних поза деревом-джерелом
  • просто не дайте цінних секретів розробникам

0

Не тримайте приватну інформацію поза контролем джерела. Створіть для завантаження не завантажений за замовчуванням і нехай ваш VCS ігнорує справжній. Ваш процес встановлення (будь то керівництво, налаштування / збирання чи майстер) повинен керувати створенням та заповненням нового файлу. Необов’язково змінюйте дозволи на файл, щоб переконатися, що його може прочитати лише потрібний користувач (веб-сервер?)

Переваги:

  • Не передбачає, що організація розвитку == виробнича особа
  • Не передбачає, що всі співпрацівники / рецензенти коду довіряють
  • Запобігайте легким помилкам, не допускаючи контролю версій
  • Легко автоматизувати встановлення з власною конфігурацією для QA / build

Якщо ви вже робите це і випадково перевіряєте це, додайте його до свого проекту .gitignore. Це зробить неможливим знову.

Навколо є багато безкоштовних хостів Git, які надають приватні сховища. Хоча вам ніколи не слід вносити версії своїх облікових даних, ви можете бути дешевими і мати приватні репости теж. ^ _ ^


-2

Замість того, щоб ключ OAuth зберігався як вихідні дані скрізь, чому б не запустити рядок через якийсь алгоритм шифрування і не зберегти його як солений хеш? Потім використовуйте файл конфігурації, щоб відновити його під час виконання. Таким чином ключ ніде не зберігається, чи він зберігається у вікні розробки, чи на самому сервері.

Ви навіть можете створити API таким чином, що ваш сервер автоматично генерує новий засолений і хешований ключ API на основі запиту, таким чином навіть ваша команда не може бачити джерело OAuth.

Редагувати: Можливо, спробуйте Бібліотеку криптовалют Стенфорда , це дозволяє зробити досить безпечне симетричне шифрування / дешифрування.


1
Хеши, як правило, суть одне із способів. Існують симетричні алгоритми шифрування, які б робили так, як ви пропонуєте.

3
Чувак, ти не можеш розшифрувати (легко) хеш. У цьому вся суть хешей. Це для ME, який споживає чужий API, і вони присвоюють мені секретний ключ. Моє хешування воно гарантує (якщо я не вибираю поганий альго і не ламаю його кожен раз), що я не можу використовувати їх API.
Буде
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.