diff --git a/README.md b/README.md new file mode 100644 index 0000000..c1f0778 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# KiwiOS Go Utilities + +This repository offers various utility packages for Go artifacts in KiwiOS. It does not provide any direct executable. + +## GatewayJWT + +Provides the function `GetGatewayJWT(tokenURL string)` which fetches a JWT from the [Gateway Identity Service](https://bitbucket.dev.kiwigrid.com/projects/GM/repos/gateway-registry). This JWT can be used to authenticate against Kiwigrid Cloud services. + +The `tokenURL` is usually retrieved via the [gateway-registry-bridge](https://bitbucket.dev.kiwigrid.com/projects/BOSS/repos/gateway-registry-bridge). diff --git a/gatewayjwt/jwt.go b/gatewayjwt/jwt.go new file mode 100644 index 0000000..4cb4ce1 --- /dev/null +++ b/gatewayjwt/jwt.go @@ -0,0 +1,84 @@ +package gatewayjwt + +import ( + "encoding/json" + "errors" + "io/ioutil" + "net/http" + "strings" + "time" + + "github.com/dgrijalva/jwt-go" +) + +var client = &http.Client{} +var gatewayID = "" +var gatewayKey = "" + +func fetchAuthTokens() error { + cmdline, err := ioutil.ReadFile("/proc/cmdline") + if err != nil { + return err + } + + args := strings.Fields(string(cmdline)) + for _, v := range args { + if strings.HasPrefix(v, "kg.gateway.id=") { + gatewayID = v[14:] + } else if strings.HasPrefix(v, "kg.gateway.key=") { + gatewayKey = v[15:] + } + } + + if gatewayID == "" || gatewayKey == "" { + return errors.New("Cannot read gateway id or key") + } + + return nil +} + +// GetGatewayJWT fetches a JWT from the IoT Identity Service used for authenticating against various Kiwigrid services. +func GetGatewayJWT(tokenURL string) (string, error) { + if gatewayID == "" || gatewayKey == "" { + err := fetchAuthTokens() + if err != nil { + return "", err + } + } + + claims := &jwt.StandardClaims{ + ExpiresAt: time.Now().Add(30 * time.Minute).Unix(), + Issuer: gatewayID, + Subject: gatewayID, + } + + clientJwt, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(gatewayKey)) + + if err != nil { + return "", err + } + + req, err := http.NewRequest("POST", tokenURL, nil) + req.Header.Add("Authorization", "Bearer "+clientJwt) + req.Header.Add("Accept", "application/json") + req.Header.Add("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var data map[string]interface{} + + if err := json.Unmarshal(body, &data); err != nil { + return "", err + } + + return data["access_token"].(string), nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1d07ed3 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module bitbucket.dev.kiwigrid.com/BOSS/kiwios-go-utils + +go 1.13 + +require github.com/dgrijalva/jwt-go v3.2.0+incompatible diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6a8f140 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=