From 823eab4775e125296d0a3df2a7bf1533f2a31388 Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown Date: Sun, 10 May 2020 12:11:26 +0100 Subject: [PATCH] secretsync: escape $ in variable content GitLab doesn't treat $ as literals in file content, which means that it tries to do variable interpolation. This is bad and annoying, because e.g. password hashes tend to contain $, so they get variable-interpolated and thus corrupted. Fix this by escaping $ on input to GitLab. --- nix/pkgs/secretsync/secretsync.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/nix/pkgs/secretsync/secretsync.go b/nix/pkgs/secretsync/secretsync.go index bb9a328fb3..f3ed0f71d7 100644 --- a/nix/pkgs/secretsync/secretsync.go +++ b/nix/pkgs/secretsync/secretsync.go @@ -134,6 +134,19 @@ type ProjectVariable struct { Masked bool `json:"masked" url:"masked"` } +func (v ProjectVariable) EncodedValue() string { + return strings.ReplaceAll(v.Value, "$", "$$") +} + +func (v ProjectVariable) Values() url.Values { + data, err := query.Values(v) + if err != nil { + panic("query.Values failed unexpectedly") + } + data.Set("value", v.EncodedValue()) + return data +} + // Variables gets the list of variables from GitLab. func (gl *GitLabAPI) Variables(ctx context.Context, project string) (map[string]ProjectVariable, error) { resp, err := gl.get(ctx, fmt.Sprintf("/api/v4/projects/%s/variables", url.PathEscape(project))) @@ -149,6 +162,7 @@ func (gl *GitLabAPI) Variables(ctx context.Context, project string) (map[string] out := make(map[string]ProjectVariable, len(pvs)) for _, s := range pvs { + s.Value = strings.ReplaceAll(s.Value, "$$", "$") out[s.Key] = s } return out, nil @@ -156,11 +170,7 @@ func (gl *GitLabAPI) Variables(ctx context.Context, project string) (map[string] // CreateVariable creates a new project variable. func (gl *GitLabAPI) CreateVariable(ctx context.Context, project string, varData ProjectVariable) error { - data, err := query.Values(varData) - if err != nil { - return fmt.Errorf("encoding variable data") - } - resp, err := gl.doWithForm(ctx, "POST", fmt.Sprintf("/api/v4/projects/%s/variables", url.PathEscape(project)), data) + resp, err := gl.doWithForm(ctx, "POST", fmt.Sprintf("/api/v4/projects/%s/variables", url.PathEscape(project)), varData.Values()) if err != nil { return err } @@ -173,11 +183,7 @@ func (gl *GitLabAPI) CreateVariable(ctx context.Context, project string, varData // UpdateVariable updates a project variable. func (gl *GitLabAPI) UpdateVariable(ctx context.Context, project string, varData ProjectVariable) error { - data, err := query.Values(varData) - if err != nil { - return fmt.Errorf("encoding variable data") - } - resp, err := gl.doWithForm(ctx, "PUT", fmt.Sprintf("/api/v4/projects/%s/variables/%s", url.PathEscape(project), url.PathEscape(varData.Key)), data) + resp, err := gl.doWithForm(ctx, "PUT", fmt.Sprintf("/api/v4/projects/%s/variables/%s", url.PathEscape(project), url.PathEscape(varData.Key)), varData.Values()) if err != nil { return err }