Exemple #1
0
        public async Task GetToken()
        {
            var isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;
            var cmd       = Path.Combine(Directory.GetCurrentDirectory(), "assets", isWindows ? "mock-gcloud.cmd" : "mock-gcloud.sh");

            if (!isWindows)
            {
                System.Diagnostics.Process.Start("chmod", $"+x {cmd}").WaitForExit();
            }
            var sut    = new GcpTokenProvider(cmd);
            var result = await sut.GetAuthenticationHeaderAsync(CancellationToken.None);

            result.Scheme.Should().Be("Bearer");
            result.Parameter.Should().Be("ACCESS-TOKEN");
        }
        private void SetUserDetails(K8SConfiguration k8SConfig, Context activeContext)
        {
            if (string.IsNullOrWhiteSpace(activeContext.ContextDetails.User))
            {
                return;
            }

            var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(
                                                                 activeContext.ContextDetails.User,
                                                                 StringComparison.OrdinalIgnoreCase));

            if (userDetails == null)
            {
                throw new KubeConfigException($"User not found for context {activeContext.Name} in kubeconfig");
            }

            if (userDetails.UserCredentials == null)
            {
                throw new KubeConfigException($"User credentials not found for user: {userDetails.Name} in kubeconfig");
            }

            var userCredentialsFound = false;

            // Basic and bearer tokens are mutually exclusive
            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.Token))
            {
                AccessToken          = userDetails.UserCredentials.Token;
                userCredentialsFound = true;
            }
            else if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.UserName) &&
                     !string.IsNullOrWhiteSpace(userDetails.UserCredentials.Password))
            {
                Username             = userDetails.UserCredentials.UserName;
                Password             = userDetails.UserCredentials.Password;
                userCredentialsFound = true;
            }

            // Token and cert based auth can co-exist
            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificateData) &&
                !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKeyData))
            {
                ClientCertificateData    = userDetails.UserCredentials.ClientCertificateData;
                ClientCertificateKeyData = userDetails.UserCredentials.ClientKeyData;
                userCredentialsFound     = true;
            }

            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificate) &&
                !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKey))
            {
                ClientCertificateFilePath = GetFullPath(k8SConfig, userDetails.UserCredentials.ClientCertificate);
                ClientKeyFilePath         = GetFullPath(k8SConfig, userDetails.UserCredentials.ClientKey);
                userCredentialsFound      = true;
            }

            if (userDetails.UserCredentials.AuthProvider != null)
            {
                if (userDetails.UserCredentials.AuthProvider.Config != null &&
                    (userDetails.UserCredentials.AuthProvider.Config.ContainsKey("access-token") ||
                     userDetails.UserCredentials.AuthProvider.Config.ContainsKey("id-token")))
                {
                    switch (userDetails.UserCredentials.AuthProvider.Name)
                    {
                    case "azure":
                    {
                        var config = userDetails.UserCredentials.AuthProvider.Config;
                        if (config.ContainsKey("expires-on"))
                        {
                            var            expiresOn = int.Parse(config["expires-on"]);
                            DateTimeOffset expires;
                            expires = DateTimeOffset.FromUnixTimeSeconds(expiresOn);

                            if (DateTimeOffset.Compare(
                                    expires,
                                    DateTimeOffset.Now)
                                <= 0)
                            {
                                var tenantId    = config["tenant-id"];
                                var clientId    = config["client-id"];
                                var apiServerId = config["apiserver-id"];
                                var refresh     = config["refresh-token"];
                                var newToken    = RenewAzureToken(
                                    tenantId,
                                    clientId,
                                    apiServerId,
                                    refresh);
                                config["access-token"] = newToken;
                            }
                        }

                        AccessToken          = config["access-token"];
                        userCredentialsFound = true;
                        break;
                    }

                    case "gcp":
                    {
                        // config
                        var config = userDetails.UserCredentials.AuthProvider.Config;
                        TokenProvider        = new GcpTokenProvider(config["cmd-path"]);
                        userCredentialsFound = true;
                        break;
                    }

                    case "oidc":
                    {
                        var config = userDetails.UserCredentials.AuthProvider.Config;
                        AccessToken = config["id-token"];
                        if (config.ContainsKey("client-id") &&
                            config.ContainsKey("idp-issuer-url") &&
                            config.ContainsKey("id-token") &&
                            config.ContainsKey("refresh-token"))
                        {
                            string clientId     = config["client-id"];
                            string clientSecret = config.ContainsKey("client-secret") ? config["client-secret"] : null;
                            string idpIssuerUrl = config["idp-issuer-url"];
                            string idToken      = config["id-token"];
                            string refreshToken = config["refresh-token"];

                            TokenProvider = new OidcTokenProvider(clientId, clientSecret, idpIssuerUrl, idToken, refreshToken);

                            userCredentialsFound = true;
                        }

                        break;
                    }
                    }
                }
            }

            if (userDetails.UserCredentials.ExternalExecution != null)
            {
                if (string.IsNullOrWhiteSpace(userDetails.UserCredentials.ExternalExecution.Command))
                {
                    throw new KubeConfigException(
                              "External command execution to receive user credentials must include a command to execute");
                }

                if (string.IsNullOrWhiteSpace(userDetails.UserCredentials.ExternalExecution.ApiVersion))
                {
                    throw new KubeConfigException("External command execution missing ApiVersion key");
                }

                var(accessToken, clientCertificateData, clientCertificateKeyData) = ExecuteExternalCommand(userDetails.UserCredentials.ExternalExecution);
                AccessToken = accessToken;
                // When reading ClientCertificateData from a config file it will be base64 encoded, and code later in the system (see CertUtils.GeneratePfx)
                // expects ClientCertificateData and ClientCertificateKeyData to be base64 encoded because of this. However the string returned by external
                // auth providers is the raw certificate and key PEM text, so we need to take that and base64 encoded it here so it can be decoded later.
                ClientCertificateData    = clientCertificateData == null ? null : Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(clientCertificateData));
                ClientCertificateKeyData = clientCertificateKeyData == null ? null : Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(clientCertificateKeyData));

                userCredentialsFound = true;
            }

            if (!userCredentialsFound)
            {
                throw new KubeConfigException(
                          $"User: {userDetails.Name} does not have appropriate auth credentials in kubeconfig");
            }
        }
        private void SetUserDetails(K8SConfiguration k8SConfig, Context activeContext)
        {
            if (string.IsNullOrWhiteSpace(activeContext.ContextDetails.User))
            {
                return;
            }

            var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.User,
                                                                                StringComparison.OrdinalIgnoreCase));

            if (userDetails == null)
            {
                throw new KubeConfigException($"User not found for context {activeContext.Name} in kubeconfig");
            }

            if (userDetails.UserCredentials == null)
            {
                throw new KubeConfigException($"User credentials not found for user: {userDetails.Name} in kubeconfig");
            }

            var userCredentialsFound = false;

            // Basic and bearer tokens are mutually exclusive
            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.Token))
            {
                AccessToken          = userDetails.UserCredentials.Token;
                userCredentialsFound = true;
            }
            else if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.UserName) &&
                     !string.IsNullOrWhiteSpace(userDetails.UserCredentials.Password))
            {
                Username             = userDetails.UserCredentials.UserName;
                Password             = userDetails.UserCredentials.Password;
                userCredentialsFound = true;
            }

            // Token and cert based auth can co-exist
            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificateData) &&
                !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKeyData))
            {
                ClientCertificateData    = userDetails.UserCredentials.ClientCertificateData;
                ClientCertificateKeyData = userDetails.UserCredentials.ClientKeyData;
                userCredentialsFound     = true;
            }

            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificate) &&
                !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKey))
            {
                ClientCertificateFilePath = GetFullPath(k8SConfig, userDetails.UserCredentials.ClientCertificate);
                ClientKeyFilePath         = GetFullPath(k8SConfig, userDetails.UserCredentials.ClientKey);
                userCredentialsFound      = true;
            }

            if (userDetails.UserCredentials.AuthProvider != null)
            {
                if (userDetails.UserCredentials.AuthProvider.Config != null &&
                    userDetails.UserCredentials.AuthProvider.Config.ContainsKey("access-token"))
                {
                    switch (userDetails.UserCredentials.AuthProvider.Name)
                    {
                    case "azure":
                    {
                        var config = userDetails.UserCredentials.AuthProvider.Config;
                        if (config.ContainsKey("expires-on"))
                        {
                            var            expiresOn = Int32.Parse(config["expires-on"]);
                            DateTimeOffset expires;
#if NET452
                            var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
                            expires
                                = epoch.AddSeconds(expiresOn);
#else
                            expires = DateTimeOffset.FromUnixTimeSeconds(expiresOn);
#endif

                            if (DateTimeOffset.Compare(expires
                                                       , DateTimeOffset.Now)
                                <= 0)
                            {
                                var tenantId    = config["tenant-id"];
                                var clientId    = config["client-id"];
                                var apiServerId = config["apiserver-id"];
                                var refresh     = config["refresh-token"];
                                var newToken    = RenewAzureToken(tenantId
                                                                  , clientId
                                                                  , apiServerId
                                                                  , refresh);
                                config["access-token"] = newToken;
                            }
                        }

                        AccessToken          = config["access-token"];
                        userCredentialsFound = true;
                        break;
                    }

                    case "gcp":
                    {
                        // config
                        var config = userDetails.UserCredentials.AuthProvider.Config;
                        TokenProvider        = new GcpTokenProvider(config["cmd-path"]);
                        userCredentialsFound = true;
                        break;
                    }
                    }
                }
            }

            if (userDetails.UserCredentials.ExternalExecution != null)
            {
                if (string.IsNullOrWhiteSpace(userDetails.UserCredentials.ExternalExecution.Command))
                {
                    throw new KubeConfigException(
                              "External command execution to receive user credentials must include a command to execute");
                }

                if (string.IsNullOrWhiteSpace(userDetails.UserCredentials.ExternalExecution.ApiVersion))
                {
                    throw new KubeConfigException("External command execution missing ApiVersion key");
                }

                var(accessToken, clientCertificateData, clientCertificateKeyData) = ExecuteExternalCommand(userDetails.UserCredentials.ExternalExecution);
                AccessToken              = accessToken;
                ClientCertificateData    = clientCertificateData;
                ClientCertificateKeyData = clientCertificateKeyData;

                userCredentialsFound = true;
            }

            if (!userCredentialsFound)
            {
                throw new KubeConfigException(
                          $"User: {userDetails.Name} does not have appropriate auth credentials in kubeconfig");
            }
        }