【问题标题】:Programmatically authenticate AKS with Azure AD and Managed Identity使用 Azure AD 和托管标识以编程方式对 AKS 进行身份验证
【发布时间】:2022-06-14 17:10:17
【问题描述】:

我是 AKS 和 Azure Identity 平台的新手。我有一个使用 Azure AD 集成的 AKS 群集。从具有用户分配的托管标识的 Azure VM 中,我尝试运行 C# 控制台应用程序以针对 Azure AD 进行身份验证,获取 kubeconfig 内容,然后使用 kubernetes 客户端执行一些列表操作。运行以下代码时,尝试执行列表操作时出现未经授权的错误。我已确保在集群访问角色中,用户分配的托管标识具有 Owner 角色。

代码执行以下操作:

  • 使用用户管理的标识 ID 创建 DefaultAzureCredential 实例
  • 将令牌从 DefaultAzureCredential 转换为 Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentials 的实例并进行身份验证
  • 获取经过身份验证的用户的 kubeconfig 内容
  • 从http://169.254.169.254/metadata/identity/oauth2/token获取访问令牌
  • 在 kubeconfig 上设置访问令牌并创建 Kubernetes 客户端的新实例
  • 尝试列出集群中的命名空间

我已经从 POST 以及 POST 中提取了信息。

我不确定TokenRequestContext的范围是否正确,以及oauth令牌请求的资源参数是否正确。

string userAssignedClientId = "0f2a4a25-e37f-4aba-942a-5c58f39eb136";
    var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId });

    var defaultToken = credential.GetToken(new TokenRequestContext(new[] { "https://management.azure.com/.default" })).Token;
    var defaultTokenCredentials = new Microsoft.Rest.TokenCredentials(defaultToken);
    var azureCredentials = new Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentials(defaultTokenCredentials, defaultTokenCredentials, null, AzureEnvironment.AzureGlobalCloud);
    var azure = Microsoft.Azure.Management.Fluent.Azure.Authenticate(azureCredentials).WithSubscription("XXX");

    var kubeConfigBytes = azure.KubernetesClusters.GetUserKubeConfigContents(
        "XXX",
        "XXX"
    );

    var kubeConfigRaw = KubernetesClientConfiguration.LoadKubeConfig(new MemoryStream(kubeConfigBytes));

    var authProvider = kubeConfigRaw.Users.Single().UserCredentials.AuthProvider;
    if (!authProvider.Name.Equals("azure", StringComparison.OrdinalIgnoreCase))
        throw new Exception("Invalid k8s auth provider!");

    var httpClient = new HttpClient();
    var token = string.Empty;
    using (var requestMessage =
                new HttpRequestMessage(HttpMethod.Get, $"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource={Uri.EscapeUriString("6dae42f8-4368-4678-94ff-3960e28e3630/.default")}&client_id={userAssignedClientId}"))
    {
        requestMessage.Headers.Add("Metadata", "true");

        var response = await httpClient.SendAsync(requestMessage);
        token = await response.Content.ReadAsStringAsync();

        Console.WriteLine(token);
    }

    var tokenNode = JsonNode.Parse(token);

    authProvider.Config["access-token"] = tokenNode["access_token"].GetValue<string>();
    authProvider.Config["expires-on"] = DateTimeOffset.UtcNow.AddSeconds(double.Parse(tokenNode["expires_in"].GetValue<string>())).ToUnixTimeSeconds().ToString();

    var kubeConfig = KubernetesClientConfiguration.BuildConfigFromConfigObject(kubeConfigRaw);
    var kubernetes = new Kubernetes(kubeConfig);

    var namespaces = kubernetes.CoreV1.ListNamespace();
    foreach (var ns in namespaces.Items)
    {
        Console.WriteLine(ns.Metadata.Name);
        var list = kubernetes.CoreV1.ListNamespacedPod(ns.Metadata.Name);
        foreach (var item in list.Items)
        {
            Console.WriteLine(item.Metadata.Name);
        }
    }

感谢任何帮助!

【问题讨论】:

标签: azure kubernetes azure-active-directory azure-aks


【解决方案1】:

尝试在令牌请求中使用不带“/.default”的资源。 所以应该是 resource=6dae42f8-4368-4678-94ff-3960e28e3630

【讨论】:

    猜你喜欢
    • 2021-12-23
    • 2021-08-16
    • 2018-11-14
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多