pii handling for restore config (#3896)
add pii concealer compliance for restore config structs. --- #### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🌻 Feature
This commit is contained in:
parent
c75ca7e41c
commit
92412645ec
@ -36,7 +36,7 @@ func (ctrl *Controller) ConsumeRestoreCollections(
|
||||
defer end()
|
||||
|
||||
ctx = graph.BindRateLimiterConfig(ctx, graph.LimiterCfg{Service: sels.PathService()})
|
||||
ctx = clues.Add(ctx, "restore_config", restoreCfg) // TODO(rkeepers): needs PII control
|
||||
ctx = clues.Add(ctx, "restore_config", restoreCfg)
|
||||
|
||||
if len(dcs) == 0 {
|
||||
return nil, clues.New("no data collections to restore")
|
||||
|
||||
@ -2,13 +2,17 @@ package control
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/alcionai/clues"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common/dttm"
|
||||
"github.com/alcionai/corso/src/pkg/logger"
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -39,24 +43,24 @@ const RootLocation = "/"
|
||||
type RestoreConfig struct {
|
||||
// Defines the per-item collision handling policy.
|
||||
// Defaults to Skip.
|
||||
OnCollision CollisionPolicy
|
||||
OnCollision CollisionPolicy `json:"onCollision"`
|
||||
|
||||
// ProtectedResource specifies which resource the data will be restored to.
|
||||
// If empty, restores to the same resource that was backed up.
|
||||
// Defaults to empty.
|
||||
ProtectedResource string
|
||||
ProtectedResource string `json:"protectedResource"`
|
||||
|
||||
// Location specifies the container into which the data will be restored.
|
||||
// Only accepts container names, does not accept IDs.
|
||||
// If empty or "/", data will get restored in place, beginning at the root.
|
||||
// Defaults to "Corso_Restore_<current_dttm>"
|
||||
Location string
|
||||
Location string `json:"location"`
|
||||
|
||||
// Drive specifies the name of the drive into which the data will be
|
||||
// restored. If empty, data is restored to the same drive that was backed
|
||||
// up.
|
||||
// Defaults to empty.
|
||||
Drive string
|
||||
Drive string `json:"drive"`
|
||||
}
|
||||
|
||||
func DefaultRestoreConfig(timeFormat dttm.TimeFormat) RestoreConfig {
|
||||
@ -90,3 +94,58 @@ func EnsureRestoreConfigDefaults(
|
||||
|
||||
return rc
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// pii control
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
var (
|
||||
// interface compliance required for handling PII
|
||||
_ clues.Concealer = &RestoreConfig{}
|
||||
_ fmt.Stringer = &RestoreConfig{}
|
||||
|
||||
// interface compliance for the observe package to display
|
||||
// values without concealing PII.
|
||||
_ clues.PlainStringer = &RestoreConfig{}
|
||||
)
|
||||
|
||||
func (rc RestoreConfig) marshal() string {
|
||||
bs, err := json.Marshal(rc)
|
||||
if err != nil {
|
||||
return "err marshalling"
|
||||
}
|
||||
|
||||
return string(bs)
|
||||
}
|
||||
|
||||
func (rc RestoreConfig) concealed() RestoreConfig {
|
||||
return RestoreConfig{
|
||||
OnCollision: rc.OnCollision,
|
||||
ProtectedResource: clues.Hide(rc.ProtectedResource).Conceal(),
|
||||
Location: path.LoggableDir(rc.Location),
|
||||
Drive: clues.Hide(rc.Drive).Conceal(),
|
||||
}
|
||||
}
|
||||
|
||||
// Conceal produces a concealed representation of the config, suitable for
|
||||
// logging, storing in errors, and other output.
|
||||
func (rc RestoreConfig) Conceal() string {
|
||||
return rc.concealed().marshal()
|
||||
}
|
||||
|
||||
// Format produces a concealed representation of the config, even when
|
||||
// used within a PrintF, suitable for logging, storing in errors,
|
||||
// and other output.
|
||||
func (rc RestoreConfig) Format(fs fmt.State, _ rune) {
|
||||
fmt.Fprint(fs, rc.concealed())
|
||||
}
|
||||
|
||||
// String returns a plain text version of the restoreConfig.
|
||||
func (rc RestoreConfig) String() string {
|
||||
return rc.PlainString()
|
||||
}
|
||||
|
||||
// PlainString returns an unescaped, unmodified string of the restore configuration.
|
||||
func (rc RestoreConfig) PlainString() string {
|
||||
return rc.marshal()
|
||||
}
|
||||
|
||||
@ -225,13 +225,13 @@ func ValidateSite(item models.Siteable) error {
|
||||
|
||||
wURL := ptr.Val(item.GetWebUrl())
|
||||
if len(wURL) == 0 {
|
||||
return clues.New("missing webURL").With("site_id", id) // TODO: pii
|
||||
return clues.New("missing webURL").With("site_id", clues.Hide(id))
|
||||
}
|
||||
|
||||
// personal (ie: oneDrive) sites have to be filtered out server-side.
|
||||
if strings.Contains(wURL, PersonalSitePath) {
|
||||
return clues.Stack(ErrKnownSkippableCase).
|
||||
With("site_id", id, "site_web_url", wURL) // TODO: pii
|
||||
With("site_id", clues.Hide(id), "site_web_url", clues.Hide(wURL))
|
||||
}
|
||||
|
||||
name := ptr.Val(item.GetDisplayName())
|
||||
@ -239,10 +239,10 @@ func ValidateSite(item models.Siteable) error {
|
||||
// the built-in site at "https://{tenant-domain}/search" never has a name.
|
||||
if strings.HasSuffix(wURL, "/search") {
|
||||
return clues.Stack(ErrKnownSkippableCase).
|
||||
With("site_id", id, "site_web_url", wURL) // TODO: pii
|
||||
With("site_id", clues.Hide(id), "site_web_url", clues.Hide(wURL))
|
||||
}
|
||||
|
||||
return clues.New("missing site display name").With("site_id", id)
|
||||
return clues.New("missing site display name").With("site_id", clues.Hide(id))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user