fix(secretstores): fix handling of TOML strings (#12490)

This commit is contained in:
Sven Rebhan 2023-01-11 15:43:20 +01:00 committed by GitHub
parent e9c0487e54
commit a3e4a14233
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 51 deletions

View File

@ -41,9 +41,9 @@ func NewSecret(b []byte) Secret {
return s return s
} }
// UnmarshalTOML creates a secret from a toml value. // UnmarshalText creates a secret from a toml value following the "string" rule.
func (s *Secret) UnmarshalTOML(b []byte) error { func (s *Secret) UnmarshalText(b []byte) error {
// Unmarshal raw secret from TOML and put it into protected memory // Unmarshal secret from TOML and put it into protected memory
s.init(b) s.init(b)
// Keep track of secrets that contain references to secret-stores // Keep track of secrets that contain references to secret-stores
@ -56,9 +56,7 @@ func (s *Secret) UnmarshalTOML(b []byte) error {
} }
// Initialize the secret content // Initialize the secret content
func (s *Secret) init(b []byte) { func (s *Secret) init(secret []byte) {
secret := unquoteTomlString(b)
// Remember if the secret is completely empty // Remember if the secret is completely empty
s.notempty = len(secret) != 0 s.notempty = len(secret) != 0

View File

@ -169,97 +169,128 @@ func TestSecretConstant(t *testing.T) {
func TestSecretUnquote(t *testing.T) { func TestSecretUnquote(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
cfg []byte cfg []byte
expected string
}{ }{
{ {
name: "single quotes", name: "single quotes",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = 'a secret' secret = 'a secret'
expected = 'a secret'
`), `),
expected: "a secret",
}, },
{ {
name: "double quotes", name: "double quotes",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = "a secret" secret = "a secret"
expected = "a secret"
`), `),
expected: "a secret",
}, },
{ {
name: "triple single quotes", name: "triple single quotes",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = '''a secret''' secret = '''a secret'''
expected = '''a secret'''
`), `),
expected: "a secret",
}, },
{ {
name: "triple double quotes", name: "triple double quotes",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = """a secret""" secret = """a secret"""
expected = """a secret"""
`), `),
expected: "a secret",
}, },
{ {
name: "escaped double quotes", name: "escaped double quotes",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = "\"a secret\"" secret = "\"a secret\""
expected = "\"a secret\""
`), `),
expected: `\"a secret\"`,
}, },
{ {
name: "mix double-single quotes (single)", name: "mix double-single quotes (single)",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = "'a secret'" secret = "'a secret'"
expected = "'a secret'"
`), `),
expected: `'a secret'`,
}, },
{ {
name: "mix single-double quotes (single)", name: "mix single-double quotes (single)",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = '"a secret"' secret = '"a secret"'
expected = '"a secret"'
`), `),
expected: `"a secret"`,
}, },
{ {
name: "mix double-single quotes (triple-single)", name: "mix double-single quotes (triple-single)",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = """'a secret'""" secret = """'a secret'"""
expected = """'a secret'"""
`), `),
expected: `'a secret'`,
}, },
{ {
name: "mix single-double quotes (triple-single)", name: "mix single-double quotes (triple-single)",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = '''"a secret"''' secret = '''"a secret"'''
expected = '''"a secret"'''
`), `),
expected: `"a secret"`,
}, },
{ {
name: "mix double-single quotes (triple)", name: "mix double-single quotes (triple)",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = """'''a secret'''""" secret = """'''a secret'''"""
expected = """'''a secret'''"""
`), `),
expected: `'''a secret'''`,
}, },
{ {
name: "mix single-double quotes (triple)", name: "mix single-double quotes (triple)",
cfg: []byte(` cfg: []byte(`
[[inputs.mockup]] [[inputs.mockup]]
secret = '''"""a secret"""''' secret = '''"""a secret"""'''
expected = '''"""a secret"""'''
`),
},
{
name: "single quotes with backslashes",
cfg: []byte(`
[[inputs.mockup]]
secret = 'Server=SQLTELEGRAF\\SQL2022;app name=telegraf;log=1;'
expected = 'Server=SQLTELEGRAF\\SQL2022;app name=telegraf;log=1;'
`),
},
{
name: "double quotes with backslashes",
cfg: []byte(`
[[inputs.mockup]]
secret = "Server=SQLTELEGRAF\\SQL2022;app name=telegraf;log=1;"
expected = "Server=SQLTELEGRAF\\SQL2022;app name=telegraf;log=1;"
`),
},
{
name: "triple single quotes with backslashes",
cfg: []byte(`
[[inputs.mockup]]
secret = '''Server=SQLTELEGRAF\\SQL2022;app name=telegraf;log=1;'''
expected = '''Server=SQLTELEGRAF\\SQL2022;app name=telegraf;log=1;'''
`),
},
{
name: "triple double quotes with backslashes",
cfg: []byte(`
[[inputs.mockup]]
secret = """Server=SQLTELEGRAF\\SQL2022;app name=telegraf;log=1;"""
expected = """Server=SQLTELEGRAF\\SQL2022;app name=telegraf;log=1;"""
`), `),
expected: `"""a secret"""`,
}, },
} }
@ -282,7 +313,7 @@ func TestSecretUnquote(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(secret) defer ReleaseSecret(secret)
require.EqualValues(t, tt.expected, string(secret)) require.EqualValues(t, plugin.Expected, string(secret))
}) })
} }
} }
@ -325,7 +356,7 @@ func TestSecretStoreStatic(t *testing.T) {
[[inputs.mockup]] [[inputs.mockup]]
secret = "@{mock:a_strange_secret}" secret = "@{mock:a_strange_secret}"
[[inputs.mockup]] [[inputs.mockup]]
secret = "@{mock:a_wierd_secret}" secret = "@{mock:a_weird_secret}"
`) `)
c := NewConfig() c := NewConfig()
@ -339,7 +370,7 @@ func TestSecretStoreStatic(t *testing.T) {
"secret1": []byte("Ood Bnar"), "secret1": []byte("Ood Bnar"),
"secret2": []byte("Thon"), "secret2": []byte("Thon"),
"a_strange_secret": []byte("Obi-Wan Kenobi"), "a_strange_secret": []byte("Obi-Wan Kenobi"),
"a_wierd_secret": []byte("Arca Jeth"), "a_weird_secret": []byte("Arca Jeth"),
}, },
} }
require.NoError(t, store.Init()) require.NoError(t, store.Init())
@ -366,7 +397,7 @@ func TestSecretStoreInvalidKeys(t *testing.T) {
[[inputs.mockup]] [[inputs.mockup]]
secret = "@{mock:a-strange-secret}" secret = "@{mock:a-strange-secret}"
[[inputs.mockup]] [[inputs.mockup]]
secret = "@{mock:a wierd secret}" secret = "@{mock:a weird secret}"
`) `)
c := NewConfig() c := NewConfig()
@ -380,7 +411,7 @@ func TestSecretStoreInvalidKeys(t *testing.T) {
"": []byte("Ood Bnar"), "": []byte("Ood Bnar"),
"wild?%go": []byte("Thon"), "wild?%go": []byte("Thon"),
"a-strange-secret": []byte("Obi-Wan Kenobi"), "a-strange-secret": []byte("Obi-Wan Kenobi"),
"a wierd secret": []byte("Arca Jeth"), "a weird secret": []byte("Arca Jeth"),
}, },
} }
require.NoError(t, store.Init()) require.NoError(t, store.Init())
@ -391,7 +422,7 @@ func TestSecretStoreInvalidKeys(t *testing.T) {
"@{mock:}", "@{mock:}",
"@{mock:wild?%go}", "@{mock:wild?%go}",
"@{mock:a-strange-secret}", "@{mock:a-strange-secret}",
"@{mock:a wierd secret}", "@{mock:a weird secret}",
} }
for i, input := range c.Inputs { for i, input := range c.Inputs {
plugin := input.Input.(*MockupSecretPlugin) plugin := input.Input.(*MockupSecretPlugin)
@ -509,7 +540,8 @@ func TestSecretStoreDynamic(t *testing.T) {
/*** Mockup (input) plugin for testing to avoid cyclic dependencies ***/ /*** Mockup (input) plugin for testing to avoid cyclic dependencies ***/
type MockupSecretPlugin struct { type MockupSecretPlugin struct {
Secret Secret `toml:"secret"` Secret Secret `toml:"secret"`
Expected string `toml:"expected"`
} }
func (*MockupSecretPlugin) SampleConfig() string { return "Mockup test secret plugin" } func (*MockupSecretPlugin) SampleConfig() string { return "Mockup test secret plugin" }

View File

@ -1,23 +0,0 @@
package config
import "bytes"
func unquoteTomlString(b []byte) []byte {
if len(b) >= 6 {
if bytes.HasPrefix(b, []byte(`'''`)) && bytes.HasSuffix(b, []byte(`'''`)) {
return b[3 : len(b)-3]
}
if bytes.HasPrefix(b, []byte(`"""`)) && bytes.HasSuffix(b, []byte(`"""`)) {
return b[3 : len(b)-3]
}
}
if len(b) >= 2 {
if bytes.HasPrefix(b, []byte(`'`)) && bytes.HasSuffix(b, []byte(`'`)) {
return b[1 : len(b)-1]
}
if bytes.HasPrefix(b, []byte(`"`)) && bytes.HasSuffix(b, []byte(`"`)) {
return b[1 : len(b)-1]
}
}
return b
}