-
Notifications
You must be signed in to change notification settings - Fork 126
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
DEVPROD-10509 Update git.clone project command to redact for modules #8330
DEVPROD-10509 Update git.clone project command to redact for modules #8330
Conversation
|
||
logger.Execution().Info("Fetching source from git...") | ||
redactedCmds := fetchScript |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our redaction logic takes care of this
out := stdErr.String() | ||
if out != "" { | ||
if opts.token != "" { | ||
out = strings.Replace(out, opts.token, "[redacted github token]", -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our redaction logic takes care of this
@@ -725,17 +716,19 @@ func (c *gitFetchProject) fetchModuleSource(ctx context.Context, | |||
return errors.Wrap(err, "setting location to clone from") | |||
} | |||
|
|||
if opts.method == cloneMethodOAuth { | |||
if opts.method == cloneMethodOAuth || opts.method == cloneMethodAccessToken { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixes the problem where modules always generate an installation token regardless if the user passed in an access token
agent/command/git.go
Outdated
// Otherwise, create an installation token for to clone the module. | ||
// Fallback to the legacy global token if the token cannot be created. | ||
appToken, err := comm.CreateInstallationToken(ctx, td, opts.owner, opts.repo) | ||
if err == nil { | ||
opts.token = appToken | ||
opts.method = cloneMethodAccessToken | ||
|
||
// After generating, redact the token from the logs. | ||
conf.NewExpansions.Redact("EVERGREEN_GENERATED_GITHUB_TOKEN", appToken) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always after creating an installation token on the fly, we should redact it
@@ -791,9 +784,7 @@ func (c *gitFetchProject) fetchModuleSource(ctx context.Context, | |||
|
|||
errOutput := stdErr.String() | |||
if errOutput != "" { | |||
if opts.token != "" { | |||
errOutput = strings.Replace(errOutput, opts.token, "[redacted github token]", -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our redaction logic should take care of this.
if opts.token != "" { | ||
errOutput = strings.Replace(errOutput, opts.token, "[redacted github token]", -1) | ||
} | ||
errOutput = strings.ReplaceAll(errOutput, "\n", fmt.Sprintf("\n%s: ", module.Name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this line to append every line with the module name for easier debugging
@@ -403,7 +403,7 @@ func (c *baseCommunicator) makeSender(ctx context.Context, tsk *task.Task, confi | |||
levelInfo := send.LevelInfo{Default: level.Info, Threshold: level.Debug} | |||
var senders []send.Sender | |||
if config.SendToGlobalSender { | |||
senders = append(senders, grip.GetSender()) | |||
senders = append(senders, redactor.NewRedactingSender(grip.GetSender(), config.RedactorOpts)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds the redactor to a global sender, just in case
@@ -620,11 +620,6 @@ func (c *PluginCommandConf) unmarshalParams() error { | |||
return nil | |||
} | |||
|
|||
type ArtifactInstructions struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random unused code
bf74c84
to
3d1a179
Compare
I'm waiting for a review to update the agent version because of merge conflicts |
@@ -461,8 +462,8 @@ func (s *GitGetProjectSuite) TestBuildHTTPCloneCommand() { | |||
s.Require().Len(cmds, 5) | |||
s.True(utility.ContainsOrderedSubset(cmds, []string{ | |||
"set +o xtrace", | |||
"echo \"git clone https://[redacted github token]:[email protected]/evergreen-ci/sample.git 'dir' --branch 'main'\"", | |||
"git clone https://PROJECTTOKEN:[email protected]/evergreen-ci/sample.git 'dir' --branch 'main'", | |||
fmt.Sprintf("echo \"git clone https://%s:[email protected]/evergreen-ci/sample.git 'dir' --branch 'main'\"", projectGitHubToken), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since these now return the unredacted commands, are there other tests that cover the functionality that GetLoggerProducer
loggers redact sensitive secrets? Reading through some of the logic, it looks like the relies on some slightly risky assumptions, like the fact that the expansions must be passed as a pointer to the redaction opts so that the memory is shared between the task config and the redacting sender.
If not, we should either add new tests or make a separate ticket to add tests that the loggers do redact correctly because it's critical functionality at this point and we shouldn't rely on manual testing to verify that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I improved the test in this file (here) and I added another more specific test here to the base communicator.
The git test uses the mock communicator, so it isn't a full on test of how it would work in production.
The test on the base communicator is more of a test on how it will work on production.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM mod couple nits.
@@ -23,6 +29,88 @@ func TestEvergreenCommunicatorConstructor(t *testing.T) { | |||
assert.Equal(t, defaultTimeoutMax, c.retry.MaxDelay) | |||
} | |||
|
|||
func TestLoggerProducerRedactorOptions(t *testing.T) { | |||
secret := "super_soccer_ball" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⚽
agent/command/git_test.go
Outdated
findTokenInRedacted := func() bool { | ||
for _, redacted := range conf.NewExpansions.GetRedacted() { | ||
if redacted.Key == generatedTokenKey { | ||
if redacted.Value == token { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mega nit: could combine the two ifs into one if redacted.Key == generatedTokenKey && redacted.Value == token
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I originally did two different booleans (found and then correctValue) but this is an artifact from that
agent/internal/client/client_test.go
Outdated
t.Run("LeaksWithoutRedactor", func(t *testing.T) { | ||
task := createTask() | ||
comm := newBaseCommunicator("whatever", map[string]string{}) | ||
logger, err := comm.GetLoggerProducer(context.Background(), task, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use a context.WithCancel
if possible rather than plain context.Background()
.
Same with the test below.
agent/internal/client/client_test.go
Outdated
|
||
data := readLogs(t, task) | ||
assert.NotContains(t, data, secret) | ||
assert.Contains(t, data, "secret_key") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: might be clearer that this is checking for the redacted string by explicitly looking for <REDACTED:secret_key>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update it, I was only worried about if we changed the redacted format (which I think the test would be easy to amend then anyways)
assert.Contains(t, data, "More fluff") | ||
assert.Contains(t, data, "Even more fluff") | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The redacting test is great, love the helper functions and clear test cases. Thanks for adding it! 😎
…al redacting logic
b8633cd
to
8512cdd
Compare
DEVPROD-10509
Description
This ticket cleans up some of the redacting logic and adds redaction to the generated tokens.
It also fixes a bug where modules would still generate a token even if the user passed in an access token.
Testing
Existing unit tests
This task on staging after the fix, the token for
git clone ... github-merge-queue-sandbox
is redacted.