...

Source file src/edge-infra.dev/pkg/edge/apis/meta/name.go

Documentation: edge-infra.dev/pkg/edge/apis/meta

     1  package meta
     2  
     3  import (
     4  	"crypto/md5" //nolint:gosec // not used for security
     5  	"encoding/base64"
     6  	"fmt"
     7  	"strings"
     8  	"unicode"
     9  
    10  	"edge-infra.dev/pkg/lib/gcp/iam"
    11  )
    12  
    13  // ResourceName creates a valid + unique name for K8s Config Connector IAM
    14  // resources that have their name used directly as the name of the corresponding
    15  // GCP resource.  It could also be used when working directly against the
    16  // GCP API, but you could simply rely on the GCP clients to return an error
    17  // when an invalid name is provided.
    18  //
    19  // Due to name limits on some IAM resources in  GCP, we need a resource name
    20  // under 28 characters. We cant just shorten the id name because names which are
    21  // mostly the same will be shortened to the same name and collide within the
    22  // namespace
    23  //
    24  // To simplify code managing groups of these resources (SA, API key, policies),
    25  // we typically use the same resource name.
    26  //
    27  // note on length:
    28  // k8s-cfg-conn is our longest resource suffix @ 12 chars, with a max
    29  // length of 28 for GCP SA name, we have 16 characters to work with total,
    30  // drop that by 4 to give us wiggle room
    31  func ResourceName(id string, purpose string) (string, error) {
    32  	name := fmt.Sprintf("%s-%s", hashName(id, 12), purpose)
    33  	if ok := iam.ValidAccountID(name); !ok {
    34  		return "", fmt.Errorf("%s is an invalid service account name", name)
    35  	}
    36  	return name, nil
    37  }
    38  
    39  // Hash thinly wraps hashName to generate resource hashes of fixed length
    40  func Hash(name string) string {
    41  	return hashName(name, 12)
    42  }
    43  
    44  // requirements:
    45  // - deterministic
    46  // - valid kube resource name
    47  // - starts with alaphabet character (some GCP resources dont like names that begin with numbers)
    48  // - no longer than 12 characters long
    49  //   - some GCP IAM resources have name limits of 28 characters
    50  //   - we also need other text in the resource name
    51  func hashName(name string, n int) string {
    52  	// create md5 hash
    53  	md5Hash := md5.Sum([]byte(name)) //nolint:gosec // not used for security
    54  	// encode it as base64 to get more character space thana hex
    55  	hashString := base64.StdEncoding.EncodeToString(md5Hash[:])
    56  
    57  	var hash []rune
    58  	// find first n letters
    59  	for _, r := range hashString {
    60  		// first letter must be an alphabet character
    61  		if len(hash) == 0 && !unicode.IsLetter(r) {
    62  			continue
    63  		}
    64  		// dont add characters from the base64 characterspace that are invalid
    65  		// for k8s resource names
    66  		if !unicode.IsLetter(r) && !unicode.IsNumber(r) {
    67  			continue
    68  		}
    69  		// exit when we have as many letters as we want
    70  		if len(hash) == n {
    71  			break
    72  		}
    73  		// add current hash character to final result
    74  		hash = append(hash, r)
    75  	}
    76  
    77  	// must be lower case to be a valid kube resource name
    78  	return strings.ToLower(string(hash))
    79  }
    80  

View as plain text