(originally from my proposal on moby/moby#17142 (comment) but generic)
The profile would generate artificats of an apparmor profile and seccomp filters.
Obviously doesn't have to be toml since that's super hipster :p
Assumptions
- no one is going to sit and write out all the syscalls/capabilities their app needs
- automatic profiling would be super cool but like
aa-genprof
it is never perfect, leads to pain or removing the profile altogether, and an unmaintainable config file (we can always attempt this later)
Goals
- maintainable config
- readable by humans and not a linux syscall/cap nerd
- something an app developer would want to write
- someone who did not write the config should be able to understand, at least at a high level, what is restricted
Inspiration
Grouping into categories
High level things you would want to configure should be generic and limited to (for example):
- Networking
- Filesystem (Disk)
- Runtime (CPU/Memory operations)
- User Operations
- Misc
Defining Permissions
The cool thing about tame
I think we should implement are what they refer to as "flags". It's a set of
syscalls that they allow for a common goal, such as TAME_RW
will allow all
the syscalls for i/o operations but TAME_RPATH
only allows the syscalls that
will enable read-only
effects on the filesystem.
We can have this same concept and define them w syscalls and capabilities.
We would need to discuss what these were and find the most common use cases for them.
Behaviors
- If one permission denies a syscall and another allows it, the deny should always override the allow.
- Passing an empty config drops everything and nothing is allowed
Super super super alpha example
Kinda like jessfraz/bane
but better.
[Networking]
Flags = [
# this will allow sendto(2), recvfrom(2), socket(2), connect(2)
"dns",
# adds CAP_NET_RAW
"ping"
# very high-level
"incoming"
"outgoing"
]
[Filesystem]
Flags = [
# will allow lstat(2), chmod(2), chflags(2),
# chown(2), unlink(2), fstat(2) on /tmp
"tmp"
]
# filepaths where you would like to log on write
LogOnWrite = [
"/etc/**",
"/root/**"
]
# read-only filepaths
ReadOnly = [
"/sys/**"
]
[Runtime]
Flags = [
# allows getentropy(2), madvise(2), minherit(2),
# mmap(2), mprotect(2), mquery(2), munmap(2)
"malloc"
]
[User]
Flags = [
# allows getuid(2), getgid(2), setuid(2), setugid(2)
"create"
]
Backends
Will use whatever is installed on the system so if they have apparmor but no seccomp, then it will use apparmor (which can technically do all the syscall, cap, and filesystem privileges).
- AppArmor
- Seccomp
- Capabilities
File Globbing
Taken from apparmor profiles file globbing.
Glob Example | Description |
---|---|
/dir/file |
match a specific file |
/dir/* |
match any files in a directory (including dot files) |
/dir/a* |
match any file in a directory starting with a |
/dir/*.png |
match any file in a directory ending with .png |
/dir/[^.]* |
match any file in a directory except dot files |
/dir/ |
match a directory |
/dir/*/ |
match any directory within /dir/ |
/dir/a*/ |
match any directory within /dir/ starting with a |
/dir/*a/ |
match any directory within /dir/ ending with a |
/dir/** |
match any file or directory in or below /dir/ |
/dir/**/ |
match any directory in or below /dir/ |
/dir/**[^/] |
match any file in or below /dir/ |
/dir{,1,2}/** |
match any file or directory in or below /dir/, /dir1/, and /dir2/ |
More Goodness
- I think we should allow people to define their own
flags
(or whatever we end up calling them). It could be cool to have a way to do it with adefine
intext/template
I believe this is possible if it is implemented the way I am thinking ;)
audit2allow
audit2why