X509Chain
X509Chain is a class for managing X509 chains with their Pkeys
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
- class DIRAC.Core.Security.m2crypto.X509Chain.X509Chain(certList=False, keyObj=False)
Bases:
object
An X509Chain is basically a list of X509Certificate object, as well as a PKey object, which is associated to the X509Certificate the lowest in the chain.
This is what you will want to use for user certificate (because they will turn into proxy….), and for proxy.
A priori, once we get rid of pyGSI, we could even meld the X509Certificate into this one, and use the X509Chain for host certificates. After all, a certificate is nothing but a chain of length 1…
There are normally 4 ways you would instanciate an X509Chain object:
You are loading a proxy from a file
Loading the chain from a file
You are getting information about your peer during an SSL connection
You are delegating
Typical usages of X509Chain are illustrated below
Loading a proxy from a file (this will load the chain and the key, assuming the key is in the same file):
proxy = X509Chain() res = proxy.loadProxyFromFile(myFile) if not res['OK']: return res
Generating a proxy from a Certificate:
cert = X509Chain() # Load user cert retVal = cert.loadChainFromFile('/home/chaen/.globus/userkey.pem') if not retVal['OK']: return retVal # Load the key from a different place, with a password retVal = cert.loadKeyFromFile('/home/chaen/.globus/userkey.pem', password='MySecretKey') if not retVal['OK']: return res # Generate a limited proxy, valid one hour retVal = cert.generateProxyToFile('/tmp/proxy.pem', 3600, # only 1 h diracGroup = 'lhcb_user', strength= 2048, limited=True)
Getting information from a peer in an SSL Connection:
# conn is an M2Crypto.SSL.Connection instance chain = X509Chain.generateX509ChainFromSSLConnection(conn) creds = chain.getCredentials()
Delegating a proxy to a service:
# The server side generates a request # Equivalent to ProxyManager.requestDelegationUpload x509Req = X509Request() x509Req.generateProxyRequest() # This reqStr object is sent to the client reqStr = x509Req.dumpRequest()['Value'] # This object contains both the public and private key pkeyReq = x509Req.getPKey() ####################################################### # The client side signs the request, with its proxy # Assume the proxy chain was already loaded one way or the otjer # The proxy will not contain a private key res = proxyChain.generateChainFromRequestString(reqStr, lifetime=lifetime) # This is sent back to the server delegatedProxyString = res['Value'] ###################################################### # Equivalent to ProxyManager.completeDelegationUpload # Create the new chain # the pkey was generated together with the Request delegatedProxy = X509Chain(keyObj=pkeyReq) delegatedProxy.loadChainFromString(delegatedProxyString) # make sure the public key match between Request and the new Chain # (Stupid, of course it will ! But it is done in the ProxyManager...) res = x509Req.checkChain(delegatedProxy)
- __init__(certList=False, keyObj=False)
C’tor
- Parameters:
certList – list of X509Certificate to constitute the chain
keyObj – ~M2Crypto.EVP.PKey object. The public or public/private key associated to the last certificate of the chain
- dumpAllToFile(filename=False)
Dump all to file.
- Parameters:
filename – If not specified, a temporary one will be created
- Returns:
S_OK(filename)/S_ERROR
- dumpAllToString()
Dump the current chain as a PEM encoded string The order would be:
first certificate
private key (without passphrase)
other certificates
- Returns:
S_OK(PEM encoded chain with private key)
- dumpChainToString()
Dump only cert chain to string, without the PKey
- Returns:
S_OK(pem chain)
- dumpPKeyToString()
Dump only the key to string, not encoded
- Returns:
S_OK(PEM encoded key)
- generateChainFromRequestString(pemData, lifetime=86400, requireLimited=False, diracGroup=False)
Generate a x509 chain from a request.
- Parameters:
pemData – PEM encoded request
lifetime – lifetime of the delegated proxy in seconds (default 1 day)
requireLimited – if True, requires a limited proxy
diracGroup – DIRAC group to put in the proxy
rfc – placeholder for compatibility, ignored
- Returns:
S_OK( X509 chain pem encoded string ) / S_ERROR. The new chain will have been signed with the public key included in the request
- generateProxyRequest(bitStrength=2048, limited=False)
Generate a proxy request. See
DIRAC.Core.Security.m2crypto.X509Certificate.X509Certificate.generateProxyRequest()
Return S_OK( X509Request ) / S_ERROR
- generateProxyToFile(filePath, lifetime, diracGroup=False, strength=2048, limited=False)
Generate a proxy and put it into a file
- Parameters:
filePath – file to write
lifetime – expected lifetime in seconds of proxy
diracGroup – diracGroup to add to the certificate
strength – length in bits of the pair
limited – Create a limited proxy
rfc – placeholder and ignored
- generateProxyToString(lifetime, diracGroup=False, strength=2048, limited=False, proxyKey=False)
Generate a proxy and get it as a string.
Check here: https://github.com/eventbrite/m2crypto/blob/master/demo/x509/ca.py#L45
- Parameters:
lifetime (int) – expected lifetime in seconds of proxy
diracGroup (str) – diracGroup to add to the certificate
strength (int) – length in bits of the pair if proxyKey not given (default 2048)
limited (bool) – Create a limited proxy (default False)
proxyKey – M2Crypto.EVP.PKey instance with private and public key. If not given, generate one
rfc – placeholder for backward compatibility and ignored
- Returns:
S_OK(PEM encoded string), S_ERROR. The PEM string contains all the certificates in the chain and the private key associated to the last X509Certificate just generated.
- static generateX509ChainFromSSLConnection(sslConnection)
Returns an instance of X509Chain from the SSL connection
- Parameters:
sslConnection – ~M2Crypto.SSl.Connection instance
- Returns:
a X509Chain instance
- getCertInChain(certPos=0)
Get then a certificate in the chain
- Warning:
Contrary to the pygsi version, this is not a copy!
- Parameters:
certPos – position of the certificate in the chain. Default: 0
- Returns:
S_OK(X509Certificate)/S_ERROR
- getCertList()
Get the cert list
Deprecated: Only here for compatibility reason
- getCredentials(ignoreDefault=False, withRegistryInfo=True)
Returns a summary of the credentials contained in the current chain
- Params ignoreDefault:
(default False) If True and if no DIRAC group is found in the proxy, lookup the CS
- Params withRegistryInfo:
(default True) if set to True, will enhance the returned dict with info from the registry
- Returns:
S_OK with the credential dict. Some parameters of the dict are always there, other depends on the nature of the Chain
- Always present:
subject: str. The last DN in the chain
issuer: str. The issuer of the last cert in the chain
secondsLeft: validity of the chain in seconds (see
getRemainingSecs()
)isProxy: boolean (see
isProxy()
)isLimitedProxy: boolean (see
isLimitedProxy()
)validDN: boolean if the DN is known to DIRAC
validGroup: False (see further definition)
DN: either the DN of the host, or the DN of the user corresponding to the proxy
- 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
isPUSP()
- username: DIRAC username associated to the DN (needs withRegistryInfo)
(see
DIRAC.ConfigurationSystem.Client.Helpers.Registry.getUsernameForDN()
)
group: DIRAC group, depending on ignoreDefault param(see
getDIRACGroup()
)validGroup: True if the group found is in the list of groups the user belongs to
groupProperty: (only if validGroup) get the properties of the group
- For Host certificate (needs withRegistryInfo):
group: always hosts
- hostname: name of the host as registered in the CS
(see
DIRAC.ConfigurationSystem.Client.Helpers.Registry.getHostnameForDN()
)
validGroup: True
- groupProperties: host options
(see
DIRAC.ConfigurationSystem.Client.Helpers.Registry.getHostOption()
)
- If it is a user certificate (needs withRegistryInfo):
username: like for proxy
validDN: like proxy
- getDIRACGroup(ignoreDefault=False)
Retrieve the dirac group of the chain
- Parameters:
ignoreDefault – (default False) if True, do not lookup the CS for a group if it is not in the proxy
- Returns:
S_OK(dirac group)/S_ERROR
- getIssuerCert()
Returns the issuer certificate of the last one if it is a proxy, otherwise the last one in the chain
- Returns:
S_OK(X509Certificate)/S_ERROR
- getNotAfterDate()
Get the smallest not after date
- Returns:
S_OK(datetime.datetime)
- getNumCertsInChain()
length of the certificate chain
- Returns:
length of the certificate chain
- getPKeyObj()
Get the pkey obj
- returns:
~M2Crypto.EVP.PKey object
Deprecated: Only here for compatibility reason
- getRemainingSecs()
Get remaining time (minimum of all cert in the chain)
- Returns:
S_OK(time left in seconds)
- getStrength()
Returns the strength in bit of the key of the first certificate in the chain
- getVOMSData()
Returns the voms data.
- Returns:
See
getVOMSData()
If no VOMS data is available, return DErrno.EVOMS- Warning:
In case the chain is not a proxy, this method will return False. Yes, it’s stupid, but it is for compatibility…
- hasExpired()
Check whether any element of the chain has expired
- Returns:
S_OK(boolean)
- hash()
Get a hash of the chain In practice, this is only used to index the chain in a DictCache
- Returns:
S_OK(string hash)
- classmethod instanceFromFile(chainLocation)
Class method to generate a X509Chain from a file
- param chainLocation:
path to the file
- returns:
S_OK(X509Chain)
Deprecated: Use loadChainFromFile instead
- isLimitedProxy()
Check whether this chain is a limited proxy
- Returns:
S_OK(boolean)
- isPUSP()
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
- isProxy()
Check whether this chain is a proxy
- Returns:
S_OK(boolean)
- isRFC()
Check whether this is an RFC proxy. It can only be true, providing it is a proxy
- Returns:
S_OK(boolean)
- isVOMS()
Check whether this proxy contains VOMS extensions. It is enough for one of the certificate of the chain to have VOMS extension
- Returns:
S_OK(boolean)
- isValidProxy(ignoreDefault=False)
- Check whether this chain is a valid proxy, that is:
a proxy
still valid
with a valid group
- Parameters:
ignoreDefault – (what a stupid name) if True, do not lookup the CS
- Returns:
S_OK(True) if the proxy is valid, S_ERROR otherwise
- loadChainFromFile(chainLocation)
Load a x509 chain from a pem file
- Parameters:
chainLocation – path to the file
- Returns:
S_OK/S_ERROR
- loadChainFromString(data)
Load a x509 cert from a string containing the pem data
- Parameters:
data – data representing the chain of certificate in the
Return : S_OK / S_ERROR
- loadKeyFromFile(chainLocation, password=False)
Load a PKey from a pem file
- Parameters:
chainLocation – path to the file
password – password to decode the file.
- Returns:
S_OK / S_ERROR
- loadKeyFromString(pemData, password=False)
Load a PKey from a string containing the pem data
- Parameters:
pemData – pem data of the key, potentially encoded with the password
password – password to decode the file.
- Returns:
S_OK / S_ERROR
- loadProxyFromFile(chainLocation)
Load a Proxy from a pem file, that is both the Cert chain and the PKey
- Parameters:
chainLocation – path to the proxy file
- Returns:
S_OK / S_ERROR
- loadProxyFromString(pemData)
Load a Proxy from a pem buffer, that is both the Cert chain and the PKey
- Parameters:
pemData – PEM encoded cert chain and pkey
- Returns:
S_OK / S_ERROR
- setPKey(pkeyObj)
Set the chain Return : S_OK / S_ERROR