Generalizing Go analytics plugin code

Hello tyk community,

This is in extension of Mask sensitive data in API request/response in log browser
I am trying to mask sensitive information in the headers, I have my Go Plugin code and the analytics_plugin section done.
I am exploring a way to pass the headers to mask through argument, without having to hardcode them in the plugin code.
Where can I configure this in the API definition on the dashboard?

I think you could Config Data. We have an example with Virtual Endpoints that shows what the input values can be. What I am unsure is if you could reverse engineer the raw_request to retrieve the config data from the API.

But I think you could get the value you need from a custom header i.e. X-Mask-Records in the analytics record. You could allow the client pass this as arguments or hardcode it in the API definition with modify headers.

@Olu
I explored ConfigData.
I came up with the following implementation -

The below block is added to the Api Definition -

 "config_data": {
      "sensitiverequestheaders": [
        "X-header1", "X-header2"
      ]
    }

The plugin code -

func MyAnalyticsPluginMaskHeader(record *analytics.AnalyticsRecord) {
   
    str, err := base64.StdEncoding.DecodeString(record.RawRequest)
    if err != nil {
        return
    }

    var b = &bytes.Buffer{}
    b.Write(str)
    r := bufio.NewReader(b)
    var req *http.Request
    req, err = http.ReadRequest(r)

    if err != nil {
        return
    }

    apiDefinition := ctx.GetDefinition(req)

    logger.Info("APIDEFINITION: ", apiDefinition)

    pluginConfig, ok := apiDefinition.ConfigData["sensitiverequestheaders"].(string)
   <rest of the code>
   ....
   ....
   ....
}

Log output -
image

Am I extracting the api definition in a right way ? Suggest any changes that I need.

referred this for reading apiDefinition - https://github.com/TykTechnologies/tyk/blob/master/test/goplugins/test_goplugin.go#L80

@Olu
Upon debugging, realized that the ctx object is not present in the analytics record. Please suggest a way to get the API Definition object.

Have you tried importing “github.com/TykTechnologies/tyk/ctx”? I was going to test this later when I found the time.

If this doesn’t work, then you might have to use global / modify headers instead. You would

@Olu, Yes the ctx package is imported. My guess that if we directly use the incoming http Request rather than building the http request from analytics record, it might be possible to extract the Context, and consequently the API Definition.
But when I tried defining the Plugin function as below -

func MyAnalyticsPluginMaskHeader(record *analytics.AnalyticsRecord, rq *http.Request) 

I got an error saying

time="Jul 13 10:48:06" level=error msg="Could not load Go-plugin for analytics" error="could not cast function symbol to AnalyticsPlugin function" mwPath="/opt/tyk-gateway/middleware/CustomGoPlugin_v4.3.3_linux_amd64.so" mwSymbolName=MyAnalyticsPluginMaskHeader

The analytics handler only allows the analytics record as an input variable. Putting the http Request wouldn’t work.

I’d have to ask the engineering team if the context can be gotten from a reverse engineered http Request. I’ll update this thread when I hear back from them.

In the meantime, the only way seems to be to add your sensitive headers using our modify headers feature. You could simply add it in the global headers section

"global_headers": {
      "X-Sensitive-Headers": "Header-1, Header2, Header-3",
    },
1 Like

@Olu
Thanks for the suggestion on the global_headers, this works but it injects the header X-Sensitive-Headers to the request, we dont want to inject any additional header to the request.
Any other field in the api definition that is captured by the analytics record that can be used in the plgin code to capture the info?

@deepthi.ar I would suggest abusing the tags field in the API definition as it can hold arbitrary strings, another option could be using policy meta data which would get passed to the api key the analytics record holds. Tags is for sure the easiest though.

2 Likes

@Josh Thank you for suggesting tags, it worked well, but its not flexible enough for our use case. Is there anyway we can extract config_data from the api definition from the analyticsRecord? Config data fits our use case perfectly.
Thank you!

@deepthi.ar You could also try using policy tags. I’m pretty sure these will appear in the analytics record and so should be accessible in your custom plugin to make decisions.