如何在没有kubeconfig文件的情况下为C# Kubernetes客户端启用TLS验证?

fnatzsnv  于 2023-04-05  发布在  Kubernetes
关注(0)|答案(1)|浏览(220)

我希望C#代码连接到K8s集群,现在只列出命名空间。我尝试了以下C#代码,并连接到Kubernetes集群,但它只在“SkipTlsVerify = true”时才有效。当我将SkipTlsVerify设置为false时,我得到以下错误:
Unhandled exception: k8s.Exceptions.KubeConfigException: A CA must be set when SkipTlsVerify === false
我不想跳过TLS验证。如何向C# Kubernetes客户端提供必要的CA信息以启用TLS验证?
我不想使用BuildConfigFromConfigFile()。这些都不能访问文件系统来读取或写入文件。现在我只能使用局部变量
我一开始尝试了这个,它工作正常,但它跳过了TLS验证:

var contextName = "mycontext, i copied this from my kubeconfig file"
        var server = "https://...*** copied from 'server' in kubeconfig file *** "

        var config = new KubernetesClientConfiguration()
        {
            Host = server,
            AccessToken = accessToken,
            SkipTlsVerify = true,
        };
        var client = new Kubernetes(config);
        var namespaces = client.CoreV1.ListNamespace();
        foreach (var ns in namespaces)
        {
            Console.WriteLine(ns.Name());
        }

我也尝试了下面的代码,得到了相同的错误消息结果。下面的代码可以工作,除非config.SkipTlsVerify设置为false。内部的SkipTlsVerify没有影响,但外部的SkipTlsVerify会影响结果。我假设“ClientCertificateKeyData”C#字段与我的kubeconfig文件中的“client-key-data”匹配。

var clientCertificateData = "*** copied and pasted from client-certificate-data in kube-config ****";
        var clientKeyData = "*** copied from client-key-data in kube-config ****";
        var certificateAuthorityData = "...copied from certificate-authority-data in kube-config"
        var config = KubernetesClientConfiguration.BuildConfigFromConfigObject(new K8SConfiguration
        {
            ApiVersion = "v1",
            Clusters = new List<Cluster>
            {
                new()
                {
                    ClusterEndpoint = new ClusterEndpoint
                    {
                        CertificateAuthorityData = certificateAuthorityData,
                        Server = server,
                        //SkipTlsVerify = true // This one has no effect. I still get the same 
                                               //error even when setting this to true
                    },
                    Name = contextName
                }
            }
        }, masterUrl: server); // I think it's a little strange that I need to put in server here  
                               // If I omit masterUrl, i get the error 
                               //"k8s.Exceptions.KubeConfigException: 
                               // Cannot infer server host url either from context or masterUrl"
        //config.SkipTlsVerify = true;  // uncommenting this makes it work
        config.Host = server;
        config.AccessToken = accessToken;
        config.ClientCertificateData = clientCertificateData;
        config.ClientCertificateKeyData = clientKeyData; // I assume this line is supposed to be client-key-data from the kubeconfig?
        var client2 = new Kubernetes(config);
        var namespaces2 = client2.CoreV1.ListNamespace();
        foreach (var ns in namespaces2)
        {
            Console.WriteLine(ns.Name());
        }
egdjgwm8

egdjgwm81#

请原谅我生 rust 的dotnet,我主要是一个python程序员。这个答案主要是基于www.example.com的代码https://github.com/kubernetes-client/csharp/issues/621#issuecomment-843584577
因此,该算法可以归结为:
1.创建名为config的KubernetesClientConfiguration,就像您已经做的那样
1.如果要使用base64编码的certificate-authority-data字符串,请从该字符串中提取CA证书
1.从该字符串创建X509 Certificate 2
1.创建X509 Certificate 2Collection,包含以前的X509 Certificate 2
1.将此X509 Certificate 2Collection添加为config.SslCaCerts
这里是我的测试,我的集群使用基于证书的认证而不是令牌,所以配置对象有点不同,你应该只使用accessToken。构建最新的mcr.microsoft.com/dotnet/sdk镜像。

InvestigateX509.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="KubernetesClient" Version="5.0.5" />
  </ItemGroup>

</Project>

InvestigateX509.cs

namespace InvestigateX509
{
    using System;
    using System.Security.Cryptography.X509Certificates;
    using k8s;

    class Program
    {

        static void Main(string[] args)
        {
            var server = "https://YOUR_HOST:6443";
            var certificateAuthorityData = "YOUR_BASE64_ENCODED_certificate-authority-data_FROM_KUBECONFIG";
            var clientCertificateData = "YOUR_BASE64_ENCODED_client-certificate-data_FROM_KUBECONFIG";
            var clientCertificateKeyData = "YOUR_BASE64_ENCODED_client-key-data_FROM_KUBECONFIG";
            var myNamespace = "ingress-nginx";

            var config = new KubernetesClientConfiguration()
            {
                Host = server,
                ClientCertificateKeyData = clientCertificateKeyData,
                ClientCertificateData = clientCertificateData,
            };
            byte[] decodedCertificateAuthorityData = Convert.FromBase64String(certificateAuthorityData);
            X509Certificate2 caCert = new X509Certificate2(decodedCertificateAuthorityData);
            X509Certificate2Collection caCollection = new X509Certificate2Collection();
            caCollection.Add(caCert);
            config.SslCaCerts = caCollection;
            var client = new Kubernetes(config);
            var pods = client.ListNamespacedPod(myNamespace);
            foreach (var pod in pods.Items)
            {
                Console.WriteLine($"Pod: {pod.Metadata.Name}");
            }
        }
    }
}

我的dotnet容器输出示例

root@84fc24bd18c2:/src/InvestigateX509# ./bin/Debug/net7.0/InvestigateX509 
Pod: ingress-nginx-1656961013-controller-97k82
Pod: ingress-nginx-1656961013-controller-h7dhm
Pod: ingress-nginx-1656961013-controller-lndjw

它打印了我的3节点集群中的所有3个来自ingress-nginx ingress的pod

相关问题