Получите сертификат X509 от Azure Keyvault для использования в вызове REST - PullRequest
0 голосов
/ 25 марта 2020

Я пытаюсь получить сертификат от Azure Keyvault, а затем использовать его для вызова REST API, для которого требуется сертификат для его аутентификации.

Я попытался сделать это локально - у меня есть файл .pfx на диске, я загружаю его в байтовый массив, а затем создаю из него свой сертификат:

X509Certificate2 x509 = new X509Certificate2(File.ReadAllBytes(path), password);

, а затем использую этот сертификат в RestSharp для выполнения моего вызова REST:

IRestClient client = new RestClient(url);
client.ClientCertificates = new X509CertificateCollection { x509 };

var request = new RestRequest(lastUrlPart, Method.GET);
request.AddHeader("Cache-Control", "no-cache");
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");

IRestResponse response = client.Execute(request);

if (response.IsSuccessful)
{
    // read out the response and process it
}

работает как брелок.

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

Я нашел этот код для извлечения сертификата из Keyvault:

var azureServiceTokenProvider = new AzureServiceTokenProvider();

var kv = new KeyVaultClient(async (authority, resource, scope) =>
                                        {
                                            var authContext = new AuthenticationContext(authority, TokenCache.DefaultShared);
                                            var clientCred = new ClientCredential(clientAppId, clientSecret);
                                            var result = await authContext.AcquireTokenAsync(resource, clientCred);

                                            if (result == null)
                                            {
                                                throw new InvalidOperationException("Failed to obtain the JWT token");
                                            }

                                            return result.AccessToken;
                                        });

string certIdentifier = "https://mykeyvault.vault.azure.net/certificates/Certificate-TEST/14753af7586445fe9d57efa136ac090c";

var vaultCertificate = kv.GetCertificateAsync(certIdentifier).GetAwaiter().GetResult();

Это также работает - я могу получить доступ к keyvault с помощью своего идентификатора приложения, и Я могу получить сертификат из keyvault, и отпечаток X.509 действителен - но теперь это CertificateBundle из пространства имен Microsoft.Azure.KeyVault.Models - как мне "преобразовать" это в "обычный" объект X509Certificate2 так что я могу использовать его для вызова REST?

Я пробовал несколько вещей, например

X509Certificate2 x509 = new X509Certificate2(vaultCertificate.Cer);

, но ничего не работает - когда я выполняю вызов REST, я получаю HTTP 403 - Запретная ошибка назад ....

Чего мне не хватает ?? Как я могу получить сертификат от Azure Keyvault в формате, который можно использовать для аутентификации при последующем вызове REST ??

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Конечно - сразу после того, как я отправил этот вопрос, я наткнулся на решение ....

Этот пост в блоге Мэтта Смолла объясняет это в мельчайших деталях (и с очень хорошим и рабочие примеры кода тоже).

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

Вам нужно получить сертификат как секрет , а затем декодировать его с помощью base64 - тогда вы получите все необходимые биты и вызов REST работает.

GOSH !! Почему это так чертовски запутанно ?? Почему в вызове GetCertificateAsync не может быть просто параметр includePrivate: bool, чтобы сообщить Keyvault, что вам нужны только публичные c и закрытые части вашего сертификата?

Вы храните сертификат - но чтобы получить его, вам нужно получить секрет .... это просто неправильно и нарушает Basi c Принцип Наименьшего Сюрприза! MS , если вы слушаете - этот API действительно требует немного больше работы, чтобы сделать его более доступным для новичка Azure devs !!

И PS: это, конечно, также означает, что пользователь / личность вы используете для доступа к keyvault теперь необходимы разрешения для чтения секретов, а не только сертификатов .....

0 голосов
/ 25 марта 2020

Попробуйте следующий код:

var cert = kvc.GetCertificateAsync(baseUrl, "Demo").ConfigureAwait(false).GetAwaiter().GetResult();
var cert_content = cert.Cer;
X509Certificate2 x509 = new X509Certificate2(cert_content);

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

...