github.com/lulzWill/go-agent@v2.1.2+incompatible/internal/security_policies.go (about) 1 package internal 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 ) 8 9 // Security policies documentation: 10 // https://source.datanerd.us/agents/agent-specs/blob/master/Language-Agent-Security-Policies.md 11 12 // SecurityPolicies contains the security policies. 13 type SecurityPolicies struct { 14 RecordSQL securityPolicy `json:"record_sql"` 15 AttributesInclude securityPolicy `json:"attributes_include"` 16 AllowRawExceptionMessages securityPolicy `json:"allow_raw_exception_messages"` 17 CustomEvents securityPolicy `json:"custom_events"` 18 CustomParameters securityPolicy `json:"custom_parameters"` 19 } 20 21 // PointerIfPopulated returns a reference to the security policies if they have 22 // been populated from JSON. 23 func (sp *SecurityPolicies) PointerIfPopulated() *SecurityPolicies { 24 emptyPolicies := SecurityPolicies{} 25 if nil != sp && *sp != emptyPolicies { 26 return sp 27 } 28 return nil 29 } 30 31 type securityPolicy struct { 32 EnabledVal *bool `json:"enabled"` 33 } 34 35 func (p *securityPolicy) Enabled() bool { return nil == p.EnabledVal || *p.EnabledVal } 36 func (p *securityPolicy) SetEnabled(enabled bool) { p.EnabledVal = &enabled } 37 func (p *securityPolicy) IsSet() bool { return nil != p.EnabledVal } 38 39 type policyer interface { 40 SetEnabled(bool) 41 IsSet() bool 42 } 43 44 // UnmarshalJSON decodes security policies sent from the preconnect endpoint. 45 func (sp *SecurityPolicies) UnmarshalJSON(data []byte) (er error) { 46 defer func() { 47 // Zero out all fields if there is an error to ensure that the 48 // populated check works. 49 if er != nil { 50 *sp = SecurityPolicies{} 51 } 52 }() 53 54 var raw map[string]struct { 55 Enabled bool `json:"enabled"` 56 Required bool `json:"required"` 57 } 58 err := json.Unmarshal(data, &raw) 59 if err != nil { 60 return fmt.Errorf("unable to unmarshal security policies: %v", err) 61 } 62 63 knownPolicies := make(map[string]policyer) 64 65 spv := reflect.ValueOf(sp).Elem() 66 for i := 0; i < spv.NumField(); i++ { 67 fieldAddress := spv.Field(i).Addr() 68 field := fieldAddress.Interface().(policyer) 69 name := spv.Type().Field(i).Tag.Get("json") 70 knownPolicies[name] = field 71 } 72 73 for name, policy := range raw { 74 p, ok := knownPolicies[name] 75 if !ok { 76 if policy.Required { 77 return errUnknownRequiredPolicy{name: name} 78 } 79 } else { 80 p.SetEnabled(policy.Enabled) 81 } 82 } 83 for name, policy := range knownPolicies { 84 if !policy.IsSet() { 85 return errUnsetPolicy{name: name} 86 } 87 } 88 return nil 89 } 90 91 type errUnknownRequiredPolicy struct{ name string } 92 93 func (err errUnknownRequiredPolicy) Error() string { 94 return fmt.Sprintf("policy '%s' is unrecognized, please check for a newer agent version or contact support", err.name) 95 } 96 97 type errUnsetPolicy struct{ name string } 98 99 func (err errUnsetPolicy) Error() string { 100 return fmt.Sprintf("policy '%s' not received, please contact support", err.name) 101 }