From 773e2db0e8e3bfa1e4af4756e6fa5faf19a15e98 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sat, 14 Mar 2020 16:34:58 -0700 Subject: [PATCH] [go-experimental] Do not generate HTTP signature unit test for every generated SDK (#5588) * Do not generate HTTP signature unit test for every generated SDK * Add golang 1.14 to CI environment * fix unit test issues * remove script commands that were commented out * add support for ed25519 private keys --- CI/circle_parallel.sh | 6 + .../http_signature_test.mustache | 720 ------------------ .../go-experimental/signing.mustache | 5 +- .../go-experimental/go-petstore/signing.go | 5 +- .../{go-petstore => }/http_signature_test.go | 158 ++-- 5 files changed, 89 insertions(+), 805 deletions(-) delete mode 100644 modules/openapi-generator/src/main/resources/go-experimental/http_signature_test.mustache rename samples/openapi3/client/petstore/go-experimental/{go-petstore => }/http_signature_test.go (84%) diff --git a/CI/circle_parallel.sh b/CI/circle_parallel.sh index c28cd709ea0f..811973af9764 100755 --- a/CI/circle_parallel.sh +++ b/CI/circle_parallel.sh @@ -10,6 +10,12 @@ set -e if [ "$NODE_INDEX" = "1" ]; then echo "Running node $NODE_INDEX to test 'samples.circleci' defined in pom.xml ..." java -version + # Install golang version 1.14 + go version + sudo mkdir /usr/local/go1.14 + wget -c https://dl.google.com/go/go1.14.linux-amd64.tar.gz -O - | sudo tar -xz -C /usr/local/go1.14 + export PATH="/usr/local/go1.14/go/bin:$PATH" + go version mvn --quiet verify -Psamples.circleci -Dorg.slf4j.simpleLogger.defaultLogLevel=error mvn --quiet javadoc:javadoc -Psamples.circleci -Dorg.slf4j.simpleLogger.defaultLogLevel=error diff --git a/modules/openapi-generator/src/main/resources/go-experimental/http_signature_test.mustache b/modules/openapi-generator/src/main/resources/go-experimental/http_signature_test.mustache deleted file mode 100644 index 79202f6f4aff..000000000000 --- a/modules/openapi-generator/src/main/resources/go-experimental/http_signature_test.mustache +++ /dev/null @@ -1,720 +0,0 @@ -{{>partial_header}} -package {{packageName}} - -import ( - "bytes" - "context" - "crypto" - "crypto/ecdsa" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/asn1" - "encoding/base64" - "encoding/pem" - "fmt" - "io/ioutil" - "math/big" - "net/http" - "net/http/httputil" - "os" - "path/filepath" - "regexp" - "strings" - "testing" - "time" -) - -// Test RSA private key as published in Appendix C 'Test Values' of -// https://www.ietf.org/id/draft-cavage-http-signatures-12.txt -const rsaTestPrivateKey string = `-----BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF -NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F -UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB -AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA -QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK -kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg -f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u -412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc -mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7 -kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA -gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW -G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI -7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA== ------END RSA PRIVATE KEY-----` - -func writeTestRsaPemKey(t *testing.T, filePath string) { - err := ioutil.WriteFile(filePath, []byte(rsaTestPrivateKey), 0644) - if err != nil { - t.Fatalf("Error writing private key: %v", err) - } -} - -type keyFormat int // The serialization format of the private key. - -const ( - keyFormatPem keyFormat = iota // Private key is serialized in PEM format. - keyFormatPkcs8Pem // Private key is serialized as PKCS#8 encoded in PEM format. - keyFormatPkcs8Der // Private key is serialized as PKCS#8 encoded in DER format. -) - -func writeRandomTestRsaPemKey(t *testing.T, filePath string, bits int, format keyFormat, passphrase string, alg *x509.PEMCipher) { - key, err := rsa.GenerateKey(rand.Reader, bits) - if err != nil { - t.Fatalf("Error generating RSA private key file: %v", err) - } - var outFile *os.File - outFile, err = os.Create(filePath) - if err != nil { - t.Fatalf("Error creating RSA private key file: %v", err) - } - defer outFile.Close() - var privKeyBytes []byte - switch format { - case keyFormatPem: - if passphrase != "" { - t.Fatalf("Encrypting PKCS#1-encoded private key with passphrase is not supported") - } - privKeyBytes = x509.MarshalPKCS1PrivateKey(key) - case keyFormatPkcs8Pem: - privKeyBytes, err = x509.MarshalPKCS8PrivateKey(key) - if err != nil { - t.Fatalf("Error writing private key: %v", err) - } - case keyFormatPkcs8Der: - if passphrase != "" { - t.Fatalf("Encrypting DER-encoded private key with passphrase is not supported") - } - privKeyBytes, err = x509.MarshalPKCS8PrivateKey(key) - if err != nil { - t.Fatalf("Error writing private key: %v", err) - } - _, err = outFile.Write(privKeyBytes) - if err != nil { - t.Fatalf("Error writing DER-encoded private key: %v", err) - } - default: - t.Fatalf("Unsupported key format: %v", format) - } - - switch format { - case keyFormatPem, keyFormatPkcs8Der: - var pemBlock *pem.Block - if passphrase == "" { - pemBlock = &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: privKeyBytes, - } - } else { - pemBlock, err = x509.EncryptPEMBlock(rand.Reader, "ENCRYPTED PRIVATE KEY", privKeyBytes, []byte(passphrase), *alg) - if err != nil { - t.Fatalf("Error encoding RSA private key: %v", err) - } - } - err = pem.Encode(outFile, pemBlock) - if err != nil { - t.Fatalf("Error encoding RSA private key: %v", err) - } - } - fmt.Printf("Wrote private key '%s'\n", filePath) -} - -/* -Commented out because OpenAPITools is configured to use golang 1.8 at build time -x509.MarshalPKCS8PrivateKey is not present. -func writeRandomTestEcdsaPemKey(t *testing.T, filePath string) { - key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) - if err != nil { - t.Fatalf("Error generating ECDSA private key file: %v", err) - } - var outFile *os.File - outFile, err = os.Create(filePath) - if err != nil { - t.Fatalf("Error creating ECDSA private key file: %v", err) - } - defer outFile.Close() - - var keybytes []byte - keybytes, err = x509.MarshalPKCS8PrivateKey(key) - if err != nil { - t.Fatalf("Error marshaling ECDSA private key: %v", err) - } - var privateKey = &pem.Block{ - Type: "PRIVATE KEY", - Bytes: keybytes, - } - - err = pem.Encode(outFile, privateKey) - if err != nil { - t.Fatalf("Error encoding ECDSA private key: %v", err) - } -} -*/ - -// TestHttpSignaturePrivateKeys creates private keys of various sizes, serialization format, -// clear-text and password encrypted. -// Test unmarshaling of the private key. -func TestHttpSignaturePrivateKeys(t *testing.T) { - var err error - var dir string - dir, err = ioutil.TempDir("", "go-http-sign") - if err != nil { - t.Fatalf("Failed to create temporary directory") - } - defer os.RemoveAll(dir) - - pemCiphers := []x509.PEMCipher{ - x509.PEMCipherDES, - x509.PEMCipher3DES, - x509.PEMCipherAES128, - x509.PEMCipherAES192, - x509.PEMCipherAES256, - } - // Test RSA private keys with various key lengths. - for _, bits := range []int{1024, 2048, 3072, 4096} { - - for _, format := range []keyFormat{keyFormatPem, keyFormatPkcs8Pem, keyFormatPkcs8Der} { - // Generate test private key. - var privateKeyPath string - switch format { - case keyFormatPem, keyFormatPkcs8Pem: - privateKeyPath = "privatekey.pem" - case keyFormatPkcs8Der: - privateKeyPath = "privatekey.der" - default: - t.Fatalf("Unsupported private key format: %v", format) - } - privateKeyPath = filepath.Join(dir, privateKeyPath) - // Generate keys in PEM format. - writeRandomTestRsaPemKey(t, privateKeyPath, bits, format, "", nil) - - authConfig := HttpSignatureAuth{ - KeyId: "my-key-id", - PrivateKeyPath: privateKeyPath, - Passphrase: "", - SigningScheme: "hs2019", - SignedHeaders: []string{"Content-Type"}, - } - - // Create a context with the HTTP signature configuration parameters. - _, err = authConfig.ContextWithValue(context.Background()) - if err != nil { - t.Fatalf("Error loading private key '%s': %v", privateKeyPath, err) - } - - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - PrivateKeyPath: privateKeyPath, - Passphrase: "my-secret-passphrase", - SigningScheme: "hs2019", - SignedHeaders: []string{"Content-Type"}, - } - switch format { - case keyFormatPem: - // Do nothing. Keys cannot be encrypted when using PKCS#1. - case keyFormatPkcs8Pem: - for _, alg := range pemCiphers { - writeRandomTestRsaPemKey(t, privateKeyPath, bits, format, authConfig.Passphrase, &alg) - _, err := authConfig.ContextWithValue(context.Background()) - if err != nil { - t.Fatalf("Error loading private key '%s': %v", privateKeyPath, err) - } - } - } - } - } - - /* - Unfortunately, currently the build environment for OpenAPITools is using an old version - of golang that does not support ECDSA keys. - { - privateKeyPath := "privatekey.pem" - authConfig := HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: "hs2019", - SignedHeaders: []string{"Content-Type"}, - } - // Generate test private key. - writeRandomTestEcdsaPemKey(t, privateKeyPath) - err := authConfig.LoadPrivateKey(privateKeyPath) - if err != nil { - t.Fatalf("Error loading private key '%s': %v", privateKeyPath, err) - } - } - */ -} - -const testHost = "petstore.swagger.io:80" -const testScheme = "http" - -func executeHttpSignatureAuth(t *testing.T, authConfig *HttpSignatureAuth, expectSuccess bool) string { - var err error - var dir string - dir, err = ioutil.TempDir("", "go-http-sign") - if err != nil { - t.Fatalf("Failed to create temporary directory") - } - defer os.RemoveAll(dir) - - cfg := NewConfiguration() - cfg.AddDefaultHeader("testheader", "testvalue") - cfg.AddDefaultHeader("Content-Type", "application/json") - cfg.Host = testHost - cfg.Scheme = testScheme - apiClient := NewAPIClient(cfg) - - privateKeyPath := filepath.Join(dir, "rsa.pem") - writeTestRsaPemKey(t, privateKeyPath) - authConfig.PrivateKeyPath = privateKeyPath - var authCtx context.Context - authCtx, err = authConfig.ContextWithValue(context.Background()) - if expectSuccess && err != nil { - t.Fatalf("Error validating HTTP signature configuration: %v", err) - } - if !expectSuccess && err != nil { - // Do not continue. Error is expected. - return "" - } - newPet := (Pet{Id: PtrInt64(12992), Name: "gopher", - PhotoUrls: []string{"http://1.com", "http://2.com"}, - Status: PtrString("pending"), - Tags: &[]Tag{Tag{Id: PtrInt64(1), Name: PtrString("tag2")}}}) - - fmt.Printf("Request with HTTP signature. Scheme: '%s'. Algorithm: '%s'. MaxValidity: %v. Headers: '%v'\n", - authConfig.SigningScheme, authConfig.SigningAlgorithm, authConfig.SignatureMaxValidity, authConfig.SignedHeaders) - - r, err2 := apiClient.PetApi.AddPet(authCtx).Pet(newPet).Execute() - if expectSuccess && err2 != nil { - t.Fatalf("Error while adding pet: %v", err2) - } - if !expectSuccess { - if err2 == nil { - t.Fatalf("Error was expected, but no error was generated") - } else { - // Do not continue. Error is expected. - return "" - } - } - if r.StatusCode != 200 { - t.Log(r) - } - - _, r, err = apiClient.PetApi.GetPetById(authCtx, 12992).Execute() - if expectSuccess && err != nil { - t.Fatalf("Error while deleting pet by id: %v", err) - } - - // The request should look like this: - // - // GET /v2/pet/12992 HTTP/1.1 - // Host: petstore.swagger.io:80 - // Accept: application/json - // Authorization: Signature keyId="my-key-id",algorithm="hs2019",created=1579033245,headers="(request-target) date host digest content-type",signature="RMJZjVVxzlH02wlxiQgUYDe4QxZaI5IJNIfB2BK8Dhbv3WQ2gw0xyqC+5HiKUmT/cfchhhkUNNsUtiVRnjZmFwtSfYxHfiQvH3KWXlLCMwKGNQC3YzD9lnoWdx0pA5Kxbr0/ygmr3+lTyuN2PJg4IS7Ji/AaKAqIZx7RsHS8Bxw=" - // Date: Tue, 14 Jan 2020 06:41:22 GMT - // Digest: SHA-512=z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg== - // Testheader: testvalue - // User-Agent: OpenAPI-Generator/1.0.0/go - reqb, _ := httputil.DumpRequest(r.Request, true) - reqt := (string)(reqb) - fmt.Printf("REQUEST:\n%v\n", reqt) - var sb bytes.Buffer - fmt.Fprintf(&sb, `Signature keyId="%s",algorithm="%s",`, - authConfig.KeyId, authConfig.SigningScheme) - if len(authConfig.SignedHeaders) == 0 { - fmt.Fprintf(&sb, `created=[0-9]+,`) - } else { - for _, header := range authConfig.SignedHeaders { - header = strings.ToLower(header) - if header == HttpSignatureParameterCreated { - fmt.Fprintf(&sb, `created=[0-9]+,`) - } - if header == HttpSignatureParameterExpires { - fmt.Fprintf(&sb, `expires=[0-9]+\.[0-9]{3},`) - } - } - } - fmt.Fprintf(&sb, `headers="`) - for i, header := range authConfig.SignedHeaders { - header = strings.ToLower(header) - if i > 0 { - fmt.Fprintf(&sb, " ") - } - fmt.Fprintf(&sb, regexp.QuoteMeta(header)) - switch header { - case "date": - if !strings.Contains(reqt, "Date: ") { - t.Errorf("Date header is incorrect") - } - case "digest": - var prefix string - switch authConfig.SigningScheme { - case HttpSigningSchemeRsaSha256: - prefix = "SHA-256=" - default: - prefix = "SHA-512=" - } - if !strings.Contains(reqt, fmt.Sprintf("Digest: %s", prefix)) { - t.Errorf("Digest header is incorrect") - } - } - } - if len(authConfig.SignedHeaders) == 0 { - fmt.Fprintf(&sb, regexp.QuoteMeta(HttpSignatureParameterCreated)) - } - fmt.Fprintf(&sb, `",signature="[a-zA-Z0-9+/]+="`) - re := regexp.MustCompile(sb.String()) - actual := r.Request.Header.Get("Authorization") - if !re.MatchString(actual) { - t.Errorf("Authorization header is incorrect. Expected regex\n'%s'\nbut got\n'%s'", sb.String(), actual) - } - - validateHttpAuthorizationSignature(t, authConfig, r) - return r.Request.Header.Get("Authorization") -} - -var ( - // signatureRe is a regular expression to capture the fields from the signature. - signatureRe = regexp.MustCompile( - `Signature keyId="(?P[^"]+)",algorithm="(?P[^"]+)"` + - `(,created=(?P[0-9]+))?(,expires=(?P[0-9.]+))?,headers="(?P[^"]+)",signature="(?P[^"]+)"`) -) - -// validateHttpAuthorizationSignature validates the HTTP signature in the HTTP request. -// The signature verification would normally be done by the server. -// Note: this is NOT a complete implementation of the HTTP signature validation. This code is for unit test purpose, do not use -// it for server side implementation. -// In particular, this code does not validate the calculation of the HTTP body digest. -func validateHttpAuthorizationSignature(t *testing.T, authConfig *HttpSignatureAuth, r *http.Response) { - authHeader := r.Request.Header.Get("Authorization") - match := signatureRe.FindStringSubmatch(authHeader) - if len(match) < 3 { - t.Fatalf("Unexpected Authorization header: %s", authHeader) - } - result := make(map[string]string) - for i, name := range signatureRe.SubexpNames() { - if i != 0 && name != "" { - result[name] = match[i] - } - } - b64signature := result["signature"] - fmt.Printf("Algorithm: '%s' Headers: '%s' b64signature: '%s'\n", result["algorithm"], result["headers"], b64signature) - var sb bytes.Buffer - fmt.Fprintf(&sb, "%s %s", strings.ToLower(r.Request.Method), r.Request.URL.EscapedPath()) - if r.Request.URL.RawQuery != "" { - // The ":path" pseudo-header field includes the path and query parts - // of the target URI (the "path-absolute" production and optionally a - // '?' character followed by the "query" production (see Sections 3.3 - // and 3.4 of [RFC3986] - fmt.Fprintf(&sb, "?%s", r.Request.URL.RawQuery) - } - requestTarget := sb.String() - - var signedHeaderKvs []string - signedHeaders := strings.Split(result["headers"], " ") - for _, h := range signedHeaders { - var value string - switch h { - case HttpSignatureParameterRequestTarget: - value = requestTarget - case HttpSignatureParameterCreated: - value = result["created"] - case HttpSignatureParameterExpires: - value = result["expires"] - default: - value = r.Request.Header.Get(h) - } - signedHeaderKvs = append(signedHeaderKvs, fmt.Sprintf("%s: %s", h, value)) - } - stringToSign := strings.Join(signedHeaderKvs, "\n") - - var h crypto.Hash - switch result["algorithm"] { - case HttpSigningSchemeHs2019, HttpSigningSchemeRsaSha512: - h = crypto.SHA512 - case HttpSigningSchemeRsaSha256: - h = crypto.SHA256 - default: - t.Fatalf("Unexpected signing algorithm: %s", result["algorithm"]) - } - msgHash := h.New() - if _, err := msgHash.Write([]byte(stringToSign)); err != nil { - t.Fatalf("Unable to compute hash: %v", err) - } - d := msgHash.Sum(nil) - var pub crypto.PublicKey - var err error - if pub, err = authConfig.GetPublicKey(); err != nil { - t.Fatalf("Unable to get public key: %v", err) - } - if pub == nil { - t.Fatalf("Public key is nil") - } - var signature []byte - if signature, err = base64.StdEncoding.DecodeString(b64signature); err != nil { - t.Fatalf("Failed to decode signature: %v", err) - } - switch publicKey := pub.(type) { - case *rsa.PublicKey: - // It could be PKCS1v15 or PSS signature - var errPKCS1v15, errPSS error - // In a server-side implementation, we wouldn't try to validate both signatures. The specific - // signature algorithm would be derived from the key id. But here we just want to validate for unit test purpose. - errPKCS1v15 = rsa.VerifyPKCS1v15(publicKey, h, d, signature) - errPSS = rsa.VerifyPSS(publicKey, h, d, signature, nil) - if errPKCS1v15 != nil && errPSS != nil { - t.Fatalf("RSA Signature verification failed: %v. %v", errPKCS1v15, errPSS) - } - case *ecdsa.PublicKey: - type ecdsaSignature struct { - R, S *big.Int - } - var lEcdsa ecdsaSignature - if _, err = asn1.Unmarshal(signature, &lEcdsa); err != nil { - t.Fatalf("Unable to parse ECDSA signature: %v", err) - } - if !ecdsa.Verify(publicKey, d, lEcdsa.R, lEcdsa.S) { - t.Fatalf("ECDSA Signature verification failed") - } - default: - t.Fatalf("Unsupported public key: %T", pub) - } -} - -func TestHttpSignatureAuth(t *testing.T) { - // Test with 'hs2019' signature scheme, and default signature algorithm (RSA SSA PKCS1.5) - authConfig := HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. - "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. - "Date", // The date and time at which the message was originated. - "Content-Type", // The Media type of the body of the request. - "Digest", // A cryptographic digest of the request body. - }, - } - executeHttpSignatureAuth(t, &authConfig, true) - - // Test with duplicate headers. This is invalid and should be rejected. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{"Host", "Date", "Host"}, - } - executeHttpSignatureAuth(t, &authConfig, false) - - // Test with non-existent header. This is invalid and should be rejected. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{"Host", "Date", "Garbage-HeaderDoesNotExist"}, - } - executeHttpSignatureAuth(t, &authConfig, false) - - // Test with 'Authorization' header in the signed headers. This is invalid and should be rejected. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{"Host", "Authorization"}, - } - executeHttpSignatureAuth(t, &authConfig, false) - - // Specify signature max validity, but '(expires)' parameter is missing. This should cause an error. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignatureMaxValidity: 7 * time.Minute, - } - executeHttpSignatureAuth(t, &authConfig, false) - - // Specify invalid signature max validity. This should cause an error. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignatureMaxValidity: -3 * time.Minute, - } - executeHttpSignatureAuth(t, &authConfig, false) - - // Specify signature max validity and '(expires)' parameter. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignatureMaxValidity: time.Minute, - SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. - HttpSignatureParameterExpires, // Time when signature expires. - }, - } - executeHttpSignatureAuth(t, &authConfig, true) - - // Specify '(expires)' parameter but no signature max validity. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. - HttpSignatureParameterExpires, // Time when signature expires. - }, - } - executeHttpSignatureAuth(t, &authConfig, false) - - // Test with empty signed headers. The client should automatically add the "(created)" parameter by default. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{}, - } - executeHttpSignatureAuth(t, &authConfig, true) - - // Test with deprecated RSA-SHA512, some servers may still support it. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeRsaSha512, - SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. - "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. - "Date", // The date and time at which the message was originated. - "Content-Type", // The Media type of the body of the request. - "Digest", // A cryptographic digest of the request body. - }, - } - executeHttpSignatureAuth(t, &authConfig, true) - - // Test with deprecated RSA-SHA256, some servers may still support it. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeRsaSha256, - SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. - "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. - "Date", // The date and time at which the message was originated. - "Content-Type", // The Media type of the body of the request. - "Digest", // A cryptographic digest of the request body. - }, - } - executeHttpSignatureAuth(t, &authConfig, true) - - // Test with headers without date. This makes it possible to get a fixed signature, used for unit test purpose. - // This should not be used in production code as it could potentially allow replay attacks. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SigningAlgorithm: HttpSigningAlgorithmRsaPKCS1v15, - SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, - "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. - "Content-Type", // The Media type of the body of the request. - "Digest", // A cryptographic digest of the request body. - }, - } - authorizationHeaderValue := executeHttpSignatureAuth(t, &authConfig, true) - expectedSignature := "sXE2MDeW8os6ywv1oUWaFEPFcSPCEb/msQ/NZGKNA9Emm/e42axaAPojzfkZ9Hacyw/iS/5nH4YIkczMgXu3z5fAwFjumxtf3OxbqvUcQ80wvw2/7B5aQmsF6ZwrCFHZ+L/cj9/bg7L1EGUGtdyDzoRKti4zf9QF/03OsP7QljI=" - expectedAuthorizationHeader := fmt.Sprintf( - `Signature keyId="my-key-id",`+ - `algorithm="hs2019",headers="(request-target) host content-type digest",`+ - `signature="%s"`, expectedSignature) - if authorizationHeaderValue != expectedAuthorizationHeader { - t.Errorf("Authorization header value is incorrect. Got\n'%s'\nbut expected\n'%s'", authorizationHeaderValue, expectedAuthorizationHeader) - } - - // Test with PSS signature. The PSS signature creates a new signature every time it is invoked. - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SigningAlgorithm: HttpSigningAlgorithmRsaPSS, - SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, - "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. - "Content-Type", // The Media type of the body of the request. - "Digest", // A cryptographic digest of the request body. - }, - } - authorizationHeaderValue = executeHttpSignatureAuth(t, &authConfig, true) - expectedSignature = `[a-zA-Z0-9+/]+=` - expectedAuthorizationHeader = fmt.Sprintf( - `Signature keyId="my-key-id",`+ - `algorithm="hs2019",headers="\(request-target\) host content-type digest",`+ - `signature="%s"`, expectedSignature) - re := regexp.MustCompile(expectedAuthorizationHeader) - if !re.MatchString(authorizationHeaderValue) { - t.Errorf("Authorization header value is incorrect. Got\n'%s'\nbut expected\n'%s'", authorizationHeaderValue, expectedAuthorizationHeader) - } -} - -func TestInvalidHttpSignatureConfiguration(t *testing.T) { - var err error - var authConfig HttpSignatureAuth - - authConfig = HttpSignatureAuth{ - } - _, err = authConfig.ContextWithValue(context.Background()) - if err == nil || !strings.Contains(err.Error(), "Key ID must be specified") { - t.Fatalf("Invalid configuration: %v", err) - } - - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - } - _, err = authConfig.ContextWithValue(context.Background()) - if err == nil || !strings.Contains(err.Error(), "Private key path must be specified") { - t.Fatalf("Invalid configuration: %v", err) - } - - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - PrivateKeyPath: "test.pem", - } - _, err = authConfig.ContextWithValue(context.Background()) - if err == nil || !strings.Contains(err.Error(), "Invalid signing scheme") { - t.Fatalf("Invalid configuration: %v", err) - } - - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - PrivateKeyPath: "test.pem", - SigningScheme: "garbage", - } - _, err = authConfig.ContextWithValue(context.Background()) - if err == nil || !strings.Contains(err.Error(), "Invalid signing scheme") { - t.Fatalf("Invalid configuration: %v", err) - } - - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - PrivateKeyPath: "test.pem", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{"foo", "bar", "foo"}, - } - _, err = authConfig.ContextWithValue(context.Background()) - if err == nil || !strings.Contains(err.Error(), "cannot have duplicate names") { - t.Fatalf("Invalid configuration: %v", err) - } - - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - PrivateKeyPath: "test.pem", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{"foo", "bar", "Authorization"}, - } - _, err = authConfig.ContextWithValue(context.Background()) - if err == nil || !strings.Contains(err.Error(), "Signed headers cannot include the 'Authorization' header") { - t.Fatalf("Invalid configuration: %v", err) - } - - authConfig = HttpSignatureAuth{ - KeyId: "my-key-id", - PrivateKeyPath: "test.pem", - SigningScheme: HttpSigningSchemeHs2019, - SignedHeaders: []string{"foo", "bar"}, - SignatureMaxValidity: -7 * time.Minute, - } - _, err = authConfig.ContextWithValue(context.Background()) - if err == nil || !strings.Contains(err.Error(), "Signature max validity must be a positive value") { - t.Fatalf("Invalid configuration: %v", err) - } -} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/go-experimental/signing.mustache b/modules/openapi-generator/src/main/resources/go-experimental/signing.mustache index 0dbfd0e5fa44..df11e4006ab2 100644 --- a/modules/openapi-generator/src/main/resources/go-experimental/signing.mustache +++ b/modules/openapi-generator/src/main/resources/go-experimental/signing.mustache @@ -6,6 +6,7 @@ import ( "context" "crypto" "crypto/ecdsa" + "crypto/ed25519" "crypto/rand" "crypto/rsa" "crypto/x509" @@ -382,8 +383,8 @@ func SignRequest( } case *ecdsa.PrivateKey: signature, err = key.Sign(rand.Reader, d, h) - //case ed25519.PrivateKey: requires go 1.13 - // signature, err = key.Sign(rand.Reader, msg, crypto.Hash(0)) + case ed25519.PrivateKey: // requires go 1.13 + signature, err = key.Sign(rand.Reader, msg, crypto.Hash(0)) default: return fmt.Errorf("Unsupported private key") } diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/signing.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/signing.go index d28fd6a379e3..07209028266d 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/signing.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/signing.go @@ -14,6 +14,7 @@ import ( "context" "crypto" "crypto/ecdsa" + "crypto/ed25519" "crypto/rand" "crypto/rsa" "crypto/x509" @@ -390,8 +391,8 @@ func SignRequest( } case *ecdsa.PrivateKey: signature, err = key.Sign(rand.Reader, d, h) - //case ed25519.PrivateKey: requires go 1.13 - // signature, err = key.Sign(rand.Reader, msg, crypto.Hash(0)) + case ed25519.PrivateKey: // requires go 1.13 + signature, err = key.Sign(rand.Reader, msg, crypto.Hash(0)) default: return fmt.Errorf("Unsupported private key") } diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/http_signature_test.go b/samples/openapi3/client/petstore/go-experimental/http_signature_test.go similarity index 84% rename from samples/openapi3/client/petstore/go-experimental/go-petstore/http_signature_test.go rename to samples/openapi3/client/petstore/go-experimental/http_signature_test.go index f5f08b2ae6ef..9336d0ca420a 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/http_signature_test.go +++ b/samples/openapi3/client/petstore/go-experimental/http_signature_test.go @@ -1,13 +1,10 @@ /* * OpenAPI Petstore * - * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ - * - * API version: 1.0.0 - * Generated by: OpenAPI Generator (https://openapi-generator.tech) + * Unit Tests for HTTP signature. */ -package petstore +package main import ( "bytes" @@ -31,6 +28,8 @@ import ( "strings" "testing" "time" + + sw "./go-petstore" ) // Test RSA private key as published in Appendix C 'Test Values' of @@ -196,7 +195,7 @@ func TestHttpSignaturePrivateKeys(t *testing.T) { // Generate keys in PEM format. writeRandomTestRsaPemKey(t, privateKeyPath, bits, format, "", nil) - authConfig := HttpSignatureAuth{ + authConfig := sw.HttpSignatureAuth{ KeyId: "my-key-id", PrivateKeyPath: privateKeyPath, Passphrase: "", @@ -210,7 +209,7 @@ func TestHttpSignaturePrivateKeys(t *testing.T) { t.Fatalf("Error loading private key '%s': %v", privateKeyPath, err) } - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", PrivateKeyPath: privateKeyPath, Passphrase: "my-secret-passphrase", @@ -237,7 +236,7 @@ func TestHttpSignaturePrivateKeys(t *testing.T) { of golang that does not support ECDSA keys. { privateKeyPath := "privatekey.pem" - authConfig := HttpSignatureAuth{ + authConfig := sw.HttpSignatureAuth{ KeyId: "my-key-id", SigningScheme: "hs2019", SignedHeaders: []string{"Content-Type"}, @@ -252,10 +251,7 @@ func TestHttpSignaturePrivateKeys(t *testing.T) { */ } -const testHost = "petstore.swagger.io:80" -const testScheme = "http" - -func executeHttpSignatureAuth(t *testing.T, authConfig *HttpSignatureAuth, expectSuccess bool) string { +func executeHttpSignatureAuth(t *testing.T, authConfig *sw.HttpSignatureAuth, expectSuccess bool) string { var err error var dir string dir, err = ioutil.TempDir("", "go-http-sign") @@ -264,12 +260,12 @@ func executeHttpSignatureAuth(t *testing.T, authConfig *HttpSignatureAuth, expec } defer os.RemoveAll(dir) - cfg := NewConfiguration() + cfg := sw.NewConfiguration() cfg.AddDefaultHeader("testheader", "testvalue") cfg.AddDefaultHeader("Content-Type", "application/json") cfg.Host = testHost cfg.Scheme = testScheme - apiClient := NewAPIClient(cfg) + apiClient := sw.NewAPIClient(cfg) privateKeyPath := filepath.Join(dir, "rsa.pem") writeTestRsaPemKey(t, privateKeyPath) @@ -283,10 +279,10 @@ func executeHttpSignatureAuth(t *testing.T, authConfig *HttpSignatureAuth, expec // Do not continue. Error is expected. return "" } - newPet := (Pet{Id: PtrInt64(12992), Name: "gopher", + newPet := (sw.Pet{Id: sw.PtrInt64(12992), Name: "gopher", PhotoUrls: []string{"http://1.com", "http://2.com"}, - Status: PtrString("pending"), - Tags: &[]Tag{Tag{Id: PtrInt64(1), Name: PtrString("tag2")}}}) + Status: sw.PtrString("pending"), + Tags: &[]sw.Tag{sw.Tag{Id: sw.PtrInt64(1), Name: sw.PtrString("tag2")}}}) fmt.Printf("Request with HTTP signature. Scheme: '%s'. Algorithm: '%s'. MaxValidity: %v. Headers: '%v'\n", authConfig.SigningScheme, authConfig.SigningAlgorithm, authConfig.SignatureMaxValidity, authConfig.SignedHeaders) @@ -333,10 +329,10 @@ func executeHttpSignatureAuth(t *testing.T, authConfig *HttpSignatureAuth, expec } else { for _, header := range authConfig.SignedHeaders { header = strings.ToLower(header) - if header == HttpSignatureParameterCreated { + if header == sw.HttpSignatureParameterCreated { fmt.Fprintf(&sb, `created=[0-9]+,`) } - if header == HttpSignatureParameterExpires { + if header == sw.HttpSignatureParameterExpires { fmt.Fprintf(&sb, `expires=[0-9]+\.[0-9]{3},`) } } @@ -356,7 +352,7 @@ func executeHttpSignatureAuth(t *testing.T, authConfig *HttpSignatureAuth, expec case "digest": var prefix string switch authConfig.SigningScheme { - case HttpSigningSchemeRsaSha256: + case sw.HttpSigningSchemeRsaSha256: prefix = "SHA-256=" default: prefix = "SHA-512=" @@ -367,7 +363,7 @@ func executeHttpSignatureAuth(t *testing.T, authConfig *HttpSignatureAuth, expec } } if len(authConfig.SignedHeaders) == 0 { - fmt.Fprintf(&sb, regexp.QuoteMeta(HttpSignatureParameterCreated)) + fmt.Fprintf(&sb, regexp.QuoteMeta(sw.HttpSignatureParameterCreated)) } fmt.Fprintf(&sb, `",signature="[a-zA-Z0-9+/]+="`) re := regexp.MustCompile(sb.String()) @@ -392,7 +388,7 @@ var ( // Note: this is NOT a complete implementation of the HTTP signature validation. This code is for unit test purpose, do not use // it for server side implementation. // In particular, this code does not validate the calculation of the HTTP body digest. -func validateHttpAuthorizationSignature(t *testing.T, authConfig *HttpSignatureAuth, r *http.Response) { +func validateHttpAuthorizationSignature(t *testing.T, authConfig *sw.HttpSignatureAuth, r *http.Response) { authHeader := r.Request.Header.Get("Authorization") match := signatureRe.FindStringSubmatch(authHeader) if len(match) < 3 { @@ -422,11 +418,11 @@ func validateHttpAuthorizationSignature(t *testing.T, authConfig *HttpSignatureA for _, h := range signedHeaders { var value string switch h { - case HttpSignatureParameterRequestTarget: + case sw.HttpSignatureParameterRequestTarget: value = requestTarget - case HttpSignatureParameterCreated: + case sw.HttpSignatureParameterCreated: value = result["created"] - case HttpSignatureParameterExpires: + case sw.HttpSignatureParameterExpires: value = result["expires"] default: value = r.Request.Header.Get(h) @@ -437,9 +433,9 @@ func validateHttpAuthorizationSignature(t *testing.T, authConfig *HttpSignatureA var h crypto.Hash switch result["algorithm"] { - case HttpSigningSchemeHs2019, HttpSigningSchemeRsaSha512: + case sw.HttpSigningSchemeHs2019, sw.HttpSigningSchemeRsaSha512: h = crypto.SHA512 - case HttpSigningSchemeRsaSha256: + case sw.HttpSigningSchemeRsaSha256: h = crypto.SHA256 default: t.Fatalf("Unexpected signing algorithm: %s", result["algorithm"]) @@ -490,12 +486,12 @@ func validateHttpAuthorizationSignature(t *testing.T, authConfig *HttpSignatureA func TestHttpSignatureAuth(t *testing.T) { // Test with 'hs2019' signature scheme, and default signature algorithm (RSA SSA PKCS1.5) - authConfig := HttpSignatureAuth{ + authConfig := sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. + sw.HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. + sw.HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. "Date", // The date and time at which the message was originated. "Content-Type", // The Media type of the body of the request. @@ -505,85 +501,85 @@ func TestHttpSignatureAuth(t *testing.T) { executeHttpSignatureAuth(t, &authConfig, true) // Test with duplicate headers. This is invalid and should be rejected. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{"Host", "Date", "Host"}, } executeHttpSignatureAuth(t, &authConfig, false) // Test with non-existent header. This is invalid and should be rejected. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{"Host", "Date", "Garbage-HeaderDoesNotExist"}, } executeHttpSignatureAuth(t, &authConfig, false) // Test with 'Authorization' header in the signed headers. This is invalid and should be rejected. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{"Host", "Authorization"}, } executeHttpSignatureAuth(t, &authConfig, false) // Specify signature max validity, but '(expires)' parameter is missing. This should cause an error. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignatureMaxValidity: 7 * time.Minute, } executeHttpSignatureAuth(t, &authConfig, false) // Specify invalid signature max validity. This should cause an error. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignatureMaxValidity: -3 * time.Minute, } executeHttpSignatureAuth(t, &authConfig, false) // Specify signature max validity and '(expires)' parameter. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignatureMaxValidity: time.Minute, SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. - HttpSignatureParameterExpires, // Time when signature expires. + sw.HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. + sw.HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. + sw.HttpSignatureParameterExpires, // Time when signature expires. }, } executeHttpSignatureAuth(t, &authConfig, true) // Specify '(expires)' parameter but no signature max validity. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. - HttpSignatureParameterExpires, // Time when signature expires. + sw.HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. + sw.HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. + sw.HttpSignatureParameterExpires, // Time when signature expires. }, } executeHttpSignatureAuth(t, &authConfig, false) // Test with empty signed headers. The client should automatically add the "(created)" parameter by default. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{}, } executeHttpSignatureAuth(t, &authConfig, true) // Test with deprecated RSA-SHA512, some servers may still support it. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeRsaSha512, + SigningScheme: sw.HttpSigningSchemeRsaSha512, SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. + sw.HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. + sw.HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. "Date", // The date and time at which the message was originated. "Content-Type", // The Media type of the body of the request. @@ -593,12 +589,12 @@ func TestHttpSignatureAuth(t *testing.T) { executeHttpSignatureAuth(t, &authConfig, true) // Test with deprecated RSA-SHA256, some servers may still support it. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeRsaSha256, + SigningScheme: sw.HttpSigningSchemeRsaSha256, SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. - HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. + sw.HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target. + sw.HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value. "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. "Date", // The date and time at which the message was originated. "Content-Type", // The Media type of the body of the request. @@ -609,12 +605,12 @@ func TestHttpSignatureAuth(t *testing.T) { // Test with headers without date. This makes it possible to get a fixed signature, used for unit test purpose. // This should not be used in production code as it could potentially allow replay attacks. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SigningAlgorithm: HttpSigningAlgorithmRsaPKCS1v15, + SigningScheme: sw.HttpSigningSchemeHs2019, + SigningAlgorithm: sw.HttpSigningAlgorithmRsaPKCS1v15, SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, + sw.HttpSignatureParameterRequestTarget, "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. "Content-Type", // The Media type of the body of the request. "Digest", // A cryptographic digest of the request body. @@ -631,12 +627,12 @@ func TestHttpSignatureAuth(t *testing.T) { } // Test with PSS signature. The PSS signature creates a new signature every time it is invoked. - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", - SigningScheme: HttpSigningSchemeHs2019, - SigningAlgorithm: HttpSigningAlgorithmRsaPSS, + SigningScheme: sw.HttpSigningSchemeHs2019, + SigningAlgorithm: sw.HttpSigningAlgorithmRsaPSS, SignedHeaders: []string{ - HttpSignatureParameterRequestTarget, + sw.HttpSignatureParameterRequestTarget, "Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number. "Content-Type", // The Media type of the body of the request. "Digest", // A cryptographic digest of the request body. @@ -656,16 +652,16 @@ func TestHttpSignatureAuth(t *testing.T) { func TestInvalidHttpSignatureConfiguration(t *testing.T) { var err error - var authConfig HttpSignatureAuth + var authConfig sw.HttpSignatureAuth - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ } _, err = authConfig.ContextWithValue(context.Background()) if err == nil || !strings.Contains(err.Error(), "Key ID must be specified") { t.Fatalf("Invalid configuration: %v", err) } - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", } _, err = authConfig.ContextWithValue(context.Background()) @@ -673,7 +669,7 @@ func TestInvalidHttpSignatureConfiguration(t *testing.T) { t.Fatalf("Invalid configuration: %v", err) } - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", PrivateKeyPath: "test.pem", } @@ -682,7 +678,7 @@ func TestInvalidHttpSignatureConfiguration(t *testing.T) { t.Fatalf("Invalid configuration: %v", err) } - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", PrivateKeyPath: "test.pem", SigningScheme: "garbage", @@ -692,10 +688,10 @@ func TestInvalidHttpSignatureConfiguration(t *testing.T) { t.Fatalf("Invalid configuration: %v", err) } - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", PrivateKeyPath: "test.pem", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{"foo", "bar", "foo"}, } _, err = authConfig.ContextWithValue(context.Background()) @@ -703,10 +699,10 @@ func TestInvalidHttpSignatureConfiguration(t *testing.T) { t.Fatalf("Invalid configuration: %v", err) } - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", PrivateKeyPath: "test.pem", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{"foo", "bar", "Authorization"}, } _, err = authConfig.ContextWithValue(context.Background()) @@ -714,10 +710,10 @@ func TestInvalidHttpSignatureConfiguration(t *testing.T) { t.Fatalf("Invalid configuration: %v", err) } - authConfig = HttpSignatureAuth{ + authConfig = sw.HttpSignatureAuth{ KeyId: "my-key-id", PrivateKeyPath: "test.pem", - SigningScheme: HttpSigningSchemeHs2019, + SigningScheme: sw.HttpSigningSchemeHs2019, SignedHeaders: []string{"foo", "bar"}, SignatureMaxValidity: -7 * time.Minute, } @@ -725,4 +721,4 @@ func TestInvalidHttpSignatureConfiguration(t *testing.T) { if err == nil || !strings.Contains(err.Error(), "Signature max validity must be a positive value") { t.Fatalf("Invalid configuration: %v", err) } -} \ No newline at end of file +}