😎

【Go】機密情報の出力書式をダミー化する

2022/10/08に公開

やり方

Stringer と GoStringer インタフェースを満たす型を定義することで、fmt.Println などから出力される書式を別のテキストに置き換えることができます。

const dummyCardNumber = "xxxx-xxxx-xxxx-xxxx"

type CardNumber string

func (c CardNumber) String() string {
  return dummyCardNumber
}

func (c CardNumber) GoString() string {
  return dummyCardNumber
}

func main() {
  c := CardNumber("1111-1111-1111-1111")
  fmt.Println(c)
  // => xxxx-xxxx-xxxx-xxxx

  fmt.Printf("%#v", c)
  // => xxxx-xxxx-xxxx-xxxx
}

Stringer とは

fmt パッケージで定義されている、文字列の出力書式を決定するためのインタフェースのことです。

type Stringer interface {
  String() string
}

多くのパッケージでは、文字列の出力に Stringer インタフェースを使用しているため、このインタフェースを満たしてあげることで出力書式をカスタマイズすることができます。
Stringer

GoStringer とは

Go 言語の構文の出力書式を決定するためのインタフェースのことです。
Stringer と同じで fmt パッケージで定義されています。

type GoStringer interface {
  GoString() string
}

GoStringer を満たしてあげることで、fmt.Printf の書式指定子である %#v を用いて出力される書式を制御できます。
GoStringer

機密情報をダミーする理由

機密情報の漏洩リスクを減らすためです。
特にログなどで出力する必要のない機密情報は、冗長ですが上記の対策をしておくことをオススメします。

【おまけ】zap の場合

zap とは、高速なサードパーティーの構造化ロギングパッケージのことです。
ベンチマークによると標準パッケージよりも高速みたいで、アプリ開発などでよく利用されています。
zap

そして zap でも、zap.Stringer を使用することで問題なく出力書式をダミー化することができます。

const dummyCardNumber = "xxxx-xxxx-xxxx-xxxx"

type CardNumber string

func (c CardNumber) String() string {
  return dummyCardNumber
}

func (c CardNumber) GoString() string {
  return dummyCardNumber
}

func main() {
  logger, _ := zap.NewProduction()
  defer logger.Sync()

  c := CardNumber("1111-1111-1111-1111")
  logger.Info("クレカ", zap.Stringer("カード番号", c))
  // => {"level":"info", ... "msg":"クレカ","カード番号":"xxxx-xxxx-xxxx-xxxx"}
}

最後に

記念すべき zenn 初投稿です!
マサカリが大好きなので、ご指摘お待ちしております!

引用

Discussion