From b8788fdb207da1678aa305b5c0f072a6ad548504 Mon Sep 17 00:00:00 2001 From: Yannis Zarkadas Date: Thu, 16 Jul 2020 12:36:35 +0300 Subject: [PATCH] Introduce a new type for security-sensitive fields We should take extra care not to log security-sensitive fields. Introduce a new type `Sensitive` for exactly this purpose. When this type is converted to String or JSON bytes, its value is redacted. Signed-off-by: Yannis Zarkadas --- main.go | 11 +++++---- pkg/common/doc.go | 5 ++++ pkg/common/protect.go | 54 +++++++++++++++++++++++++++++++++++++++++++ settings.go | 17 ++++++++------ 4 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 pkg/common/doc.go create mode 100644 pkg/common/protect.go diff --git a/main.go b/main.go index 1164115b..f1d55a3c 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,11 @@ package main import ( "context" "fmt" + "io/ioutil" + "net/http" + "path" + "time" + "github.com/boltdb/bolt" "github.com/coreos/go-oidc" "github.com/gorilla/handlers" @@ -14,10 +19,6 @@ import ( "github.com/yosssi/boltstore/reaper" "github.com/yosssi/boltstore/store" "golang.org/x/oauth2" - "io/ioutil" - "net/http" - "path" - "time" ) // Issue: https://github.com/gorilla/sessions/issues/200 @@ -130,7 +131,7 @@ func main() { provider: provider, oauth2Config: &oauth2.Config{ ClientID: c.ClientID, - ClientSecret: c.ClientSecret, + ClientSecret: c.ClientSecret.Reveal(), Endpoint: endpoint, RedirectURL: c.RedirectURL.String(), Scopes: c.OIDCScopes, diff --git a/pkg/common/doc.go b/pkg/common/doc.go new file mode 100644 index 00000000..0ae4a531 --- /dev/null +++ b/pkg/common/doc.go @@ -0,0 +1,5 @@ +// Package common contains helpers for common things that are needed when +// developing Go programs. The goal is to standardize on using high-quality +// implementations that follow best-practices. + +package common diff --git a/pkg/common/protect.go b/pkg/common/protect.go new file mode 100644 index 00000000..3a00b451 --- /dev/null +++ b/pkg/common/protect.go @@ -0,0 +1,54 @@ +package common + +import ( + "encoding" + "encoding/json" + "fmt" +) + +// ProtectedString is a type for security-ProtectedString fields. +// It hides its value when printed or marshalled to JSON. +// Used to hide ProtectedString fields from loggers. +type ProtectedString struct { + value string +} + +var message = "" + +func NewProtectedString(val string) ProtectedString { + return ProtectedString{ + value: val, + } +} + +// Reveal returns the secret value. +func (p ProtectedString) Reveal() string { + return p.value +} + +// String returns the string representation of the type. Override it to avoid +// logging the secret value. +func (p ProtectedString) String() string { + return message +} + +var _ fmt.Stringer = (*ProtectedString)(nil) + +// MarshalJSON returns the JSON representation of the type. Many loggers will +// log JSON representation of types. Override it to avoid logging the secret +// value. +func (p *ProtectedString) MarshalJSON() ([]byte, error) { + return json.Marshal(&message) +} + +var _ json.Marshaler = (*ProtectedString)(nil) + +// UnmarshalText can unmarshal a textual representation of a ProtectedString. +// Needed for use with the envconfig library: +// https://github.com/kelseyhightower/envconfig +func (p *ProtectedString) UnmarshalText(text []byte) error { + p.value = string(text) + return nil +} + +var _ encoding.TextUnmarshaler = (*ProtectedString)(nil) diff --git a/settings.go b/settings.go index 085a47a0..4363764e 100644 --- a/settings.go +++ b/settings.go @@ -1,23 +1,26 @@ package main import ( - "github.com/kelseyhightower/envconfig" "net/url" "os" "strings" + + "github.com/arrikto/oidc-authservice/pkg/common" + "github.com/kelseyhightower/envconfig" ) +// config holds all the configuration for the AuthService. type config struct { // OIDC Provider ProviderURL *url.URL `required:"true" split_words:"true" envconfig:"OIDC_PROVIDER"` // OIDC Client - ClientID string `required:"true" split_words:"true"` - ClientSecret string `required:"true" split_words:"true"` - OIDCAuthURL *url.URL `split_words:"true"` - RedirectURL *url.URL `split_words:"true"` - OIDCScopes []string `split_words:"true" default:"openid,email"` - StrictSessionValidation bool `split_words:"true"` + ClientID string `required:"true" split_words:"true"` + ClientSecret common.ProtectedString `required:"true" split_words:"true"` + OIDCAuthURL *url.URL `split_words:"true"` + RedirectURL *url.URL `split_words:"true"` + OIDCScopes []string `split_words:"true" default:"openid,email"` + StrictSessionValidation bool `split_words:"true"` // General AuthserviceURLPrefix *url.URL `required:"true" split_words:"true"`