github.com/Axway/agent-sdk@v1.1.101/pkg/transaction/httpprotocolbuilder.go (about)

     1  package transaction
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/Axway/agent-sdk/pkg/traceability/redaction"
     9  )
    10  
    11  // HTTPProtocolBuilder - Interface to build the HTTP protocol details for transaction log event
    12  type HTTPProtocolBuilder interface {
    13  	SetURI(uri string) HTTPProtocolBuilder
    14  	SetVersion(version string) HTTPProtocolBuilder
    15  	SetArgs(args string) HTTPProtocolBuilder
    16  	SetArgsMap(args map[string][]string) HTTPProtocolBuilder
    17  	AddArg(key string, value []string) HTTPProtocolBuilder
    18  	SetMethod(method string) HTTPProtocolBuilder
    19  	SetStatus(status int, statusText string) HTTPProtocolBuilder
    20  	SetUserAgent(userAgent string) HTTPProtocolBuilder
    21  	SetHost(host string) HTTPProtocolBuilder
    22  	SetByteLength(byteReceived, byteSent int) HTTPProtocolBuilder
    23  	SetRemoteAddress(remoteName string, remoteAddr string, remotePort int) HTTPProtocolBuilder
    24  	SetLocalAddress(localAddr string, localPort int) HTTPProtocolBuilder
    25  	SetSSLProperties(sslProtocol, sslServerName, sslSubject string) HTTPProtocolBuilder
    26  	SetAuthSubjectID(authSubjectID string) HTTPProtocolBuilder
    27  	SetHeaders(requestHeaders, responseHeaders string) HTTPProtocolBuilder
    28  	SetRequestHeaders(requestHeaders map[string]string) HTTPProtocolBuilder
    29  	SetResponseHeaders(responseHeaders map[string]string) HTTPProtocolBuilder
    30  	AddRequestHeader(headerKey string, headerValue string) HTTPProtocolBuilder
    31  	AddResponseHeader(headerKey string, headerValue string) HTTPProtocolBuilder
    32  	SetIndexedHeaders(indexedRequestHeaders, indexedResponseHeaders string) HTTPProtocolBuilder
    33  	SetIndexedRequestHeaders(indexedRequestHeaders map[string]string) HTTPProtocolBuilder
    34  	SetIndexedResponseHeaders(indexedResponseHeaders map[string]string) HTTPProtocolBuilder
    35  	AddIndexedRequestHeader(headerKey string, headerValue string) HTTPProtocolBuilder
    36  	AddIndexedResponseHeader(headerKey string, headerValue string) HTTPProtocolBuilder
    37  	SetPayload(requestPayload, responsePayload string) HTTPProtocolBuilder
    38  	SetWAFStatus(wasStatus int) HTTPProtocolBuilder
    39  	SetRedactionConfig(config redaction.Redactions) HTTPProtocolBuilder
    40  
    41  	Build() (TransportProtocol, error)
    42  }
    43  
    44  type httpProtocolBuilder struct {
    45  	HTTPProtocolBuilder
    46  	err                    error
    47  	httpProtocol           *Protocol
    48  	argsMap                map[string][]string
    49  	requestHeaders         map[string]string
    50  	responseHeaders        map[string]string
    51  	indexedRequestHeaders  map[string]string
    52  	indexedResponseHeaders map[string]string
    53  	redactionConfig        redaction.Redactions
    54  }
    55  
    56  // NewHTTPProtocolBuilder - Creates a new http protocol builder
    57  func NewHTTPProtocolBuilder() HTTPProtocolBuilder {
    58  	builder := &httpProtocolBuilder{
    59  		httpProtocol: &Protocol{
    60  			Type:    "http",
    61  			Version: "1.1",
    62  		},
    63  		argsMap:                make(map[string][]string),
    64  		requestHeaders:         make(map[string]string),
    65  		responseHeaders:        make(map[string]string),
    66  		indexedRequestHeaders:  make(map[string]string),
    67  		indexedResponseHeaders: make(map[string]string),
    68  	}
    69  	return builder
    70  }
    71  
    72  func (b *httpProtocolBuilder) SetURI(uri string) HTTPProtocolBuilder {
    73  	if b.err != nil {
    74  		return b
    75  	}
    76  	b.httpProtocol.uriRaw = uri
    77  	return b
    78  }
    79  
    80  func (b *httpProtocolBuilder) SetVersion(version string) HTTPProtocolBuilder {
    81  	if b.err != nil {
    82  		return b
    83  	}
    84  	b.httpProtocol.Version = version
    85  	return b
    86  }
    87  
    88  func (b *httpProtocolBuilder) SetArgs(args string) HTTPProtocolBuilder {
    89  	if b.err != nil || args == "" {
    90  		return b
    91  	}
    92  	var argMap map[string][]string
    93  	b.err = json.Unmarshal([]byte(args), &argMap)
    94  	if b.err == nil {
    95  		b.argsMap = argMap
    96  	}
    97  	return b
    98  }
    99  
   100  func (b *httpProtocolBuilder) AddArg(key string, value []string) HTTPProtocolBuilder {
   101  	if b.err != nil {
   102  		return b
   103  	}
   104  	if _, ok := b.argsMap[key]; ok {
   105  		b.err = fmt.Errorf("arg with key %s has already been added", key)
   106  	} else {
   107  		b.argsMap[key] = value
   108  	}
   109  	return b
   110  }
   111  
   112  func (b *httpProtocolBuilder) SetArgsMap(args map[string][]string) HTTPProtocolBuilder {
   113  	if b.err != nil {
   114  		return b
   115  	}
   116  	b.argsMap = args
   117  	return b
   118  }
   119  
   120  func (b *httpProtocolBuilder) SetMethod(method string) HTTPProtocolBuilder {
   121  	if b.err != nil {
   122  		return b
   123  	}
   124  	b.httpProtocol.Method = method
   125  	return b
   126  }
   127  
   128  func (b *httpProtocolBuilder) SetStatus(status int, statusText string) HTTPProtocolBuilder {
   129  	if b.err != nil {
   130  		return b
   131  	}
   132  	b.httpProtocol.Status = status
   133  	b.httpProtocol.StatusText = statusText
   134  	return b
   135  }
   136  
   137  func (b *httpProtocolBuilder) SetUserAgent(userAgent string) HTTPProtocolBuilder {
   138  	if b.err != nil {
   139  		return b
   140  	}
   141  	b.httpProtocol.UserAgent = userAgent
   142  	return b
   143  }
   144  
   145  func (b *httpProtocolBuilder) SetHost(host string) HTTPProtocolBuilder {
   146  	if b.err != nil {
   147  		return b
   148  	}
   149  	b.httpProtocol.Host = host
   150  	return b
   151  }
   152  
   153  func (b *httpProtocolBuilder) SetByteLength(byteReceived, byteSent int) HTTPProtocolBuilder {
   154  	if b.err != nil {
   155  		return b
   156  	}
   157  	b.httpProtocol.BytesReceived = byteReceived
   158  	b.httpProtocol.BytesSent = byteSent
   159  	return b
   160  }
   161  
   162  func (b *httpProtocolBuilder) SetRemoteAddress(remoteName string, remoteAddr string, remotePort int) HTTPProtocolBuilder {
   163  	if b.err != nil {
   164  		return b
   165  	}
   166  	b.httpProtocol.RemoteName = remoteName
   167  	b.httpProtocol.RemoteAddr = remoteAddr
   168  	b.httpProtocol.RemotePort = remotePort
   169  	return b
   170  }
   171  
   172  func (b *httpProtocolBuilder) SetLocalAddress(localAddr string, localPort int) HTTPProtocolBuilder {
   173  	if b.err != nil {
   174  		return b
   175  	}
   176  	b.httpProtocol.LocalAddr = localAddr
   177  	b.httpProtocol.LocalPort = localPort
   178  	return b
   179  }
   180  
   181  func (b *httpProtocolBuilder) SetSSLProperties(sslProtocol string, sslServerName string, sslSubject string) HTTPProtocolBuilder {
   182  	if b.err != nil {
   183  		return b
   184  	}
   185  	b.httpProtocol.SslProtocol = sslProtocol
   186  	b.httpProtocol.SslServerName = sslServerName
   187  	b.httpProtocol.SslSubject = sslSubject
   188  	return b
   189  }
   190  
   191  func (b *httpProtocolBuilder) SetAuthSubjectID(authSubjectID string) HTTPProtocolBuilder {
   192  	if b.err != nil {
   193  		return b
   194  	}
   195  	b.httpProtocol.AuthSubjectID = authSubjectID
   196  	return b
   197  }
   198  
   199  func (b *httpProtocolBuilder) SetHeaders(requestHeadersString, responseHeadersString string) HTTPProtocolBuilder {
   200  	if b.err != nil {
   201  		return b
   202  	}
   203  
   204  	if requestHeadersString != "" {
   205  		var requestHeaders map[string]string
   206  		b.err = json.Unmarshal([]byte(requestHeadersString), &requestHeaders)
   207  		if b.err != nil {
   208  			return b
   209  		}
   210  		b.requestHeaders = requestHeaders
   211  	}
   212  
   213  	if requestHeadersString != "" {
   214  		var responseHeaders map[string]string
   215  		b.err = json.Unmarshal([]byte(responseHeadersString), &responseHeaders)
   216  		if b.err != nil {
   217  			return b
   218  		}
   219  		b.responseHeaders = responseHeaders
   220  	}
   221  	return b
   222  }
   223  
   224  func (b *httpProtocolBuilder) SetRequestHeaders(requestHeaders map[string]string) HTTPProtocolBuilder {
   225  	if b.err != nil {
   226  		return b
   227  	}
   228  	b.requestHeaders = requestHeaders
   229  	return b
   230  }
   231  
   232  func (b *httpProtocolBuilder) AddRequestHeader(key string, value string) HTTPProtocolBuilder {
   233  	if b.err != nil {
   234  		return b
   235  	}
   236  	if _, ok := b.requestHeaders[key]; ok {
   237  		b.err = fmt.Errorf("response Header with key %s has already been added", key)
   238  	} else {
   239  		b.requestHeaders[key] = value
   240  	}
   241  	return b
   242  }
   243  
   244  func (b *httpProtocolBuilder) SetResponseHeaders(responseHeaders map[string]string) HTTPProtocolBuilder {
   245  	if b.err != nil {
   246  		return b
   247  	}
   248  	b.responseHeaders = responseHeaders
   249  	return b
   250  }
   251  
   252  func (b *httpProtocolBuilder) AddResponseHeader(key string, value string) HTTPProtocolBuilder {
   253  	if b.err != nil {
   254  		return b
   255  	}
   256  	if _, ok := b.responseHeaders[key]; ok {
   257  		b.err = fmt.Errorf("response Header with key %s has already been added", key)
   258  	} else {
   259  		b.responseHeaders[key] = value
   260  	}
   261  	return b
   262  }
   263  
   264  func (b *httpProtocolBuilder) SetIndexedHeaders(indexedRequestHeadersString, indexedResponseHeadersString string) HTTPProtocolBuilder {
   265  	if b.err != nil {
   266  		return b
   267  	}
   268  
   269  	var indexedRequestHeaders map[string]string
   270  	b.err = json.Unmarshal([]byte(indexedRequestHeadersString), &indexedRequestHeaders)
   271  	if b.err != nil {
   272  		return b
   273  	}
   274  	b.indexedRequestHeaders = indexedRequestHeaders
   275  
   276  	var indexedResponseHeaders map[string]string
   277  	b.err = json.Unmarshal([]byte(indexedResponseHeadersString), &indexedResponseHeaders)
   278  	if b.err != nil {
   279  		return b
   280  	}
   281  	b.indexedResponseHeaders = indexedResponseHeaders
   282  	return b
   283  }
   284  
   285  func (b *httpProtocolBuilder) SetIndexedRequestHeaders(indexedRequestHeaders map[string]string) HTTPProtocolBuilder {
   286  	if b.err != nil {
   287  		return b
   288  	}
   289  	b.indexedRequestHeaders = indexedRequestHeaders
   290  	return b
   291  }
   292  
   293  func (b *httpProtocolBuilder) AddIndexedRequestHeader(key string, value string) HTTPProtocolBuilder {
   294  	if b.err != nil {
   295  		return b
   296  	}
   297  	if _, ok := b.indexedRequestHeaders[key]; ok {
   298  		b.err = fmt.Errorf("indexed Response Header with key %s has already been added", key)
   299  	} else {
   300  		b.indexedRequestHeaders[key] = value
   301  	}
   302  	return b
   303  }
   304  
   305  func (b *httpProtocolBuilder) SetIndexedResponseHeaders(indexedResponseHeaders map[string]string) HTTPProtocolBuilder {
   306  	if b.err != nil {
   307  		return b
   308  	}
   309  	b.indexedResponseHeaders = indexedResponseHeaders
   310  	return b
   311  }
   312  
   313  func (b *httpProtocolBuilder) AddIndexedResponseHeader(key string, value string) HTTPProtocolBuilder {
   314  	if b.err != nil {
   315  		return b
   316  	}
   317  	if _, ok := b.indexedResponseHeaders[key]; ok {
   318  		b.err = fmt.Errorf("indexed Response Header with key %s has already been added", key)
   319  	} else {
   320  		b.indexedResponseHeaders[key] = value
   321  	}
   322  	return b
   323  }
   324  
   325  func (b *httpProtocolBuilder) SetPayload(requestPayload, responsePayload string) HTTPProtocolBuilder {
   326  	if b.err != nil {
   327  		return b
   328  	}
   329  	b.httpProtocol.RequestPayload = requestPayload
   330  	b.httpProtocol.ResponsePayload = responsePayload
   331  	return b
   332  }
   333  
   334  func (b *httpProtocolBuilder) SetWAFStatus(wasStatus int) HTTPProtocolBuilder {
   335  	if b.err != nil {
   336  		return b
   337  	}
   338  	b.httpProtocol.WafStatus = wasStatus
   339  	return b
   340  }
   341  
   342  func (b *httpProtocolBuilder) SetRedactionConfig(config redaction.Redactions) HTTPProtocolBuilder {
   343  	if b.err != nil {
   344  		return b
   345  	}
   346  	b.redactionConfig = config
   347  	return b
   348  }
   349  
   350  func (b *httpProtocolBuilder) Build() (TransportProtocol, error) {
   351  	if b.err != nil {
   352  		return nil, b.err
   353  	}
   354  	// Complete the redactions
   355  	b.queryArgsRedaction()
   356  	if b.err != nil {
   357  		return nil, b.err
   358  	}
   359  	b.headersRedaction()
   360  	if b.err != nil {
   361  		return nil, b.err
   362  	}
   363  	//set redacted URI
   364  	if b.httpProtocol.uriRaw == "" {
   365  		return nil, errors.New("Raw Uri property not set in HTTP protocol details")
   366  	}
   367  	if b.redactionConfig == nil {
   368  		b.httpProtocol.URI, _ = redaction.URIRedaction(b.httpProtocol.uriRaw)
   369  	} else {
   370  		b.httpProtocol.URI, _ = b.redactionConfig.URIRedaction(b.httpProtocol.uriRaw)
   371  	}
   372  
   373  	// b.indexedHeadersRedaction()  // Indexed headers are not currently used in central
   374  
   375  	if b.httpProtocol.RequestHeaders == "" || b.httpProtocol.ResponseHeaders == "" {
   376  		return nil, errors.New("request or Response Headers not set in HTTP protocol details")
   377  	}
   378  
   379  	if b.httpProtocol.URI == "" {
   380  		return nil, errors.New("uri property not set in HTTP protocol details")
   381  	}
   382  
   383  	if b.httpProtocol.Method == "" {
   384  		return nil, errors.New("method property not set in HTTP protocol details")
   385  	}
   386  
   387  	if b.httpProtocol.Host == "" {
   388  		return nil, errors.New("host property not set in HTTP protocol details")
   389  	}
   390  
   391  	if b.httpProtocol.Status < 100 || b.httpProtocol.Status > 600 {
   392  		return nil, errors.New("invalid status code set in HTTP protocol details")
   393  	}
   394  	return b.httpProtocol, nil
   395  }
   396  
   397  func (b *httpProtocolBuilder) queryArgsRedaction() {
   398  	// skip if there is already an error
   399  	if b.err != nil {
   400  		return
   401  	}
   402  	var redactedArgs map[string][]string
   403  	var err error
   404  	if len(b.argsMap) > 0 {
   405  		if b.redactionConfig == nil {
   406  			redactedArgs, err = redaction.QueryArgsRedaction(b.argsMap)
   407  		} else {
   408  			redactedArgs, err = b.redactionConfig.QueryArgsRedaction(b.argsMap)
   409  		}
   410  		if err != nil {
   411  			b.err = ErrInRedactions.FormatError("QueryArgs", err)
   412  			return
   413  		}
   414  		argBytes, err := json.Marshal(redactedArgs)
   415  		if err != nil {
   416  			b.err = err
   417  			return
   418  		}
   419  		b.httpProtocol.Args = string(argBytes)
   420  	}
   421  }
   422  
   423  func (b *httpProtocolBuilder) headersRedaction() {
   424  	// skip if there is already an error
   425  	if b.err != nil {
   426  		return
   427  	}
   428  
   429  	b.httpProtocol.RequestHeaders, b.httpProtocol.ResponseHeaders, b.err =
   430  		headersRedaction(b.requestHeaders, b.responseHeaders, b.redactionConfig)
   431  }
   432  
   433  func (b *httpProtocolBuilder) indexedHeadersRedaction() {
   434  	// skip if there is already an error
   435  	if b.err != nil {
   436  		return
   437  	}
   438  
   439  	b.httpProtocol.IndexedRequestHeaders, b.httpProtocol.IndexedResponseHeaders, b.err =
   440  		headersRedaction(b.indexedRequestHeaders, b.indexedResponseHeaders, b.redactionConfig)
   441  }
   442  
   443  func headersRedaction(requestHeaders, responseHeaders map[string]string, redactionConfig redaction.Redactions) (string, string, error) {
   444  	const emptyHeaders = "{}"
   445  	reqHeadersBytes := []byte(emptyHeaders)
   446  	resHeadersBytes := []byte(emptyHeaders)
   447  
   448  	if len(requestHeaders) > 0 {
   449  		var redactedHeaders map[string]string
   450  		var err error
   451  		if redactionConfig == nil {
   452  			redactedHeaders, err = redaction.RequestHeadersRedaction(requestHeaders)
   453  		} else {
   454  			redactedHeaders, err = redactionConfig.RequestHeadersRedaction(requestHeaders)
   455  		}
   456  		if err != nil {
   457  			return emptyHeaders, emptyHeaders, ErrInRedactions.FormatError("RequestHeaders", err)
   458  		}
   459  		reqHeadersBytes, err = json.Marshal(redactedHeaders)
   460  		if err != nil {
   461  			return emptyHeaders, emptyHeaders, ErrInRedactions.FormatError("RequestHeaders", err)
   462  		}
   463  	}
   464  
   465  	if len(responseHeaders) > 0 {
   466  		var redactedHeaders map[string]string
   467  		var err error
   468  		if redactionConfig == nil {
   469  			redactedHeaders, err = redaction.ResponseHeadersRedaction(responseHeaders)
   470  		} else {
   471  			redactedHeaders, err = redactionConfig.ResponseHeadersRedaction(responseHeaders)
   472  		}
   473  		if err != nil {
   474  			return emptyHeaders, emptyHeaders, ErrInRedactions.FormatError("ResponseHeaders", err)
   475  		}
   476  		resHeadersBytes, err = json.Marshal(redactedHeaders)
   477  		if err != nil {
   478  			return emptyHeaders, emptyHeaders, ErrInRedactions.FormatError("ResponseHeaders", err)
   479  		}
   480  	}
   481  
   482  	return string(reqHeadersBytes), string(resHeadersBytes), nil
   483  }