jwtcurl/main.go

176 lines
4.5 KiB
Go

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 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.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)
}
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
}
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 string, secret string) {
signer := &jwt.Signer{
Key: []byte(secret),
DefaultClaims: jwt.Claims{
Audience: "qualtrics",
Issuer: issuer,
UserID: "breel",
BrandID: brandID,
Custom: map[string]interface{}{
"IsolationPartitionID": brandID,
},
},
IncludeBodyHash: true,
}
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)
}