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

Better error messaging when writing invalid sudoer entries #46731

Merged
merged 1 commit into from
Oct 3, 2024

Conversation

eriktate
Copy link
Contributor

Related to #34515

Adds an expanded error message and WARN level log when writing sudoers fails due to invalid entries in a role's host_sudoers or a static host user's sudoers.

@github-actions github-actions bot requested a review from espadolini September 18, 2024 19:38
@github-actions github-actions bot requested a review from tcsc September 18, 2024 19:38
@eriktate eriktate added the no-changelog Indicates that a PR does not require a changelog entry label Sep 18, 2024
@gravitational gravitational deleted a comment from github-actions bot Sep 19, 2024
@@ -218,6 +218,10 @@ func (u *HostSudoersManagement) WriteSudoers(name string, sudoers []string) erro
sudoersOut.WriteString(fmt.Sprintf("%s %s\n", name, entry))
}
err := u.backend.WriteSudoersFile(name, []byte(sudoersOut.String()))
if errors.Is(err, host.ErrInvalidSudoers) {
log.Warnf("encountered invalid sudoers entry in: %s", sudoersOut.String())
Copy link
Contributor

@espadolini espadolini Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use structured logging whenever possible:

Suggested change
log.Warnf("encountered invalid sudoers entry in: %s", sudoersOut.String())
log.WithFields(logrus.Fields{
"host_username": name,
"sudoers_entry": sudoersOut.String(),
}).Warn("Encountered invalid sudoers entry.")

Should we truncate the string? Do we have concerns about it being potentially sensitive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we truncate the string? Do we have concerns about it being potentially sensitive?

I wondered about this, but I couldn't think of a good reason not to off the top of my head 🤔 An alternative, that actually might be more useful to end-users, would be to validate the entries while resolving matching rules. That way we could inform them which role has the broken entry instead of falling back to logging the entire sudoers file and leaving it up to them to figure out which role needs attention.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm yeah I agree that dumping the entire sudoers file into a log message might not be ideal. What if we reworded the message to indicate that writing the sudoers file failed due an invalid host_sudoers entry in one of the users roles?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rebased this on the slog changes and adjusted the message we're logging a bit. The log and the error are a bit redundant in cases where the returned error also ends up getting logged (e.g. in regular/sshserver.go), but I think that's probably okay since this shouldn't happen unless there's an incorrectly configured resource. And I think it's better in this case to ensure we're always surfacing something actionable when this happens

@@ -218,6 +218,10 @@ func (u *HostSudoersManagement) WriteSudoers(name string, sudoers []string) erro
sudoersOut.WriteString(fmt.Sprintf("%s %s\n", name, entry))
}
err := u.backend.WriteSudoersFile(name, []byte(sudoersOut.String()))
if errors.Is(err, host.ErrInvalidSudoers) {
log.Warnf("encountered invalid sudoers entry in: %s", sudoersOut.String())
return trace.Errorf("invalid sudoers entry for login %q, inspect role's host_sudoers field or static host user's sudoers field for invalid syntax", name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a BadParameterError?

Suggested change
return trace.Errorf("invalid sudoers entry for login %q, inspect role's host_sudoers field or static host user's sudoers field for invalid syntax", name)
return trace.BadParameter("invalid sudoers entry for login %q, inspect role's host_sudoers field or static host user's sudoers field for invalid syntax", name)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@eriktate eriktate force-pushed the eriktate/34515/better-errors-on-invalid-sudoers branch 2 times, most recently from 26281ca to 28bef41 Compare October 1, 2024 21:11
@@ -222,6 +225,10 @@ func (u *HostSudoersManagement) WriteSudoers(name string, sudoers []string) erro
sudoersOut.WriteString(fmt.Sprintf("%s %s\n", name, entry))
}
err := u.backend.WriteSudoersFile(name, []byte(sudoersOut.String()))
if errors.Is(err, host.ErrInvalidSudoers) {
u.log.With("error", err, "host_username", name).Warn("Invalid sudoers entry. If using a login managed by a static host user resource, inspect its configured sudoers field for invalid entries. Otherwise, inspect the host_sudoers field for roles targeting this host.")
Copy link
Contributor

@rosstimothy rosstimothy Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With is a small optimization that formats arguments a single time, which is beneficial if they are to be included in multiple log messages. For one off arguments to a single message prefer passing them in directly to the logging function.

Also don't forget to use the context variant for logging.

Suggested change
u.log.With("error", err, "host_username", name).Warn("Invalid sudoers entry. If using a login managed by a static host user resource, inspect its configured sudoers field for invalid entries. Otherwise, inspect the host_sudoers field for roles targeting this host.")
u.log.WarnContext(<some_context_here>, "Invalid sudoers entry. If using a login managed by a static host user resource, inspect its configured sudoers field for invalid entries. Otherwise, inspect the host_sudoers field for roles targeting this host.", "error", err, "host_username", name)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be the final nudge I need to get the linter integrated properly into my editor 😅

@@ -78,6 +78,7 @@ func NewHostSudoers(uuid string) HostSudoers {
}
return &HostSudoersManagement{
backend: backend,
log: slog.With(teleport.ComponentKey, teleport.Component(teleport.ComponentHostUsers)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You really only need to use teleport.Component if you have multiple components for the key. For single values you can pass the string in directly.

Suggested change
log: slog.With(teleport.ComponentKey, teleport.Component(teleport.ComponentHostUsers)),
log: slog.With(teleport.ComponentKey, teleport.ComponentHostUsers),

@eriktate eriktate force-pushed the eriktate/34515/better-errors-on-invalid-sudoers branch 2 times, most recently from 2973331 to 1c7b562 Compare October 1, 2024 21:23
@eriktate eriktate force-pushed the eriktate/34515/better-errors-on-invalid-sudoers branch from 1c7b562 to 733ce30 Compare October 1, 2024 21:24
@public-teleport-github-review-bot public-teleport-github-review-bot bot removed the request for review from tcsc October 1, 2024 21:39
@eriktate eriktate added this pull request to the merge queue Oct 3, 2024
Merged via the queue into master with commit 7df2747 Oct 3, 2024
40 checks passed
@eriktate eriktate deleted the eriktate/34515/better-errors-on-invalid-sudoers branch October 3, 2024 18:48
@public-teleport-github-review-bot

@eriktate See the table below for backport results.

Branch Result
branch/v15 Create PR
branch/v16 Create PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport/branch/v15 backport/branch/v16 no-changelog Indicates that a PR does not require a changelog entry size/sm
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants