From 59b457f573a69ecbcb20a1dd6996291e9f06e2c7 Mon Sep 17 00:00:00 2001 From: Ben Drucker Date: Fri, 12 Mar 2021 13:25:16 -0800 Subject: [PATCH] validate actions secret names (#714) * validate actions secret names * remove duplicate case --- ...urce_github_actions_organization_secret.go | 7 +-- github/resource_github_actions_secret.go | 7 +-- github/util.go | 21 ++++++++ github/util_test.go | 49 +++++++++++++++++++ 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/github/resource_github_actions_organization_secret.go b/github/resource_github_actions_organization_secret.go index 9648f2cc22..54f44d6a67 100644 --- a/github/resource_github_actions_organization_secret.go +++ b/github/resource_github_actions_organization_secret.go @@ -20,9 +20,10 @@ func resourceGithubActionsOrganizationSecret() *schema.Resource { Schema: map[string]*schema.Schema{ "secret_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateSecretNameFunc, }, "plaintext_value": { Type: schema.TypeString, diff --git a/github/resource_github_actions_secret.go b/github/resource_github_actions_secret.go index 4169a511a5..46a820b362 100644 --- a/github/resource_github_actions_secret.go +++ b/github/resource_github_actions_secret.go @@ -25,9 +25,10 @@ func resourceGithubActionsSecret() *schema.Resource { Required: true, }, "secret_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateSecretNameFunc, }, "plaintext_value": { Type: schema.TypeString, diff --git a/github/util.go b/github/util.go index 3c7f147dcc..051ab379e9 100644 --- a/github/util.go +++ b/github/util.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "regexp" "strconv" "strings" @@ -143,3 +144,23 @@ func getTeamID(teamIDString string, meta interface{}) (int64, error) { return team.GetID(), nil } } + +// https://docs.github.com/en/actions/reference/encrypted-secrets#naming-your-secrets +var secretNameRegexp = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") + +func validateSecretNameFunc(v interface{}, keyName string) (we []string, errs []error) { + name, ok := v.(string) + if !ok { + return nil, []error{fmt.Errorf("expected type of %s to be string", keyName)} + } + + if !secretNameRegexp.MatchString(name) { + errs = append(errs, errors.New("Secret names can only contain alphanumeric characters or underscores and must not start with a number")) + } + + if strings.HasPrefix(strings.ToUpper(name), "GITHUB_") { + errs = append(errs, errors.New("Secret names must not start with the GITHUB_ prefix")) + } + + return we, errs +} diff --git a/github/util_test.go b/github/util_test.go index 82c4d5b632..aafe7021d3 100644 --- a/github/util_test.go +++ b/github/util_test.go @@ -106,3 +106,52 @@ func flipUsernameCase(username string) string { } return string(oc) } + +func TestAccGithubUtilValidateSecretName(t *testing.T) { + cases := []struct { + Name string + Error bool + }{ + { + Name: "valid", + }, + { + Name: "v", + }, + { + Name: "_valid_underscore_", + }, + { + Name: "valid_digit_1", + }, + { + Name: "invalid-dashed", + Error: true, + }, + { + Name: "1_invalid_leading_digit", + Error: true, + }, + { + Name: "GITHUB_PREFIX", + Error: true, + }, + { + Name: "github_prefix", + Error: true, + }, + } + + for _, tc := range cases { + var name interface{} = tc.Name + _, errors := validateSecretNameFunc(name, "") + + if tc.Error != (len(errors) != 0) { + if tc.Error { + t.Fatalf("expected error, got none (%s)", tc.Name) + } else { + t.Fatalf("unexpected error(s): %s (%s)", errors, tc.Name) + } + } + } +}