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 }