-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Use sudo for privileged process checks on filedescriptors #715
Conversation
Hey @pdecat! Thanks a lot for your contribution! This is a good idea but I am not sure that it should be turned on by default in the package. I am wary about giving our agent any sudo power that it doesn't absolutely need. So I don't think this should be turned on by default in the packages. Can you add instructions to turn it on in the readme and in the case of failure after attempting to use sudo. Thanks a lot, again, for your contribution! 😄 |
Hi @gmmeyer , I'll document the sudoers part in the README. Also, what would you think about adding an option to the process check's configuration to enable the use of |
I think that's very wise, it shouldn't fail when it doesn't have the proper permissions. It should log something on info but not fail. |
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.
Hey @pdecat! Thanks again for this PR!
This is a cool solution. I have two comments, and after you resolve them in one way or another I'm pretty happy to merge.
process/check.py
Outdated
if method == 'num_fds' and Platform.is_unix(): | ||
try: | ||
# It is up the agent's packager to grant corresponding sudo policy on unix platforms | ||
result = int(subprocess.check_output(['sudo', sys.executable, __file__, method, str(process.pid)])) |
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 is a cool solution but I am not certain it will work with Agent6, where we're calling the python library from within golang. At least for now, you'd have to ensure this happens only in Agent5. You can import the version from here: https://github.com/DataDog/dd-agent/blob/master/config.py#L44.
@masci how do you think we would be able to do this in Agent6?
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.
As a second note here, why did you choose to execute this file rather than including that as a string that would be passed to the interpreter? I think that's more likely to work in Agent6 than this is.
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.
Hi @gmmeyer, I chose to invoke this script on purpose for two reasons:
- For security reasons: passing the process id to this script requires wildcards. Knowing that this script can only accept a process id and not anything else feels safe to me.
Passing an arbitrary string to an interpreter with a wildcard has dangerous implications: https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-4-wildcards/
An alternative may be to have several sudoers entries to match all possible pid lengths:
dd-agent ALL=NOPASSWD: /opt/datadog-agent/embedded/bin/python -c "import psutil; import sys; psutil.num_fds(sys.argv[1])" [1-9]
dd-agent ALL=NOPASSWD: /opt/datadog-agent/embedded/bin/python -c "import psutil; import sys; psutil.num_fds(sys.argv[1])" [1-9][0-9]
dd-agent ALL=NOPASSWD: /opt/datadog-agent/embedded/bin/python -c "import psutil; import sys; psutil.num_fds(sys.argv[1])" [1-9][0-9][0-9]
dd-agent ALL=NOPASSWD: /opt/datadog-agent/embedded/bin/python -c "import psutil; import sys; psutil.num_fds(sys.argv[1])" [1-9][0-9][0-9][0-9]
dd-agent ALL=NOPASSWD: /opt/datadog-agent/embedded/bin/python -c "import psutil; import sys; psutil.num_fds(sys.argv[1])" [1-6][0-5][0-9][0-9][0-9]
- For easy distribution: as the omnibus packaging rename files, this solution should work everywhere, no need to know the path to the script.
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.
Okay, so that makes sense. However, in Agent v6 we're not using a python interpreter, though, it's embedded within a go application. I think (I haven't verified this) that this would just call the go application instead of the python interpreter.
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 tested github.com/sbinet/go-python that is used in agent 6 to wrap the python interpreter and it seems to be ok:
main.go
:
package main
import (
"fmt"
"log"
"github.com/sbinet/go-python"
)
func init() {
err := python.Initialize()
if err != nil {
log.Panic(err.Error())
}
}
func main() {
module := python.PyImport_ImportModule("testsys")
if module == nil {
log.Fatal("could not import 'testsys'")
}
name := module.GetAttrString("__name__")
if name == nil {
log.Fatal("could not getattr '__name__'")
}
defer name.DecRef()
fmt.Printf("testsys.__name__: %q\n", python.PyString_AsString(name))
testsys := module.GetAttrString("testsys")
if testsys == nil {
log.Fatal("could not getattr 'testsys'")
}
defer testsys.DecRef()
o1 := testsys.CallFunction()
if o1 == nil {
log.Fatal("could not call 'testsys.testsys()'")
}
fmt.Printf("%s\n", python.PyString_AsString(o1))
o1.DecRef()
}
testsys.py
:
#!/usr/bin/env python2
import sys
def testsys():
return "sys.executable=" + sys.executable
Result:
# PYTHONPATH=.:$PYTHONPATH go run ./main.go
testsys.__name__: "testsys"
sys.executable=/usr/bin/python
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'm down to merge this then! I'll approve it!
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.
Can you rebase it and then I'll approve, sorry for taking so long on this 😄
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.
No prob, rebased!
However, I did not yet implement the part about adding an option to the process check's configuration to enable the use of sudo, disabled by default.
…ataDog/dd-agent/issues#2033)
Added |
…with psutil (`num_fds`)
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.
🎉 we're gonna merge!
Thanks! 🎉 |
…)" This reverts commit e1f1d53. Check is not sending the open_file_descriptor metric. Reverting for 5.22.0 release.
…)" This reverts commit e1f1d53. Check is not sending the open_file_descriptor metric. Reverting for 5.22.0 release.
…)" This reverts commit e1f1d53. Check is not sending the open_file_descriptor metric. Reverting for 5.22.0 release.
Hi @hush-hush / @ChristineTChen, I get that this was reverted for 5.22. What issues did you have? Did you enable the sudo part to actually get open_file_descriptor metrics? |
Bump ^ @hush-hush @ChristineTChen |
Re-submitted this PR as #1235 |
What does this PR do?
Repackaged the patch I suggested at DataDog/dd-agent#2033 (comment) in a dd-agent-omnibus compatible way (no additional python file, only
process/check.py
is modified).Motivation
Datadog does not provide out of box support for monitoring file descriptors used by processes not running under the same user (
dd-agent
by default).The suggested work-around of running the datadog agent as root is explicitly not recommended which is probably reasonable: https://help.datadoghq.com/hc/en-us/articles/115000066506-Why-don-t-I-see-the-system-processes-open-file-descriptors-metric-
Additional Notes
This requires the addition of the following sudo policies in the deb and rpm packages:
Usage of sudo generates frequent logging in
/var/log/auth.log
. That may be silenced with additional PAM rules in/etc/pam.d/sudo
if desired.Resolves DataDog/dd-agent/issues#2033
The same may be done for the
io_counters
method.