Unix Cmnd_Alias and User_Alias sudoer retrieval

From the many sudoer files on a Unix operating system, I am trying to retrieve the users that have full root permissions via a User_Alias and/or Cmnd_Alias. To get the result, I currently have 3 different different queries where one result is feed into a text search for the following query.
Is there a way to “stich” these a result from one query to another? The challenge is that there could be multiple results for each query but in this example there is only 1. I have a .sh script that can give me the results but I don’t want to have to execute a fixlet just to write the results to a log file and have an Analysis read it.

In this example, a Cmnd_Alias exists called ADM_CMD that has full root permission to ksh. A User_Alias called BISADM exists tied to the Cmnd_Alias. Then individual users are given access to that User_alias.

important lines from the sudoer file(s):
Cmnd_Alias ADM_CMD=/bin/ksh
BISADM ALL=NOPASSWD:ADM_CMD
User_Alias BISADM=user1,user2,user3

Q: (if it contains "%09" then following text of first "%09" of it else if it contains " " then following text of first " " of it else it) of preceding text of first "=" of (lines whose (it as lowercase starts with "cmnd_alias" AND (it contains "ALL=(ALL)" or it contains "ALL = (ALL)" or it contains "ALL=(root)" or it contains "ALL = (root)" or it contains "/bin/su" or it contains "/bin/sh" or it contains "/bin/bash" or it contains "/bin/ksh" or it contains "echo" or it contains "cat" or it contains "passwd" or it contains "shadow" or it contains "vi") AND (it does not contain "#" and it does not contain "!visiblepw")) of (files ("/etc/sudoers";"/usr/local/etc/sudoers";"/opt/sfw/etc/sudoers";"/etc/opt/csw/sudoers");(if exists folder "/etc/sudoers.d" whose (exists files of it) then (files of folder "/etc/sudoers.d") else nothing)))
A: ADM_CMD
T: 9362

===================

Q: `(if it contains "%09" then preceding text of first "%09" of it else if it contains " " then preceding text of first " " of it else it) of lines whose (it as string as lowercase contains "adm_cmd" and it as string as lowercase does not start with "cmnd_alias") of (files ("/etc/sudoers";"/usr/local/etc/sudoers";"/opt/sfw/etc/sudoers";"/etc/opt/csw/sudoers");(if exists folder "/etc/sudoers.d" whose (exists files of it) then (files of folder "/etc/sudoers.d") else nothing))`
A: BISADM
T: 11057

========================

Q: unique values whose (it != "") of (following text of first "=" of it) of lines whose (it as string as lowercase contains "bisadm" and it as string as lowercase does not contain "adm_cmd") of (files ("/etc/sudoers";"/usr/local/etc/sudoers";"/opt/sfw/etc/sudoers";"/etc/opt/csw/sudoers");(if exists folder "/etc/sudoers.d" whose (exists files of it) then (files of folder "/etc/sudoers.d") else nothing))
A: user1,user2,user3
T: 11292

Just to check I understand correctly - each of the sudoers files is independent, right? We can’t have a file in /etc/sudoers.d reference something like ADM_CMD that was defined in /etc/sudoers ?

Interesting puzzle, I’ll need some time to look through it.

You may need to add some more handling for spaces versus tabs, but I think this is a workable approach. The trick is, I believe, to pass both the original file and the values we’re searching for as a tuple up to the next step of the search.

q: lines of files "c:\temp\sudoers.txt"
A: Cmnd_Alias ADM_CMD=/bin/ksh
A: otherline1
A: BISADM ALL=NOPASSWD:ADM_CMD
A: otherline2
A: User_Alias BISADM=user1,user2,user3
A: otherline3
T: 5.975 ms
I: plural file line

Illustrate that “following texts of firsts” only keeps the lines that actually contain the string

q: items 1 of (it, following texts of firsts "Cmnd_Alias" of lines of it as trimmed string) of files "c:\temp\sudoers.txt"
A: ADM_CMD=/bin/ksh
T: 4.782 ms
I: plural string

Filter to keep only the “Cmnd_Alias” lines referencing a command we care about; and preserve the original file so we can pass it up to the next search.

q: (it, following texts of firsts "Cmnd_Alias" of lines of it as trimmed string) whose ((it contains "/bin/ksh" /* OR more commands here */) of (following text of first "=" of item 1 of it)) of files "c:\temp\sudoers.txt"
A: "sudoers.txt" "" "" "" "", ADM_CMD=/bin/ksh
T: 5.164 ms
I: plural ( file, string )

Perform a second search of the file, to find the lines where the “variable value” contains the ADM_CMD of interest.

q:  (item 0 of it, item 1 of it, lines of item 0 of it) whose (following text of first ":" of item 2 of it contains preceding text of first "=" of item 1 of it) of (it, following texts of firsts "Cmnd_Alias" of lines of it as trimmed string) whose ((it contains "/bin/ksh" /* OR more commands here */) of (following text of first "=" of item 1 of it)) of files "c:\temp\sudoers.txt"
A: "sudoers.txt" "" "" "" "", ADM_CMD=/bin/ksh, BISADM ALL=NOPASSWD:ADM_CMD
T: 3.964 ms
I: plural ( file, string, file line )

Now perform a third search of the file, finding the lines where the “variable name” matches the BISADM string

q:  (item 0 of it, item 1 of it, item 2 of it, following texts of firsts "User_Alias" of lines of item 0 of it) whose (preceding text of first "=" of item 3 of it as trimmed string = preceding text of first " " of item 2 of it) of (item 0 of it, item 1 of it, lines of item 0 of it) whose (following text of first ":" of item 2 of it contains preceding text of first "=" of item 1 of it) of (it, following texts of firsts "Cmnd_Alias" of lines of it as trimmed string) whose ((it contains "/bin/ksh" /* OR more commands here */) of (following text of first "=" of item 1 of it)) of files "c:\temp\sudoers.txt"
A: "sudoers.txt" "" "" "" "", ADM_CMD=/bin/ksh, BISADM ALL=NOPASSWD:ADM_CMD, (  BISADM=user1,user2,user3 )
T: 2.271 ms
I: plural ( file, string, file line, substring )

It could be of interest to return all of that info, but if we only want the list of user names we can extract that out of ‘item 3’

q:  following texts of firsts "=" of items 3 of (item 0 of it, item 1 of it, item 2 of it, following texts of firsts "User_Alias" of lines of item 0 of it) whose (preceding text of first "=" of item 3 of it as trimmed string = preceding text of first " " of item 2 of it) of (item 0 of it, item 1 of it, lines of item 0 of it) whose (following text of first ":" of item 2 of it contains preceding text of first "=" of item 1 of it) of (it, following texts of firsts "Cmnd_Alias" of lines of it as trimmed string) whose ((it contains "/bin/ksh" /* OR more commands here */) of (following text of first "=" of item 1 of it)) of files ("c:\temp\sudoers.txt" /* ; more files here */)
A: user1,user2,user3
T: 1.562 ms
I: plural substring
1 Like

I have done that couple of years back using the shell script. I think script is better way to parse the sudoers using sed/grep/awk. our sudoers has 27K lines.

27103 /etc/sudoers

wow, that’s alot. If I can get away from having to manage a policy action and just use an Analysis property, that would be best for our enviornment.

@JasonWalker yes, it is per file. This is very good progress and does work for the user_alias. One catch is that there could not be a user alias and just a cmnd_alias.

example:
:~ # cat /etc/sudoers.d/file
Cmnd_Alias QCMD=/bin/su
user1 ALL=QCMD

In this case, would it be possible in just this cmnd_alias example stop at “user1” but if there is a user_alias like your above example, continue evaluating?

I’m tending to agree that this is better handled in an script than in relevance directly…but for the sake of argument, here I have basically the same approach, except I make the third search return a singular value for matching the “user” field against a user alias; if no match is found that would throw an error, which I handle with the pipe operator | to substitute back in the user name instead of a lookup.

q: lines of files "c:\temp\sudoers.txt"
A: Cmnd_Alias ADM_CMD=/bin/ksh
A: otherline1
A: BISADM ALL=NOPASSWD:ADM_CMD
A: otherline2
A: User_Alias BISADM=user1,user2,user3
A: otherline3
A: user5 ALL=NOPASSWD:ADM_CMD
T: 22.306 ms
I: plural file line


q: (following text of first "=" of item 3 of (item 0 of it, item 1 of it, item 2 of it, following texts of firsts "User_Alias" of lines of item 0 of it) whose (preceding text of first "=" of item 3 of it as trimmed string = preceding text of first " " of item 2 of it) | preceding text of last " " of preceding text of first "=" of item 2 of it) of (item 0 of it, item 1 of it, lines of item 0 of it) whose (following text of first ":" of item 2 of it contains preceding text of first "=" of item 1 of it) of (it, following texts of firsts "Cmnd_Alias" of lines of it as trimmed string) whose ((it contains "/bin/ksh" /* OR more commands here */) of (following text of first "=" of item 1 of it)) of files "c:\temp\sudoers.txt"
A: user1,user2,user3
A: user5
T: 2.177 ms
I: plural substring
2 Likes

this is great, i’ll give it a try. thanks