Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Commit

Permalink
add middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
avish42 committed Jul 21, 2023
1 parent cfaf3ec commit fd4fe77
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 19 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
- [ ] Add Context
- [ ] Add Authentication
- [ ] Add Abort Option
- [ ] Add Abort Option
- [ ]
2 changes: 1 addition & 1 deletion cmd/cli/cmd/cmdPlan.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func init() {

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// planCmd.PersistentFlags().String("foo", "", "A help for foo")
planCmd.PersistentFlags().String("server-addr", "", "the server address")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
Expand Down
4 changes: 2 additions & 2 deletions cmd/cli/cmd/cmdRoot.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var rootCmd = &cobra.Command{
Long: `terrasome a cli tool that is configured to work with terrasome server. It allows us to run the terraform code
at the server side and provides integrated RBAC for running the terraform modules`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("running rool")
fmt.Println("running tool")
},
}

Expand All @@ -39,5 +39,5 @@ func init() {

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
// rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
13 changes: 9 additions & 4 deletions cmd/cli/cmd/runPlan.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"log"
"net/url"
"os"

Expand Down Expand Up @@ -60,11 +61,15 @@ func RunPlan(cmd *cobra.Command, args []string) {
err = targz.TarDir(cwd, tarFile)
checkError(err)

// get the server address from env variable
// get the server address from flags
serverAddr, err := cmd.Flags().GetString("server-addr")
if err != nil {
checkError(err)
}

serverAddr, ok := os.LookupEnv(ServerAddrEnv)
if !ok {
panic("var serverAddr is not set")
if serverAddr == "" {
// get the server address from env
log.Fatal("server address not provided")
}

// log the server address
Expand Down
5 changes: 4 additions & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"net/http"

"github.com/vishu42/terrasome/pkg/middleware"
"github.com/vishu42/terrasome/pkg/terraform"
)

Expand All @@ -20,9 +21,11 @@ func main() {
m.HandleFunc("/apply", t.Action)
m.HandleFunc("/destroy", t.Action)

ea := middleware.NewEnsureAuth(m)

s := &http.Server{
Addr: ":80",
Handler: m,
Handler: ea,
}
err := s.ListenAndServe()
if err != nil {
Expand Down
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ module github.com/vishu42/terrasome

go 1.20

require (
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/spf13/cobra v1.7.0
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/tools v0.9.3 // indirect
)
8 changes: 2 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
119 changes: 119 additions & 0 deletions pkg/middleware/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package middleware

import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"

"github.com/golang-jwt/jwt"
)

type PublicKey struct {
KTY string `json:"kty"`
KID string `json:"kid"`
Use string `json:"use"`
N string `json:"n"`
E string `json:"e"`
X5C string `json:"x5c"`
Issuer string `json:"issuer"`
}

func GetMsPublicKey() []PublicKey {
microsoftKeysURL := "https://login.microsoftonline.com/common/discovery/v2.0/keys"

client := &http.Client{}

body := &bytes.Buffer{}
req, err := http.NewRequest(http.MethodGet, microsoftKeysURL, body)
if err != nil {
log.Fatalf("unable to generate http req - %v", err)
}

resp, err := client.Do(req)
if err != nil {
log.Fatalf("error executing http req - %v", err)
}

if resp.StatusCode != http.StatusOK {
log.Fatal("Status Not OK")
}

var publicKey []PublicKey
err = resp.Body.Close()
if err != nil {
log.Fatalf("error closing resp body - %v", err)
}

err = json.NewDecoder(resp.Body).Decode(&publicKey)
if err != nil {
log.Fatalf("error decoding resp body - %v", err)
}

return publicKey
}

type EnsureAuth struct {
logHandler http.Handler
}

func (ea *EnsureAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Println("hello - I am middleware :)")

// get the authorization header
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("missing authorization header"))
return
}

// get the token
token := authHeader[len("Bearer "):]

// get the public key set
publicKeySet := GetMsPublicKey()

// verify the token
// Parse the token without verifying the signature
t, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
// Don't forget to validate the alg is what you expect:
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}

// find the public key
var key string
for _, v := range publicKeySet {
if v.KID == token.Header["kid"] {
key = v.X5C
break
}
}

// embed the public key in the PEM format
pem := "-----BEGIN CERTIFICATE-----\n" + key + "\n-----END CERTIFICATE-----"

// parse the PEM encoded public key
result, err := jwt.ParseRSAPublicKeyFromPEM([]byte(pem))
if err != nil {
return nil, err
}

return result, nil
})
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
return
}

// print the claims
fmt.Println(t.Claims)

ea.logHandler.ServeHTTP(w, r)
}

func NewEnsureAuth(handlerToWrap http.Handler) *EnsureAuth {
return &EnsureAuth{handlerToWrap}
}
1 change: 1 addition & 0 deletions pkg/terraform/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Terraform struct {
}

func (t Terraform) Version(w http.ResponseWriter, r *http.Request) {
fmt.Println("i should be printed after middleware")
cmd := exec.Command(t.Binary, "version")
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
Expand Down

0 comments on commit fd4fe77

Please sign in to comment.