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.
This commit is contained in:
Luke Granger-Brown 2020-05-10 12:11:26 +01:00
parent f994f155cd
commit 823eab4775

View file

@ -134,6 +134,19 @@ type ProjectVariable struct {
Masked bool `json:"masked" url:"masked"` 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. // Variables gets the list of variables from GitLab.
func (gl *GitLabAPI) Variables(ctx context.Context, project string) (map[string]ProjectVariable, error) { 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))) 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)) out := make(map[string]ProjectVariable, len(pvs))
for _, s := range pvs { for _, s := range pvs {
s.Value = strings.ReplaceAll(s.Value, "$$", "$")
out[s.Key] = s out[s.Key] = s
} }
return out, nil return out, nil
@ -156,11 +170,7 @@ func (gl *GitLabAPI) Variables(ctx context.Context, project string) (map[string]
// CreateVariable creates a new project variable. // CreateVariable creates a new project variable.
func (gl *GitLabAPI) CreateVariable(ctx context.Context, project string, varData ProjectVariable) error { func (gl *GitLabAPI) CreateVariable(ctx context.Context, project string, varData ProjectVariable) error {
data, err := query.Values(varData) resp, err := gl.doWithForm(ctx, "POST", fmt.Sprintf("/api/v4/projects/%s/variables", url.PathEscape(project)), varData.Values())
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)
if err != nil { if err != nil {
return err return err
} }
@ -173,11 +183,7 @@ func (gl *GitLabAPI) CreateVariable(ctx context.Context, project string, varData
// UpdateVariable updates a project variable. // UpdateVariable updates a project variable.
func (gl *GitLabAPI) UpdateVariable(ctx context.Context, project string, varData ProjectVariable) error { func (gl *GitLabAPI) UpdateVariable(ctx context.Context, project string, varData ProjectVariable) error {
data, err := query.Values(varData) 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 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)
if err != nil { if err != nil {
return err return err
} }