github.com/wunderio/silta-cli@v0.0.0-20240508100559-3017e4ab3a20/internal/common/ciAuthFunctions.go (about)

     1  package common
     2  
     3  import (
     4  	"encoding/json"
     5  	"io/ioutil"
     6  	"log"
     7  	"net/http"
     8  	"net/url"
     9  	"strings"
    10  )
    11  
    12  // Access scopes:
    13  //
    14  //	Catalog - registry:catalog:* - listing images
    15  //	Image - repository:<image_name>:pull - info on image. <image_name> must include repository name e.x. silta-dev/
    16  type RegistryAccessScope uint8
    17  
    18  const (
    19  	Catalog RegistryAccessScope = iota + 1
    20  	Image
    21  )
    22  
    23  // Returns JWT (JSON Web Token) for docker registries.
    24  //
    25  // If 'scope' is set to 'Catalog', 'projectName' and 'imageName' is not used and can be empty strings
    26  func GetJWT(authToken string, imageRepoHost string, scope RegistryAccessScope, projectName string, imageName string) string {
    27  	// <LOCATION.>gcr.io - container registry ,  need url.QueryEscape
    28  	// <LOCATION>-docker.pkg.dev - artifact registry , dont need url.QueryEscape
    29  
    30  	const gcr_substr string = "gcr.io" // container registry domain
    31  	const ar_substr string = "pkg.dev" // artifact registry domain
    32  
    33  	requestURL := "https://" + imageRepoHost + "/v2/token?service=" + imageRepoHost
    34  
    35  	if imageRepoHost == "docker.io" {
    36  		requestURL = "https://auth.docker.io/token?service=registry.docker.io"
    37  	}
    38  
    39  	if scope == Catalog {
    40  		requestURL += "&scope=registry:catalog:*"
    41  	} else if scope == Image {
    42  		if !(len(imageName) > 0) || !(len(projectName) > 0) {
    43  			log.Fatal("Error: Image and project(repository) names must be set")
    44  		}
    45  		requestURL += "&scope=repository:" + projectName + "/" + imageName + ":pull"
    46  	}
    47  
    48  	req, err := http.NewRequest("GET", requestURL, nil)
    49  	if err != nil {
    50  		log.Fatalln("Error: ", err)
    51  	}
    52  	if strings.Contains(imageRepoHost, gcr_substr) {
    53  		req.SetBasicAuth(url.QueryEscape("_token"), url.QueryEscape(authToken))
    54  	} else if strings.Contains(imageRepoHost, ar_substr) {
    55  		req.SetBasicAuth("_token", authToken)
    56  	} else {
    57  		req.Header.Set("Authorization", "Basic "+string(authToken))
    58  	}
    59  
    60  	resp, err := http.DefaultClient.Do(req)
    61  	if err != nil {
    62  		log.Fatalln("Error: ", err)
    63  	}
    64  	defer resp.Body.Close()
    65  	response_json, err := ioutil.ReadAll(resp.Body)
    66  	if err != nil {
    67  		log.Fatalln("Error: ", err)
    68  	}
    69  
    70  	// Parsing out token from response
    71  	var response_data map[string]interface{}
    72  	err = json.Unmarshal(response_json, &response_data)
    73  	if err != nil {
    74  		log.Fatal("Error: ", err)
    75  	}
    76  	rawToken, ok := response_data["token"]
    77  	if !ok {
    78  		log.Fatal("Error: couldnt parse key 'token'")
    79  	}
    80  	token, ok := rawToken.(string)
    81  	if !ok {
    82  		log.Fatal("Error: couldnt parse out raw token value")
    83  	}
    84  	return string(token)
    85  }
    86  
    87  func HasString(a []string, b string) bool {
    88  	for _, c := range a {
    89  		if c == b {
    90  			return true
    91  		}
    92  	}
    93  	return false
    94  }