dmwm / WMCore

Core workflow management components for CMS.
Apache License 2.0
45 stars 106 forks source link

Add MyProxy context manager #3026

Closed ericvaandering closed 11 years ago

ericvaandering commented 12 years ago

Add a context manager for MyProxy that allows us to run commands with the user's proxy and return the original environment afterwards.

spigad commented 12 years ago

spiga: Eric could you expand a bit how'd you mean exactly ? (and where you are planning to use it?)

ericvaandering commented 12 years ago

ewv: Sure. First the where: This is needed for data publication in the server which must be done with the user's proxy.

How: So what I've got (still working on unit tests) is a context manager wrapper which I can call that will fetch a new delegated proxy and correctly set X509_USER_PROXY and then restore the original environment when it's done.

Code:

{{{ @contextlib.contextmanager def myProxyEnvironment(userDN, serverCert, serverKey, myproxySrv, proxyDir, logger): """ Allows us to user a context manager within which a MyProxy delegated proxy is set to X509_USER_PROXY and things are restored on exit """

originalEnvironment = copy.deepcopy(os.environ)
try:
    args = {}
    args['server_cert'] = serverCert
    args['server_key']  = serverKey
    args['myProxySvr']  = myproxySrv
    args['credServerPath'] = proxyDir
    args['logger'] = logger
    proxy = Proxy(args = args)

    proxy.userDN = userDN
    filename = proxy.logonRenewMyProxy()
    os.environ['X509_USER_PROXY'] = filename
    yield filename 
finally:
    os.environ = originalEnvironment

}}}

ericvaandering commented 12 years ago

ewv: Please review.

I have a working unit test which I will paste in but Proxy_t is the subject of a new ticket (#3031) so this test will have to wait until that's resolved.

ericvaandering commented 12 years ago

ewv: Here's the unit test:

{{{

!/usr/bin/env python

""" _Proxyt

"""

import unittest import os import logging

from nose.plugins.attrib import attr

from WMCore.Credential.Proxy import Proxy, myProxyEnvironment

You may have to change these variables to run in a local environment

uiPath = '/afs/cern.ch/cms/LCG/LCG-2/UI/cms_ui_env.sh' serverKey = '/home/crab/.globus/hostkey.pem' serverCert = '/home/crab/.globus/hostcert.pem' serverDN = '/DC=org/DC=doegrids/OU=Services/CN=crab3dev/cms-xen39.fnal.gov'

uiPath = '/uscmst1/prod/grid/gLite_SL5.sh' serverKey = '/data/ewv/cms-xen39crab3devkey.pem' serverCert = '/data/ewv/cms-xen39crab3devcert.pem' serverDN = '/DC=org/DC=doegrids/OU=Services/CN=crab3dev/cms-xen39.fnal.gov'

class ProxyTest(unittest.TestCase):

def setUp(self):
    """
    Setup for unit tests
    """
    logging.basicConfig(level=logging.DEBUG,
                format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                datefmt='%m-%d %H:%M',
                filename='proxy_unittests.log',
                filemode='w')

    logger_name = 'ProxyTest'

    self.logger = logging.getLogger(logger_name)

    self.dict = {'logger': self.logger, 'server_key': serverKey, 'server_cert': serverCert,
                 'vo': 'cms', 'role': 'NULL', 'myProxySvr': 'myproxy.cern.ch',
                 'proxyValidity': '192:00', 'min_time_left': 36000, 'uisource': uiPath,
                 'serverDN': serverDN}
    self.myProxy = Proxy(self.dict)
    if self.dict.has_key('serverDN'):
        self.serverDN = self.dict['serverDN']

    self.dict = {'logger': self.logger, 'proxyValidity': '192:00',}
    self.userProxy = Proxy(self.dict)

def tearDown(self):
    """
    _tearDown_

    Tear down the proxy.
    """
    return

def testMyProxyEnvironment(self):
    """
    Test the myProxyEnvironment context manager
    """

    # Create the proxy
    self.userProxy.create()
    proxyPath = self.userProxy.getProxyFilename()
    userDN = self.userProxy.getSubject()
    self.assertTrue(os.path.exists(proxyPath))

    # Delegate and check the proxy
    self.myProxy.delegate(credential=proxyPath, serverRenewer=True)
    valid = self.myProxy.checkMyProxy()
    self.assertTrue(valid)

    # Make sure X509_USER_PROXY exists only in the context manager and corresponds to a file
    self.assertFalse(os.environ.has_key('X509_USER_PROXY'))
    with myProxyEnvironment(userDN=userDN, serverCert=serverCert, serverKey=serverKey,
                            myproxySrv='myproxy.cern.ch', proxyDir='/tmp/', logger=self.logger):
        self.assertTrue(os.environ.has_key('X509_USER_PROXY'))
        self.assertTrue(os.path.exists(os.environ['X509_USER_PROXY']))
    self.assertFalse(os.environ.has_key('X509_USER_PROXY'))

    return

if name == 'main': unittest.main() }}}

spigad commented 12 years ago

spiga: ok thanks Eric. Please remember that if, as I suspect, you are planning to do this on CRAB REST you can't. Grid commands are not available at all on CMSWEB. Of course this doesn't mean that you cannot have the user proxy on the back-end, you can have it by passing it through the HTTP headers (you may want have a look at various comments on #2485, particularly comments:5 )

ericvaandering commented 12 years ago

ewv: Daniele and I discussed this and while this is not exactly how we'll do this in the final cmsweb deployment, that should also be able to use this code with slight modifications which will be done at that time.

So please check this in now and we'll revisit in 2012.

sfoulkes commented 12 years ago

sfoulkes: (In 8c094d4f02e1975a8e65c9488e30f558f3bcf290) Add a MyProxy context mananger. Fixes #3026.

From: Eric Vaanderring ewv@fnal.gov Signed-off-by: Steve Foulkes sfoulkes@fnal.gov