package main import ( "io" "net/http" "entanglement.garden/common/cloudinit" "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" ) var ( httpStaticContent = map[string][]byte{} ) func runHTTPServer(bind string) { logrus.WithField("bind", bind).Debug("starting temporary HTTP server") http.ListenAndServe(bind, httphandler{}) } type httphandler struct{} func (httphandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { log := logrus.WithFields(logrus.Fields{ "method": r.Method, "path": r.URL, "remote_addr": r.RemoteAddr, }) log.Debug("handling HTTP request") switch r.Method { case http.MethodGet: resp, ok := httpStaticContent[r.URL.Path] if !ok { w.WriteHeader(http.StatusNotFound) return } if resp == nil { w.WriteHeader(http.StatusNoContent) return } _, err := w.Write(resp) if err != nil { log.WithError(err).Error("error serving HTTP response") } case http.MethodPost: printRequestBody(r) log.Info("VM booted") w.WriteHeader(http.StatusNoContent) wg.Done() default: w.WriteHeader(http.StatusNotFound) w.Write([]byte("not found")) } } func buildCloudConfig(base cloudinit.UserData, name string, phoneHomeURL string) error { userdata, err := yaml.Marshal(base) if err != nil { return err } httpStaticContent["/user-data"] = append([]byte("#cloud-config\n"), userdata...) metadata, err := yaml.Marshal(cloudinit.MetaData{ InstanceID: name, LocalHostname: name, }) if err != nil { return err } httpStaticContent["/meta-data"] = metadata vendorData, err := yaml.Marshal(cloudinit.UserData{ PhoneHome: cloudinit.PhoneHome{ URL: phoneHomeURL, Post: []string{"pub_key_dsa", "pub_key_rsa", "pub_key_ed25519", "fqdn"}, }, }) if err != nil { return err } httpStaticContent["/vendor-data"] = vendorData return nil } func printRequestBody(r *http.Request) { log := logrus.WithFields(logrus.Fields{ "method": r.Method, "path": r.URL, "remote_addr": r.RemoteAddr, }) switch r.Header.Get("Content-Type") { case "application/x-www-form-urlencoded": if err := r.ParseForm(); err != nil { logrus.WithError(err).Error("error parsing request body") return } fields := logrus.Fields{} for k, v := range r.Form { if len(v) == 1 { fields[k] = v[0] } else { fields[k] = v } } log.WithFields(fields).Debug("form request body") default: body, err := io.ReadAll(r.Body) if err != nil { log.WithError(err).Error("error reading body") } r.Body.Close() log.Debug(string(body)) } }