Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
e3928c6
refactor: use environment variable for compilation parameters
LeChatP Mar 28, 2025
06fd1ab
Merge branch 'dev' of github.com:LeChatP/RootAsRole into dev
LeChatP Mar 28, 2025
e6b5f79
feat: add RAR_BIN_PATH constant and update executable copy paths
LeChatP Mar 28, 2025
edebb28
fix: update file paths to use RAR_BIN_PATH constant in installer
LeChatP Mar 28, 2025
c6562c1
feat: add '-E' argument for passing env vars
LeChatP Mar 28, 2025
a36484a
fix: correct logic for environment override behavior in TaskMatcher
LeChatP Mar 28, 2025
cc9efc9
feat: enhance environment variable handling
LeChatP Mar 29, 2025
2d4b450
fix: unused import warning
LeChatP Mar 29, 2025
797781e
fix: enhance configuration step installation
LeChatP Mar 29, 2025
36f0cc4
better parsing options
LeChatP Mar 29, 2025
a4e2507
fix: ignore modifications on configuration
LeChatP Mar 29, 2025
137db7a
fix: deploy file config requires dac_override capability
LeChatP Mar 29, 2025
daa5b3a
fix: wrong config key
LeChatP Mar 29, 2025
63830ba
feat: add methods to extend actors and tasks in SRoleBuilder
LeChatP Mar 29, 2025
464bbb0
fix: add u64 deserialisation
LeChatP Mar 29, 2025
00744b8
fix: correct return type in SGenericActorType deserialization
LeChatP Mar 29, 2025
74fc353
feat: introduce CBOR file format
LeChatP Mar 31, 2025
1086b31
fix: add default builder option for config in SettingsFile
LeChatP Mar 31, 2025
291d090
fix: structurate get_settings and save_settings
LeChatP Mar 31, 2025
056d0ba
tests: save_config and load_config tested and fixed
LeChatP Mar 31, 2025
e7f67da
test: add unit test for saving settings in CBOR format (and fixes it)
LeChatP Mar 31, 2025
2c9d729
WIP: huge optimization
LeChatP Apr 15, 2025
5ed37f9
fix: enhance CmdMin comparison logic and refactor option handling in …
LeChatP Apr 15, 2025
e38ebe1
feat: add EnumString derive for StorageMethod to support case-insensi…
LeChatP Apr 15, 2025
a4ac4b9
fix: add 'into' attribute to StorageMethod default in Settings struct
LeChatP Apr 15, 2025
06fd95d
fix: improve role display logic and enhance serialization for command…
LeChatP Apr 16, 2025
1b6321c
feat: Rewrite it thread safe
LeChatP Apr 21, 2025
ef5f3da
fix: add serde_json_borrow dependency to improve JSON handling
LeChatP Apr 21, 2025
320ac61
refactor: clean up imports and adjust feature flags in score and util…
LeChatP Apr 21, 2025
7b99737
WIP: considering borrowing opt
LeChatP Apr 26, 2025
3c0e3fe
Using Borrowed data instead of cloning.
LeChatP Apr 26, 2025
4462015
feat: optimize User deserialization
LeChatP Apr 26, 2025
ef54018
WIP : test serializing in cbor optimization
LeChatP Apr 27, 2025
92396c7
WIP testing optimizing
LeChatP Apr 27, 2025
e69766c
WIP: enhance CredFinderDeserializer to support binary field variants
LeChatP Apr 27, 2025
60707aa
TODO: There are many optimisations that could be made and reaching ba…
LeChatP Apr 27, 2025
8a5f78e
refactor: more optimisations
LeChatP Apr 29, 2025
b223e6c
refactor: remove coz
LeChatP Apr 29, 2025
accb8f4
refactor: improve logic in CmdMin::better for performance
LeChatP Apr 29, 2025
4c964f6
refactor: more performant path matching logic in match_single_path fu…
LeChatP Apr 29, 2025
bec5b0f
refactor: update env_path type from PathBuf to &str across multiple m…
LeChatP Apr 30, 2025
004ea58
refactor: update deserialization logic and improve match_args functio…
LeChatP May 1, 2025
7d1439e
Implement custom serialization for various structs in the database mo…
LeChatP May 1, 2025
537e1f7
Implement conversion functionality and refactor process_input
LeChatP May 4, 2025
34788aa
tests: Refactor path options handling in finder module
LeChatP May 4, 2025
d6d968a
fmt: cargo fmt
LeChatP May 4, 2025
7cd6605
tests: add several tests
LeChatP May 5, 2025
998dc0a
tests: more tests and fixes
LeChatP May 9, 2025
899f21f
tests: more tests
LeChatP May 11, 2025
0688f70
tests: more tests!
LeChatP May 12, 2025
a46b5fe
fmt: cargo fmt
LeChatP May 12, 2025
709a1eb
tests: update test for read-only file handling and remove root privil…
LeChatP May 12, 2025
d8f1309
tests: fix tests as root
LeChatP May 12, 2025
b47b67a
fix: fix some bugs
LeChatP May 12, 2025
86ee156
fix: bugs
LeChatP May 12, 2025
1f48c14
fmt: cargo fmt
LeChatP May 12, 2025
f7fbd08
fix: tests
LeChatP May 12, 2025
ed23780
fix: setgid can be a simple string
LeChatP May 12, 2025
4e05f83
Format Rust code using rustfmt
github-actions[bot] May 12, 2025
77854c0
refactor: replace println! with debug! for logging instead of printing
LeChatP May 12, 2025
175c333
fix: just remove logs in tests
LeChatP May 12, 2025
f5e5f25
refactor: replace println! with debug! for logging in lib.rs and ser.rs
LeChatP May 12, 2025
b2b6721
tests: more tests
LeChatP May 17, 2025
abbf4e6
Format Rust code using rustfmt
github-actions[bot] May 17, 2025
5bb3491
refactor(tests): remove commented-out test for from_json_execution_se…
LeChatP May 17, 2025
8e9f016
fix(tests): add --privileged option to tarpaulin container
LeChatP May 17, 2025
cae0e67
Merge pull request #70 from LeChatP/optimize
LeChatP May 17, 2025
f523e52
refactor: MORE optimization by using constants instead of dyn alloc...
LeChatP Jul 4, 2025
4895316
Format Rust code using rustfmt
github-actions[bot] Jul 4, 2025
3a038d8
Merge pull request #71 from LeChatP/optimize
LeChatP Jul 5, 2025
941f022
fix: update serde aliases for group fields in SActor and DActor enums
LeChatP Jul 14, 2025
e5d555a
docs: update README and documentation for file format conversion and …
LeChatP Jul 14, 2025
f07de89
bump: update version to 3.1.0 in configuration and documentation files
LeChatP Jul 14, 2025
8b7c702
Format Rust code using rustfmt
github-actions[bot] Jul 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,25 @@
[alias]
xtask = "run --package xtask --release --bin xtask --"

[env]
RAR_CFG_TYPE = "json"
RAR_CFG_PATH = "/etc/security/rootasrole.json"
RAR_CFG_DATA_PATH = "/etc/security/rootasrole.json"
RAR_BIN_PATH = "/usr/bin"
RAR_CFG_IMMUTABLE = "true"
RAR_TIMEOUT_TYPE = "ppid"
RAR_TIMEOUT_DURATION = "00:05:00"
RAR_TIMEOUT_MAX_USAGE = ""
RAR_PATH_DEFAULT = "delete"
RAR_PATH_ADD_LIST = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
RAR_PATH_REMOVE_LIST = ""
RAR_ENV_DEFAULT = "delete"
RAR_ENV_KEEP_LIST = "HOME,USER,LOGNAME,COLORS,DISPLAY,HOSTNAME,KRB5CCNAME,LS_COLORS,PS1,PS2,XAUTHORY,XAUTHORIZATION,XDG_CURRENT_DESKTOP"
RAR_ENV_CHECK_LIST = "COLORTERM,LANG,LANGUAGE,LC_.*,LINGUAS,TERM,TZ"
RAR_ENV_DELETE_LIST = "PS4,SHELLOPTS,PERLLIB,PERL5LIB,PERL5OPT,PYTHONINSPECT"
RAR_ENV_SET_LIST = ""
RAR_ENV_OVERRIDE_BEHAVIOR = "false"
RAR_AUTHENTICATION = "perform"
RAR_USER_CONSIDERED = "user"
RAR_BOUNDING = "strict"
RAR_WILDCARD_DENIED = "&|"
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
container:
image: xd009642/tarpaulin:develop-nightly
options: --security-opt seccomp=unconfined
options: --security-opt seccomp=unconfined --privileged
steps:
- name: Checkout code
uses: actions/checkout@v2
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,7 @@ Cargo.lock

# Vagrant
*.env
*.vagrant/
*.vagrant/

# Cargo config
.cargo/config.toml
57 changes: 6 additions & 51 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,14 @@
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Test",
"type": "cppdbg",
"request": "launch",
"preLaunchTask": "make build_unit_test",
"program": "${workspaceFolder}/bin/unit_test",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
},
{ "description": "The new process is debugged after a fork. The parent process runs unimpeded.",
"text": "-gdb-set follow-fork-mode child",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) Launch",
"type": "cppdbg",
"type": "lldb",
"request": "launch",
"preLaunchTask": "setcap",
"program": "/usr/bin/sr",
"name": "Launch",
"program": "${workspaceFolder}/target/debug/sr",
"args": ["ls"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "${workspaceFolder}/.vscode/gdb_root.sh",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"cwd": "${workspaceFolder}"
}


]
}
100 changes: 2 additions & 98 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,14 @@
}
},
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc build active file",
"command": "/usr/bin/gcc",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
},
{
"type": "shell",
"label": "make",
"command": "sudo",
"args": [
"-E",
"/usr/bin/make",
"install"
],
"options": {
"cwd": "${cwd}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
},

{
"type": "shell",
"label": "setcap",
"dependsOn": "make",
"command": "sudo",
"args": [
"/usr/bin/setcap",
"=eip",
"=p",
"${cwd}/bin/sr"
],
"options": {
Expand All @@ -66,58 +22,6 @@
"group": {
"kind": "none"
}
},
{
"type": "shell",
"label": "make build_unit_test",
"command": "sudo",
"args": [
"/usr/bin/make",
"build_unit_test"
],
"options": {
"cwd": "${workspaceFolder}",
"env": {
"GDB_DEBUG": "1",
"DEBUG": "1"
}
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
},
{
"type": "shell",
"label": "debug unit_test",
"dependsOn": "make build_unit_test",
"command": "${cwd}/bin/unit_test",
"args": [
"--debug=gdb"
],
"options": {
"cwd": "${cwd}"
},
"isBackground": true,
"problemMatcher": {
"pattern": [
{
"regexp": ".",
"file": 1,
"location": 2,
"message": 3
}
],
"background": {
"activeOnStart": true,
"beginsPattern": ".",
"endsPattern": "Listening on port"
}
}
}

],
Expand Down
18 changes: 15 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = ["xtask", "rar-common"]
[package]
name = "rootasrole"
# The project version is managed on json file in resources/rootasrole.json
version = "3.0.6"
version = "3.1.0"
rust-version = "1.76.0"
authors = ["Eddie Billoir <[email protected]>"]
edition = "2021"
Expand All @@ -25,9 +25,17 @@ maintainance ={ status = "actively-maintained", badge = "https://img.shields.io/
[profile.release]
strip = "symbols"
lto = true
opt-level = "s"
opt-level = 3
codegen-units = 1

[profile.profiling]
strip = "none"
lto = false
opt-level = 1
inherits = "release"
debug = true


#[features]
#cursive_lib = [ "cursive" ]
#srlibs = [ "pam-client", "bitflags" ]
Expand All @@ -45,6 +53,7 @@ path = "src/chsr/main.rs"
[features]
default = ["finder"]
finder = ["dep:pcre2", "rar-common/pcre2", "rar-common/finder"]
pcre2 = ["dep:pcre2", "rar-common/pcre2"]

[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(tarpaulin_include)'] }
Expand All @@ -65,7 +74,7 @@ capctl = "0.2"
pcre2 = { version = "0.2", optional = true }
serde = { version = "1.0", features=["rc", "derive"] }
serde_json = "1.0"
ciborium = "0.2"
cbor4ii = { version = "1.0.0", features = ["serde", "serde1", "use_std"] }
glob = "0.3"
pam-client2 = "0.5"
bitflags = { version = "2.6" }
Expand All @@ -80,6 +89,9 @@ pest = "2.7"
pest_derive = "2.7"
const_format = "0.2"
hex = "0.4"
bon = "3.5.1"
serde_json_borrow = "0.7.1"
konst = "0.3.16"

[dev-dependencies]
log = "0.4"
Expand Down
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<!-- The project version is managed on json file in resources/rootasrole.json -->
<!-- markdownlint-restore -->

# RootAsRole (V3.0.6) : A memory-safe and security-oriented alternative to sudo/su commands
# RootAsRole (V3.1.0) : A memory-safe and security-oriented alternative to sudo/su commands

**RootAsRole** is a project to allow Linux/Unix administrators to delegate their administrative tasks access rights to users. Its main features are :

Expand All @@ -29,13 +29,15 @@
* File relocation ability.
* Multi-layered and inheritable execution environment configuration.
* Interoperable and evolvable by using [JSON](https://www.json.org/) as the main configuration file format.
* Interchangeable file format with [JSON5](https://www.json.org/) and [CBOR](https://cbor.io/) for performance and human readability.
* Setuid managed by set of users or (set-of-)groups (all-and-deny, or nothing-then-grant), Thanks to @[hocineait7](https://github.com/hocineait7).
* Command matching based on commonly-used open-source libraries:
* [glob](https://docs.rs/glob/latest/glob/) for binary path
* [glob](https://docs.rs/glob/latest/glob/) for binary pathv
* [PCRE2](https://www.pcre.org/) for command arguments

If you need help to configure a RootAsRole policy, you can use our **[capable tool](https://github.com/LeChatP/RootAsRole-capable)**. This tool identifies the rights required by specific commands, making it easier to define a precise policy.

For administrators who already use **Ansible playbooks** for their tasks and wish to implement **RootAsRole**, our tool [gensr](https://github.com/LeChatP/RootAsRole-utils) can generate an initial draft of a **RootAsRole policy**. The `gensr` tool works by running your Ansible playbook alongside the [capable tool](https://github.com/LeChatP/RootAsRole-capable), creating a draft policy based on the observed required rights. This process helps administrators to harden their Ansible tasks. It helps to verify eventual third-party supply-chain attacks.
For administrators who already use **Ansible playbooks** for their tasks and wish to implement RootAsRole, our tool [gensr](https://github.com/LeChatP/RootAsRole-utils) can generate an initial draft of a RootAsRole policy. The `gensr` tool works by running your Ansible playbook alongside the [capable tool](https://github.com/LeChatP/RootAsRole-capable), creating a draft policy based on the observed required rights. This process helps administrators to harden their Ansible tasks. It helps to verify eventual **third-party supply-chain attacks**.

**Note:** The `gensr` tool is still in development and may not work with all playbooks. If you wish to contribute to this project, feel free to make issues and pull requests.

Expand Down Expand Up @@ -105,6 +107,9 @@ Execute privileged commands with a role-based access control system
<u><b>Options</b></u>:
<b>-r, --role</b> &lt;ROLE&gt; Role to select
<b>-t, --task</b> &lt;TASK&gt; Task to select (--role required)
<b>-u, --user</b> &lt;USER&gt; User to execute the command as
<b>-g, --group</b> &lt;GROUP<,GROUP...>&gt; Group(s) to execute the command as
<b>-E, --preserve-env</b> Keep environment variables from the current process
<b>-p, --prompt</b> &lt;PROMPT&gt; Prompt to display
<b>-i, --info</b> Display rights of executor
<b>-h, --help</b> Print help (see more with '--help')
Expand All @@ -116,7 +121,22 @@ If you're accustomed to utilizing the sudo tool and find it difficult to break t
alias sudo="sr"
```

However you won't find out exact same options as sudo, you can use the `--role` option to specify the role you want to use instead.
## Performance outperforms `sudo` (and `sudo-rs`) command

[![Performance comparison](https://github.com/LeChatP/RaR-perf/raw/main/result_25-07-04_15.44.png)](https://github.com/LeChatP/RaR-perf)

Since RootAsRole 3.1.0, the project introduced CBOR file format, consequently the performance of the `sr` command has been significantly improved. The new version now outperforms the `sudo` command by a raw 77% (with 1 rule each side), and more you add rules, more the performance gap increases. The slope between the `sudo` and `sr` commands is 40% better, meaning that the more rules you add, the more the `sr` command will outperform the `sudo` command. You can reproduce this performance test by following the [RaR-perf](https://github.com/LeChatP/RaR-perf) repository guideline.

The performance of `sudo-rs` are actually even-or-worse than `sudo` command for the few tests I was able to do. However, the sudo-rs project is crashing when you try to add more than 100 rules. [I created an issue on their repository, but it's tagged as won't fix](https://github.com/trifectatechfoundation/sudo-rs/issues/1192).

But that is not all, as we wish to introduce RDBMS (Relational Database Management System) support in the future (with Limbo SQLite and regular DBMS solutions), the performance will be even better.


### Why Performance Matters

When it comes to managing infrastructure with tools like Ansible, executing privileged commands will become a common task, so you multiply the number of commands executed by the number of rules. With the `sudo` command, it didn't matters as long you had only one rule everywhere, but now with RootAsRole, you can have a lot of rules as long you configure it with `gensr` --- generating a first version of a very-specific policy --- thus increasing the number of rules inside the policy, so the performance of the `sr` command now matters.

With RootAsRole, you add more access control rules, enforcing a better POLP, without sacrificing performance.


## Why do you need this tool ?
Expand Down
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
# Reference Guide

- [Configure RootAsRole](chsr/file-config.md)
- [File Config Conversion](chsr/convert.md)
- [Continuous Integration](continuous-integration.md)
- [How to contribute](dev/CONTRIBUTE.md)
- [FAQ](faq.md)
Expand Down
9 changes: 8 additions & 1 deletion book/src/chsr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,11 @@ chsr options timeout [operation]
del [items,...] Remove items from the list.
set [items,...] Set items in the list.
purge Remove all items from the list.
</pre>

<u><b>Convert policy format :</b></u>
chsr convert (-r) (--from [from_type] [from_file]) [to_type] [to_file]
Supported types: json, cbor
<b>-r, --reconfigure</b> Reconfigure /etc/security/rootasrole.json file to specify the new location.
<b>--from</b> [from_type] [from_file] Specify the type and file to convert from.
<b>Warning</b>: the new location should be under a protected directory.
</pre>
15 changes: 15 additions & 0 deletions book/src/chsr/convert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# File Config Conversion

## Converting JSON to CBOR and vice versa

Converting the `/etc/security/rootasrole.json` file to CBOR format (and configure the policy to the new location with `-r` option) :

`chsr convert -r cbor /etc/security/rootasrole.bin`

This command will read the JSON file, convert it to CBOR format, and save it to `/etc/security/rootasrole.bin`. The `-r` option changes the file `/etc/security/rootasrole.json` to specify the new location in `path` field of the configuration file.

To convert the CBOR file back to JSON format, you can use the following command:

`chsr convert -r json /etc/security/rootasrole.json`

This command will read the CBOR file, convert it back to JSON format, and save it to `/etc/security/rootasrole.json`. The `-r` option changes the file `/etc/security/rootasrole.json` to specify the new location in `path` field of the configuration file.
Loading