Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ const (
// ParamSubtoken optionally specifies which subtoken should be used.
// Default is SubtokenAccessToken.
ParamSubtoken = "st"

// ParamDelimiter specifies the delimiter to replace in the request body
// with the token value. Used by InjectBodyProcessor.
ParamDelimiter = "delimiter"
)

const (
Expand All @@ -54,7 +58,9 @@ type ProcessorConfig interface {
type wireProcessor struct {
InjectProcessorConfig *InjectProcessorConfig `json:"inject_processor,omitempty"`
InjectHMACProcessorConfig *InjectHMACProcessorConfig `json:"inject_hmac_processor,omitempty"`
InjectBodyProcessorConfig *InjectBodyProcessorConfig `json:"inject_body_processor,omitempty"`
OAuthProcessorConfig *OAuthProcessorConfig `json:"oauth2_processor,omitempty"`
OAuthBodyProcessorConfig *OAuthBodyProcessorConfig `json:"oauth2_body_processor,omitempty"`
Sigv4ProcessorConfig *Sigv4ProcessorConfig `json:"sigv4_processor,omitempty"`
MultiProcessorConfig *MultiProcessorConfig `json:"multi_processor,omitempty"`
}
Expand All @@ -65,8 +71,12 @@ func newWireProcessor(p ProcessorConfig) (wireProcessor, error) {
return wireProcessor{InjectProcessorConfig: p}, nil
case *InjectHMACProcessorConfig:
return wireProcessor{InjectHMACProcessorConfig: p}, nil
case *InjectBodyProcessorConfig:
return wireProcessor{InjectBodyProcessorConfig: p}, nil
case *OAuthProcessorConfig:
return wireProcessor{OAuthProcessorConfig: p}, nil
case *OAuthBodyProcessorConfig:
return wireProcessor{OAuthBodyProcessorConfig: p}, nil
case *Sigv4ProcessorConfig:
return wireProcessor{Sigv4ProcessorConfig: p}, nil
case *MultiProcessorConfig:
Expand All @@ -88,10 +98,18 @@ func (wp *wireProcessor) getProcessorConfig() (ProcessorConfig, error) {
np += 1
p = wp.InjectHMACProcessorConfig
}
if wp.InjectBodyProcessorConfig != nil {
np += 1
p = wp.InjectBodyProcessorConfig
}
if wp.OAuthProcessorConfig != nil {
np += 1
p = wp.OAuthProcessorConfig
}
if wp.OAuthBodyProcessorConfig != nil {
np += 1
p = wp.OAuthBodyProcessorConfig
}
if wp.Sigv4ProcessorConfig != nil {
np += 1
p = wp.Sigv4ProcessorConfig
Expand Down Expand Up @@ -198,6 +216,58 @@ func (c *InjectHMACProcessorConfig) StripHazmat() ProcessorConfig {
}
}

type InjectBodyProcessorConfig struct {
Token string `json:"token"`
Delimiter string `json:"delimiter,omitempty"`
}

var _ ProcessorConfig = new(InjectBodyProcessorConfig)

func (c *InjectBodyProcessorConfig) Processor(params map[string]string) (RequestProcessor, error) {
if c.Token == "" {
return nil, errors.New("missing token")
}

// Get delimiter from params or use config default or fallback
delimiter := c.Delimiter
if paramDelim, ok := params[ParamDelimiter]; ok {
delimiter = paramDelim
}
if delimiter == "" {
delimiter = "{{ACCESS_TOKEN}}"
}

return func(r *http.Request) error {
// Read the entire request body
if r.Body == nil {
return nil
}

bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("failed to read request body: %w", err)
}
r.Body.Close()

// Replace delimiter with token
bodyStr := string(bodyBytes)
newBody := strings.ReplaceAll(bodyStr, delimiter, c.Token)

// Set the new body
r.Body = io.NopCloser(strings.NewReader(newBody))
r.ContentLength = int64(len(newBody))

return nil
}, nil
}

func (c *InjectBodyProcessorConfig) StripHazmat() ProcessorConfig {
return &InjectBodyProcessorConfig{
Token: redactedStr,
Delimiter: c.Delimiter,
}
}

type OAuthProcessorConfig struct {
Token *OAuthToken `json:"token"`
}
Expand All @@ -219,6 +289,33 @@ func (c *OAuthProcessorConfig) Processor(params map[string]string) (RequestProce
return nil, errors.New("missing token")
}

// Check if delimiter parameter is present for body injection
if delimiter, ok := params[ParamDelimiter]; ok && delimiter != "" {
// Inject token into request body by replacing delimiter
return func(r *http.Request) error {
if r.Body == nil {
return nil
}

bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("failed to read request body: %w", err)
}
r.Body.Close()

// Replace delimiter with token
bodyStr := string(bodyBytes)
newBody := strings.ReplaceAll(bodyStr, delimiter, token)

// Set the new body
r.Body = io.NopCloser(strings.NewReader(newBody))
r.ContentLength = int64(len(newBody))

return nil
}, nil
}

// Default behavior: inject into Authorization header
return func(r *http.Request) error {
r.Header.Set("Authorization", "Bearer "+token)
return nil
Expand All @@ -234,6 +331,66 @@ func (c *OAuthProcessorConfig) StripHazmat() ProcessorConfig {
}
}

type OAuthBodyProcessorConfig struct {
Token *OAuthToken `json:"token"`
Delimiter string `json:"delimiter,omitempty"`
}

var _ ProcessorConfig = (*OAuthBodyProcessorConfig)(nil)

func (c *OAuthBodyProcessorConfig) Processor(params map[string]string) (RequestProcessor, error) {
token := c.Token.AccessToken
if params[ParamSubtoken] == SubtokenRefresh {
token = c.Token.RefreshToken
}

if token == "" {
return nil, errors.New("missing token")
}

// Get delimiter from params or use config default or fallback
delimiter := c.Delimiter
if paramDelim, ok := params[ParamDelimiter]; ok {
delimiter = paramDelim
}
if delimiter == "" {
delimiter = "{{ACCESS_TOKEN}}"
}

return func(r *http.Request) error {
// Read the entire request body
if r.Body == nil {
return nil
}

bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("failed to read request body: %w", err)
}
r.Body.Close()

// Replace delimiter with token
bodyStr := string(bodyBytes)
newBody := strings.ReplaceAll(bodyStr, delimiter, token)

// Set the new body
r.Body = io.NopCloser(strings.NewReader(newBody))
r.ContentLength = int64(len(newBody))

return nil
}, nil
}

func (c *OAuthBodyProcessorConfig) StripHazmat() ProcessorConfig {
return &OAuthBodyProcessorConfig{
Token: &OAuthToken{
AccessToken: redactedStr,
RefreshToken: redactedStr,
},
Delimiter: c.Delimiter,
}
}

type Sigv4ProcessorConfig struct {
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key"`
Expand Down