Zones, X and Roles

My last two blog entries were actually written to set up this entry. What if I'm logged into the zone, assumed a role and need to run a GUI? An example use case here would be assuming the role of oracle and wanting to run something like the Oracle Database Configuration Assistant (DBCA). For the purposes of this entry, however, I'll stick to the simple Python GUI I used in my previous entry.

You might think it would just work, and you might be wrong. Check it out:

bleonard@opensolaris:~$ ssh -X bleonard@10.0.1.196
Password: 
Last login: Sat Sep 19 09:43:20 2009 from 10.0.1.9
Sun Microsystems Inc.   SunOS 5.11      snv_111b        November 2008
bleonard@myzone:~$ su - oracle
Password: 
Sun Microsystems Inc.   SunOS 5.11      snv_111b        November 2008
oracle@myzone:~$ python ../bleonard/gui.py 
Traceback (most recent call last):
  File "../bleonard/gui.py", line 2, in ?
    widget = Label(None, text='Hello GUI world!')
  File "/usr/lib/python2.4/lib-tk/Tkinter.py", line 2397, in __init__
    Widget.__init__(self, master, 'label', cnf, kw)
  File "/usr/lib/python2.4/lib-tk/Tkinter.py", line 1856, in __init__
    BaseWidget._setup(self, master, cnf)
  File "/usr/lib/python2.4/lib-tk/Tkinter.py", line 1831, in _setup
    _default_root = Tk()
  File "/usr/lib/python2.4/lib-tk/Tkinter.py", line 1569, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable

X11 forwarding is doing a couple of things on your behalf, but those things are not happening when you switch to a role. Let's compare the DISPLAY environment variable between the role and the user:

oracle@myzone:~$ echo $DISPLAY

oracle@myzone:~$ exit
logout
bleonard@myzone:~$ echo $DISPLAY
localhost:12.0

So let's set the role's DISPLAY environment variable to match that of the user and see where that gets us:

bleonard@myzone:~$ su - oracle
Password: 
Sun Microsystems Inc.   SunOS 5.11      snv_111b        November 2008
oracle@myzone:~$ export DISPLAY=localhost:12.0
oracle@myzone:~$ python ../bleonard/gui.py 
X11 connection rejected because of wrong authentication.
X connection to localhost:12.0 broken (explicit kill or server shutdown).

OK, so we've gotten past the DISPLAY issue, but now we are hung up on a X authentication issue.

Machines that wish to connect to the X server must also authenticate themselves to the server and this is managed through the X authorization file utility xauth. This is another thing that ssh X11 forwarding handled for the user, but not so for the role.

To see the X authorization record that was established for user bleonard:

bleonard@myzone:~$ xauth list
myzone/unix:12  MIT-MAGIC-COOKIE-1  516f5bbcc4697039f4635ba1a8be2a03

So in order to get our GUI to work from the role, we'll need to add the X authorization record to the role's authority file (which is ~/.Xauthority). There are a couple of ways to add the X authorization record:

  1. Copy the output from xauth list and paste it to  xauth add:
    bleonard@myzone:~$ xauth list
    myzone/unix:12  MIT-MAGIC-COOKIE-1  516f5bbcc4697039f4635ba1a8be2a03
    bleonard@myzone:~$ su - oracle
    Password: 
    Sun Microsystems Inc.   SunOS 5.11      snv_111b        November 2008
    oracle@myzone:~$ export DISPLAY=localhost:12.0
    oracle@myzone:~$ xauth add myzone/unix:12  MIT-MAGIC-COOKIE-1  516f5bbcc4697039f4635ba1a8be2a03
    xauth:  creating new authority file /export/home/oracle/.Xauthority
    oracle@myzone:~$ python ../bleonard/gui.py &
    [1] 6404
    
    Here's a little wrapper script for su (thanks to Andreas Huber) that will handle this for you:
    bleonard@myzone:~$ cat sux 
    #!/bin/bash
    if [ ! $1 ]; then
            echo "Missing parameter user/role"
            exit
    fi
    PRE_AUTH="xauth add $(xauth list ${DISPLAY//\*:/:})"
    su - $1 -c "$PRE_AUTH;DISPLAY=$DISPLAY \\$SHELL"
    
    And using the script:
    bleonard@myzone:~$ ./sux oracle
    Password: 
    Sun Microsystems Inc.   SunOS 5.11      snv_111b        November 2008
    xauth:  creating new authority file /export/home/oracle/.Xauthority
    
  2. Export the data from using xauth extract and add it using xauth merge:
    bleonard@myzone:~$ xauth list             
    myzone/unix:12  MIT-MAGIC-COOKIE-1  516f5bbcc4697039f4635ba1a8be2a03
    bleonard@myzone:~$ xauth extract - myzone/unix:12 > /tmp/xauth.data
    bleonard@myzone:~$ su - oracle
    Password: 
    Sun Microsystems Inc.   SunOS 5.11      snv_111b        November 2008
    oracle@myzone:~$ export DISPLAY=localhost:12.0
    oracle@myzone:~$ xauth merge - < /tmp/xauth.data 
    xauth:  creating new authority file /export/home/oracle/.Xauthority
    oracle@myzone:~$ python ../bleonard/gui.py &
    [1] 6434
  3. This third option is more of a hack, but you could copy the user's authority file to the role. The problem with this approach is that it will screw up other users that have also switched to the role and are using X.

    Recall, the user's authority file was generated by ssh's X11 forwarding, so to locate it, use xauth info:
    bleonard@myzone:~$ xauth info
    Authority file:       /tmp/ssh-xauth-mQaixo/xauthfile
    File new:             no
    File locked:          no
    Number of entries:    1
    Changes honored:      yes
    Changes made:         no
    Current input:        (argv):1
    
  4. Now you could use a script like the following to extract the authority file and copy it to the role. As a convenience, I also output the command to set the DISPLAY variable:

    bleonard@myzone:~$ cat sux
    #!/bin/bash
    if [ ! $1 ]; then
            echo "Missing parameter user/role"
            exit
    fi
    info=`xauth info`
    for entry in $info
    do
      if [ ${entry:0:4} = "/tmp" ]; then
        xfile=$entry
      fi
    done
    pfexec cp $xfile /export/home/$1/.Xauthority
    pfexec chown $1 /export/home/$1/.Xauthority
    echo "\*\*\* Copy and paste the following to set your DISPLAY \*\*\*"
    echo "export DISPLAY="$DISPLAY
    su - $1
    

    And using the script:

    bleonard@myzone:~$ ./sux oracle
    \*\*\* Copy and paste the following to set your DISPLAY \*\*\*
    export DISPLAY=localhost:10.0
    Password: 
    Sun Microsystems Inc.   SunOS 5.11      snv_111b        November 2008
    oracle@myzone:~$ export DISPLAY=localhost:10.0
    oracle@myzone:~$ python ../bleonard/gui.py
    [1] 7872
    

In all cases, after switching to the role, my GUI now displays correctly:


Comments:

Hi Brian,

that's a very cool script that you wrote.
As you pointed out yourself that copying the .Xauthority is a hack, I thought how to use the first approach with xauth list/add.

So let me suggest this solution:

First, collect the xauth info for the current display and store it to the $PRE_AUTH variable:

PRE_AUTH="/usr/X/bin/xauth add $(/usr/X/bin/xauth list ${DISPLAY//\*:/:})"

Then switch to the role, execute $PRE_AUTH, set $DISPLAY and then execute a shell.

su - $1 -c "$PRE_AUTH;DISPLAY=$DISPLAY \\$SHELL"

Cheers,

Andreas

Posted by Andreas Huber on May 31, 2010 at 05:16 AM GMT #

Andreas, awesome! I've updated the entry to include your script - that's definitely the way to go. I should actually delete option 3 - there's no reason to go that route.

Thanks,
Brian

Posted by William Leonard on June 01, 2010 at 07:19 AM GMT #

Another option is to use the XAUTHORITY environment variable and grant the user you are su-ing to rights on the original .Xauthority file through either chmod or setfacl.

E.g.
user1$ setfacl -m user:$user2:rw $HOME/.Xauthority
user1$ su - $user2
user2$ export XAUTHORITY=/export/home/$user1/.Xauthority

Posted by Brian King on June 08, 2010 at 09:11 AM GMT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

The Observatory is a blog for users of Oracle Solaris. Tune in here for tips, tricks and more as we explore the Solaris operating system from Oracle.

Connect with Oracle Solaris:


Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
20
21
22
23
24
25
26
27
28
29
30
   
       
Today