﻿# Як безпечно зберігати та використовувати секреті дані за допомогою Azure Key Vault

- Canonical URL: https://taraskovalenko.github.io/posts/azure-key-vault/
- Published: 2023-03-22
- Categories: .net, azure, security
- Tags: .net, ssl, tls, Azure, Azure Key Vault, Security

Під час розробки практично будь якого рішення, нам потрібно зберігати певні секретні дані. Це може буде як рядок підключення до БД з обліковими даними про користувача (логін/пароль), так і дані про платіжні системи. В кожному додатку це буде те що потрібно для виконання автоматизації тих чи інших задач.
Зазвичай, і це є небезпечно та погана практика, ці дані зберігаються в файлах налаштувань додатку, і (на жаль дуже часто) ці дані додають до систем контролю версій (git).
Чому це не правильно? - Перш за все вся команда розробників які працюють над додатком мають копію цих даних, коли та чи інша людина звільнюється ви не можете бути впевненими що ваші секретні дані не будуть використані або розповсюджені. Звісно ви може замінити секретні дані на нові і попередні будуть не актуальні, але це займає час і також інколи може бути не надто простим процесом, якщо у вас є залежності в інших додатках.
Також, якщо вихідний код вашого додатку буде викрадено, всі ваші секретні дані, а також персональні дані користувачів які його використовують будуть під загрозою.

## Як зберігати секретні дані безпечно?
---
Існує багато механізмів які забезпечують безпечне зберігати секретних даних, це може бути змінні середовища (Environment variables, якщо ми говоримо про .net), певні механізми шифрування та розшифровування, але як на мене, одним із найпростіших варіантів, а особливо якщо ви використовуєте Azure, є Azure Key Vault.
Azure Key Vault - це хмарна сервіс, в якому ви можете безпечно зберігати паролі, ключі, сертифікати і всю необхідну секретну інформацію.

Для того щоб зберегти дані в Azure Key Vault його потрібно створити, для цього перейдіть на портал [Azure](https://portal.azure.com/){:target="_blank"}, натисніть "створити новий ресурс" і виберіть "Key Vault", заповніть обов'язкові поля та натисніть створити.

![kv-create](/assets/img/posts/2023-03-22/kv-create.png){: width="1086" height="542"}

За декілька секунд ваш ресурс буде створено і ви зможете почати його використовувати.
Для збереження секретних даних у вигляді ключ -> значення, перейдіть в розділ `Secrets` та натисніть `Generate/Import`.

![kv-secret-1](/assets/img/posts/2023-03-22/kv-secret-1.png){: width="640" height="480"}
![kv-secret-2](/assets/img/posts/2023-03-22/kv-secret-2.png){: width="640" height="480"}

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

І так, ми створили новий Key Vault ресурс та додали новий секретний запис.

## Як отримати дані з Key Vault у нашому додатку?
---
Для того щоб почати використовувати дані з Key Vault у .net додатку, який буде розгорнуто і доступний для користувачів, нам потрібно створити в `Azure Active Directory` новий додаток який буде мати доступ до сервісу де знаходяться наші секретні дані.
Щоб це зробити перейдіть в розділ `Azure Active Directory -> App registrations` та натисніть створити нову реєстрацію.
У вікні що появиться нам достатньо вказати імя і натиснути кнопку "зареєструвати".
![ad-app-1](/assets/img/posts/2023-03-22/ad-app-0.png){: width="640" height="480"}

Після успішного створення нового Active Directory додатку нам потрібно додати SSL сертифікат, і з допомогою сертифікату ми будемо перевіряти чи можемо ми отримати доступ до секретних даних які будуть знаходитися у нас в Azure Key Vault.

> Як створити сертифікат ви можете прочитати у моїй попередній статті [Використання TLS/SSL сертифікатів в .net додатку для Azure App Service](/posts/configure-ssl-certificate-in-code/)
{: .prompt-info }

![ad-app-1](/assets/img/posts/2023-03-22/ad-app-1.png){: width="640" height="480"}

Сертифікат потрібний для підтвердження того, що додаток який хоче отримати дані з Key Vault це дійсно наш додаток і він має встановлений сертифікат (_Як додати сертифікат до Azure App Service ви також можете подивитися в попередній статті_).

І так у нас є новий зареєстрований Active Directory App, для того щоб отримати дані з Key Vault нам буде потрібна ще інформація про цей додаток.
Для початку нам потрібний `Thumbprint` нашого сертифікату, ви повинні його побачити відразу після додавання його до App Active Directory, а також нам потрібні `Application (client) ID` та `Directory (tenant) ID`, для цього перейдіть в розділ "Overview".

![ad-app-2](/assets/img/posts/2023-03-22/ad-app-2.png){: width="640" height="480"}

Щоб дозволити нашій Active Directory App отримувати секретні дані з Azure Key Vault, потрібно створити нову політику доступу.

Поверніться до нашого створеного Azure Key Vault, перейдіть в розділ "Access policies" та натисніть "Створити". У новому вікні виберіть з спадного списку `Key & Secret Management` та натисніть "Далі". На наступному крокові створення політики доступу виберіть нашу Active Directory App. Перейдіть на останній крок створення та натисніть "Створити".

> Key & Secret Management - надасть доступ не тільки на читання але також на модифікацію, видалення. Якщо вам це не потрібно тоді виберіть тільки необхідні дозволи.
{: .prompt-warning }

![kv-access-0](/assets/img/posts/2023-03-22/kv-access-0.png){: width="640" height="480"}
![kv-access-1](/assets/img/posts/2023-03-22/kv-access-1.png){: width="640" height="480"}

Ми налаштували політику доступу і тепер можемо написати код який буде отримувати доступ до наших секретних даних.

## Написання коду
---
Для роботі з Azure Key Vault нам потрібно встановити два NuGet пакети:
```bash
dotnet add package Azure.Identity
dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
```
Azure.Identity - надає змогу працювати з Active Directory, у нашому випадку автентифікація.
Azure.Extensions.AspNetCore.Configuration.Secrets - безпосередньо робота з Azure Key Vault.

Наступним кроком змінимо `appsettings.json` файл та додамо інформацію про Azure Key Vault та AD App.

```json
{
  "KeyVault": {
    "Vault": "taras-kv",
    "TenantId": "e4e08b73-e6c2-4c56-8cc0-b3813a030420",
    "ClientId": "36fc9800-c4b3-46a7-8f7e-b245a38ddc04",
    "Thumbprint": "67F592325E454FDE9B43FFEA5AFB6168"
  }
}
```

`appsettings.json` містить інформацію таку як назва нашого Key Vault, `Application (client) ID` та `Directory (tenant) ID` нашого Active Directory App та `Thumbprint` сертифікату який ми створили та завантажили.

Тепер нам потрібно написати код який буде використовувати ці дані та завантажувати в секретні дані з Azure Key Vault.
Для цього нам потрібно викликати метод розширення `AddAzureKeyVault` для `IConfigurationBuilder`.

```cs
using System.Security.Cryptography.X509Certificates;
using Azure.Identity;

var builder = WebApplication.CreateBuilder(args);
var env = builder.Environment;

builder.Configuration.AddJsonFile($"appsettings.{env.EnvironmentName}.json");

var root = builder.Configuration;
builder.Configuration.AddAzureKeyVault(
    new Uri($"https://{root["KeyVault:Vault"]}.vault.azure.net/"),
    new ClientCertificateCredential(
        root["KeyVault:TenantId"],
        root["KeyVault:ClientId"],
        GetX509Certificate(root["KeyVault:Thumbprint"])
    )
);

var app = builder.Build();
app.Run();
```
> Реалізацію методу `GetX509Certificate` можна знайти у моїй попередній статті [Використання TLS/SSL сертифікатів в .net додатку для Azure App Service](/posts/configure-ssl-certificate-in-code/)
{: .prompt-info }

Що даний код виконує? - спочатку ми додаємо до конфігурації `appsettings.json` файл який містить інформацію про Key Vault та AD App. Формуємо `Uri` для Key Vault та створюємо екземпляр класу `ClientCertificateCredential` щоб автентифікуватися в Azure Active Directory за допомогою вказаного сертифіката.

> Сертифікат повинен бути встановленим на ваш ПК щоб ви отримали доступ до даних KV.
{: .prompt-info }

Даний підхід дозволяє нам зберігати секретні дані в захищеному середовищі Key Vault і тільки якщо ви маєте встановлений SSL сертифікат ви зможете зчитати з нього дані.

Але тут виникає наступна проблема, нам потрібно надати доступ до сертифікату всім розробникам і це знову ж таки проблема безпеки.
Щоб уникнути даної проблеми ми можемо модифікувати код таким чином, щоб усі хто працює з додатком використовували власний обліковий запис Azure і для цього нам достатньо змінити `ClientCertificateCredential` на `AzureCliCredential`.

```cs
var root = builder.Configuration;
builder.Configuration.AddAzureKeyVault(
    new Uri($"https://{root["KeyVault:Vault"]}.vault.azure.net/"),
    new AzureCliCredential()
);
```

Тепер, якщо ви спробуєте запустити ваш додаток система буде перевіряти чи ви увійшли в Azure з допомогою [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli){:target="_blank"}

```bash
az login
```

і відповідно доступ до Key Vault буде базуватися на ваших Azure дозволах.

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

Ми розібрали як створити Azure Key Vault сервіс, додати в нього запис та отримати цей запис з вашого додатку. Також як реалізувати механізм при якому не потрібно надавати доступ до SSL сертифікату усім розробникам проекту.

Якщо ви не хочете додавати до систем контролю версій інформацію яку ми додали до `appsettings.json`, а саме Key Vault імя, TenantId, ClientId та Thumbprint, тоді ви можете використовувати змінні середовища (Environment variables) і отримувати їх безпосередньо звідти, для прикладу - `Environment.GetEnvironmentVariable("Vault")`.

