Перший урок: не друкуйте свої секрети в середній ілюстрації

Найкращий спосіб зберігати секрети у вашому додатку - це не зберігати секрети у вашому додатку

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

Якщо ви коли-небудь створювали додаток в Інтернеті, ви натрапили на боротьбу за збереження секретів (облікові дані бази даних, ключі api тощо) на своєму сервері.

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

Зберігання секретів у коді

# налаштування / instance_settings.py
STRIPE_API_KEY = '3ef8-843a-49dc-a34d' # Не кажи нікому! плз?

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

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

Зберігання секретів у навколишньому середовищі

stripe_api_key = os.environ ["STRIPE_API_KEY"]

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

Є ще деякі проблеми: проста неправильна конфігурація (наприклад, запуск виробничого сервера в режимі налагодження) або помилка безпеки може призвести до витоку всіх змінних оточення.

Зберігання секретів у базі даних

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

Використання служби синхронізації секретів

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

Зберігання секретів у коді…, але зашифровано

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

Чому це небезпечно?

Усі ці методи мають однакову характеристику; вони все ще включають в себе секрети на вашому сервері, і вони можуть витікати або вкрастись

Найгірший випадок

Уявіть такий сценарій. Зловмисник увірвався на ваш сервер, використовуючи вразливість в Apache. Потім він / вона починає пошук облікових даних і ключів API у вашому файлі конфігурації, вашому коді, оточенні. Якщо ваші секрети якимось чином приховані / зашифровані, зловмисник нічого не знайде. Але це не означає, що він / вона зупиниться на цьому. Використовуючи щось на зразок LiME, хакер все ще може переглядати пам’ять сервера, щоб витягти ці секрети.

Ми можемо зробити краще

Представляємо:

Безпечний доступ до сервісних даних, використовуючи аутентифікований IAM шлюз API як проксі ™

(Мені страшно знайти цікаві імена, і це не дуже торгова марка)

Огляд

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

Кажуть, картина вартує 1000 слів. ВИКЛИК ПРИЙНЯТО

Все-таки загубили? Розберемо це

По-перше, для цього нам потрібно використовувати рідний спосіб для екземплярів EC2 (або ECS Containers і Lambdas) для здійснення дзвінків до інших ресурсів AWS, тобто за допомогою ролей IAM.

По-друге, нам потрібно створити ресурс Rest API в шлюзі API. Є деякі конкретні конфігурації, які потрібно застосувати, щоб параметри тіла, заголовків та запитів могли бути передані. Крім того, нам потрібно змінити запит, щоб ми могли ввести цільові дані служби. Нарешті, ми повинні активувати секретну зброю: авторизацію на основі IAM.

Третій і останній крок полягає в підписанні URL-адреси перед викликом потрібних проксі-сервісів.

¿Que?

Для тих, хто не надто знайомий з технологіями, про які я нещодавно згадував, і все ще не знаю, про що це йдеться, ось порівняння до та після використання сервісного доступу без сертифікатів, використовуючи аутентифікований IAM шлюз API в якості проксі ™:

Я буду використовувати для цього демонстрацію відомих API GitHub та листоноші:

До (Прямий дзвінок на GitHub):

Після (виклик через проксі через шлюз API):

Я вже чую, як ти кажеш:

Ви сказали нам, що це менше даних, і я бачу ключ доступу, секретний ключ та маркер !!!

Це тому, що мій ноутбук не має секретної зброї. Після того, як ви це запустили та запустите на екземплярі EC2, ці тимчасові облікові дані безпеки будуть автоматично отримані з метаданих екземпляра. Якщо поняття тимчасових облікових даних вам нове, ось уривок із документації (моє наголос):

Додаток до екземпляра […] надає дозволи для дій та ресурсів, які ви визначили для ролі, через дані безпеки, пов’язані з роллю. Ці дані безпеки є тимчасовими, і ми повертаємо їх автоматично. Ми надаємо нові облікові дані щонайменше за п'ять хвилин до закінчення терміну дії старих даних.

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

Це величезне оновлення з точки зору безпеки

Помітні покращення безпеки:

  • Розробники тимчасових облікових даних ніколи не повинні обробляти
  • Вони запитуються програмно, тому не потрібно записувати їх у файл конфігурації
  • Якщо витік або викрадений, ці тимчасові облікові дані працюватимуть не більше години
  • Усі запити можна ввійти в CloudWatch для аудиту
  • Ви можете обмежити цільовий API за допомогою політики IAM

Остання точка відмітки особливо корисна при роботі з таким API, як GitHub, якому не вистачає тонкої моделі дозволів. Використовуючи наведену нижче політику IAM, я можу обмежити свій API лише дозволити метод GET лише в кінцевій точці / repos / PokaInc / test-github-api / issues.

{
    "Версія": "2012-10-17",
    "Заява": [
        {
            "Дія": [
                "Execute-api: Invoke"
            ],
            "Ресурс": [
                "arn: aws: Execute-api: us-east-1: 123456789010: w974f1rs6e / dev / GET / repos / PokaInc / test-github-api / issues"
            ],
            "Ефект": "Дозволити"
        }
    ]
}

Але зачекай, є ще більше!

Інші переваги використання шлюзу API як проксі

  • Статистика використання Це може бути корисно для виявлення тенденцій та запобігання обмеженню ставок від сторонніх послуг.
  • Ведення журналів. Якщо ввімкнено, ви можете мати докладні журнали кожного запиту, включаючи його походження та використовувані параметри.
  • Кешування. Виникли проблеми із затримкою або обмеженням ставок? За допомогою трьох рядків коду CloudFormation ви можете додати резервний кешбек у ваш проксі.
  • Місцевий розвиток. Розробники, які користуються користувачем IAM на локальному рівні, можуть отримувати доступ до проксі-сервісів безпосередньо замість того, щоб покладатися на жорсткі коди облікових даних на своєму комп’ютері.

На даний момент я припускаю, що вас продали за ідеєю, і ви хочете спробувати метод для себе.

Код

Зважаючи на те, що в Poka ми обладнані CloudFormation afi · cio · nados, я створив шаблон підтвердження концепції, доступний на GitHub.

Забезпечення

Щоб створити проксі, дотримуйтесь вказівок README.md.

Використання проксі

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

Розглянемо цей блок коду:

повернути AWSRequestsAuth (
      [...]
      ** boto_utils.get_credentials ()
)

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

Висновок

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

Печери (та їх вирішення)

  • Що робити, якщо я хочу проксі-сервер внутрішньої послуги, не доступної до Інтернету?

У поясненні може бути своя спеціальна публікація в блозі. Якщо коротко розповісти, ви можете надати VPC з увімкненою AWS Lambda як ціль вашого проксі-сервера API шлюзу. Lambda повинен буде передати заголовки, параметри запиту та тіло до внутрішньої служби, зібрати відповідь та повернути її до шлюзу API.

  • Це чудово працює з API REST, але що робити з послугами TCP, такими як реляційні бази даних або кеш-сервери?

Знову ж таки, це заслуговує на повну публікацію в блозі. Коротше кажучи, ми можемо створити мікро-сервіс (доступний через, ви вже здогадалися, IAT-аутентифікований шлюз API), який створить повноваження для потрібних послуг. Для прикладу: якщо мікро-сервіс запитує для облікових даних PostgreSQL, він може видавати команду CREATE ROLE з випадково згенерованим паролем. Крім того, роль може мати час існування, використовуючи властивість VALID UNTIL.

Альтернативи

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

  • http://engineering.nike.com/cerberus/
  • https://www.vaultproject.io/
  • https://docs.docker.com/engine/swarm/secrets/

Посилання на цю статтю:

http://blog.arkency.com/2017/07/how-to-safely-store-api-keys-in-rails-apps/
https://blog.rackspace.com/securing-application-secrets-with-ec2-parameter-store
https://www.envkey.com/
https://www.hashicorp.com/blog/Vault-announcement/
https://docs.docker.com/engine/swarm/secrets/
http://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html
http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html
http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html

Особлива подяка Tea Rudolf, Etienne Talbot, Simon-Pierre Gingras, Maxime Leblanc та Marilou Simard-Baril за виправлення (Так, мені потрібно стільки людей, щоб переглянути мою англійську) та дякую Джулі Доріон-Белангер за ілюстрації.

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