github.com/secure-build/gitlab-runner@v12.5.0+incompatible/executors/kubernetes/overwrites.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"strings"
     7  
     8  	"gitlab.com/gitlab-org/gitlab-runner/common"
     9  )
    10  
    11  const (
    12  	// NamespaceOverwriteVariableName is the key for the JobVariable containing user overwritten Namespace
    13  	NamespaceOverwriteVariableName = "KUBERNETES_NAMESPACE_OVERWRITE"
    14  	// ServiceAccountOverwriteVariableName is the key for the JobVariable containing user overwritten ServiceAccount
    15  	ServiceAccountOverwriteVariableName = "KUBERNETES_SERVICE_ACCOUNT_OVERWRITE"
    16  	// BearerTokenOverwriteVariableValue is the key for the JobVariable containing user overwritten BearerToken
    17  	BearerTokenOverwriteVariableValue = "KUBERNETES_BEARER_TOKEN"
    18  	// PodAnnotationsOverwriteVariablePrefix is the prefix for all the JobVariable keys containing user overwritten PodAnnotations
    19  	PodAnnotationsOverwriteVariablePrefix = "KUBERNETES_POD_ANNOTATIONS_"
    20  )
    21  
    22  type overwrites struct {
    23  	namespace      string
    24  	serviceAccount string
    25  	bearerToken    string
    26  	podAnnotations map[string]string
    27  }
    28  
    29  func createOverwrites(config *common.KubernetesConfig, variables common.JobVariables, logger common.BuildLogger) (*overwrites, error) {
    30  	var err error
    31  	o := &overwrites{}
    32  
    33  	namespaceOverwrite := variables.Expand().Get(NamespaceOverwriteVariableName)
    34  	o.namespace, err = o.evaluateOverwrite("Namespace", config.Namespace, config.NamespaceOverwriteAllowed, namespaceOverwrite, logger)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	serviceAccountOverwrite := variables.Expand().Get(ServiceAccountOverwriteVariableName)
    40  	o.serviceAccount, err = o.evaluateOverwrite("ServiceAccount", config.ServiceAccount, config.ServiceAccountOverwriteAllowed, serviceAccountOverwrite, logger)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	bearerTokenOverwrite := variables.Expand().Get(BearerTokenOverwriteVariableValue)
    46  	o.bearerToken, err = o.evaluateBoolControlledOverwrite("BearerToken", config.BearerToken, config.BearerTokenOverwriteAllowed, bearerTokenOverwrite, logger)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	o.podAnnotations, err = o.evaluateMapOverwrite("PodAnnotations", config.PodAnnotations, config.PodAnnotationsOverwriteAllowed, variables, PodAnnotationsOverwriteVariablePrefix, logger)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	return o, nil
    57  }
    58  
    59  func (o *overwrites) evaluateBoolControlledOverwrite(fieldName, value string, canOverride bool, overwriteValue string, logger common.BuildLogger) (string, error) {
    60  	if canOverride {
    61  		return o.evaluateOverwrite(fieldName, value, ".+", overwriteValue, logger)
    62  	}
    63  	return o.evaluateOverwrite(fieldName, value, "", overwriteValue, logger)
    64  }
    65  
    66  func (o *overwrites) evaluateOverwrite(fieldName, value, regex, overwriteValue string, logger common.BuildLogger) (string, error) {
    67  	if regex == "" {
    68  		logger.Debugln("Regex allowing overrides for", fieldName, "is empty, disabling override.")
    69  		return value, nil
    70  	}
    71  
    72  	if overwriteValue == "" {
    73  		return value, nil
    74  	}
    75  
    76  	if err := overwriteRegexCheck(regex, overwriteValue); err != nil {
    77  		return value, err
    78  	}
    79  
    80  	logValue := overwriteValue
    81  	if fieldName == "BearerToken" {
    82  		logValue = "XXXXXXXX..."
    83  	}
    84  
    85  	logger.Println(fmt.Sprintf("%q overwritten with %q", fieldName, logValue))
    86  
    87  	return overwriteValue, nil
    88  }
    89  
    90  func overwriteRegexCheck(regex, value string) error {
    91  	var err error
    92  	var r *regexp.Regexp
    93  	if r, err = regexp.Compile(regex); err != nil {
    94  		return err
    95  	}
    96  	if match := r.MatchString(value); !match {
    97  		return fmt.Errorf("Provided value %q does not match regex %q", value, regex)
    98  	}
    99  	return nil
   100  }
   101  
   102  // splitMapOverwrite splits provided string on the first "=" and returns (key, value, nil).
   103  // If the argument cannot be split an error is returned
   104  func splitMapOverwrite(str string) (string, string, error) {
   105  	if split := strings.SplitN(str, "=", 2); len(split) > 1 {
   106  		return split[0], split[1], nil
   107  	}
   108  
   109  	return "", "", fmt.Errorf("Provided value %q is malformed, does not match k=v", str)
   110  }
   111  
   112  func (o *overwrites) evaluateMapOverwrite(fieldName string, values map[string]string, regex string, variables common.JobVariables, variablesSelector string, logger common.BuildLogger) (map[string]string, error) {
   113  	if regex == "" {
   114  		logger.Debugln("Regex allowing overrides for", fieldName, "is empty, disabling override.")
   115  		return values, nil
   116  	}
   117  
   118  	finalValues := make(map[string]string)
   119  	for k, v := range values {
   120  		finalValues[k] = v
   121  	}
   122  
   123  	for _, variable := range variables {
   124  		if strings.HasPrefix(variable.Key, variablesSelector) {
   125  			if err := overwriteRegexCheck(regex, variable.Value); err != nil {
   126  				return nil, err
   127  			}
   128  
   129  			key, value, err := splitMapOverwrite(variable.Value)
   130  			if err != nil {
   131  				return nil, err
   132  			}
   133  
   134  			finalValues[key] = value
   135  			logger.Println(fmt.Sprintf("%q %q overwritten with %q", fieldName, key, value))
   136  		}
   137  	}
   138  	return finalValues, nil
   139  }