fix(secretstores): fix handling of TOML strings (#12490)
This commit is contained in:
parent
e9c0487e54
commit
a3e4a14233
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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" }
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue