Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(secret)!: remove implicit repo secrets and clean up secrets testing #230

Merged
merged 4 commits into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions constants/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ const (

// SecretLogMask defines the secret mask to be used when distributing logs that contain secrets.
SecretLogMask = "***"

// SecretRestrictedCharacters defines the set of characters that a secret name cannot contain.
GregoryDosh marked this conversation as resolved.
Show resolved Hide resolved
SecretRestrictedCharacters = "=\x00"
)
96 changes: 67 additions & 29 deletions pipeline/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ var (
// ErrInvalidPath defines the error type when the
// path provided for a type (org, repo, shared) is invalid.
ErrInvalidPath = errors.New("invalid secret path")
// ErrInvalidName defines the error type when the name
// contains restricted characters or is empty.
ErrInvalidName = errors.New("invalid secret name")
)

// Purge removes the secrets that have a ruleset
Expand Down Expand Up @@ -105,25 +108,40 @@ func (s *Secret) ParseOrg(org string) (string, string, error) {
// check if the secret is not a native or vault type
if !strings.EqualFold(s.Engine, constants.DriverNative) &&
!strings.EqualFold(s.Engine, constants.DriverVault) {
return "", "", fmt.Errorf("%s: %s", ErrInvalidEngine, s.Engine)
return "", "", fmt.Errorf("%w: %s", ErrInvalidEngine, s.Engine)
}

// check if a path was provided
if !strings.Contains(path, "/") {
return "", "", fmt.Errorf("%s: %s ", ErrInvalidPath, path)
return "", "", fmt.Errorf("%w: %s ", ErrInvalidPath, path)
}

// split the full path into parts
parts := strings.SplitN(path, "/", 2)

// secret is invalid
if len(parts) != 2 {
return "", "", fmt.Errorf("%s: %s ", ErrInvalidPath, path)
return "", "", fmt.Errorf("%w: %s ", ErrInvalidPath, path)
}

// check if the org provided matches what we expect
if !strings.EqualFold(parts[0], org) {
return "", "", fmt.Errorf("%s: %s ", ErrInvalidOrg, parts[0])
return "", "", fmt.Errorf("%w: %s ", ErrInvalidOrg, parts[0])
}

// check if path segments empty
if len(parts[1]) == 0 {
return "", "", fmt.Errorf("%w: %s ", ErrInvalidPath, path)
}

// secret names can't be empty.
if len(s.Name) == 0 {
return "", "", fmt.Errorf("%w: %s missing name", ErrInvalidName, s.Key)
}

// environmental variables can't contain certain restricted characters.
if strings.ContainsAny(s.Name, constants.SecretRestrictedCharacters) {
return "", "", fmt.Errorf("%w (contains restricted characters): %s ", ErrInvalidName, s.Name)
}

return parts[0], parts[1], nil
Expand All @@ -137,38 +155,43 @@ func (s *Secret) ParseRepo(org, repo string) (string, string, string, error) {
// check if the secret is not a native or vault type
if !strings.EqualFold(s.Engine, constants.DriverNative) &&
!strings.EqualFold(s.Engine, constants.DriverVault) {
return "", "", "", fmt.Errorf("%s: %s", ErrInvalidEngine, s.Engine)
return "", "", "", fmt.Errorf("%w: %s", ErrInvalidEngine, s.Engine)
}

// check if a path was provided for explicit definition
if strings.Contains(path, "/") {
// split the full path into parts
parts := strings.SplitN(path, "/", 3)
// split the full path into parts
parts := strings.SplitN(path, "/", 3)

// secret is invalid
if len(parts) != 3 {
return "", "", "", fmt.Errorf("%s: %s ", ErrInvalidPath, path)
}
// secret is invalid
if len(parts) != 3 {
return "", "", "", fmt.Errorf("%w: %s ", ErrInvalidPath, path)
}

// check if the org provided matches what we expect
if !strings.EqualFold(parts[0], org) {
return "", "", "", fmt.Errorf("%s: %s ", ErrInvalidOrg, parts[0])
}
// check if the org provided matches what we expect
if !strings.EqualFold(parts[0], org) {
return "", "", "", fmt.Errorf("%w: %s ", ErrInvalidOrg, parts[0])
}

// check if the repo provided matches what we expect
if !strings.EqualFold(parts[1], repo) {
return "", "", "", fmt.Errorf("%s: %s ", ErrInvalidRepo, parts[1])
}
// check if the repo provided matches what we expect
if !strings.EqualFold(parts[1], repo) {
return "", "", "", fmt.Errorf("%w: %s ", ErrInvalidRepo, parts[1])
}

return parts[0], parts[1], parts[2], nil
// check if path segments empty
if len(parts[2]) == 0 {
return "", "", "", fmt.Errorf("%w: %s ", ErrInvalidPath, path)
}

// check if name equals key for implicit definition
if !strings.EqualFold(s.Name, s.Key) {
return "", "", "", fmt.Errorf("%s: %s ", ErrInvalidPath, path)
// secret names can't be empty.
if len(s.Name) == 0 {
return "", "", "", fmt.Errorf("%w: %s missing name", ErrInvalidName, s.Key)
}

return org, repo, s.Name, nil
// environmental variables can't contain certain restricted characters.
if strings.ContainsAny(s.Name, constants.SecretRestrictedCharacters) {
return "", "", "", fmt.Errorf("%w (contains restricted characters): %s ", ErrInvalidName, s.Name)
}

return parts[0], parts[1], parts[2], nil
}

// ParseShared returns the parts (org, team, key) of the secret path
Expand All @@ -179,20 +202,35 @@ func (s *Secret) ParseShared() (string, string, string, error) {
// check if the secret is not a native or vault type
if !strings.EqualFold(s.Engine, constants.DriverNative) &&
!strings.EqualFold(s.Engine, constants.DriverVault) {
return "", "", "", fmt.Errorf("%s: %s", ErrInvalidEngine, s.Engine)
return "", "", "", fmt.Errorf("%w: %s", ErrInvalidEngine, s.Engine)
}

// check if a path was provided
if !strings.Contains(path, "/") {
return "", "", "", fmt.Errorf("%s: %s ", ErrInvalidPath, path)
return "", "", "", fmt.Errorf("%w: %s ", ErrInvalidPath, path)
}

// split the full path into parts
parts := strings.SplitN(path, "/", 3)

// secret is invalid
if len(parts) != 3 {
return "", "", "", fmt.Errorf("%s: %s ", ErrInvalidPath, path)
return "", "", "", fmt.Errorf("%w: %s ", ErrInvalidPath, path)
}

// check if path segments empty
if len(parts[1]) == 0 || len(parts[2]) == 0 {
return "", "", "", fmt.Errorf("%w: %s ", ErrInvalidPath, path)
}

// secret names can't be empty.
if len(s.Name) == 0 {
return "", "", "", fmt.Errorf("%w: %s missing name", ErrInvalidName, s.Key)
}

// environmental variables can't contain certain restricted characters.
if strings.ContainsAny(s.Name, constants.SecretRestrictedCharacters) {
return "", "", "", fmt.Errorf("%w (contains restricted characters): %s ", ErrInvalidName, s.Name)
}

return parts[0], parts[1], parts[2], nil
Expand Down
Loading