Skip to content

Commit

Permalink
reposition fmt and secrets (#62)
Browse files Browse the repository at this point in the history
In preparation for otel support, I'm repositioning some files and funcs.

1. secrets is moving into `/clues/cecrets`. This move is for two
reasons: 1/ reduce clues api surface area. 2/ isolate "secret" handling
from general clues patterns.

2. marshal() and normalize() are moving into
`/clues/internal/stringify`. Marshal will get exposed with a Fmt command
for other packages to use (this will be a requirement for otel attribute
management).

Outside of the introduction of the Fmt() func, no logical changes should
have occurred in this PR. It's all movement/renaming.
  • Loading branch information
ryanfkeepers authored Nov 5, 2024
1 parent 5fd5083 commit 9db2431
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 85 deletions.
23 changes: 12 additions & 11 deletions secrets.go → cecrets/cecrets.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package clues
package cecrets

import (
"crypto/hmac"
Expand All @@ -8,6 +8,8 @@ import (
"fmt"
"io"
"time"

"github.com/alcionai/clues/internal/stringify"
)

const hashTruncateLen = 16
Expand All @@ -32,8 +34,7 @@ type HashCfg struct {
}

// SetHasher sets the hashing configuration used in
// all clues concealer structs, and clues.Conceal()
// and clues.Hash() calls.
// all concealer structs, and Conceal() and Hash() calls.
func SetHasher(sc HashCfg) {
config = sc
}
Expand Down Expand Up @@ -66,12 +67,12 @@ func makeDefaultHash() HashCfg {
// ---------------------------------------------------------------------------

type Concealer interface {
// Conceal produces an obfuscated representation of the value.
Conceal() string
// Concealers also need to comply with Format
// It's a bit overbearing, but complying with Concealer
// doesn't provide guarantees that the variable won't
// pass into fmt.Printf("%v") and skip the whole hash.
// This is for your protection, too.
// Concealers also need to comply with Format.
// Complying with Conceal() alone doesn't guarantee that
// the variable won't pass into fmt.Printf("%v") and skip
// the whole conceal process.
Format(fs fmt.State, verb rune)
// PlainStringer is the opposite of conceal.
// Useful for if you want to retrieve the raw value of a secret.
Expand Down Expand Up @@ -113,7 +114,7 @@ func Hide(a any) secret {

return secret{
hashText: Conceal(a),
plainText: marshal(a, false),
plainText: stringify.Fmt(a)[0],
value: a,
}
}
Expand All @@ -135,7 +136,7 @@ func HideAll(a ...any) []secret {
func Mask(a any) secret {
return secret{
hashText: "***",
plainText: marshal(a, false),
plainText: stringify.Fmt(a)[0],
value: a,
}
}
Expand All @@ -145,7 +146,7 @@ func Mask(a any) secret {
func Conceal(a any) string {
// marshal with false or else we hit a double hash (at best)
// or an infinite loop (at worst).
return ConcealWith(config.HashAlg, marshal(a, false))
return ConcealWith(config.HashAlg, stringify.Fmt(a)[0])
}

// Conceal runs one of clues' hashing algorithms on
Expand Down
2 changes: 1 addition & 1 deletion secrets_test.go → cecrets/cecrets_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package clues
package cecrets

import (
"fmt"
Expand Down
8 changes: 4 additions & 4 deletions clog/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"golang.org/x/exp/slices"

"github.com/alcionai/clues"
"github.com/alcionai/clues/cecrets"
)

// ---------------------------------------------------
Expand Down Expand Up @@ -163,10 +163,10 @@ func GetLogFileOrDefault(useThisFile string) string {
func setCluesSecretsHash(alg sensitiveInfoHandlingAlgo) {
switch alg {
case HashSensitiveInfo:
clues.SetHasher(clues.DefaultHash())
cecrets.SetHasher(cecrets.DefaultHash())
case MaskSensitiveInfo:
clues.SetHasher(clues.HashCfg{HashAlg: clues.Flatmask})
cecrets.SetHasher(cecrets.HashCfg{HashAlg: cecrets.Flatmask})
case ShowSensitiveInfoInPlainText:
clues.SetHasher(clues.NoHash())
cecrets.SetHasher(cecrets.NoHash())
}
}
10 changes: 6 additions & 4 deletions clues.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package clues

import (
"context"

"github.com/alcionai/clues/internal/stringify"
)

// ---------------------------------------------------------------------------
Expand All @@ -11,7 +13,7 @@ import (
// Add adds all key-value pairs to the clues.
func Add(ctx context.Context, kvs ...any) context.Context {
nc := nodeFromCtx(ctx)
return setNodeInCtx(ctx, nc.addValues(normalize(kvs...)))
return setNodeInCtx(ctx, nc.addValues(stringify.Normalize(kvs...)))
}

// AddMap adds a shallow clone of the map to a namespaced set of clues.
Expand All @@ -26,7 +28,7 @@ func AddMap[K comparable, V any](
kvs = append(kvs, k, v)
}

return setNodeInCtx(ctx, nc.addValues(normalize(kvs...)))
return setNodeInCtx(ctx, nc.addValues(stringify.Normalize(kvs...)))
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -58,7 +60,7 @@ func AddTraceWith(

var node *dataNode
if len(kvs) > 0 {
node = nc.addValues(normalize(kvs...))
node = nc.addValues(stringify.Normalize(kvs...))
node.id = traceID
} else {
node = nc.trace(traceID)
Expand Down Expand Up @@ -146,5 +148,5 @@ func Relay(
}

// set values, not add. We don't want agents to own a full clues tree.
ag.data.setValues(normalize(vs...))
ag.data.setValues(stringify.Normalize(vs...))
}
24 changes: 16 additions & 8 deletions clues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ import (
"testing"

"github.com/alcionai/clues"
"github.com/alcionai/clues/cecrets"
"golang.org/x/exp/slices"
)

func init() {
cecrets.SetHasher(cecrets.HashCfg{
HashAlg: cecrets.HMAC_SHA256,
HMACKey: []byte("gobbledeygook-believe-it-or-not-this-is-randomly-generated"),
})
}

func mapEquals(
t *testing.T,
ctx context.Context,
Expand Down Expand Up @@ -342,7 +350,7 @@ func TestImmutableCtx(t *testing.T) {
mustEquals(t, msa{"foo": "bar", "beaux": "regard"}, clues.In(lr).Map(), true)
}

var _ clues.Concealer = &safe{}
var _ cecrets.Concealer = &safe{}

type safe struct {
v any
Expand All @@ -360,7 +368,7 @@ func (s safe) Conceal() string {
return string(bs)
}

var _ clues.Concealer = &custom{}
var _ cecrets.Concealer = &custom{}

type custom struct {
a, b string
Expand All @@ -370,11 +378,11 @@ func (c custom) PlainString() string { return c.a + " - " + c.b }
func (c custom) Format(fs fmt.State, verb rune) { io.WriteString(fs, c.Conceal()) }

func (c custom) Conceal() string {
return c.a + " - " + clues.ConcealWith(clues.SHA256, c.b)
return c.a + " - " + cecrets.ConcealWith(cecrets.SHA256, c.b)
}

func concealed(a any) string {
c, ok := a.(clues.Concealer)
c, ok := a.(cecrets.Concealer)
if !ok {
return "NOT CONCEALER"
}
Expand All @@ -391,13 +399,13 @@ func TestAdd_concealed(t *testing.T) {
}{
{
name: "all hidden",
concealers: [][]any{{clues.Hide("k"), clues.Hide("v")}, {clues.Hide("not_k"), clues.Hide("not_v")}},
expectM: msa{"cc69e8e6a3b991d5": "f669b3b5927161b2", "ba3acd7f61e405ca": "509bf4fb69f55ca3"},
expectS: sa{"cc69e8e6a3b991d5", "f669b3b5927161b2", "ba3acd7f61e405ca", "509bf4fb69f55ca3"},
concealers: [][]any{{cecrets.Hide("k"), cecrets.Hide("v")}, {cecrets.Hide("not_k"), cecrets.Hide("not_v")}},
expectM: msa{"ba3acd7f61e405ca": "509bf4fb69f55ca3", "cc69e8e6a3b991d5": "f669b3b5927161b2"},
expectS: sa{"ba3acd7f61e405ca", "509bf4fb69f55ca3", "cc69e8e6a3b991d5", "f669b3b5927161b2"},
},
{
name: "partially hidden",
concealers: [][]any{{clues.Hide("a"), safe{1}}, {clues.Hide(2), safe{"b"}}},
concealers: [][]any{{cecrets.Hide("a"), safe{1}}, {cecrets.Hide(2), safe{"b"}}},
expectM: msa{"7d2ded59f6a549d7": "1", "cbdd96fab83ece85": `"b"`},
expectS: sa{"7d2ded59f6a549d7", "1", "cbdd96fab83ece85", `"b"`},
},
Expand Down
55 changes: 0 additions & 55 deletions datanode.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"path"
"reflect"
"runtime"
"strings"

Expand Down Expand Up @@ -80,60 +79,6 @@ func (dn *dataNode) spawnDescendant() *dataNode {
// setters
// ---------------------------------------------------------------------------

// normalize ensures that the variadic of key-value pairs is even in length,
// and then transforms that slice of values into a map[string]any, where all
// keys are transformed to string using the marshal() func.
func normalize(kvs ...any) map[string]any {
norm := map[string]any{}

for i := 0; i < len(kvs); i += 2 {
key := marshal(kvs[i], true)

var value any
if i+1 < len(kvs) {
value = marshal(kvs[i+1], true)
}

norm[key] = value
}

return norm
}

// marshal is the central marshalling handler for the entire package. All
// stringification of values comes down to this function. Priority for
// stringification follows this order:
// 1. nil -> ""
// 2. conceal all concealer interfaces
// 3. flat string values
// 4. string all stringer interfaces
// 5. fmt.sprintf the rest
func marshal(a any, conceal bool) string {
if a == nil {
return ""
}

// protect against nil pointer values with value-receiver funcs
rvo := reflect.ValueOf(a)
if rvo.Kind() == reflect.Ptr && rvo.IsNil() {
return ""
}

if as, ok := a.(Concealer); conceal && ok {
return as.Conceal()
}

if as, ok := a.(string); ok {
return as
}

if as, ok := a.(fmt.Stringer); ok {
return as.String()
}

return fmt.Sprintf("%+v", a)
}

// addValues adds all entries in the map to the dataNode's values.
func (dn *dataNode) addValues(m map[string]any) *dataNode {
if m == nil {
Expand Down
3 changes: 2 additions & 1 deletion err.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"reflect"
"strings"

"github.com/alcionai/clues/internal/stringify"
"golang.org/x/exp/maps"
)

Expand Down Expand Up @@ -889,7 +890,7 @@ func (err *Err) With(kvs ...any) *Err {
}

if len(kvs) > 0 {
err.data = err.data.addValues(normalize(kvs...))
err.data = err.data.addValues(stringify.Normalize(kvs...))
}

return err
Expand Down
3 changes: 2 additions & 1 deletion errcore.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"strings"

"github.com/alcionai/clues/internal/stringify"
"golang.org/x/exp/maps"
)

Expand Down Expand Up @@ -72,7 +73,7 @@ func (ec *ErrCore) stringer(fancy bool) string {

vsl := []string{}
for k, v := range ec.Values {
vsl = append(vsl, k+":"+marshal(v, true))
vsl = append(vsl, k+":"+stringify.Marshal(v, true))
}

vs := strings.Join(vsl, sep)
Expand Down
Loading

0 comments on commit 9db2431

Please sign in to comment.