Skip to content

Commit

Permalink
Merge pull request #7413 from fstagni/90_remove_proxy_persistency
Browse files Browse the repository at this point in the history
[9.0] removed Proxies persistency flag and PUSP
  • Loading branch information
chrisburr authored Jan 25, 2024
2 parents e01e231 + 7f0ccc4 commit 9475045
Show file tree
Hide file tree
Showing 18 changed files with 85 additions and 473 deletions.
11 changes: 0 additions & 11 deletions dirac.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -745,17 +745,6 @@ Resources
}
##

## PUSP type:
MY_PUSP
{

ProviderType = DIRACCA

# PUSP service URL
ServiceURL = https://mypuspserver.com/
}
##

## OAuth2 type:
MY_OAuth2
{
Expand Down
15 changes: 1 addition & 14 deletions docs/source/AdministratorGuide/Resources/proxyprovider.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
ProxyProvider
==============

This resource type provides an interface to obtain proxy certificates using a user identifier. The following proxy providers are presented here: ``DIRACCA``, ``PUSP``. When all users upload their proxies to proxy manager manually, you do not need to deploy these resources. The **/Registry/Users** section describes how to specify a proxy provifer for a user's DN.
This resource type provides an interface to obtain proxy certificates using a user identifier. The following proxy providers are presented here: ``DIRACCA``. When all users upload their proxies to proxy manager manually, you do not need to deploy these resources. The **/Registry/Users** section describes how to specify a proxy provifer for a user's DN.

----------------------
DIRACCA proxy provider
Expand Down Expand Up @@ -32,19 +32,6 @@ The Proxy provider supports the following distinguished names, `more details her
* SP,ST(stateOrProvinceName)
* SERIALNUMBER(serialNumber)

-------------------
PUSP proxy provider
-------------------

ProxyProvider implementation for a Per-User Sub-Proxy(PUSP) proxy generation using PUSP proxy server. `More details about PUSP here <https://wiki.egi.eu/wiki/Usage_of_the_per_user_sub_proxy_in_EGI>`_. Required parameters in the DIRAC configuration for its implementation:

.. literalinclude:: /dirac.cfg
:start-after: ## PUSP type:
:end-before: ##
:dedent: 2
:caption: /Resources/ProxyProviders section


Usage
^^^^^

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,11 @@ Getting the proxy information

$ dirac-proxy-get-uploaded-info
Checking for DNs /O=GRID-FR/C=FR/O=CNRS/OU=CPPM/CN=Vanessa Hamar
--------------------------------------------------------------------------------------------------------
| UserDN | UserGroup | ExpirationTime | PersistentFlag |
--------------------------------------------------------------------------------------------------------
| /O=GRID-FR/C=FR/O=CNRS/OU=CPPM/CN=Vanessa Hamar | dirac_user | 2011-06-29 12:04:25 | True |
--------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------
| UserDN | ExpirationTime |
-------------------------------------------------------------------------
| /O=GRID-FR/C=FR/O=CNRS/OU=CPPM/CN=Vanessa Hamar | 2011-06-29 12:04:25 |
-------------------------------------------------------------------------

- The same can be checked in the Web Portal at the following location::

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ Columns

Date until user certificate is valid.

**Persistent**

Show if a proxy is persistent (value=true) or not (value=false).

You can choose to display the proxies by group or grouping by field choosing them in the menu, activated by pressing on a menu button.

Expand Down
12 changes: 5 additions & 7 deletions src/DIRAC/Core/Security/ProxyInfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
"""
import base64

from DIRAC import S_OK, S_ERROR, gLogger
from DIRAC.Core.Utilities import DErrno
from DIRAC.Core.Security.X509Chain import X509Chain # pylint: disable=import-error
from DIRAC.Core.Security.VOMS import VOMS
from DIRAC import S_ERROR, S_OK, gLogger
from DIRAC.ConfigurationSystem.Client.Helpers import Registry
from DIRAC.Core.Security import Locations
from DIRAC.Core.Security.DiracX import diracxTokenFromPEM

from DIRAC.ConfigurationSystem.Client.Helpers import Registry
from DIRAC.Core.Security.VOMS import VOMS
from DIRAC.Core.Security.X509Chain import X509Chain # pylint: disable=import-error
from DIRAC.Core.Utilities import DErrno


def getProxyInfo(proxy=False, disableVOMS=False):
Expand Down Expand Up @@ -98,7 +97,6 @@ def formatProxyInfoAsString(infoDict):
"subject",
"issuer",
"identity",
"subproxyUser",
("secondsLeft", "timeleft"),
("group", "DIRAC group"),
("hasDiracxToken", "DiracX"),
Expand Down
67 changes: 6 additions & 61 deletions src/DIRAC/Core/Security/m2crypto/X509Chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,22 @@
Link to the RFC 3820: https://tools.ietf.org/html/rfc3820
In particular, limited proxy: https://tools.ietf.org/html/rfc3820#section-3.8
There are also details available about Per-User Sub-Proxies (PUSP)
here: https://wiki.egi.eu/wiki/Usage_of_the_per_user_sub_proxy_in_EGI
"""
import copy
import hashlib
import os
import re
import stat
import tempfile
import hashlib

import re

import M2Crypto


from DIRAC import S_OK, S_ERROR
from DIRAC.Core.Utilities import DErrno
from DIRAC.Core.Utilities.Decorators import executeOnlyIf
from DIRAC import S_ERROR, S_OK
from DIRAC.ConfigurationSystem.Client.Helpers import Registry
from DIRAC.Core.Security.m2crypto import PROXY_OID, LIMITED_PROXY_OID, DIRAC_GROUP_OID, DEFAULT_PROXY_STRENGTH
from DIRAC.Core.Security.m2crypto import DEFAULT_PROXY_STRENGTH, DIRAC_GROUP_OID, LIMITED_PROXY_OID, PROXY_OID
from DIRAC.Core.Security.m2crypto.X509Certificate import X509Certificate

from DIRAC.Core.Utilities import DErrno
from DIRAC.Core.Utilities.Decorators import executeOnlyIf

# Decorator to check that _certList is not empty
needCertList = executeOnlyIf("_certList", S_ERROR(DErrno.ENOCHAIN))
Expand Down Expand Up @@ -687,11 +681,6 @@ def getDIRACGroup(self, ignoreDefault=False):
if not self.__isProxy:
return S_ERROR(DErrno.EX509, "Chain does not contain a valid proxy")

# If it is a PUSP, we do a lookup based on the certificate
# (you can't do a PUSP out of a proxy)
if self.isPUSP()["Value"]:
return self._certList[self.__firstProxyStep - 2].getDIRACGroup(ignoreDefault=ignoreDefault)

# The code below will find the first match of the DIRAC group
for cert in reversed(self._certList):
# We specifically say we do not want the default to first check inside the proxy
Expand Down Expand Up @@ -894,30 +883,6 @@ def __repr__(self):
"""Object representation"""
return self.__str__()

def isPUSP(self):
"""Checks whether the current chain is a PUSP
:returns: S_OK(boolean).
If True, the S_OK structure is enriched with:
* Indentity: the DN
* SubProxyUser: name of the user
"""
if self.__isProxy:
# Check if we have a subproxy
dn = self._certList[self.__firstProxyStep].getSubjectDN()
if not dn["OK"]:
return dn
dn = dn["Value"]

subproxyUser = isPUSPdn(dn)
if subproxyUser:
result = S_OK(True)
result["Identity"] = dn
result["SubproxyUser"] = subproxyUser
return result

return S_OK(False)

@needCertList
def getCredentials(self, ignoreDefault=False, withRegistryInfo=True):
"""Returns a summary of the credentials contained in the current chain
Expand All @@ -943,7 +908,6 @@ def getCredentials(self, ignoreDefault=False, withRegistryInfo=True):
Only for proxy:
* identity: If it is a normal proxy, it is the DN of the certificate.
If it is a PUSP, it contains the identity as in :py:meth:`.isPUSP`
* username: DIRAC username associated to the DN (needs withRegistryInfo)
(see :py:func:`DIRAC.ConfigurationSystem.Client.Helpers.Registry.getUsernameForDN`)
* group: DIRAC group, depending on ignoreDefault param(see :py:meth:`.getDIRACGroup`)
Expand Down Expand Up @@ -982,12 +946,6 @@ def getCredentials(self, ignoreDefault=False, withRegistryInfo=True):
# user, not the one of his proxy
credDict["DN"] = credDict["identity"]

# Check if we have the PUSP case
result = self.isPUSP()
if result["OK"] and result["Value"]:
credDict["identity"] = result["Identity"]
credDict["subproxyUser"] = result["SubproxyUser"]

if withRegistryInfo:
retVal = Registry.getUsernameForDN(credDict["identity"])
if not retVal["OK"]:
Expand Down Expand Up @@ -1042,16 +1000,3 @@ def hash(self):
sha1.update(attribute.encode())
self.__hash = sha1.hexdigest()
return S_OK(self.__hash)


def isPUSPdn(userDN):
"""Evaluate if the DN is of the PUSP type or not
:param str userDN: user DN string
:returns: the subproxy user name or None
"""
lastEntry = userDN.split("/")[-1].split("=")
if lastEntry[0] == "CN" and lastEntry[1].startswith("user:"):
return userDN.split("/")[-1].split(":")[1]
return None
13 changes: 0 additions & 13 deletions src/DIRAC/Core/Security/test/Test_X509Chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,19 +319,6 @@ def test_dumpChainToString_on_cert(cert_file, get_X509Chain_class):
assert res["Value"] == getCertOption(cert_file, "content")


@parametrize("cert_file", CERTS)
def test_isPUSP_on_cert(cert_file, get_X509Chain_class):
""" " Load a valid certificate in a chain, and check isPUSP"""

x509Chain = get_X509Chain_class()
x509Chain.loadChainFromFile(cert_file)

res = x509Chain.isPUSP()

assert res["OK"]
assert res["Value"] is False


@parametrize("cert_file", CERTS)
def test_getCredentials_on_cert(cert_file, get_X509Chain_class):
""" " Load a valid certificate in a chain, and check the information returned.
Expand Down
75 changes: 10 additions & 65 deletions src/DIRAC/FrameworkSystem/Client/ProxyManagerClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
This inherits the DIRAC base Client for direct execution of server functionality.
Client also contain caching of the requested proxy information.
"""
import os
import datetime
import os

from DIRAC import S_OK, S_ERROR, gLogger
from DIRAC import S_ERROR, S_OK, gLogger
from DIRAC.ConfigurationSystem.Client.Helpers import Registry
from DIRAC.Core.Utilities import ThreadSafe, DIRACSingleton
from DIRAC.Core.Utilities.DictCache import DictCache
from DIRAC.Core.Base.Client import Client
from DIRAC.Core.Security import Locations
from DIRAC.Core.Security.DiracX import addTokenToPEM
from DIRAC.Core.Security.ProxyFile import multiProxyArgument, deleteMultiProxy
from DIRAC.Core.Security.ProxyFile import deleteMultiProxy, multiProxyArgument
from DIRAC.Core.Security.VOMS import VOMS
from DIRAC.Core.Security.X509Chain import X509Chain # pylint: disable=import-error
from DIRAC.Core.Security.X509Request import X509Request # pylint: disable=import-error
from DIRAC.Core.Security.VOMS import VOMS
from DIRAC.Core.Security import Locations
from DIRAC.Core.Base.Client import Client
from DIRAC.Core.Utilities import DIRACSingleton, ThreadSafe
from DIRAC.Core.Utilities.DictCache import DictCache

gUsersSync = ThreadSafe.Synchronizer()
gProxiesSync = ThreadSafe.Synchronizer()
Expand Down Expand Up @@ -113,57 +113,6 @@ def userHasProxy(self, userDN, userGroup, validSeconds=0):

return S_OK(False)

@gUsersSync
def getUserPersistence(self, userDN, userGroup, validSeconds=0):
"""Check if a user(DN-group) has a proxy in the proxy management
Updates internal cache if needed to minimize queries to the service
:param str userDN: user DN
:param str userGroup: user group
:param int validSeconds: proxy valid time in a seconds
:return: S_OK()/S_ERROR()
"""
cacheKey = (userDN, userGroup)
userData = self.__usersCache.get(cacheKey, validSeconds)
if userData:
if userData["persistent"]:
return S_OK(True)
# Get list of users from the DB with proxys at least 300 seconds
gLogger.verbose("Updating list of users in proxy management")
retVal = self.__refreshUserCache(validSeconds)
if not retVal["OK"]:
return retVal
userData = self.__usersCache.get(cacheKey, validSeconds)
if userData:
return S_OK(userData["persistent"])
return S_OK(False)

def setPersistency(self, userDN, userGroup, persistent):
"""Set the persistency for user/group
:param str userDN: user DN
:param str userGroup: user group
:param boolean persistent: presistent flag
:return: S_OK()/S_ERROR()
"""
# Hack to ensure bool in the rpc call
persistentFlag = True
if not persistent:
persistentFlag = False
rpcClient = Client(url="Framework/ProxyManager", timeout=120)
retVal = rpcClient.setPersistency(userDN, userGroup, persistentFlag)
if not retVal["OK"]:
return retVal
# Update internal persistency cache
cacheKey = (userDN, userGroup)
record = self.__usersCache.get(cacheKey, 0)
if record:
record["persistent"] = persistentFlag
self.__usersCache.add(cacheKey, self.__getSecondsLeftToExpiration(record["expirationtime"]), record)
return retVal

def uploadProxy(self, proxy=None, restrictLifeTime: int = 0, rfcIfPossible=None):
"""Upload a proxy to the proxy management service using delegation
Expand Down Expand Up @@ -690,17 +639,14 @@ def getVOMSAttributes(self, chain):
"""
return VOMS().getVOMSAttributes(chain)

def getUploadedProxyLifeTime(self, DN, group=None):
def getUploadedProxyLifeTime(self, DN):
"""Get the remaining seconds for an uploaded proxy
:param str DN: user DN
:param str group: group
:return: S_OK(int)/S_ERROR()
"""
parameters = dict(UserDN=[DN])
if group:
parameters["UserGroup"] = [group]
result = self.getDBContents(parameters)
if not result["OK"]:
return result
Expand All @@ -709,10 +655,9 @@ def getUploadedProxyLifeTime(self, DN, group=None):
return S_OK(0)
pNames = list(data["ParameterNames"])
dnPos = pNames.index("UserDN")
groupPos = pNames.index("UserGroup")
expiryPos = pNames.index("ExpirationTime")
for row in data["Records"]:
if DN == row[dnPos] and group == row[groupPos]:
if DN == row[dnPos]:
td = row[expiryPos] - datetime.datetime.utcnow()
secondsLeft = td.days * 86400 + td.seconds
return S_OK(max(0, secondsLeft))
Expand Down
2 changes: 0 additions & 2 deletions src/DIRAC/FrameworkSystem/ConfigTemplate.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ Services
getVOMSProxyWithToken += LimitedDelegation
getVOMSProxyWithToken += PrivateLimitedDelegation
getLogContents = ProxyManagement
setPersistency = ProxyManagement
}
}
##END
Expand Down Expand Up @@ -94,7 +93,6 @@ Services
getVOMSProxyWithToken += LimitedDelegation
getVOMSProxyWithToken += PrivateLimitedDelegation
getLogContents = ProxyManagement
setPersistency = ProxyManagement
}
}
##END
Expand Down
Loading

0 comments on commit 9475045

Please sign in to comment.