Perl or Python script to remove user from group - python

I am putting together a Samba-based server as a Primary Domain Controller, and ran into a cute little problem that should have been solved many times over. But a number of searches did not yield a result. I need to be able to remove an existing user from an existing group with a command line script. It appears that the usermod easily allows me to add a user to a supplementary group with this command:
usermod -a -G supgroup1,supgroup2 username
Without the "-a" option, if the user is currently a member of a group which is not listed, the user will be removed from the group. Does anyone have a perl (or Python) script that allows the specification of a user and group for removal? Am I missing an obvious existing command, or well-known solution forthis? Thanks in advance!
Thanks to J.J. for the pointer to the Unix::Group module, which is part of Unix-ConfigFile. It looks like the command deluser would do what I want, but was not in any of my existing repositories. I went ahead and wrote the perl script using the Unix:Group Module. Here is the script for your sysadmining pleasure.
#!/usr/bin/perl
#
# Usage: removegroup.pl login group
# Purpose: Removes a user from a group while retaining current primary and
# supplementary groups.
# Notes: There is a Debian specific utility that can do this called deluser,
# but I did not want any cross-distribution dependencies
#
# Date: 25 September 2008
# Validate Arguments (correct number, format etc.)
if ( ($#ARGV < 1) || (2 < $#ARGV) ) {
print "\nUsage: removegroup.pl login group\n\n";
print "EXIT VALUES\n";
print " The removeuser.pl script exits with the following values:\n\n";
print " 0 success\n\n";
print " 1 Invalid number of arguments\n\n";
print " 2 Login or Group name supplied greater than 16 characters\n\n";
print " 3 Login and/or Group name contains invalid characters\n\n";
exit 1;
}
# Check for well formed group and login names
if ((16 < length($ARGV[0])) ||(16 < length($ARGV[1])))
{
print "Usage: removegroup.pl login group\n";
print "ERROR: Login and Group names must be less than 16 Characters\n";
exit 2;
}
if ( ( $ARGV[0] !~ m{^[a-z_]+[a-z0-9_-]*$}) || ( $ARGV[0] !~ m{^[a-z_]+[a-z0-9_-]*$} ) )
{
print "Usage: removegroup.pl login group\n";
print "ERROR: Login and/or Group name contains invalid characters\n";
exit 3;
}
# Set some variables for readability
$login=$ARGV[0];
$group=$ARGV[1];
# Requires the GroupFile interface from perl-Unix-Configfile
use Unix::GroupFile;
$grp = new Unix::GroupFile "/etc/group";
$grp->remove_user("$group", "$login");
$grp->commit();
undef $grp;
exit 0;

Web Link: http://www.ibm.com/developerworks/linux/library/l-roadmap4/
To add members to the group, use the gpasswd command with the -a switch and the user id you wish to add:
gpasswd -a userid mygroup
Remove users from a group with the same command, but a -d switch rather than -a:
gpasswd -d userid mygroup
"man gpasswd" for more info...
I looked for ages to find this. Sometimes it takes too much effort not to reinvent the wheel...

I found This for you. It should do what you need. As far as I can tell Perl does not have any built in functions for removing users from a group. It has several for seeing the group id of a user or process.

It looks like deluser --group [groupname] should do it.
If not, the groups command lists the groups that a user belongs to. It should be fairly straightforward to come up with some Perl to capture that list into an array (or map it into a hash), delete the unwanted group(s), and feed that back to usermod.

Here's a very simple little Perl script that should give you the list of groups you need:
my $user = 'user';
my $groupNoMore = 'somegroup';
my $groups = join ',', grep { $_ ne $groupNoMore } split /\s/, `groups $user`;
Getting and sanitizing the required arguments is left as an execrcise for the reader.

Related

Is there a way to find which firewall-profile is active?

I had a problem with servers connecting to the wrong firewall-profile so I am trying to find a solution to track this information.
I have already got the powershell commands in my python script:
subprocess.getoutput('netsh advfirewall show allprofiles')
subprocess.check_output('netsh advfirewall show currentprofile')
I can also convert them to strings.
The actual problem is that these informations look very fractured and are probably not always in the same order on different systems, as well as different languages.
Is there a simple way to find which firewall-profile is on and active?
In the best case the function gives me a String like "yes"/"no" or a boolean.
Yes you can! You just had not defined the PolicyStore to query - Details below...
Just use the following query - It returns the names of all active policies - For example "Domain"
Get-NetFirewallSetting -PolicyStore ActiveStore |
Select-Object -ExpandProperty ActiveProfile
Additionally, there is to mention that "ActiveProfile" might contain multiple profiles, as a system can have more adapters that might need different settings. So this example might also be normal "Domain, Public"
Information about "PolicyStore" and why you need it pretty often:
This store contains the currently active policy, which is the sum of all policy stores that apply to the computer
Source: https://learn.microsoft.com/en-us/powershell/module/netsecurity/get-netfirewallprofile
If you need true or false responses for each you could use this
$intvalue = (Get-NetFirewallSetting -PolicyStore activestore).`
CimInstanceProperties.Where{$_.Name -eq "Profile"}.value
$DomainEnabled = [bool]($intvalue -band 0x1)
$PrivateEnabled = [bool]($intvalue -band 0x2)
$PublicEnabled = [bool]($intvalue -band 0x4)
For this example you also can have multiple $true values

Using variables/parameters in SSIS Package w Python script

I've created a package to do the following:
Truncate Staging Tables -> Run Python Script (this pulls data from an API that populates the staging tables) -> run 3 execute SQL tasks to move last 5 days of data from staging to prod
What I'm trying to do is:
Create Parameters/Variables to allow someone to change the URL, Username, and Password to be editable in SSMS. I'm fairly new to Python and SSIS, so I don't really know what I'm doing; but, this is the line of code that I would be looking to have the variables.
rTotal = requests.get('https://jira.tpp.company.com/rest/zapi/latest/zql/executeSearch?zqlQuery=creationDate%20>%3D%20startOfDay(-5d)&offset=0&maxRecords=1', auth=HTTPBasicAuth(uid, pwd) , verify=False).json()
How would I go about doing this? For the URL, I don't know if it would be better to do something like: 'https://jira.tpp.company.com/rest/zapi/latest/zql/executeSearch?zqlQuery=' + #[User::url]
if thats even how you would do it. For the uid and pwd, can I create variables/parameters like #[User::uid] & #[User::pwd] to replace uid and pwd? Do I need to wrap it in anything or define it somewhere?
Thank in advance for any help you may provide.
I'm not 100% sure that I understand you, but I will try to answer anyway.
My suggestion would be that you create multiple variables and with these variables make a new one, the final variable with all data.
Check screenshot and see what is my suggestion:
As you see, I marked with red squares where I put variables. Also, at bottom of picture check how I created variables.
With this usage of variables, you can change value when you run package!
Here is expression for rTotal:
"requests.get('https://jira.tpp.tsysecom.com/rest/zapi/latest/zql/executeSearch?zqlQuery=" + #[User::URL] +
"', auth=HTTPBasicAuth(" + #[User::uid] + ", " + #[User::pwd] + ") , verify=False).json()"
I'm assuming you're executing this script as an Execute Process Task, with the path to your python.exe in the Executable field and the path to the script itself in the Arguments field.
There's no built-in way to make your SSIS variables available to the Python script the way you could with a C# or VB script task, but you can pass them in at the end of the Arguments field and then grab them using sys.argv as if they were command line arguments.
The way you add the variables to Arguments is in the Expressions tab of the Execute Process Task Editor window:
On that tab, there's a "Misc" header and a blank Expressions field. Click into the field and a "..." button will show up. Click that
In the new window that appears, select Arguments as the Property, then click the "..." in this window's Expression field
Here, you need to set up the argument, including both your filepath and the variables you want to pass in, using the SSIS Expression syntax. Note that you'll need to escape "s and \s with a \ before each. You're shooting for something like this:
"\"C:\\your_file_path_here\\your_script.py\" \"" + #[User::url] + "\" " + #[User::uid] + " " + #[User::pwd]
You might need to quote your UID/PW fields as well depending on what characters are allowed in them.
Once you have that set up, those variables will pass into your script the same way any other command line argument would. You can tack an "import sys" at the top of your script and use sys.argv[0] for the URL, sys.argv[1] for the UID, and sys.argv[2] for the PW.

Parse only given values to command line via Python

I'm sending I'm receiving a JSON message through MQTT in Python, and I would like to start a command line program with what the JSON gives as variables.
The problem with this is that I don't know what values are going to come through and thus this is where I have trouble.
The easiest would be if I knew all the variables that would come through and do something like this:
data = json.loads(msg.payload)
os.system("'command +f ' + data[arg1] + ' +g ' + data[arg2]")
But as mentioned previously, I don't know if they are being passed through, and as such, how can I break it down so that the command line command is build up?
Maybe:
if 'arg1' in data:
command = "+f " + data[arg1]
else:
pass
if 'arg2' in data:
command + "+g " + data[arg2]
else:
pass
Would this work? Is there a better idea?
You can use a for loop to iterate over the json, and construct the command string.
commandArgs = ["+f ","+g "]
commandCount=0
for element in data:
command= command + commandArgs[commandCount] + element
commandCount = commandCount +1
Although you could do this as described it's not something you should do. Running user-inputted commands is one of the most unsecure things a program can do. Scrubbing the commands thoroughly is possible but quite difficult to do comprehensively. The usual approach is to have a table of acceptable commands, match against the table, and then use the entries from that table to populate the command line. Nothing typed by the user ever makes it into the command line with that method.
If you do wish to take user input directly, be extremely careful about scrubbing all special characters, characters outside your preferred locale, double-byte characters, path delimiter characters, etc. Perhaps you could start with the snippet Jeff provided and add a lot of data scrubbing code.
Also, be aware that the probability that whatever you do not code for will eventually be submitted for processing corresponds roughly to the risk of that command. For example, if you fail to catch and remove cat ~/.ssh/* there's a moderately good chance one of your users will execute it or someone will break in and do so. But if you do not catch and remove rm -r /* the chance someone will submit that command approaches certainty.

How to use grep on files in python

I am trying to do make a script that will show users in a group the problem is I don't know how to properly use grep in python. My code goes something like this:
with open("/etc/group" , "r") as f2:
for line in f2:
grouplist=line.split(":")
print grouplist[0]
group_choose = raw_input("Choose a group > ")
glist = "1)show users in group \n2)Show group ID \n3)Add user to the group
print
print glist
print
I want the "Show users in the group" script to be similar to the one I just did with opening the file and doing a grep to filter only the users in the group that will be mentioned in"group_choose". I would also love to hear an explanation on how you did it since I don't really know how to use grep in python.
My take on this would be to read the content of "/etc/group" and create a key/value list based on the groupe name.
Very crude example (with harcoded values, since I don't have access to a "/etc/group" file) :
line="G1:X:T2:u1,u2,u3"
groups=[]
users=line.split(":")[3].split(",")
groupname=line.split(":")[0]
groups.append([groupname,users])
for group in groups:
if group[0]=="G1":
print group[1]

How to generate a sequence of numbers that can later be used in the command lines in python?

what I want to do is to write a script wich get some files as input and then run some command on them! I first want to know how many files dose the user has and then ask for him/her to upload it and later I want to run some command on it.
So I had used this command: for cnt inseq 19 2 31 in a similar situation long time ago but now when I use this command I get a syntex error!
this is my comand:
readnumber= raw_input("How many pares do you have?" )
for cnt in `seq 1 1 int(readnumber)`; do
pare$cnt-a = raw_input("filename of pare$cnt-a: ")
pare$cnt-b = raw_input("filename of pare$cnt-b: ")
cmd = "samtools merge pare$cnt.bam pare$cnt-a pare$cnt-b"
And this is the error that I get:
> for cnt in 'seq 1 1 int(readnumber)'; do
> ^
> SyntaxError: invalid syntax
so what I expext is when you put the readnumber=3 then it ask you to upload (or input) this:
pare1-a:
pare1-b:
pare2-a:
pare2-b:
pare3-a:
pare3-b:
and then run my command on it!
You probably want something like this:
pairs = int(raw_input("How many pairs do you have?"))
for pair_n in xrange(1, pairs + 1):
file1 = raw_input("pair%d-a: " % pair_n)
file2 = raw_input("pair%d-b: " % pair_n)
cmd = "samtools merge pair%d.bam '%s' '%s'" % (pair_n, file1, file2)
# os.system(cmd) to run the command.
You seem to be mixing up Python with bash scripting. raw_input is Python, but everything else in the script is bash.
Rather than trying to rewrite the whole thing in Python, it seems like you should just use bash, maybe with the read command instead of raw_input.
You are trying to use bash syntax in a python program. They are different languages. For instance, the seq command should instead be an xrange(...) command. You are also using bash variable syntax $somevar instead of python's variable syntax.
So either use bash or use Python, but don't try to mix-n-match.
And you may want to consider having the user provide the filenames on the commandline, rather than prompting the user for them. That will make your script more useful as a building block later.
The for-line of yours it not Python-code, it's a for-statement used in bash-shells.
What you want to do is to rewrite the for-line into this:
for cnt in range(1, readnumber):
Also, you will have to rewrite the other lines as well, since they are bash-syntax too.

Categories