[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
This commit is contained in:
Sebastien Rosset 2020-03-14 16:34:58 -07:00 committed by GitHub
parent 972bd8e280
commit 5e6a261d12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 89 additions and 805 deletions

View File

@ -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

View File

@ -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<keyId>[^"]+)",algorithm="(?P<algorithm>[^"]+)"` +
`(,created=(?P<created>[0-9]+))?(,expires=(?P<expires>[0-9.]+))?,headers="(?P<headers>[^"]+)",signature="(?P<signature>[^"]+)"`)
)
// 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)
}
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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)
}
}
}