Azure - аутентификация консольного приложения с использованием альтернативы MSI

Я работаю над решением, которое в настоящее время выполняет код в Функциях Azure. Эти функции аутентифицируются для наших служб PaaS (Key Vault / Service Bus / Blob Storage и т. Д.) С использованием аутентификации MSI.

Код для аутентификации выглядит следующим образом:

// Connect to KeyVault in the context of the running code.
var tokenProvider = new AzureServiceTokenProvider();

var config = new ConfigurationBuilder().AddAzureKeyVault(
     keyvaultUri,
     new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(tokenProvider.KeyVaultTokenCallback)),
     new DefaultKeyVaultSecretManager())
  .Build();

Затем это позволяет мне безопасно подключаться к служебной шине, используя следующий код:

// Get ServiceBus connection settings.
config.GetSection("Messaging").Bind(ConfigSettings);    
var namespaceName = Regex.Match(ConfigSettings.ConnectionString, @"Endpoint=sb:\/\/([^.]*)", RegexOptions.IgnoreCase).Groups[1].Value;


var token = tokenProvider.GetAccessTokenAsync("https://management.core.windows.net/", string.Empty).Result;
var tokenCredentials = new TokenCredentials(token);

var client = RestClient.Configure()
        .WithEnvironment(AzureEnvironment.AzureGlobalCloud)
        .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
        .WithCredentials(new AzureCredentials(tokenCredentials, tokenCredentials, string.Empty, AzureEnvironment.AzureGlobalCloud))
    .Build();

// Authenticate against Service Bus.
ServiceBusNamespace = Azure.Authenticate(client, string.Empty)
    .WithSubscription(ConfigSettings.SubscriptionId)
    .ServiceBusNamespaces.List()
    .SingleOrDefault(n => n.Name == namespaceName);

Мы меняем наше решение так, чтобы вместо запуска функций в ASE мы собирались выполнять ту же операцию в консольном приложении (работающем в Linux). Очевидно, что MSI auth не будет работать в этом сценарии, поэтому я искал использовать AppId Service Priniple и AppSercret. Я устанавливаю принцип в AAD следующим образом:

введите здесь описание изображения

Этот код для использования AppId и AppSecret Принципов службы выглядит следующим образом:

    public async static Task<string> GetAccessToken(string tenantId, string appId, string appSecret)
    {
        var authenticationContext = new AuthenticationContext($"https://login.windows.net/{tenantId}");
        var credential = new ClientCredential(clientId: appId, clientSecret: appSecret);
        var result = await authenticationContext.AcquireTokenAsync(resource: "https://management.core.windows.net/", clientCredential: credential);

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

        return result.AccessToken;    
     }

НО для этого требуется, чтобы у меня были готовые к использованию AppId, AppSecret и TenantId. Я не хочу использовать AppSettings по очевидным причинам безопасности.

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

    var namespaceName = Regex.Match(connectionString, @"Endpoint=sb:\/\/([^.]*)", RegexOptions.IgnoreCase).Groups[1].Value;

    var tokenCredentials = new TokenCredentials(token);

    var client = RestClient.Configure()
        .WithEnvironment(AzureEnvironment.AzureGlobalCloud)
        .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
        .WithCredentials(new AzureCredentials(tokenCredentials, tokenCredentials, string.Empty, AzureEnvironment.AzureGlobalCloud))
        .Build();

    var serviceBusNamespace = Azure.Authenticate(client, string.Empty)
        .WithSubscription(subscriptionId)
        .ServiceBusNamespaces.List()
        .SingleOrDefault(n => n.Name == namespaceName);

    if (serviceBusNamespace == null)
    {
        throw new InvalidOperationException($"Couldn't find the service bus namespace {namespaceName} in the subscription with ID {subscriptionId}");
    }

Мой вопрос - кажется контрпродуктивным беспокоиться о безопасности, а затем сохранять необходимые поля конфигурации (AppId, AppSecret, TenantId) в config или Env Vars. Есть ли у меня другие варианты? Я не могу использовать KeyVault, если я не прошел аутентификацию, но, опять же, мне нужно, чтобы мой принцип обслуживания был аутентифицирован, прежде чем я смогу получить к нему доступ.

Кто-нибудь делал этот подход раньше? Может быть, принцип обслуживания - неправильный подход?

Заранее благодарим за любые указатели!


person Rob McCabe    schedule 28.08.2018    source источник
comment
Вы уверены, что не можете использовать MSI? В конечном итоге он использует конечную точку HTTP, доступную из среды выполнения (которую вы также можете использовать из Linux :))   -  person juunas    schedule 28.08.2018
comment
На самом деле нет, я нет! Я просто привык настраивать его через ASE, а не в коде. Есть хорошие примеры? Я не видел конкретных примеров кода для аутентификации с использованием msi из консольного приложения, к сожалению   -  person Rob McCabe    schedule 28.08.2018
comment
Это выглядит многообещающе: azure.microsoft.com / ru-ru / resources / samples /   -  person Rob McCabe    schedule 28.08.2018
comment
Вы также можете ознакомиться с моей статьей на MSI: joonasw.net/view/azure- идентификатор-управляемой-рекламой. Я упоминаю две переменные среды, которые он использует под капотом. Конечно, проблема в том, что вам нужно получить эти переменные среды ... И я не уверен, что ваше консольное приложение может их получить.   -  person juunas    schedule 28.08.2018
comment
Спасибо, Joonas, так что, если я установлю две переменные среды MSI_ENDPOINT и MSI_SECRET и запущу эти пару строк кода, он все равно будет работать для консольного приложения? Аккуратный! Откуда мне взять MSI_ENDPOINT и MSI_SECRET? (Я не настраивал это изначально) - спасибо !!!   -  person Rob McCabe    schedule 28.08.2018
comment
Ну .. Я не думаю, что это сработает, если вы их установите. MSI устанавливает их и использует секрет для аутентификации в конечной точке.   -  person juunas    schedule 28.08.2018
comment
Не уверен, как запустить ваш пример, тогда, если они должны быть в ENV VARS для приложения, и я не могу их установить :-) в любом случае спасибо   -  person Rob McCabe    schedule 28.08.2018
comment
MSI устанавливает их, поэтому, если они видны, вы можете использовать их. Если это не так, вы не можете его использовать и должны использовать настройки приложения для начальной загрузки аутентификации.   -  person juunas    schedule 28.08.2018


Ответы (1)


Согласно вашему описанию, вы не хотите хранить AppId в файле конфигурации и хотите использовать Service Principle для аутентификации.

Если это так, вы можете обратиться к статье juunas и использовать AzureServiceTokenProvider для аутентификации и продолжения того, что хотите.

Вы можете использовать следующий код, чтобы получить секрет хранилища ключей без использования AppId и AppSecret.

var azureServiceTokenProvider = new AzureServiceTokenProvider();

var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));

var scret = keyVaultClient.GetSecretAsync("https://xxxx.vault.azure.net", "xxxx").GetAwaiter().GetResult();
person Joey Cai    schedule 29.08.2018
comment
Приложение будет работать в Linux, а не в ASE, где мы можем настроить приложение для работы в контексте принципа обслуживания. Итак, чтобы получить этот контекст, мне нужно, чтобы принципы службы AppID / AppSecret аутентифицировались в качестве этого принципа при выполнении кода - или я неправильно понял? - person Rob McCabe; 29.08.2018
comment
Да, вам нужно получить AppId и AppSecret для аутентификации, так в чем вы сомневаетесь? - person Joey Cai; 29.08.2018
comment
Я сомневаюсь в показанном вами коде - поскольку вы не устанавливаете AppId / AppSecret в коде, он будет полагаться на контекст, который он запускает (AzureServiceTokenProvider ()). Что не сработает, когда мы выведем приложение из ASE. - person Rob McCabe; 29.08.2018
comment
Да, значит, вы хотите найти способ аутентификации в Linux, верно? - person Joey Cai; 29.08.2018
comment
Да вот и все @ joey-cai Я думал, что принцип обслуживания - это то, что нужно. У меня Azure WebJob вне ASE и в консольном приложении (ядро .net), которое я буду развертывать в Linux, но не хочу терять безопасность, встроенную в ASE. - person Rob McCabe; 29.08.2018