Skip to content

Commit b063109

Browse files
committed
Set config.json to 644 permissions; add note about user permissions to README.md; add advanced example with Dockerfile
1 parent 8ab5f40 commit b063109

File tree

6 files changed

+164
-18
lines changed

6 files changed

+164
-18
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ priority = "optional"
3333
extended-description = "A plugin for the Name Service Switch (NSS) framework that parses the output of commands to resolve queries."
3434
assets = [
3535
["target/release/libnss_shim.so", "lib/libnss_shim.so.2", "644"],
36-
["default_config/config.json", "etc/libnss_shim/config.json", "640"],
36+
["default_config/config.json", "etc/libnss_shim/config.json", "644"],
3737
["README.md", "usr/share/doc/libnss_shim/README", "644"],
3838
]
3939
conf-files = ["etc/libnss_shim/config.json"]
@@ -43,7 +43,7 @@ maintainer-scripts = "debian"
4343
summary = "A plugin for the Name Service Switch (NSS) framework that parses the output of commands to resolve queries."
4444
assets = [
4545
{ source = "target/release/libnss_shim.so", dest = "/lib64/libnss_shim.so.2", mode = "644", config = false, doc = false, user = "root", group = "root" },
46-
{ source = "default_config/config.json", dest = "/etc/libnss_shim/config.json", mode = "640", config = true, doc = false, user = "root", group = "root" },
46+
{ source = "default_config/config.json", dest = "/etc/libnss_shim/config.json", mode = "644", config = true, doc = false, user = "root", group = "root" },
4747
{ source = "README.md", dest = "/usr/share/doc/libnss_shim/README", mode = "644", config = false, doc = true, user = "root", group = "root" },
4848
]
4949
post_install_script = "debian/postinst"

README.md

+24-15
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,24 @@ to be used with NSS.
103103
104104
6. Perform NSS queries to validate the installation, for example using the built-in `getent` tool.
105105
106-
Some sample commands to test your implementation:
106+
Some sample commands to test your implementation:
107107
```
108108
getent group
109109
getent passwd
110110
getent shadow
111111
getent group <groupname>
112112
```
113-
A very basic test config is available that will respond to `getent group` calls with a fake group (see the demo GIF
114-
at the top of this file):
115-
116-
curl -sLo /etc/libnss_shim/config.json https://raw.githubusercontent.com/xenago/libnss_shim/main/default_config/sample_custom_config.json
113+
A very basic test config is available that will respond to `getent group` calls with a fake group (see the demo GIF
114+
at the top of this file):
115+
116+
curl -sLo /etc/libnss_shim/config.json https://raw.githubusercontent.com/xenago/libnss_shim/main/samples/basic/custom_config.json
117117
getent group | tail -1
118-
119-
If the installation worked, the output should look like:
120-
121-
testgroup::1008:fake-username,another-user
118+
119+
If the installation worked, the output should look like:
120+
121+
test-shim-group::1008:fake-username,another-user
122+
123+
A more complex configuration example can be found at [`samples/advanced`](samples/advanced), with a `Dockerfile`.
122124
123125
## Uninstall
124126
@@ -163,7 +165,7 @@ commands run by `libnss_shim`:
163165
- `<$uid>`
164166
165167
Using only that information, here is the
166-
[extremely basic test example of `config.json`](default_config/sample_custom_config.json) - one database is defined,
168+
[extremely basic test example of `config.json`](samples/basic/custom_config.json) - one database is defined,
167169
`group`, with just a single function, `get_all_entries`:
168170
169171
```
@@ -172,7 +174,7 @@ Using only that information, here is the
172174
"group": {
173175
"functions": {
174176
"get_all_entries": {
175-
"command": "echo 'testgroup::1008:fake-username,another-user'"
177+
"command": "echo 'test-shim-group::1008:fake-username,another-user'"
176178
}
177179
}
178180
}
@@ -181,7 +183,7 @@ Using only that information, here is the
181183
```
182184
183185
The command defined for `get_all_entries` prints out a single line to `stdout`, describing a fake group
184-
called `testgroup` with `gid=1008` and two members. That output is then captured by `libss_shim` and returned
186+
called `test-shim-group` with `gid=1008` and two members. That output is then captured by `libss_shim` and returned
185187
to `NSS` whenever a call is made requesting all the group entries (e.g. `getent group`).
186188
187189
To support command execution, the following options can be set globally and overridden for specific databases and/or
@@ -359,9 +361,16 @@ and `usize` are platform-dependent and can be 32 or 64-bits):
359361
360362
## Security
361363
362-
This NSS plugin runs commands defined in the file `/etc/libnss_shim/config.json`, which is only accessible to `root` by
363-
default. Ensure that this file, the commands defined inside it, and any other related resources remain inaccessible to
364-
other users, or the system may be vulnerable to privilege escalation attacks.
364+
This NSS plugin runs commands defined in the file `/etc/libnss_shim/config.json`, which is only writable by the `root`
365+
user by default. Ensure that this file, the commands defined inside it, and any other related resources remain read-only
366+
to other users, or the system may be vulnerable to privilege escalation attacks.
367+
368+
To enable non-root users to access resources defined by `libnss_shim`, they must be able to access the commands defined
369+
in `config.json`. For example, if a file `script.py` is being used, it will need to be readable (along with the Python
370+
interpreter used to run it):
371+
372+
sudo chown root:root /path/to/custom/script.py
373+
sudo chmod 644 /path/to/custom/script.py
365374
366375
It is recommended to pass data (like `<$name>`) using environment variables rather than arguments, except for
367376
testing purposes. Environment variables are generally private, whereas commands/launch args are not.

samples/advanced/Dockerfile

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# EL distro example
2+
FROM docker.io/almalinux:9
3+
4+
# Install Python to run the `custom-resolver.py` script
5+
RUN yum install -y python3
6+
7+
# Install latest release of libnss_shim available for this architecture
8+
RUN curl -s https://api.github.com/repos/xenago/libnss_shim/releases/latest | grep "browser_download_url.*.$(uname -m)" | cut -d : -f 2,3 | tr -d \" | tr -d " " | xargs -n 1 curl -sLO
9+
RUN rpm -Ui libnss_shim*.rpm
10+
RUN rm libnss_shim*.rpm
11+
12+
# Import config and scripts
13+
COPY custom_config.json /etc/libnss_shim/config.json
14+
COPY custom-resolver.py /etc/libnss_shim/resolver.py
15+
16+
# Run bash by default
17+
ENTRYPOINT ["/bin/bash"]

samples/advanced/custom-resolver.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import os
2+
import sys
3+
4+
# Expected syntax example: `resolver.py --group --all`
5+
# The database is `--group` and the function is `--all`
6+
db = sys.argv[1]
7+
fn = sys.argv[2]
8+
9+
group_entries = {
10+
"test-shim-users": "test-shim-users:x:2000:test-shim-user-1,test-shim-user-2,test-shim-user-3",
11+
"test-shim-user-1": "test-shim-user-1:x:2001:",
12+
"test-shim-user-2": "test-shim-user-2:x:2002:",
13+
"test-shim-user-3": "test-shim-user-3:x:2003:"
14+
}
15+
16+
passwd_entries = {
17+
"test-shim-user-1": "test-shim-user-1:x:2001:2001::/home/test-shim-user-1:/bin/bash",
18+
"test-shim-user-2": "test-shim-user-2:x:2002:2002::/home/test-shim-user-1:/bin/bash",
19+
"test-shim-user-3": "test-shim-user-3:x:2003:2003::/home/test-shim-user-1:/bin/bash"
20+
}
21+
22+
# Each test user's password is the same as its username
23+
shadow_entries = {
24+
"test-shim-user-1": "test-shim-user-1:$y$j9T$mpqMRQPh51zsMQlg6Koa5/$iYcT2urasxmk99rWCuahIEcNEQDGZcVN0876t80XUm2:19879:0:99999:7:::",
25+
"test-shim-user-2": "test-shim-user-2:$y$j9T$SEsXgfv/SUN3EZQJqLfIA/$mG9uKqlqDOqY2oYzuu1O89nmf1BiYs2//3rPof97vq9:19879:0:99999:7:::",
26+
"test-shim-user-3": "test-shim-user-3:$y$j9T$loMKkB7paRkhAPE7VUa9I.$7CoM0O7XZASdb4olZ8w3YkyjMw2TpoBjlUynOXDLOEB:19879:0:99999:7:::"
27+
}
28+
29+
if db == "--group":
30+
if fn == "--all":
31+
for entry in group_entries.values():
32+
print(entry)
33+
elif fn == "--name":
34+
provided_name = os.getenv("LIBNSS_SHIM_GROUP_NAME", default = None)
35+
if provided_name is not None and provided_name in group_entries:
36+
print(group_entries[provided_name])
37+
elif fn == "--id":
38+
provided_gid = os.getenv("LIBNSS_SHIM_GROUP_ID", default = None)
39+
if provided_gid is not None:
40+
for group in group_entries.values():
41+
if group.split(":")[2] == provided_gid:
42+
print(group)
43+
elif db == "--passwd":
44+
if fn == "--all":
45+
for entry in passwd_entries.values():
46+
print(entry)
47+
elif fn == "--name":
48+
provided_name = os.getenv("LIBNSS_SHIM_PASSWD_NAME", default = None)
49+
if provided_name is not None and provided_name in passwd_entries:
50+
print(passwd_entries[provided_name])
51+
elif fn == "--id":
52+
provided_uid = os.getenv("LIBNSS_SHIM_PASSWD_ID", default = None)
53+
if provided_uid is not None:
54+
for user_entry in passwd_entries.values():
55+
if user_entry.split(":")[2] == provided_uid:
56+
print(user_entry)
57+
elif db == "--shadow":
58+
if fn == "--all":
59+
for entry in shadow_entries.values():
60+
print(entry)
61+
elif fn == "--name":
62+
provided_name = os.getenv("LIBNSS_SHIM_SHADOW_NAME", default = None)
63+
if provided_name is not None and provided_name in shadow_entries:
64+
print(shadow_entries[provided_name])

samples/advanced/custom_config.json

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"databases": {
3+
"group": {
4+
"functions": {
5+
"get_all_entries": {
6+
"command": "python3 /etc/libnss_shim/resolver.py --group --all"
7+
},
8+
"get_entry_by_gid": {
9+
"command": "python3 /etc/libnss_shim/resolver.py --group --id",
10+
"env": {
11+
"LIBNSS_SHIM_GROUP_ID": "<$gid>"
12+
}
13+
},
14+
"get_entry_by_name": {
15+
"command": "python3 /etc/libnss_shim/resolver.py --group --name",
16+
"env": {
17+
"LIBNSS_SHIM_GROUP_NAME": "<$name>"
18+
}
19+
}
20+
}
21+
},
22+
"passwd": {
23+
"functions": {
24+
"get_all_entries": {
25+
"command": "python3 /etc/libnss_shim/resolver.py --passwd --all"
26+
},
27+
"get_entry_by_uid": {
28+
"command": "python3 /etc/libnss_shim/resolver.py --passwd --id",
29+
"env": {
30+
"LIBNSS_SHIM_PASSWD_ID": "<$uid>"
31+
}
32+
},
33+
"get_entry_by_name": {
34+
"command": "python3 /etc/libnss_shim/resolver.py --passwd --name",
35+
"env": {
36+
"LIBNSS_SHIM_PASSWD_NAME": "<$name>"
37+
}
38+
}
39+
}
40+
},
41+
"shadow": {
42+
"functions": {
43+
"get_all_entries": {
44+
"command": "python3 /etc/libnss_shim/resolver.py --shadow --all"
45+
},
46+
"get_entry_by_name": {
47+
"command": "python3 /etc/libnss_shim/resolver.py --shadow --name",
48+
"env": {
49+
"LIBNSS_SHIM_SHADOW_NAME": "<$name>"
50+
}
51+
}
52+
}
53+
}
54+
},
55+
"debug" : false
56+
}

default_config/sample_custom_config.json samples/basic/custom_config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"group": {
44
"functions": {
55
"get_all_entries": {
6-
"command": "echo 'testgroup::1008:fake-username,another-user'"
6+
"command": "echo 'test-shim-group::1008:fake-username,another-user'"
77
}
88
}
99
}

0 commit comments

Comments
 (0)