I am running a Go program as a k8s
job.
The application sends an API request to an elasticsearch
cluster to create users, therefore it will contain sensitive data (user's password).
requestDump, err := httputil.DumpRequest(req, true)
responseDump, err := httputil.DumpResponse(resp, true)
esapiClient.log.Printf("got response code %d when creating user: %s\n", resp.StatusCode, user.Username)
if resp.StatusCode != http.StatusOK {
esapiClient.log.Printf("error: got response code: %d when creating user %s\n", resp.StatusCode, user.Username)
esapiClient.log.Println("Request\n", string(requestDump))
esapiClient.log.Println("Response\n", string(responseDump))
return ErrResponseCode
}
When things go south, I want to be able to dump the request and the responses (especially in 400
cases) to check what went wrong (mainly with potentially malformed requests).
What is the recommended way of of doing this? Are log levels the only way around this?
CodePudding user response:
Log levels is a non-solution. Your goal should be not having PII (personally identifiable information) end up in your log dumps altogether, including when you start the service in debug mode.
Depending on how you do the logging, just implement the relevant interfaces on your structs and omit or redact fields that contain PII. In case of fields where you need to have some clue about the original value for debugging purposes, you can redact only a part of it.
For example, if you log with fmt
verbs or similar, you can implement the Stringer
interface:
type User struct {
Name string
Password string
}
func (u User) String() string {
return fmt.Sprintf("{%s %s}", u.Name, "*****")
}
func main() {
u := User{"pkaramol", "secret"}
fmt.Println(u) // {pkaramol *****}
}
If you log in JSON, implement MarshalJSON
to redact, or use the struct tag json:"-"
to omit:
func (u User) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"name": u.Name,
"password": "*****",
})
}
func main() {
u := User{"pkaramol", "secret"}
b, _ := json.Marshal()
fmt.Println(string(b)) // {"name":"pkaramol","password":"*****"}
}