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 contain a "bullshit 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