I have a list of users in a text file. I need to query our campus Active Directory to make sure these users are still "active" users (my machines are not part of the campus AD). The list of users is mapped to a number of identical attributes on the AD (name, cn, sAMAccountName, uid, gecos). I can successfully query the AD with ldapsearch for individual users, so what I am trying to figure out is:
a) how to use the file as input for the query
b) how to construct a shell script so the query will go line by line, and then output any "non-active" users so i can email it for notification.
Any help is much appreciated.
Something you could try to accomplish what you desire would be:
emailFile="/var/tmp/emailFile.txt"
for i in $(cat ${filename}) ; do
results=$(*INPUT LDAPSEARCH HERE REPLACING USERNAME WITH ${i}* | grep -i lastlogontimestamp)
if [[ ${results} != "" ]] ; then
echo "${i} appears to be an active user"
else
echo "${i} IS INACTIVE"
echo "${i}" >> "${emailFile}"
fi
done
This is NOT a working script, but this should give you a very good idea of how to get this to work in your environment. Couple things to note...
${filename} = location/filename of your list of names
INPUT LDAPSEARCH HERE REPLACING USERNAME WITH ${i} = You would enter in your command to run an ldap search here.
example $(ldapsearch -D "cn=manager" -w password -h server.example.com -b "dc=example,dc=com" "cn=${i}" | grep -i "lastlogontimestamp")
"lastlogontimestamp" would be equal to what part of the query you want to examine to determine if the user is active or not.
This would set the ${results} variable to a string you are looking for. This could be a datestamp or empty if users have never logged in.
The next "if" statement, would compare the results to a string/pattern you are expecting. My if statement above, states that if ${results} is not equal to nothing, then inform you that the user you searched is active. If the ${results} are indeed empty, then log the username.
You will have to modify the ldapsearch portion to fit your needs, and the if statement to match what you are expecting to see from your query if the user is not active. I hope this helps.
To answer you question you provided in the comments...
You could use nested if expressions. Example.
if [[ $(some command) = "Some expected result" ]] ; then
if [[ ${results} != "" ]] ; then
echo "${i} appears to be an active user"
else
echo "${i} IS INACTIVE"
echo "${i}" >> "${emailFile}"
fi
fi
done
You could add a second variable where you run a command in the for loop such as
userExists=$(some ldapsearch command to see if user exists)
results=$(*INPUT LDAPSEARCH HERE REPLACING USERNAME WITH ${i}* | grep -i lastlogontimestamp
if [[ ${userExists} = "Some expected result" ]] ; then
if [[ ${results} != "" ]] ; then
You also asked a question about using "grep" to look for more than one item. Example is below.
grep "514\|546"
Example 2.
Lets say I have a file called test.txt with 5 lines
one
two
three
four
five
I would run the following command to look inside the file to find "two" and "three"
cat test.txt | grep "two\|three"
Related
I copied that code to make a THM exercise, I understand it and it does his job that's passing names from a wordlist ($2) to steghide to try to crack the image ($1), and it works, but the problem is that it doesn't show correctly the correct password, it just stops in the word before it, and if you click enter it keeps going, I would like to just stop when it finds it and show me the password, here's the code:
for word in $(cat $2); do
steghide extract -sf $1 -p $word &> /dev/null
if [ $? == 0 ]; then
echo
echo "[!] PWD FOUND - $word [!]"
break
else
echo "NOPE - $word"
fi
done
Steghide was asking me if I wanted to re-write the output file as I already did this process once, so that was the only problem, my script wasn't expecting another input request from steghide.
I am trying to run a command using the AWS CLI and then set the output of that command to a variable, which was easy enough. I parsed the initial command with jq and the output was an array of the GroupNames which is exactly what I wanted. Now I am trying to run an if statement that says if $1 is in the list_groups: print the users in that group. My issue is two fold. I do not know if The output from the first command is readable because it is not in a specific format.
#!/bin/bash
list_groups=$(aws iam list-groups --output json | jq -r .'Groups[] | .GroupName' --output json)
echo $list_groups
if ${1} == $list_groups;
then
echo aws iam get-group --group-name $1 --output json
else
echo 'sorry'
fi
So I am trying to take the list_groups variable that I stored the output of that CLI command in and then with user input in $1 see if what I input is in that GroupName and if it is use that $1 to then print out the users inside that group show in the command below.
echo aws iam get-group --group-name $1 --output json
I am sorry as I cannot print my output here for the GroupNames I am getting back from the first command as it is sensitive but, here is an example.
Admin Users assets.dev assets.prod
As you can see there are no separating values and I am not sure if that is contributing to the issues.
If I wanted to run this command here is what I would enter
bash accounts_parse.sh Admin
The error I get is
command not found
Thank you all for your help and I will clarify if my explanation is sub par or more information is needed.
if ${1} == $list_groups;
This isn't how if statements in bash (and other POSIX shells) work.
The word that comes after if is a command to execute, and its exit status is evaluated, and if it's 0 the if-branch is taken.
That explains your "command not found" - it's trying to execute ${1} as a command, and you don't have an "Admin" command.
Use either
if [ "${1}" = "$list_groups" ]
or
if [[ "${1}" = "$list_groups" ]]
the latter is a bashism (with some improvements) and won't work in other otherwise compatible shells. "==" is also available as a bash extension but entirely equivalent to "=", so I'd advise to just use that.
What's important is that the [ is a command (typically a builtin, also accessible as "test"). It's not a special bit of syntax but a thing that is executed with arguments and returns a status. ([[ has some special handling and is more syntax-y, but conceptually it's still "a thing to execute")
You can use read builtin in bash:
read user _ < <(aws iam list-groups --output json | jq -r .'Groups[] | .GroupName' --output json)
if [[ $user == $1 ]]; then
echo aws iam get-group --group-name $1 --output json
else
echo 'sorry'
fi
read user _ will read first word from input into variable user and ignore remaining.
I'm trying to get a user input to loop until the input/name is unique (not contained in output/variable).
I've tried to do something like this, which I thought would have worked:
read -p "$QlabelName" input
while [[ "$input" == "$(/usr/sbin/networksetup -listallnetworkservices |grep "$input")" ]]; do
read -p "Name already in use, please enter a unique name:" input
done
I've also tried putting the $(/usr/sbin/networksetup -listallnetworkservices |grep "$input") bit into a variable itself and then using the condition [[ "$input" == "GREPVARIABLE" ]] without success.
Original user input menu, without loop (working):
labelName=NJDC
QlabelName=$(echo Please enter the name of connection to be displayed from within the GUI [$labelName]: )
read -p "$QlabelName" input
labelName="${input:-$labelName}"
echo "The connection name will be set to: '$labelName'"
I've tried a variety of solutions from SO, Unix, ServerFault, etc with no success. I've tried if, while, until, !=, ==, =~ as well with no success.
I've confirmed with simple debug echo's at each step that variables contain the data, but the loop is not working.
EDIT (solution, in context to the question, thanks to #LinuxDisciple's answer):
labelName=NJDC
QlabelName=$(echo Please enter the name of connection to be displayed from within the GUI [$labelName]: )
read -p "$QlabelName" input
while /usr/sbin/networksetup -listallnetworkservices |grep -q "^${input}$"; do
read -p "Name already in use, please enter a unique name:" input
done
labelName="${input:-$labelName}"
echo "The connection name will be set to: '$labelName'"
This was important to me to keep default variable values for labelName and output the correct information to the user.
read -p "$QlabelName" input
while /usr/sbin/networksetup -listallnetworkservices |grep -q "^${input}$"; do
read -p "Name already in use, please enter a unique name:" input
done
grep's return code is good enough for while, and since we don't want to actually see the output, we can use -q to suppress it. You can also run it without -q to see what grep actually found until you're satisfied that it's running correctly.
For further debuggability, I would pipe the output to cat -A. You can echo your variable value in the while-loop and just add |cat -A immediately after the done and it should show all the characters:
read -p "$QlabelName" input
while /usr/sbin/networksetup -listallnetworkservices |grep -q "^${input}$"; do
read -p "Name already in use, please enter a unique name:" input
echo "Input was:'$input'"
done |cat -A
I have a list of names in a list (say name.txt) which has the set of name lists one by one.
name.txt
babu
praveen
kamal
sneha
This name will be passed as run time argument $1 in my bash script.
Now I have to do a match to check if the inputted name is in my list or not.
If it's not there then I will print saying invalid name and exit. Can you help me with this?
I have tried this with
if [[ "$1" != "babu" || "$1" != "praveen" || "$1" != "kamal" ... ]]; then
exit
fi
but this doesn't look good professionally.
Is there any other simple and decent way to achieve this?
I guess you could use grep:
if ! grep -qFxf name.txt <<<"$1"; then
exit
fi
-q is "quiet mode" - the exit status indicates a match
-F matches fixed strings, rather than regular expressions
-x is a full line match, so names that are substrings won't match
-f means that the list of patterns are contained within a file
The string contained within the first argument is passed to grep using a here string. This is a bash feature, so if you're using another shell, you could go with something like if ! echo "$1" | grep -qFxf name.txt instead (but the bash way is preferred as it saves invoking a subprocess).
If you want to ensure that any error output from grep is suppressed, you can add 2>/dev/null to the command, as suggested in the comments. This prevents any messages sent to standard error from being displayed.
So I am writing a script that will curl a site I've written that will return a string. I am using it to compare a value that is saved within a file. I am having trouble getting my conditional statement to return true for matching values.
Here is a snippet of my bash code
var1=$(curl -s -w %{http_code}\\n www.somesite.com)
var2=$(cat somefile)
if [[ "$var1" = "$var2" ]]; then
echo "TRUE"
else
echo "FALSE"
fi
I have manually looked at both the strings and they seem to be identical. I've done wc with all applicable options with it. I've copy and pasted both the values into Notepad++ and did a find for the expected string and it said that both values matched the find command.
Obviously, if I manually put the values in the condition it returns true, so I know its not my conditional statement.
My guess is there is some type of hidden character on the end of curl...('\r' or '\n' or something that I am unaware)...or maybe on the end of the file that I am unaware of. Is this a known issue when trying to compare curl output and file content?
This may be a dumb question, but for the life of me I cannot seem to get these strings to match doing it dynamically instead of hardcoding the values in the condition.
Any suggestions would be great. Thanks
$ diff -q -b <(echo $'abc\ndef') <(echo $'abc\r\ndef') > /dev/null ; echo $?
0
$ diff -q -b <(echo $'abc\ndef') <(echo $'abc\r\nde') > /dev/null ; echo $?
1