Skip to content

Instantly share code, notes, and snippets.

@nishakm
Created March 31, 2021 22:11
Show Gist options
  • Save nishakm/f520780bcb19ff4d33f89d4dda0d762d to your computer and use it in GitHub Desktop.
Save nishakm/f520780bcb19ff4d33f89d4dda0d762d to your computer and use it in GitHub Desktop.
Fetch manifest from registry
package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"net/url"
"strings"
)
func main() {
// This is the target we want to get from
var target string = "https://bundle.bar/v2/u/nishakm/sboms/debian/manifests/bullseye"
// these are basic auth creds
var usrname string = "yourusername"
var pswd string = "yourpassword"
// these are accept headers the registry needs
accept := []string{"application/vnd.docker.distribution.manifest.v1+json",
"application/vnd.docker.distribution.manifest.v1+prettyjws",
"application/vnd.docker.distribution.manifest.v2+json",
"application/vnd.oci.image.manifest.v1+json",
"application/vnd.docker.distribution.manifest.list.v2+json",
"application/vnd.oci.image.index.v1+json"}
acceptStr := strings.Join(accept, ",")
// First poke the url in the normal way
// 1. create a get request
req, err := http.NewRequest("GET", target, nil)
printerr(err)
req.SetBasicAuth(usrname, pswd)
req.Header.Set("Accept", acceptStr)
// make a client for this request
client := &http.Client{}
resp, err := client.Do(req)
printerr(err)
defer resp.Body.Close()
// the response headers will give a 401 with information on where to get
// an auth token
for k, v := range resp.Header {
log.Print(k)
log.Print(" : ")
log.Println(v)
}
// we extract some of the parameters required to get a token
authenticate := resp.Header.Get("Www-Authenticate")
bearer_things := strings.Split(authenticate, " ")
key_val_list := strings.Split(bearer_things[1], ",")
key_vals := make(map[string]string)
for in := range key_val_list {
k := strings.Split(key_val_list[in], "=")
key_vals[k[0]] = k[1]
}
// make a request with parameters
params := url.Values{}
params.Add("service", key_vals["service"])
params.Add("scope", key_vals["scope"])
tokenreq, err := http.NewRequest("GET", "https://bundle.bar/auth/token",
strings.NewReader(params.Encode()))
printerr(err)
// make the request with the client
tokenresp, err := client.Do(tokenreq)
printerr(err)
defer tokenresp.Body.Close()
// read the access token
body, err := ioutil.ReadAll(tokenresp.Body)
printerr(err)
// it's a json byte string
// we need to decode it
var receiver interface{}
uerr := json.Unmarshal(body, &receiver)
printerr(uerr)
content := receiver.(map[string]interface{})
bcont := "Bearer " + content["access_token"].(string)
// now you can make a request to the real endpoint with
// the right headers
req.Header.Set("Authorization", bcont)
resp2, err := client.Do(req)
printerr(err)
defer resp2.Body.Close()
result, err := ioutil.ReadAll(resp2.Body)
printerr(err)
// should be a manifest
log.Println(string(result))
// should be a manifest
log.Println(string(result))
log.Println(resp.Status)
}
func printerr(e error) {
if e != nil {
log.Println("Error!")
log.Fatalln(e)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment