package client import ( "bytes" "crypto" "crypto/ecdsa" "crypto/ed25519" "crypto/rsa" "fmt" "net/http" "net/url" "reflect" "github.com/common-fate/httpsig" "github.com/common-fate/httpsig/alg_ecdsa" "github.com/common-fate/httpsig/alg_ed25519" "github.com/common-fate/httpsig/alg_rsa" "github.com/common-fate/httpsig/signer" "github.com/opencontainers/go-digest" ) func Post(baseUrl *url.URL, key crypto.PrivateKey, keyId string, data []byte, simulateCaddy bool) (*http.Response, error) { client, err := getSigningClient(key, keyId) if err != nil { return nil, err } id := digest.FromBytes(data) authUrl := baseUrl.JoinPath("auth") var req *http.Request req, err = http.NewRequest("POST", authUrl.String(), bytes.NewBuffer(data)) if err != nil { return nil, err } req.Header.Add("Content-Digest", string(id.Algorithm())+"="+id.Encoded()) req.Header.Add("Content-Type", "application/json") if simulateCaddy { req.Header.Add("X-Forwarded-Method", req.Method) req.Header.Add("X-Forwarded-Uri", req.RequestURI) } resp, err := client.Do(req) return resp, err } func getSigningClient(key crypto.PrivateKey, keyId string) (*http.Client, error) { var alg signer.Algorithm switch p := key.(type) { case *rsa.PrivateKey: alg = alg_rsa.NewRSAPKCS256Signer(p) case *ed25519.PrivateKey: alg = alg_ed25519.Ed25519{PrivateKey: *p} case *ecdsa.PrivateKey: alg = alg_ecdsa.NewP256Signer(p) default: return nil, fmt.Errorf("type is unknown: %s", reflect.TypeOf(key)) } client := httpsig.NewClient(httpsig.ClientOpts{ Tag: "auth", KeyID: keyId, Alg: alg, }) return client, nil }