-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Better error messaging when writing invalid sudoer entries #46731
Conversation
lib/srv/usermgmt.go
Outdated
@@ -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()) |
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.
Use structured logging whenever possible:
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?
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.
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.
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.
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?
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 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
lib/srv/usermgmt.go
Outdated
@@ -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) |
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.
Maybe a BadParameterError
?
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) |
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.
Done!
26281ca
to
28bef41
Compare
lib/srv/usermgmt.go
Outdated
@@ -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.") |
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.
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.
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) |
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 might be the final nudge I need to get the linter integrated properly into my editor 😅
lib/srv/usermgmt.go
Outdated
@@ -78,6 +78,7 @@ func NewHostSudoers(uuid string) HostSudoers { | |||
} | |||
return &HostSudoersManagement{ | |||
backend: backend, | |||
log: slog.With(teleport.ComponentKey, teleport.Component(teleport.ComponentHostUsers)), |
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.
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.
log: slog.With(teleport.ComponentKey, teleport.Component(teleport.ComponentHostUsers)), | |
log: slog.With(teleport.ComponentKey, teleport.ComponentHostUsers), |
2973331
to
1c7b562
Compare
1c7b562
to
733ce30
Compare
Related to #34515
Adds an expanded error message and
WARN
level log when writing sudoers fails due to invalid entries in a role'shost_sudoers
or a static host user'ssudoers
.