...

Source file src/k8s.io/client-go/tools/auth/exec/exec.go

Documentation: k8s.io/client-go/tools/auth/exec

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package exec contains helper utilities for exec credential plugins.
    18  package exec
    19  
    20  import (
    21  	"errors"
    22  	"fmt"
    23  	"os"
    24  
    25  	"k8s.io/apimachinery/pkg/runtime"
    26  	"k8s.io/apimachinery/pkg/runtime/schema"
    27  	"k8s.io/apimachinery/pkg/runtime/serializer"
    28  	"k8s.io/client-go/pkg/apis/clientauthentication"
    29  	"k8s.io/client-go/pkg/apis/clientauthentication/install"
    30  	"k8s.io/client-go/rest"
    31  )
    32  
    33  const execInfoEnv = "KUBERNETES_EXEC_INFO"
    34  
    35  var scheme = runtime.NewScheme()
    36  var codecs = serializer.NewCodecFactory(scheme)
    37  
    38  func init() {
    39  	install.Install(scheme)
    40  }
    41  
    42  // LoadExecCredentialFromEnv is a helper-wrapper around LoadExecCredential that loads from the
    43  // well-known KUBERNETES_EXEC_INFO environment variable.
    44  //
    45  // When the KUBERNETES_EXEC_INFO environment variable is not set or is empty, then this function
    46  // will immediately return an error.
    47  func LoadExecCredentialFromEnv() (runtime.Object, *rest.Config, error) {
    48  	env := os.Getenv(execInfoEnv)
    49  	if env == "" {
    50  		return nil, nil, errors.New("KUBERNETES_EXEC_INFO env var is unset or empty")
    51  	}
    52  	return LoadExecCredential([]byte(env))
    53  }
    54  
    55  // LoadExecCredential loads the configuration needed for an exec plugin to communicate with a
    56  // cluster.
    57  //
    58  // LoadExecCredential expects the provided data to be a serialized client.authentication.k8s.io
    59  // ExecCredential object (of any version). If the provided data is invalid (i.e., it cannot be
    60  // unmarshalled into any known client.authentication.k8s.io ExecCredential version), an error will
    61  // be returned. A successfully unmarshalled ExecCredential will be returned as the first return
    62  // value.
    63  //
    64  // If the provided data is successfully unmarshalled, but it does not contain cluster information
    65  // (i.e., ExecCredential.Spec.Cluster == nil), then an error will be returned.
    66  //
    67  // Note that the returned rest.Config will use anonymous authentication, since the exec plugin has
    68  // not returned credentials for this cluster yet.
    69  func LoadExecCredential(data []byte) (runtime.Object, *rest.Config, error) {
    70  	obj, gvk, err := codecs.UniversalDeserializer().Decode(data, nil, nil)
    71  	if err != nil {
    72  		return nil, nil, fmt.Errorf("decode: %w", err)
    73  	}
    74  
    75  	expectedGK := schema.GroupKind{
    76  		Group: clientauthentication.SchemeGroupVersion.Group,
    77  		Kind:  "ExecCredential",
    78  	}
    79  	if gvk.GroupKind() != expectedGK {
    80  		return nil, nil, fmt.Errorf(
    81  			"invalid group/kind: wanted %s, got %s",
    82  			expectedGK.String(),
    83  			gvk.GroupKind().String(),
    84  		)
    85  	}
    86  
    87  	// Explicitly convert object here so that we can return a nicer error message above for when the
    88  	// data represents an invalid type.
    89  	var execCredential clientauthentication.ExecCredential
    90  	if err := scheme.Convert(obj, &execCredential, nil); err != nil {
    91  		return nil, nil, fmt.Errorf("cannot convert to ExecCredential: %w", err)
    92  	}
    93  
    94  	if execCredential.Spec.Cluster == nil {
    95  		return nil, nil, errors.New("ExecCredential does not contain cluster information")
    96  	}
    97  
    98  	restConfig, err := rest.ExecClusterToConfig(execCredential.Spec.Cluster)
    99  	if err != nil {
   100  		return nil, nil, fmt.Errorf("cannot create rest.Config: %w", err)
   101  	}
   102  
   103  	return obj, restConfig, nil
   104  }
   105  

View as plain text