diff --git a/v2/pkg/protocols/http/http.go b/v2/pkg/protocols/http/http.go index 765b217e6..ed6b9b2a6 100644 --- a/v2/pkg/protocols/http/http.go +++ b/v2/pkg/protocols/http/http.go @@ -138,8 +138,13 @@ type Request struct { // description: | // SelfContained specifies if the request is self contained. - SelfContained bool `yaml:"-" json:"-"` - PostProcessors []string `yaml:"-" json:"-"` + SelfContained bool `yaml:"-" json:"-"` + + // description: | + // Signature is the request signature method + // values: + // - "AWS" + Signature SignatureTypeHolder `yaml:"signature,omitempty" jsonschema:"title=signature is the http request signature method,description=Signature is the HTTP Request signature Method,enum=AWS"` // description: | // CookieReuse is an optional setting that enables cookie reuse for diff --git a/v2/pkg/protocols/http/request.go b/v2/pkg/protocols/http/request.go index 6059f1679..9849a5c01 100644 --- a/v2/pkg/protocols/http/request.go +++ b/v2/pkg/protocols/http/request.go @@ -197,10 +197,6 @@ func (request *Request) executeTurboHTTP(reqURL string, dynamicValues, previous return requestErr } -func (request *Request) hasPreprocessors() bool { - return len(request.PostProcessors) > 0 -} - // ExecuteWithResults executes the final request on a URL func (request *Request) ExecuteWithResults(reqURL string, dynamicValues, previous output.InternalEvent, callback protocols.OutputEventCallback) error { // verify if pipeline was requested @@ -354,37 +350,35 @@ func (request *Request) executeRequest(reqURL string, generatedRequest *generate } } if resp == nil { - for _, postProcessor := range request.PostProcessors { - switch postProcessor { - case "aws-sign": - var awsSigner *AwsSigner - payloads := request.options.Options.Vars.AsMap() - awsAccessKeyId := types.ToString(payloads["aws-id"]) - awsSecretAccessKey := types.ToString(payloads["aws-secret"]) - if awsAccessKeyId != "" && awsSecretAccessKey != "" { - awsSigner, err = NewAwsSigner(awsAccessKeyId, awsSecretAccessKey) - } else { - awsSigner, err = NewAwsSignerFromEnv() - } - if err != nil { - return err - } + switch request.Signature.Value { + case AWSSignature: + var awsSigner *AwsSigner + payloads := request.options.Options.Vars.AsMap() + awsAccessKeyId := types.ToString(payloads["aws-id"]) + awsSecretAccessKey := types.ToString(payloads["aws-secret"]) + if awsAccessKeyId != "" && awsSecretAccessKey != "" { + awsSigner, err = NewAwsSigner(awsAccessKeyId, awsSecretAccessKey) + } else { + awsSigner, err = NewAwsSignerFromEnv() + } + if err != nil { + return err + } - service := types.ToString(payloads["service"]) - region := types.ToString(payloads["region"]) - if service == "" || region == "" { - return errors.New("service and region are mandatory") - } + service := types.ToString(payloads["service"]) + region := types.ToString(payloads["region"]) + if service == "" || region == "" { + return errors.New("service and region are mandatory") + } - args := SignArguments{ - Service: types.ToString(payloads["service"]), - Region: types.ToString(payloads["region"]), - Time: time.Now(), - } - err = awsSigner.SignHTTP(generatedRequest.request.Request, args) - if err != nil { - return err - } + args := SignArguments{ + Service: types.ToString(payloads["service"]), + Region: types.ToString(payloads["region"]), + Time: time.Now(), + } + err = awsSigner.SignHTTP(generatedRequest.request.Request, args) + if err != nil { + return err } } resp, err = request.httpClient.Do(generatedRequest.request) diff --git a/v2/pkg/protocols/http/signature.go b/v2/pkg/protocols/http/signature.go new file mode 100644 index 000000000..83f4a7d5e --- /dev/null +++ b/v2/pkg/protocols/http/signature.go @@ -0,0 +1,89 @@ +package http + +import ( + "encoding/json" + "strings" + + "github.com/alecthomas/jsonschema" + "github.com/pkg/errors" +) + +// SignatureType is the type of signature +type SignatureType int + +// Supported values for the SignatureType +const ( + AWSSignature SignatureType = iota + 1 + limit +) + +// signatureTypeMappings is a table for conversion of signature type from string. +var signatureTypeMappings = map[SignatureType]string{ + AWSSignature: "aws", +} + +func GetSupportedSignaturesTypes() []SignatureType { + var result []SignatureType + for index := SignatureType(1); index < limit; index++ { + result = append(result, index) + } + return result +} + +func toSignatureType(valueToMap string) (SignatureType, error) { + normalizedValue := normalizeValue(valueToMap) + for key, currentValue := range signatureTypeMappings { + if normalizedValue == currentValue { + return key, nil + } + } + return -1, errors.New("invalid signature type: " + valueToMap) +} + +func normalizeValue(value string) string { + return strings.TrimSpace(strings.ToLower(value)) +} + +func (t SignatureType) String() string { + return signatureTypeMappings[t] +} + +// SignatureTypeHolder is used to hold internal type of the signature +type SignatureTypeHolder struct { + Value SignatureType +} + +func (holder SignatureTypeHolder) JSONSchemaType() *jsonschema.Type { + gotType := &jsonschema.Type{ + Type: "string", + Title: "type of the signature", + Description: "Type of the signature", + } + for _, types := range GetSupportedSignaturesTypes() { + gotType.Enum = append(gotType.Enum, types.String()) + } + return gotType +} + +func (holder *SignatureTypeHolder) UnmarshalYAML(unmarshal func(interface{}) error) error { + var marshalledTypes string + if err := unmarshal(&marshalledTypes); err != nil { + return err + } + + computedType, err := toSignatureType(marshalledTypes) + if err != nil { + return err + } + + holder.Value = computedType + return nil +} + +func (holder *SignatureTypeHolder) MarshalJSON() ([]byte, error) { + return json.Marshal(holder.Value.String()) +} + +func (holder SignatureTypeHolder) MarshalYAML() (interface{}, error) { + return holder.Value.String(), nil +} diff --git a/v2/pkg/templates/compile.go b/v2/pkg/templates/compile.go index 97f1afa70..092ec1d3e 100644 --- a/v2/pkg/templates/compile.go +++ b/v2/pkg/templates/compile.go @@ -107,9 +107,9 @@ func Parse(filePath string, preprocessor Preprocessor, options protocols.Execute // parseSelfContainedRequests parses the self contained template requests. func (template *Template) parseSelfContainedRequests() { - if len(template.PostProcessors) > 0 { + if template.Signature.Value.String() != "" { for _, request := range template.RequestsHTTP { - request.PostProcessors = template.PostProcessors + request.Signature = template.Signature } } if !template.SelfContained { diff --git a/v2/pkg/templates/templates.go b/v2/pkg/templates/templates.go index ed74175d7..857c8823a 100644 --- a/v2/pkg/templates/templates.go +++ b/v2/pkg/templates/templates.go @@ -73,8 +73,13 @@ type Template struct { // description: | // Self Contained marks Requests for the template as self-contained - SelfContained bool `yaml:"self-contained,omitempty" jsonschema:"title=mark requests as self-contained,description=Mark Requests for the template as self-contained"` - PostProcessors []string `yaml:"post-processors,omitempty"` + SelfContained bool `yaml:"self-contained,omitempty" jsonschema:"title=mark requests as self-contained,description=Mark Requests for the template as self-contained"` + + // description: | + // Signature is the request signature method + // values: + // - "AWS" + Signature http.SignatureTypeHolder `yaml:"signature,omitempty" jsonschema:"title=signature is the http request signature method,description=Signature is the HTTP Request signature Method,enum=AWS"` // TotalRequests is the total number of requests for the template. TotalRequests int `yaml:"-" json:"-"`