|  | 
|  | 1 | +package definition | 
|  | 2 | + | 
|  | 3 | +import ( | 
|  | 4 | +	"unsafe" | 
|  | 5 | + | 
|  | 6 | +	jsoniter "github.com/json-iterator/go" | 
|  | 7 | +	"github.com/modern-go/reflect2" | 
|  | 8 | +	amcfg "github.com/prometheus/alertmanager/config" | 
|  | 9 | +	commoncfg "github.com/prometheus/common/config" | 
|  | 10 | +) | 
|  | 11 | + | 
|  | 12 | +// secretEncoder encodes Secret to plain text JSON, | 
|  | 13 | +// avoiding the default masking behavior of the structure. | 
|  | 14 | +type secretEncoder struct{} | 
|  | 15 | + | 
|  | 16 | +func (encoder *secretEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
|  | 17 | +	stream.WriteString(getStr(ptr)) | 
|  | 18 | +} | 
|  | 19 | + | 
|  | 20 | +func (encoder *secretEncoder) IsEmpty(ptr unsafe.Pointer) bool { | 
|  | 21 | +	return len(getStr(ptr)) == 0 | 
|  | 22 | +} | 
|  | 23 | + | 
|  | 24 | +func getStr(ptr unsafe.Pointer) string { | 
|  | 25 | +	return *(*string)(ptr) | 
|  | 26 | +} | 
|  | 27 | + | 
|  | 28 | +// secretEncoder encodes SecretURL to plain text JSON, | 
|  | 29 | +// avoiding the default masking behavior of the structure. | 
|  | 30 | +type secretURLEncoder struct{} | 
|  | 31 | + | 
|  | 32 | +func (encoder *secretURLEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) { | 
|  | 33 | +	url := getURL(ptr) | 
|  | 34 | +	if url.URL != nil { | 
|  | 35 | +		stream.WriteString(url.String()) | 
|  | 36 | +	} else { | 
|  | 37 | +		stream.WriteNil() | 
|  | 38 | +	} | 
|  | 39 | +} | 
|  | 40 | + | 
|  | 41 | +func (encoder *secretURLEncoder) IsEmpty(ptr unsafe.Pointer) bool { | 
|  | 42 | +	url := getURL(ptr) | 
|  | 43 | +	return url.URL == nil | 
|  | 44 | +} | 
|  | 45 | + | 
|  | 46 | +func getURL(ptr unsafe.Pointer) *amcfg.URL { | 
|  | 47 | +	v := (*amcfg.SecretURL)(ptr) | 
|  | 48 | +	url := amcfg.URL(*v) | 
|  | 49 | +	return &url | 
|  | 50 | +} | 
|  | 51 | + | 
|  | 52 | +func newPlainAPI() jsoniter.API { | 
|  | 53 | +	api := jsoniter.ConfigCompatibleWithStandardLibrary | 
|  | 54 | + | 
|  | 55 | +	secretEnc := &secretEncoder{} | 
|  | 56 | +	secretURLEnc := &secretURLEncoder{} | 
|  | 57 | + | 
|  | 58 | +	extension := jsoniter.EncoderExtension{ | 
|  | 59 | +		// Value types | 
|  | 60 | +		reflect2.TypeOfPtr((*amcfg.Secret)(nil)).Elem():     secretEnc, | 
|  | 61 | +		reflect2.TypeOfPtr((*commoncfg.Secret)(nil)).Elem(): secretEnc, | 
|  | 62 | +		reflect2.TypeOfPtr((*amcfg.SecretURL)(nil)).Elem():  secretURLEnc, | 
|  | 63 | +		// Pointer types | 
|  | 64 | +		reflect2.TypeOfPtr((*amcfg.Secret)(nil)):     &jsoniter.OptionalEncoder{ValueEncoder: secretEnc}, | 
|  | 65 | +		reflect2.TypeOfPtr((*commoncfg.Secret)(nil)): &jsoniter.OptionalEncoder{ValueEncoder: secretEnc}, | 
|  | 66 | +		reflect2.TypeOfPtr((*amcfg.SecretURL)(nil)):  &jsoniter.OptionalEncoder{ValueEncoder: secretURLEnc}, | 
|  | 67 | +	} | 
|  | 68 | + | 
|  | 69 | +	api.RegisterExtension(extension) | 
|  | 70 | + | 
|  | 71 | +	return api | 
|  | 72 | +} | 
|  | 73 | + | 
|  | 74 | +var ( | 
|  | 75 | +	plainJSON = newPlainAPI() | 
|  | 76 | +) | 
|  | 77 | + | 
|  | 78 | +// MarshalJSONWithSecrets marshals the given value to JSON with secrets in plain text. | 
|  | 79 | +// | 
|  | 80 | +// alertmanager's and prometheus' Secret and SecretURL types mask their values | 
|  | 81 | +// when marshaled with the standard JSON or YAML marshallers. This function | 
|  | 82 | +// preserves the values of these types by using a custom JSON encoder. | 
|  | 83 | +func MarshalJSONWithSecrets(v any) ([]byte, error) { | 
|  | 84 | +	return plainJSON.Marshal(v) | 
|  | 85 | +} | 
0 commit comments