Create Multiple Virtual envs for Multiple kubernetes contexts - python

As of now i do
kubectl --context <cluster context> get pod -A
to get pod in specific cluster
is there a python way to set kubernetes context for a virtual env , so we can use multiple context at the same time
example :
Terminal 1:
(cluster context1) user#machine #
Terminal 2:
(cluster context2) user#machine #
This should be equivalent of
Terminal 1:
user#machine # kubectl --context <cluster context1> get pod -A
Terminal 2:
user#machine # kubectl --context <cluster context1> get pod -A

This isn't probably a rational solution, but anyway... At some time I used different kubectl versions for different clusters and I came up with a venv-like solution to switch between them. I wrote text files like this:
export KUBECONFIG="/path/to/kubeconfig"
export PATH="/path/including/the/right/kubectl"
And activated them in the same fashion as venv: source the_file. If you can split your contexts to separate files, you can add export KUBECONFIG="/path/to/kubeconfig" to your venv/bin/activate and it will use the desired config when you activate the venv.

i would try initializing multiple objects for the cluster as suggested in the official client repo
from pick import pick # install pick using `pip install pick`
from kubernetes import client, config
from kubernetes.client import configuration
def main():
contexts, active_context = config.list_kube_config_contexts()
if not contexts:
print("Cannot find any context in kube-config file.")
return
contexts = [context['name'] for context in contexts]
active_index = contexts.index(active_context['name'])
cluster1, first_index = pick(contexts, title="Pick the first context",
default_index=active_index)
cluster2, _ = pick(contexts, title="Pick the second context",
default_index=first_index)
client1 = client.CoreV1Api(
api_client=config.new_client_from_config(context=cluster1))
client2 = client.CoreV1Api(
api_client=config.new_client_from_config(context=cluster2))
print("\nList of pods on %s:" % cluster1)
for i in client1.list_pod_for_all_namespaces().items:
print("%s\t%s\t%s" %
(i.status.pod_ip, i.metadata.namespace, i.metadata.name))
print("\n\nList of pods on %s:" % cluster2)
for i in client2.list_pod_for_all_namespaces().items:
print("%s\t%s\t%s" %
(i.status.pod_ip, i.metadata.namespace, i.metadata.name))
if __name__ == '__main__':
main()
Read more here
You can also use python with pick for picking up the contexts
from pick import pick # `pip install pick`
from kubernetes import client, config
from kubernetes.client import configuration
def main():
contexts, active_context = config.list_kube_config_contexts()
if not contexts:
print("Cannot find any context in kube-config file.")
return
contexts = [context['name'] for context in contexts]
active_index = contexts.index(active_context['name'])
option, _ = pick(contexts, title="Pick the context to load",
default_index=active_index)
# Configs can be set in Configuration class directly or using helper
# utility
config.load_kube_config(context=option)
print("Active host is %s" % configuration.Configuration().host)
You can also try using the Environment variables in different terminals storing the different K8s contexts details.

First create separate config files for cluster context you would like to switch
Terminal 1:
user#machine $ kubectl config view --minify --flatten --context=context-1 > $HOME/.kube/config-context-1
Terminal 2:
user#machine $ kubectl config view --minify --flatten --context=context-2 > $HOME/.kube/config-context-2
Create Different virtual environments for different for different clusters and activate them
Terminal 1:
user#machine $ python3 -m venv context-1
user#machine $ . ./context-1/bin/activate
Terminal 2:
user#machine $ python3 -m venv context-2
user#machine $ . ./context-2/bin/activate
Export the new config files to the respective environments
Terminal 1:
(context-1) user#machine $ export KUBECONFIG="$HOME/.kube/config-context-1"
Terminal 2:
(context-2) user#machine $ export KUBECONFIG="$HOME/.kube/config-context-2"
You check your pods now its would be of different contexts

Related

Mount directory in docker by specifying path as argument

I have a python script that take two path, one as input folder and other as output folder via sys.argv. For example
python script.py from to
If no path is provided let say python script.py. It take default folder which is from and to.
I have created a docker image and i am mounting my local folder this way
docker run -v "$(pwd):/folder" myimage
As in this case I am not providing folder name argument, it take them by default and put them in folder folder of docker. This is working
But if i want to pass custom path,let how can i do that?
EDIT:
Let say here is the code
argl = len(sys.argv)
if argl==1:
dir_from = 'from'
dir_to = 'to'
elif argl == 3:
dir_from = sys.argv[1]
dir_to = sys.argv[2]
So if i pass
python script.py the first if condition will work, and if i pass argument like python script.py abc/from abc/to the second elif condition work.
docker run -v "$(pwd):/folder" myimage This command pick the first condition, but how to pass custom path to it.
For example some thing link that
docker run -v "abc/from abc/to:/folder" myimage
Here's how to pass in default values for your from and to path parameters at the time that you launch your container.
Define the two env vars as part of launching your container:
FROM_PATH = <get the from path default from wherever is appropriate>
TO_PATH = <get the from path default from wherever is appropriate>
Launch your container:
docker run -e FROM_PATH -e TO_PATH ... python script.py
You could specify the values for the env vars in the run command itself via something like -e FROM_PATH=/a/b/c. If you don't provide values, the values are assumed to be already defined in local env vars with the same name, as I did above.
Then inside your container code:
argl = len(sys.argv)
if argl==1:
dir_from = os.getenv('FROM_PATH')
dir_to = os.getenv('TO_PATH')
elif argl == 3:
dir_from = sys.argv[1]
dir_to = sys.argv[2]

Standard input EOF error when creating a Python container using docker-py [duplicate]

Considering this shell example:
echo "hello" | docker run --rm -ti -a stdin busybox \
/bin/sh -c "cat - >/out"
This will execute a busybox container and create a new file /out with the contents hello.
How would I accomplish this with docker-py ?
The docker-py equivalent:
container = docker_client.create_container( 'busybox',
stdin_open = True,
command = 'sh -c "cat - >/out"'
)
docker_client.start( container )
There is stdin_open = True, but where do I write the 'hello' ?
Back then it was not possible to attach stdin to a running container. This has changed.
With current version of docker-py this is now somehow possible (aka slix's workaround). This is taken from a discussion at GitHub which is focused on python 2.7.
See this example in python 3 with docker-py version 3.1.1
import docker, tarfile
from io import BytesIO
def test_send_data_via_stdin_into_container():
client = docker.APIClient()
# create container
container = client.create_container(
'busybox',
stdin_open = True,
command = 'sh -c "cat - >/received.txt"')
client.start(container)
# attach stdin to container and send data
original_text_to_send = 'hello this is from the other side'
s = client.attach_socket(container, params={'stdin': 1, 'stream': 1})
s._sock.send(original_text_to_send.encode('utf-8'))
s.close()
# stop container and collect data from the testfile
client.stop(container)
client.wait(container)
raw_stream,status = client.get_archive(container,'/received.txt')
tar_archive = BytesIO(b"".join((i for i in raw_stream)))
t = tarfile.open(mode='r:', fileobj=tar_archive)
text_from_container_file = t.extractfile('received.txt').read().decode('utf-8')
client.remove_container(container)
# check for equality
assert text_from_container_file == original_text_to_send
if __name__ == '__main__':
test_send_data_via_stdin_into_container()
Here's an updated solution:
#!/usr/bin/env python
import docker
# connect to docker
client = docker.APIClient()
# create a container
container = docker_client.create_container(
'busybox',
stdin_open = True,
command = 'sh -c "cat - >/out"')
client.start(container)
# attach to the container stdin socket
s = client.attach_socket(container, params={'stdin': 1, 'stream': 1})
# send text
s.send('hello')
# close, stop and disconnect
s.close()
client.stop(container)
client.wait(container)
client.remove_container(container)

invoke os.system as a non-root user in a root-user launched python program

I want to run a python program using sudo (e.g. sudo python test.py) but within the python program when I use os.system(<some command>) to invoke other processes, I want to run them as a non-root user.
Is this doable?
Thanks!
Example:
import os
import pwd
username = "nobody"
pwent = pwd.getpwnam(username)
uid = pwent.pw_uid
gid = pwent.pw_gid
pid = os.fork()
if pid == 0:
# child
# relinquish any privileged groups before we call setuid
# (not bothering to load the target user's supplementary groups here)
os.setgid(gid)
os.setgroups([])
# now relinquish root privs
os.setuid(uid)
# os.setuid should probably raise an exception if it fails,
# but I'm paranoid so...
if os.getuid() != uid:
print("setuid failed - bailing")
os._exit(1)
return_value = os.system("id") // 256 # or whatever
os._exit(return_value)
# parent
os.waitpid(pid, 0)
print("parent continues (still root here)")
os.system("id")
Gives:
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
parent continues (still root here)
uid=0(root) gid=0(root) groups=0(root)
Another way to do this is to add a prefix sudo -u username in front of the command one wants to run to execute as that specific user. For example, one can use os.system('sudo -u user_a python test.py') to run test.py inside a python script as user_a.

create logical volume using python cgi

I am creating python CGI script that accepts lv size from client and then creates and mount the logical volume using nfs.
Here is my code:
#!/usr/bin/python
print "Content-type:text/html"
print ""
import cgi,commands,os,socket,time,getpass
form = cgi.FieldStorage()
st=form.getvalue("st")
mount=form.getvalue('mount')
backup=form.getvalue('backup')
ip=os.environ["REMOTE_ADDR"]
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(("192.168.1.100",4444))
a,b=s.recvfrom(100)
print a
s.sendto(mount,b)
if(backup=='Yes'):
os.system("lvcreate --size "+st+" --thin volume/pooL1")
os.system("lvcreate -V "+st+" --name "+ip+" --thin volume/pooL1")
os.system("mkfs.ext4 /dev/volume/"+ip)
os.system("mkdir /mnt/"+ip)
os.system("mount /dev/volume/"+ip+" /mnt/"+ip+"" )
os.system("lvcreate -s --name snap"+ip+" /dev/volume/"+ip)
os.system("mkdir /media/snap"+ip)
os.system("mount /dev/volume/snap"+ip+" /media/snap"+ip+"")
else:
os.system("lvcreate --size "+st+" --thin volume/pooL1")
os.system("lvcreate -V "+st+" --name "+ip+" --thin volume/pooL1")
os.system("mkfs.ext4 /dev/volume/"+ip)
os.system("mkdir /mnt/"+ip)
os.system("mount /dev/volume/"+ip+" /mnt/"+ip+"/" )
f=open('/etc/fstab','a+')
f.write("/mnt/"+ip+" /dev/volume/"+ip+" ext4 defaults 0 0")
f.close()
f=open('/etc/exports','a+')
f.write("/mnt/"+ip+" "+ip+ "(rw,sync,no_root_squash) \n")
f.close()
os.system("exportfs -a")
s.sendto("now you can use your storage",b)
s.close()
st is storage size.
I have given permissions to apache to create logical volume.The problem is lv is not mounting.Also client is getting internal server error even when lv is created at server.
You need to write sudo before every command like os.system('sudo ...') if you are using rhel version 7.2.
For working sudo user you have to configure /etc/sudoers file and adding extra line #apache ALL=(ALL) NOPASSWD:ALL at any line.

Get root dialog in Python on Mac OS X, Windows?

How would I go about getting a privilege elevation dialog to pop up in my Python app? I want the UAC dialog on Windows and the password authentication dialog on Mac.
Basically, I need root privileges for part of my application and I need to get those privileges through the GUI. I'm using wxPython. Any ideas?
On Windows you cannot get the UAC dialog without starting a new process, and you cannot even start that process with CreateProcess.
The UAC dialog can be brought about by running another application that has the appropriate manifest file - see Running compiled python (py2exe) as administrator in Vista for an example of how to do this with py2exe.
You can also programatically use the runas verb with the win32 api ShellExecute http://msdn.microsoft.com/en-us/library/bb762153(v=vs.85).aspx - you can call this by using ctypes http://python.net/crew/theller/ctypes/ which is part of the standard library on python 2.5+ iirc.
Sorry don't know about Mac. If you give more detail on what you want to accomplish on Windows I might be able to provide more specific help.
I know the post is a little old, but I wrote the following as a solution to my problem (running a python script as root on both Linux and OS X).
I wrote the following bash-script to execute bash/python scripts with administrator privileges (works on Linux and OS X systems):
#!/bin/bash
if [ -z "$1" ]; then
echo "Specify executable"
exit 1
fi
EXE=$1
available(){
which $1 >/dev/null 2>&1
}
platform=`uname`
if [ "$platform" == "Darwin" ]; then
MESSAGE="Please run $1 as root with sudo or install osascript (should be installed by default)"
else
MESSAGE="Please run $1 as root with sudo or install gksu / kdesudo!"
fi
if [ `whoami` != "root" ]; then
if [ "$platform" == "Darwin" ]; then
# Apple
if available osascript
then
SUDO=`which osascript`
fi
else # assume Linux
# choose either gksudo or kdesudo
# if both are avilable check whoch desktop is running
if available gksudo
then
SUDO=`which gksudo`
fi
if available kdesudo
then
SUDO=`which kdesudo`
fi
if ( available gksudo && available kdesudo )
then
if [ $XDG_CURRENT_DESKTOP = "KDE" ]; then
SUDO=`which kdesudo`;
else
SUDO=`which gksudo`
fi
fi
# prefer polkit if available
if available pkexec
then
SUDO=`which pkexec`
fi
fi
if [ -z $SUDO ]; then
if available zenity; then
zenity --info --text "$MESSAGE"
exit 0
elif available notify-send; then
notify-send "$MESSAGE"
exit 0
elif available xmessage notify-send; then
xmessage -buttons Ok:0 "$MESSAGE"
exit 0
else
echo "$MESSAGE"
fi
fi
fi
if [ "$platform" == "Darwin" ]
then
$SUDO -e "do shell script \"$*\" with administrator privileges"
else
$SUDO $#
fi
Basically, the way I set up my system is that I keep subfolders inside the bin directories (e.g. /usr/local/bin/pyscripts in /usr/local/bin), and create symbolic links to the executables. This has three benefits for me:
(1) If I have different versions, I can easily switch which one is executed by changing the symbolic link and it keeps the bin directory cleaner (e.g. /usr/local/bin/gcc-versions/4.9/, /usr/local/bin/gcc-versions/4.8/, /usr/local/bin/gcc --> gcc-versions/4.8/gcc)
(2) I can store the scripts with their extension (helpful for syntax highlighting in IDEs), but the executables do not contain them because I like it that way (e.g. svn-tools --> pyscripts/svn-tools.py)
(3) The reason I will show below:
I name the script "run-as-root-wrapper" and place it in a very common path (e.g. /usr/local/bin) so python doesn't need anything special to locate it. Then I have the following run_command.py module:
import os
import sys
from distutils.spawn import find_executable
#===========================================================================#
def wrap_to_run_as_root(exe_install_path, true_command, expand_path = True):
run_as_root_path = find_executable("run-as-root-wrapper")
if(not run_as_root_path):
return False
else:
if(os.path.exists(exe_install_path)):
os.unlink(exe_install_path)
if(expand_path):
true_command = os.path.realpath(true_command)
true_command = os.path.abspath(true_command)
true_command = os.path.normpath(true_command)
f = open(exe_install_path, 'w')
f.write("#!/bin/bash\n\n")
f.write(run_as_root_path + " " + true_command + " $#\n\n")
f.close()
os.chmod(exe_install_path, 0755)
return True
In my actual python script, I have the following function:
def install_cmd(args):
exe_install_path = os.path.join(args.prefix,
os.path.join("bin", args.name))
if(not run_command.wrap_to_run_as_root(exe_install_path, sys.argv[0])):
os.symlink(os.path.realpath(sys.argv[0]), exe_install_path)
So if I have a script called TrackingBlocker.py (actual script I use to modify the /etc/hosts file to re-route known tracking domains to 127.0.0.1), when I call "sudo /usr/local/bin/pyscripts/TrackingBlocker.py --prefix /usr/local --name ModifyTrackingBlocker install" (arguments handled via argparse module), it installs "/usr/local/bin/ModifyTrackingBlocker", which is a bash script executing
/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py [args]
e.g.
ModifyTrackingBlocker add tracker.ads.com
executes:
/usr/local/bin/run-as-root-wrapper /usr/local/bin/pyscripts/TrackingBlocker.py add tracker.ads.com
which then displays the authentification dialog needed to get the privileges to add:
127.0.0.1 tracker.ads.com
to my hosts file (which is only writable by a superuser).
If you want to simplify/modify it to run only certain commands as root, you could simply add this to your script (with the necessary imports noted above + import subprocess):
def run_as_root(command, args, expand_path = True):
run_as_root_path = find_executable("run-as-root-wrapper")
if(not run_as_root_path):
return 1
else:
if(expand_path):
command = os.path.realpath(command)
command = os.path.abspath(command)
command = os.path.normpath(command)
cmd = []
cmd.append(run_as_root_path)
cmd.append(command)
cmd.extend(args)
return subprocess.call(' '.join(cmd), shell=True)
Using the above (in run_command module):
>>> ret = run_command.run_as_root("/usr/local/bin/pyscripts/TrackingBlocker.py", ["status", "display"])
>>> /etc/hosts is blocking approximately 16147 domains
I'm having the same problem on Mac OS X. I have a working solution, but it's not optimal. I will explain my solution here and continue looking for a better one.
At the beginning of the program I check if I'm root or not by executing
def _elevate():
"""Elevate user permissions if needed"""
if platform.system() == 'Darwin':
try:
os.setuid(0)
except OSError:
_mac_elevate()
os.setuid(0) will fail if i'm not already root and that will trigger _mac_elevate() which relaunch my program from the start as administrator with the help of osascript. osascript can be used to execute applescript and other stuff. I use it like this:
def _mac_elevate():
"""Relaunch asking for root privileges."""
print "Relaunching with root permissions"
applescript = ('do shell script "./my_program" '
'with administrator privileges')
exit_code = subprocess.call(['osascript', '-e', applescript])
sys.exit(exit_code)
The problem with this is if I use subprocess.call as above I keep the current process running and there will be two instances of my app running giving two dock icons. If I use subprocess.Popen instead and let the non-priviledged process die instantly I can't make use of the exit code, nor can I fetch the stdout/stderr streams and propagate to the terminal starting the original process.
Using osascript with with administrator privileges is actually just Apple Script wrapping a call to AuthorizationExecuteWithPrivileges().
But you can call AuthorizationExecuteWithPrivileges() directly from Python3 with ctypes.
For example, the following parent script spawn_root.py (run as a non-root user) spawns a child process root_child.py (run with root privileges).
The user will be prompted to enter their password in the OS GUI pop-up. Note that this will not work on a headless session (eg over ssh). It must be run inside the GUI (eg Terminal.app).
After entering the user's password into the MacOS challenge dialog correctly, root_child.py executes a soft shutdown of the system, which requires root permission on MacOS.
Parent (spawn_root.py)
#!/usr/bin/env python3
import sys, ctypes
import ctypes.util
from ctypes import byref
sec = ctypes.cdll.LoadLibrary(ctypes.util.find_library("Security"))
kAuthorizationFlagDefaults = 0
auth = ctypes.c_void_p()
r_auth = byref(auth)
sec.AuthorizationCreate(None,None,kAuthorizationFlagDefaults,r_auth)
exe = [sys.executable,"root_child.py"]
args = (ctypes.c_char_p * len(exe))()
for i,arg in enumerate(exe[1:]):
args[i] = arg.encode('utf8')
io = ctypes.c_void_p()
sec.AuthorizationExecuteWithPrivileges(auth,exe[0].encode('utf8'),0,args,byref(io))
Child (root_child.py)
#!/usr/bin/env python3
import os
if __name__ == "__main__":
f = open( "root_child.out", "a" )
try:
os.system( "shutdown -h now" )
f.write( "SUCCESS: I am root!\n" )
except Exception as e:
f.write( "ERROR: I am not root :'(" +str(e)+ "\n" )
f.close()
Security Note
Obviously, any time you run something as root, you need to be very careful!
AuthorizationExecuteWithPrivileges() is deprecated, but it can be used safely. But it can also be used unsafely!
It basically boils down to: do you actually know what you're running as root? If the script you're running as root is located in a Temp dir that has world-writeable permissions (as a lot of MacOS App installers have done historically), then any malicious process could gain root access.
To execute a process as root safely:
Make sure that the permissions on the process-to-be-launched are root:root 0400 (or writeable only by root)
Specify the absolute path to the process-to-be-launched, and don't allow any malicious modification of that path
Sources
https://github.com/cloudmatrix/esky/blob/master/esky/sudo/sudo_osx.py
https://github.com/BusKill/buskill-app/issues/14
https://www.jamf.com/blog/detecting-insecure-application-updates-on-macos/

Categories

Resources