diff --git a/Dockerfile b/Dockerfile index 29dc004..3960190 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,13 +36,15 @@ RUN set -ex \ # Get the boot-script-service from the builder stage. COPY cloud-init-server /usr/local/bin/ +ENV SMD_URL="http://smd:27779" +ENV SMD_TOKEN="" +ENV LISTEN_PORT="27777" # nobody 65534:65534 USER 65534:65534 # Set up the command to start the service. -CMD /usr/local/bin/cloud-init-server \ - --ci-listen ":27777" \ - --smd-endpoint "http://localhost:27779" +CMD /usr/local/bin/cloud-init-server --listen ${LISTEN_PORT} --smd-url ${SMD_URL} --smd-token ${SMD_TOKEN} + ENTRYPOINT ["/sbin/tini", "--"] diff --git a/cmd/cloud-init-server/main.go b/cmd/cloud-init-server/main.go index d37648c..b572637 100644 --- a/cmd/cloud-init-server/main.go +++ b/cmd/cloud-init-server/main.go @@ -10,27 +10,29 @@ import ( var ( ciEndpoint = ":27777" - smdEndpoint = "http://localhost:27779" + smdEndpoint = "http://smd:27779" + smdToken = "" // jwt for access to smd ) func main() { - flag.StringVar(&ciEndpoint, "ci-listen", ciEndpoint, "Server IP and port for cloud-init-server to listen on") - flag.StringVar(&smdEndpoint, "smd-endpoint", smdEndpoint, "http IP/url and port for running SMD") + flag.StringVar(&ciEndpoint, "listen", ciEndpoint, "Server IP and port for cloud-init-server to listen on") + flag.StringVar(&smdEndpoint, "smd-url", smdEndpoint, "http IP/url and port for running SMD") + flag.StringVar(&smdToken, "smd-token", smdToken, "JWT token for SMD access") flag.Parse() router := gin.Default() store := memstore.NewMemStore() - sm := smdclient.NewSMDClient(smdEndpoint) + sm := smdclient.NewSMDClient(smdEndpoint, smdToken) ciHandler := NewCiHandler(store, sm) - router.GET("/harbor", ciHandler.ListEntries) - router.POST("/harbor", ciHandler.AddEntry) - router.GET("/harbor/:id", ciHandler.GetEntry) - router.GET("/harbor/:id/user-data", ciHandler.GetUserData) - router.GET("/harbor/:id/meta-data", ciHandler.GetMetaData) - router.GET("/harbor/:id/vendor-data", ciHandler.GetVendorData) - router.PUT("/harbor/:id", ciHandler.UpdateEntry) - router.DELETE("harbor/:id", ciHandler.DeleteEntry) + router.GET("/cloud-init", ciHandler.ListEntries) + router.POST("/cloud-init", ciHandler.AddEntry) + router.GET("/cloud-init/:id", ciHandler.GetEntry) + router.GET("/cloud-init/:id/user-data", ciHandler.GetUserData) + router.GET("/cloud-init/:id/meta-data", ciHandler.GetMetaData) + router.GET("/cloud-init/:id/vendor-data", ciHandler.GetVendorData) + router.PUT("/cloud-init/:id", ciHandler.UpdateEntry) + router.DELETE("cloud-init/:id", ciHandler.DeleteEntry) router.Run(ciEndpoint) } diff --git a/go.mod b/go.mod index 1bd25c5..0bae53a 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gin-gonic/gin v1.9.1 github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible github.com/gosimple/slug v1.13.1 github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/go.sum b/go.sum index f2727a8..1409848 100644 --- a/go.sum +++ b/go.sum @@ -53,6 +53,8 @@ github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= diff --git a/internal/smdclient/SMDclient.go b/internal/smdclient/SMDclient.go index 9569e6f..60f270d 100644 --- a/internal/smdclient/SMDclient.go +++ b/internal/smdclient/SMDclient.go @@ -8,7 +8,10 @@ import ( "strings" "time" + "log" + "github.com/OpenCHAMI/smd/v2/pkg/sm" + "github.com/golang-jwt/jwt" ) // Add client usage examples @@ -20,32 +23,49 @@ var ( ErrUnmarshal = errors.New("cannot unmarshal JSON") ) -// godoc ? // SMDClient is a client for SMD type SMDClient struct { - smdClient *http.Client - smdBaseURL string + smdClient *http.Client + smdBaseURL string + accessToken string } // NewSMDClient creates a new SMDClient which connects to the SMD server at baseurl -func NewSMDClient(baseurl string) *SMDClient { +// and uses the provided JWT for authentication +func NewSMDClient(baseurl string, jwt string) *SMDClient { c := &http.Client{Timeout: 2 * time.Second} return &SMDClient{ - smdClient: c, - smdBaseURL: baseurl, + smdClient: c, + smdBaseURL: baseurl, + accessToken: jwt, } } // getSMD is a helper function to initialize the SMDClient func (s *SMDClient) getSMD(ep string, smd interface{}) error { url := s.smdBaseURL + ep - resp, err := s.smdClient.Get(url) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return err + } + if s.accessToken != "" { + //validate the JWT without verifying the signature + //if the JWT is not valid, the request will fail + token, _, err := new(jwt.Parser).ParseUnverified(s.accessToken, jwt.MapClaims{}) + if err != nil { + return errors.New("poorly formed JWT: " + err.Error()) + } + log.Println("Loaded JWT token:", s.accessToken) + log.Println("Claims:", token.Claims) + req.Header.Set("Authorization", "Bearer "+s.accessToken) + } else { + return errors.New("poorly formed JWT") + } + resp, err := s.smdClient.Do(req) if err != nil { return err } - // check http retrun value defer resp.Body.Close() - // ioutil is deprecated body, _ := io.ReadAll(resp.Body) if err := json.Unmarshal(body, smd); err != nil { return ErrUnmarshal