突然ですが、コーディングをする時にマスキングしていますか?
本番運用の際、機密情報がログへ出力されてしまい、内容を知る必要のない人に知れ渡ってしまう...なんてことが無いように
情報漏えいのリスクは最小限に抑えたいところです。
この記事では、Goのfmtパッケージ
の下記インタフェースを満たすことで、機密情報がログへ出力されることを防止する方法を紹介します。
// %#v の時に使用される
type GoStringer interface {
GoString() string
}
// %#v を除く、いかなる時にも使用される
type Stringer interface {
String() string
}
実際のコードは以下のようになります。
サンプルでマイナンバーを機密情報に見立ててみました。
main.go
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID int
Username string
MyNumber MyNumber
}
// !!機密情報(日本国内の全住民に付番される12桁の番号)!!
type MyNumber string
func (m MyNumber) GoString() string {
return "XXXX XXXX XXXX"
}
func (m MyNumber) String() string {
return "XXXX XXXX XXXX"
}
func main() {
user := User{
ID: 1,
Username: "test",
MyNumber: "1234 5678 9012",
}
fmt.Println(user)
fmt.Printf("%v\n", user)
fmt.Printf("%+v\n", user)
fmt.Printf("%#v\n", user)
// 以下のように表示される
// {1 test XXXX XXXX XXXX}
// {1 test XXXX XXXX XXXX}
// {ID:1 Username:test MyNumber:XXXX XXXX XXXX}
// main.User{ID:1, Username:"test", MyNumber:XXXX XXXX XXXX}
// プログラム本体には影響しない
user.MyNumber = "9876 5432 1098"
bytes, _ := json.Marshal(user)
fmt.Println("JSON:", string(bytes))
// 以下のように表示される
// JSON: {"ID":1,"Username":"test","MyNumber":"9876 5432 1098"}
}
以上のように、fmtパッケージの2つにインターフェースを満たすことで、簡単にマスキングができました。
面倒臭さは少しありますが、機密情報を扱う場合などに使えるのではないか思います。