Closed alovak closed 1 year ago
Could we pass a flag / config value to toggle whether to mask such fields or not?
I imagine users of this lib may want to print out this value for testing / debugging
Yeah, I see this as an option.
I would hope the same flag could be passed back into #103 so that those errors which will be passed out of the library could be masked by default as well. By default, PII data wouldn't be returned unless the library was in verbose or debug mode.
Maybe we need a list of fields that we want to mask?
Field 02: PAN (Primary account number) Field 20: Primary account number extended Field 35: Track 2 data Field 36: Track 3 data Field 45: Track 1 data Field 52: PIN (Personal Identification Number) Field 55: EMV TLV data (this is a nested tree and should have its own config)
I think because of the different meanings of the fields in different specs, we can't rely on the field number.
Maybe, as idea, we can add Mask
field into the Spec:
2: field.NewString(&field.Spec{
Length: 19,
Description: "Primary Account Number",
Enc: encoding.ASCII,
Pref: prefix.ASCII.LL,
Mask: macking.PAN,
}),
package macking
type Masker func(string) string
var PAN Masker = func(number string) string {
if number == "" || len(number) < 5 {
return ""
}
in := []byte(number)
return fmt.Sprintf("%s%s%s", in[:1], strings.Repeat("*", 6), in[len(in)-4:])
}
My assumption, that then we can mask data in errors, logs, describe.Message
using provided Mask.
P.S. We can use something like https://pkg.go.dev/github.com/ggwhite/go-masker to avoid our own implementations of different masking functions.
Adding some more ideas so we can resume work on filtering data when we dump messages...
I'm looking at it from two perspectives:
Currently, we have Describe
method:
iso8583.Describe(os.Stdout, msg)
we can make Describe
to be a variadic function that accepts optional filters for the fields:
iso8583.Describe(os.Stdout, msg, FilterField("2", PANFilter), FilterField("59", WhateverFilter))
we can also define DefaultFilters
for fields we know 100%, like field 2, etc. so the user can:
iso8583.Describe(os.Stdout, msg, iso8583.DefaultFiledFilters)
I have a working POC here for Describe
method: https://go.dev/play/p/0Efyo7kjjqe
Currently, we have the describe
command for which we can add filter argument(s) like this:
./iso8583 describe --filter 2:pan --filter 59:pan mgs.dat
where pan
is defined filter in the package.
Also, it would be good to filter fields of the composite fields as well (in my POC, it works with int IDs, not strings)
This looks pretty useful and there's prior art in the ACH package. We have fixed field positions so we can avoid having to specify the field # to mask. The decision to mask a field is passed through an Opts
struct.
https://pkg.go.dev/github.com/moov-io/ach/cmd/achcli/describe
btw, @adamdecaf what do you think about:
instead of:
iso8583.Describe(os.Stdout, msg, iso8583.DefaultFieldFilters)
apply them by default? We may assume that, in most cases, the user will be safe displaying the message fields.
if the user does not want any filters, he can:
iso8583.Describe(os.Stdout, msg, iso8583.DoNotFilterFields)
Yea, it's pretty common to use an int
and masking to pass along several flags. The ...args
option works as well and is easier to understand. The default of Describe
can be to mask (as that's safer and is only for human readable use).
https://github.com/golang/go/blob/go1.19.3/src/text/tabwriter/tabwriter.go#L168-L208
I like having a default set of masking flags, especially if the card brands use the same fields we could mask by default.
The idx:type
mapping of fields makes sense to me and can easily have a Go api.
We may create an option that will enable masking of the card number when we dump messages. That may be useful for logging, etc.