package main import ( "bytes" "crypto/tls" "crypto/x509" "encoding/json" "flag" "fmt" "io" "io/ioutil" "net/http" "os" "strings" "time" "gitlab-app.eng.qops.net/golang/jwt" ) type LagReader struct { lag time.Duration src io.Reader } func main() { var bodyRepeat int var path, host, method, body, headers, brandID, issuer, basicAuth, claims string var ca, cert, key, secret string var needJWT, verbose, jsonPP bool var timeout, lag time.Duration flag.StringVar(&method, "method", "get", "method for request") flag.StringVar(&path, "path", "fieldsetdefinitions/v1/index/surveys/SV_031sm3MMOPSa8Tz/fieldsets?assumeHasPermission=true", "path for request") flag.StringVar(&host, "host", "data-platform.service.b1-prv.consul:8080", "host and port for request") flag.StringVar(&body, "body", "", "body for request") flag.IntVar(&bodyRepeat, "bodyrepeat", 1, "repeat body for request") flag.StringVar(&brandID, "brand", "testencresponse", "brandID for request JWT") flag.StringVar(&basicAuth, "auth", "", "comma separated user,password for basic auth") flag.StringVar(&headers, "headers", "", "headers as k=v,k=v for request") flag.StringVar(&issuer, "issuer", "dataprocessing,responseengine,fieldset-definitions,qualtrics,objectstore,svs,monolith,ex,blixt,null,responseengine", "issuer for jwt") flag.BoolVar(&needJWT, "jwt", true, "need jwt boolean") flag.BoolVar(&jsonPP, "jpp", true, "try json pretty print") flag.BoolVar(&verbose, "v", false, "is verbose") flag.DurationVar(&timeout, "t", time.Second*10, "request timeout") flag.DurationVar(&lag, "lag", time.Second*0, "writing request lag after connecting") flag.StringVar(&ca, "ca", "", "ca for server") flag.StringVar(&cert, "cert", "", "cert for client") flag.StringVar(&key, "key", "", "key for client") flag.StringVar(&secret, "secret", "dnKgzTPNZyEd2Kfop", "secret for jwt") flag.StringVar(&claims, "claims", "", "extra claims as k=v,k=v") flag.Parse() if !strings.HasPrefix(host, "http") { host = "http://" + host } c := makeClient(timeout, ca, cert, key) var reqBody io.Reader if bodyRepeat >= 1 { reqBody = strings.NewReader(strings.Repeat(body, bodyRepeat)) } else { reqBody = os.Stdin } reqBody = NewLagReader(lag, reqBody) req, err := http.NewRequest( strings.ToUpper(method), host+"/"+strings.Trim(path, "/"), reqBody, ) if err != nil { panic(err) } req.Header.Add("Content-Type", "application/json") if len(headers) > 0 { for _, pair := range strings.Split(headers, ",") { kv := strings.Split(pair, "=") req.Header.Add(kv[0], kv[1]) } } if needJWT { setJWT(req, brandID, issuer, secret, claims) } if basicAuth != "" { splits := strings.Split(basicAuth, ",") req.SetBasicAuth(splits[0], splits[1]) } if verbose { fmt.Fprintf(os.Stderr, "%v\n", req) } resp, err := c.Do(req) if err != nil { fmt.Println("DO FAILED:", err) return } if verbose { fmt.Fprintf(os.Stderr, "%v\n", resp.Header) } b, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("READ BODY FAILED:", err) return } defer resp.Body.Close() fmt.Fprintf(os.Stderr, "(%d) ", resp.StatusCode) if jsonPP { var v interface{} if err := json.Unmarshal(b, &v); err == nil { if c, err := json.MarshalIndent(v, "", " "); err == nil { b = c } } } fmt.Printf("%s\n", bytes.TrimSpace(b)) } func makeClient(timeout time.Duration, ca, cert, key string) *http.Client { transport := &http.Transport{ TLSClientConfig: &tls.Config{}, } if ca == "" { transport.TLSClientConfig.InsecureSkipVerify = true } else { caBytes, err := ioutil.ReadFile(ca) if err != nil { panic(err) } rootCAs := x509.NewCertPool() rootCAs.AppendCertsFromPEM(caBytes) transport.TLSClientConfig.RootCAs = rootCAs } if cert != "" && key != "" { clientCert, err := tls.LoadX509KeyPair(cert, key) if err != nil { panic(err) } transport.TLSClientConfig.Certificates = []tls.Certificate{clientCert} transport.TLSClientConfig.BuildNameToCertificate() } return &http.Client{ Timeout: timeout, Transport: transport, } } func setJWT(r *http.Request, brandID string, issuer, secret, claims string) { signer := &jwt.Signer{ Key: []byte(secret), DefaultClaims: jwt.Claims{ Audience: "qualtrics", Issuer: issuer, UserID: "breel", BrandID: brandID, Custom: map[string]interface{}{ "IsolationPartitionID": brandID, "userType": "UT_SERVERADMIN", }, }, IncludeBodyHash: true, } for _, claim := range strings.Split(claims, ",") { c := strings.Split(claim, "=") if len(c) < 2 { continue } signer.DefaultClaims.Custom[c[0]] = c[1] } if err := signer.Sign(r, jwt.Claims{}); err != nil { panic(err) } } func NewLagReader(lag time.Duration, src io.Reader) *LagReader { return &LagReader{ lag: lag, src: src, } } func (lr *LagReader) Read(p []byte) (n int, err error) { if lr.lag > 0 { <-time.After(lr.lag) lr.lag = 0 } return lr.src.Read(p) }