security_policies.go 2.8 KB

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