-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add --var-file-allowlist in server configuration (#2362)
- Loading branch information
Showing
8 changed files
with
257 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package events | ||
|
||
import ( | ||
"fmt" | ||
"github.com/pkg/errors" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
// VarFileAllowlistChecker implements checking if paths are allowlisted to be used with | ||
// this Atlantis. | ||
type VarFileAllowlistChecker struct { | ||
rules []string | ||
} | ||
|
||
// NewVarFileAllowlistChecker constructs a new checker and validates that the | ||
// allowlist isn't malformed. | ||
func NewVarFileAllowlistChecker(allowlist string) (*VarFileAllowlistChecker, error) { | ||
var rules []string | ||
paths := strings.Split(allowlist, ",") | ||
if paths[0] != "" { | ||
for _, path := range paths { | ||
absPath, err := filepath.Abs(path) | ||
if err != nil { | ||
return nil, errors.Wrap(err, fmt.Sprintf("converting allowlist %q to absolute path", path)) | ||
} | ||
rules = append(rules, absPath) | ||
} | ||
} | ||
return &VarFileAllowlistChecker{ | ||
rules: rules, | ||
}, nil | ||
} | ||
|
||
func (p *VarFileAllowlistChecker) Check(flags []string) error { | ||
for i, flag := range flags { | ||
var path string | ||
if i < len(flags)-1 && flag == "-var-file" { | ||
// Flags are in the format of []{"-var-file", "my-file.tfvars"} | ||
path = flags[i+1] | ||
} else { | ||
flagSplit := strings.Split(flag, "=") | ||
// Flags are in the format of []{"-var-file=my-file.tfvars"} | ||
if len(flagSplit) == 2 && flagSplit[0] == "-var-file" { | ||
path = flagSplit[1] | ||
} | ||
} | ||
|
||
if path != "" && !p.isAllowedPath(path) { | ||
return fmt.Errorf("var file path %s is not allowed by the current allowlist: [%s]", | ||
path, strings.Join(p.rules, ", ")) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func (p *VarFileAllowlistChecker) isAllowedPath(path string) bool { | ||
path = filepath.Clean(path) | ||
|
||
// If the path is within the repo directory, return true without checking the rules. | ||
if !filepath.IsAbs(path) { | ||
if !strings.HasPrefix(path, "..") && !strings.HasPrefix(path, "~") { | ||
return true | ||
} | ||
} | ||
|
||
// Check the path against the rules. | ||
for _, rule := range p.rules { | ||
rel, err := filepath.Rel(rule, path) | ||
if err == nil && !strings.HasPrefix(rel, "..") { | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package events_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/runatlantis/atlantis/server/events" | ||
. "github.com/runatlantis/atlantis/testing" | ||
) | ||
|
||
func TestVarFileAllowlistChecker_IsAllowlisted(t *testing.T) { | ||
cases := []struct { | ||
Description string | ||
Allowlist string | ||
Flags []string | ||
ExpErr string | ||
}{ | ||
{ | ||
"Empty Allowlist, no var file", | ||
"", | ||
[]string{""}, | ||
"", | ||
}, | ||
{ | ||
"Empty Allowlist, single var file under the repo directory", | ||
"", | ||
[]string{"-var-file=test.tfvars"}, | ||
"", | ||
}, | ||
{ | ||
"Empty Allowlist, single var file under the repo directory, specified in separate flags", | ||
"", | ||
[]string{"-var-file", "test.tfvars"}, | ||
"", | ||
}, | ||
{ | ||
"Empty Allowlist, single var file under the subdirectory of the repo directory", | ||
"", | ||
[]string{"-var-file=sub/test.tfvars"}, | ||
"", | ||
}, | ||
{ | ||
"Empty Allowlist, single var file outside the repo directory", | ||
"", | ||
[]string{"-var-file=/path/to/file"}, | ||
"var file path /path/to/file is not allowed by the current allowlist: []", | ||
}, | ||
{ | ||
"Empty Allowlist, single var file under the parent directory of the repo directory", | ||
"", | ||
[]string{"-var-file=../test.tfvars"}, | ||
"var file path ../test.tfvars is not allowed by the current allowlist: []", | ||
}, | ||
{ | ||
"Empty Allowlist, single var file under the home directory", | ||
"", | ||
[]string{"-var-file=~/test.tfvars"}, | ||
"var file path ~/test.tfvars is not allowed by the current allowlist: []", | ||
}, | ||
{ | ||
"Single path in allowlist, no var file", | ||
"/path", | ||
[]string{""}, | ||
"", | ||
}, | ||
{ | ||
"Single path in allowlist, single var file under the repo directory", | ||
"/path", | ||
[]string{"-var-file=test.tfvars"}, | ||
"", | ||
}, | ||
{ | ||
"Single path in allowlist, single var file under the allowlisted directory", | ||
"/path", | ||
[]string{"-var-file=/path/test.tfvars"}, | ||
"", | ||
}, | ||
{ | ||
"Single path with ending slash in allowlist, single var file under the allowlisted directory", | ||
"/path/", | ||
[]string{"-var-file=/path/test.tfvars"}, | ||
"", | ||
}, | ||
{ | ||
"Single path in allowlist, single var file in the parent directory of the repo directory", | ||
"/path", | ||
[]string{"-var-file=../test.tfvars"}, | ||
"var file path ../test.tfvars is not allowed by the current allowlist: [/path]", | ||
}, | ||
{ | ||
"Single path in allowlist, single var file outside the allowlisted directory", | ||
"/path", | ||
[]string{"-var-file=/path_not_allowed/test.tfvars"}, | ||
"var file path /path_not_allowed/test.tfvars is not allowed by the current allowlist: [/path]", | ||
}, | ||
{ | ||
"Single path in allowlist, single var file in the parent directory of the allowlisted directory", | ||
"/path", | ||
[]string{"-var-file=/test.tfvars"}, | ||
"var file path /test.tfvars is not allowed by the current allowlist: [/path]", | ||
}, | ||
{ | ||
"Root path in allowlist, with multiple var files", | ||
"/", | ||
[]string{"-var-file=test.tfvars", "-var-file=/path/test.tfvars", "-var-file=/test.tfvars"}, | ||
"", | ||
}, | ||
{ | ||
"Multiple paths in allowlist, with multiple var files under allowlisted directories", | ||
"/path,/another/path", | ||
[]string{"-var-file=test.tfvars", "-var-file", "/path/test.tfvars", "unused-flag", "-var-file=/another/path/sub/test.tfvars"}, | ||
"", | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
t.Run(c.Description, func(t *testing.T) { | ||
v, err := events.NewVarFileAllowlistChecker(c.Allowlist) | ||
Ok(t, err) | ||
|
||
err = v.Check(c.Flags) | ||
if c.ExpErr != "" { | ||
ErrEquals(t, c.ExpErr, err) | ||
} else { | ||
Ok(t, err) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters