英文:
Conditionally print debug info containing sensitive data
问题
我正在运行一个作为k8s
作业的Go程序。
该应用程序向elasticsearch
集群发送API请求以创建用户,因此它将包含敏感数据(用户的密码)。
requestDump, err := httputil.DumpRequest(req, true)
responseDump, err := httputil.DumpResponse(resp, true)
esapiClient.log.Printf("在创建用户时收到响应代码 %d:%s\n", resp.StatusCode, user.Username)
if resp.StatusCode != http.StatusOK {
esapiClient.log.Printf("错误:在创建用户%s时收到响应代码:%d\n", user.Username, resp.StatusCode)
esapiClient.log.Println("请求\n", string(requestDump))
esapiClient.log.Println("响应\n", string(responseDump))
return ErrResponseCode
}
当事情出错时,我希望能够转储请求和响应(尤其是在400
情况下),以检查出错的原因(主要是潜在的格式错误的请求)。
有没有推荐的方法来实现这一点?日志级别是唯一的解决方法吗?
英文:
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?
答案1
得分: 3
日志级别不是一个解决方案。你的目标应该是在日志转储中完全避免包含个人身份信息(PII),包括在调试模式下启动服务时。
根据你的日志记录方式,只需在结构体上实现相关接口,并省略或隐藏包含PII的字段。对于需要在调试目的下保留一些关于原始值的线索的字段,你可以只隐藏部分信息。
例如,如果你使用fmt
格式化或类似的方式记录日志,可以实现Stringer
接口:
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 *****}
}
如果你以JSON格式记录日志,可以实现MarshalJSON
方法进行隐藏,或使用结构体标签json:"-"
进行省略:
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(u)
fmt.Println(string(b)) // {"name":"pkaramol","password":"*****"}
}
英文:
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":"*****"}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论