Loading .gitlab-ci.yml +9 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,7 @@ test-on-local: - curl -sSf "$VAULT_BASE_URL/sys/health" # create a secret in Vault - | curl --silent --header "X-Vault-Token: ${VAULT_DEV_ROOT_TOKEN_ID}" --request PUT --data '{"data": {"foo": "bar", "zip": "zap"}}' "${VAULT_BASE_URL}/secret/data/my-secret" curl --silent --header "X-Vault-Token: ${VAULT_DEV_ROOT_TOKEN_ID}" --request PUT --data '{"data": {"foo": "bar", "zip": "zap", "dede.1": "toto"}}' "${VAULT_BASE_URL}/secret/data/my-secret" # test: get existing secret shall succeed - | resp_status=$(curl -s -o "resp.txt" -w "%{http_code}" "http://vault-secrets-provider/api/secrets/my-secret?field=foo") Loading @@ -94,6 +94,14 @@ test-on-local: cat resp.txt exit 1 fi # test: get existing secret with escaping character shall succeed - | resp_status=$(curl -s -o "resp.txt" -w "%{http_code}" "http://vault-secrets-provider/api/secrets/my-secret?field=dede\.1") if [[ "$resp_status" != "200" ]]; then echo "FAILED get existing secret ($resp_status)" cat resp.txt exit 1 fi # test: get secret with non existing path shall fail with code 404 - | resp_status=$(curl -s -o "resp.txt" -w "%{http_code}" "http://vault-secrets-provider/api/secrets/no/such/path?field=foo") Loading README.md +5 −1 Original line number Diff line number Diff line Loading @@ -60,14 +60,18 @@ Let's suppose your have a secret stored under `/b7ecb6ebabc231/my-backend/prod` "mysql": { "user": "root", "password": "p@s5w0rd" } }, "golang.nickname": "Go" } ``` > :warning: You can use `\` as an escape character when a secret key contains `.` Then you may retrieve: * the token calling `GET http://vault-secrets-provider/api/secrets/b7ecb6ebabc231/my-backend/prod?field=token` * the MySql password calling `GET http://vault-secrets-provider/api/secrets/b7ecb6ebabc231/my-backend/prod?field=mysql.password` * the Golang nickname calling `GET http://vault-secrets-provider/api/secrets/b7ecb6ebabc231/my-backend/prod?field=golang\.nickname` #### PUT secret endpoint Loading cmd/vault_service/internal/vault_client.go +12 −1 Original line number Diff line number Diff line Loading @@ -565,13 +565,24 @@ func doDeleteSecret(secretPath string) error { } } // splitWithEscaping slices s into all substrings separated by sep and returns a slice of the substrings between those separators. // It considers an escape character for separator func splitWithEscaping(s, sep, escape string) []string { s = strings.ReplaceAll(s, escape+sep, `\x00`) subStrings := strings.Split(s, sep) for i, subString := range subStrings { subStrings[i] = strings.ReplaceAll(subString, `\x00`, sep) } return subStrings } /** * Retrieves a sub object within a map * @arg obj: a map object * @arg keyPath: dot separated keys path (ex: '.', 'path.to.field') */ func getObj(obj map[string]interface{}, keyPath string) (string, error) { keys := strings.Split(keyPath, ".") keys := splitWithEscaping(keyPath, ".", `\`) var sub interface{} sub = obj for index := 0; index < len(keys); index++ { Loading cmd/vault_service/internal/vault_client_test.go +18 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,24 @@ func Test_get_sub_map(t *testing.T) { } } func Test_get_sub_key_with_dot(t *testing.T) { obj := map[string]interface{}{ "key": "value", "map": map[string]interface{}{ "k1.1": "111", "k2": "222", "k3": "333", }, } path := `map.k1\.1` expected := `111` if sub, err := getObj(obj, path); err != nil { t.Fatalf("Error retrieving sub object: %v", err) } else if sub != expected { t.Fatalf("Assert error\nExpected:\n%s\nGot:\n%s", string(expected), string(sub)) } } func Test_get_sub_sub_key(t *testing.T) { obj := map[string]interface{}{ "key": "value", Loading Loading
.gitlab-ci.yml +9 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,7 @@ test-on-local: - curl -sSf "$VAULT_BASE_URL/sys/health" # create a secret in Vault - | curl --silent --header "X-Vault-Token: ${VAULT_DEV_ROOT_TOKEN_ID}" --request PUT --data '{"data": {"foo": "bar", "zip": "zap"}}' "${VAULT_BASE_URL}/secret/data/my-secret" curl --silent --header "X-Vault-Token: ${VAULT_DEV_ROOT_TOKEN_ID}" --request PUT --data '{"data": {"foo": "bar", "zip": "zap", "dede.1": "toto"}}' "${VAULT_BASE_URL}/secret/data/my-secret" # test: get existing secret shall succeed - | resp_status=$(curl -s -o "resp.txt" -w "%{http_code}" "http://vault-secrets-provider/api/secrets/my-secret?field=foo") Loading @@ -94,6 +94,14 @@ test-on-local: cat resp.txt exit 1 fi # test: get existing secret with escaping character shall succeed - | resp_status=$(curl -s -o "resp.txt" -w "%{http_code}" "http://vault-secrets-provider/api/secrets/my-secret?field=dede\.1") if [[ "$resp_status" != "200" ]]; then echo "FAILED get existing secret ($resp_status)" cat resp.txt exit 1 fi # test: get secret with non existing path shall fail with code 404 - | resp_status=$(curl -s -o "resp.txt" -w "%{http_code}" "http://vault-secrets-provider/api/secrets/no/such/path?field=foo") Loading
README.md +5 −1 Original line number Diff line number Diff line Loading @@ -60,14 +60,18 @@ Let's suppose your have a secret stored under `/b7ecb6ebabc231/my-backend/prod` "mysql": { "user": "root", "password": "p@s5w0rd" } }, "golang.nickname": "Go" } ``` > :warning: You can use `\` as an escape character when a secret key contains `.` Then you may retrieve: * the token calling `GET http://vault-secrets-provider/api/secrets/b7ecb6ebabc231/my-backend/prod?field=token` * the MySql password calling `GET http://vault-secrets-provider/api/secrets/b7ecb6ebabc231/my-backend/prod?field=mysql.password` * the Golang nickname calling `GET http://vault-secrets-provider/api/secrets/b7ecb6ebabc231/my-backend/prod?field=golang\.nickname` #### PUT secret endpoint Loading
cmd/vault_service/internal/vault_client.go +12 −1 Original line number Diff line number Diff line Loading @@ -565,13 +565,24 @@ func doDeleteSecret(secretPath string) error { } } // splitWithEscaping slices s into all substrings separated by sep and returns a slice of the substrings between those separators. // It considers an escape character for separator func splitWithEscaping(s, sep, escape string) []string { s = strings.ReplaceAll(s, escape+sep, `\x00`) subStrings := strings.Split(s, sep) for i, subString := range subStrings { subStrings[i] = strings.ReplaceAll(subString, `\x00`, sep) } return subStrings } /** * Retrieves a sub object within a map * @arg obj: a map object * @arg keyPath: dot separated keys path (ex: '.', 'path.to.field') */ func getObj(obj map[string]interface{}, keyPath string) (string, error) { keys := strings.Split(keyPath, ".") keys := splitWithEscaping(keyPath, ".", `\`) var sub interface{} sub = obj for index := 0; index < len(keys); index++ { Loading
cmd/vault_service/internal/vault_client_test.go +18 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,24 @@ func Test_get_sub_map(t *testing.T) { } } func Test_get_sub_key_with_dot(t *testing.T) { obj := map[string]interface{}{ "key": "value", "map": map[string]interface{}{ "k1.1": "111", "k2": "222", "k3": "333", }, } path := `map.k1\.1` expected := `111` if sub, err := getObj(obj, path); err != nil { t.Fatalf("Error retrieving sub object: %v", err) } else if sub != expected { t.Fatalf("Assert error\nExpected:\n%s\nGot:\n%s", string(expected), string(sub)) } } func Test_get_sub_sub_key(t *testing.T) { obj := map[string]interface{}{ "key": "value", Loading