@ -646,12 +646,14 @@ class ACMEAccount(object):
def _new_reg ( self , contact = None , agreement = None , terms_agreed = False , allow_creation = True ) :
def _new_reg ( self , contact = None , agreement = None , terms_agreed = False , allow_creation = True ) :
'''
'''
Registers a new ACME account . Returns True if the account was
Registers a new ACME account . Returns a pair ` ` ( created , data ) ` ` .
created and False if it already existed ( e . g . it was not newly
Here , ` ` created ` ` is ` ` True ` ` if the account was created and
created ) .
` ` False ` ` if it already existed ( e . g . it was not newly created ) ,
or does not exist . In case the account was created or exists ,
` ` data ` ` contains the account data ; otherwise , it is ` ` None ` ` .
https : / / tools . ietf . org / html / draft - ietf - acme - acme - 14 #section-7.3
https : / / tools . ietf . org / html / draft - ietf - acme - acme - 14 #section-7.3
'''
'''
contact = [ ] if contact is None else contact
contact = contact or [ ]
if self . version == 1 :
if self . version == 1 :
new_reg = {
new_reg = {
@ -668,6 +670,7 @@ class ACMEAccount(object):
' contact ' : contact
' contact ' : contact
}
}
if not allow_creation :
if not allow_creation :
# https://tools.ietf.org/html/draft-ietf-acme-acme-14#section-7.3.1
new_reg [ ' onlyReturnExisting ' ] = True
new_reg [ ' onlyReturnExisting ' ] = True
if terms_agreed :
if terms_agreed :
new_reg [ ' termsOfServiceAgreed ' ] = True
new_reg [ ' termsOfServiceAgreed ' ] = True
@ -679,7 +682,7 @@ class ACMEAccount(object):
# Account did not exist
# Account did not exist
if ' location ' in info :
if ' location ' in info :
self . set_account_uri ( info [ ' location ' ] )
self . set_account_uri ( info [ ' location ' ] )
return True
return True , result
elif info [ ' status ' ] == ( 409 if self . version == 1 else 200 ) :
elif info [ ' status ' ] == ( 409 if self . version == 1 else 200 ) :
# Account did exist
# Account did exist
if result . get ( ' status ' ) == ' deactivated ' :
if result . get ( ' status ' ) == ' deactivated ' :
@ -689,22 +692,22 @@ class ACMEAccount(object):
# "Once an account is deactivated, the server MUST NOT accept further
# "Once an account is deactivated, the server MUST NOT accept further
# requests authorized by that account's key."
# requests authorized by that account's key."
if not allow_creation :
if not allow_creation :
return False
return False , None
else :
else :
raise ModuleFailException ( " Account is deactivated " )
raise ModuleFailException ( " Account is deactivated " )
if ' location ' in info :
if ' location ' in info :
self . set_account_uri ( info [ ' location ' ] )
self . set_account_uri ( info [ ' location ' ] )
return False
return False , result
elif info [ ' status ' ] == 400 and result [ ' type ' ] == ' urn:ietf:params:acme:error:accountDoesNotExist ' and not allow_creation :
elif info [ ' status ' ] == 400 and result [ ' type ' ] == ' urn:ietf:params:acme:error:accountDoesNotExist ' and not allow_creation :
# Account does not exist (and we didn't try to create it)
# Account does not exist (and we didn't try to create it)
return False
return False , None
else :
else :
raise ModuleFailException ( " Error registering: {0} {1} " . format ( info [ ' status ' ] , result ) )
raise ModuleFailException ( " Error registering: {0} {1} " . format ( info [ ' status ' ] , result ) )
def get_account_data ( self ) :
def get_account_data ( self ) :
'''
'''
Retrieve account information . Can only be called when the account
Retrieve account information . Can only be called when the account
URI is already known ( such as after calling init _account) .
URI is already known ( such as after calling setup _account) .
Return None if the account was deactivated , or a dict otherwise .
Return None if the account was deactivated , or a dict otherwise .
'''
'''
if self . uri is None :
if self . uri is None :
@ -732,66 +735,82 @@ class ACMEAccount(object):
raise ModuleFailException ( " Error getting account data from {2} : {0} {1} " . format ( info [ ' status ' ] , result , self . uri ) )
raise ModuleFailException ( " Error getting account data from {2} : {0} {1} " . format ( info [ ' status ' ] , result , self . uri ) )
return result
return result
def init _account( self , contact , agreement = None , terms_agreed = False , allow_creation = True , update_contact = True , remove_account_uri_if_not_exists = False ) :
def setup _account( self , contact = None , agreement = None , terms_agreed = False , allow_creation = True , remove_account_uri_if_not_exists = False ) :
'''
'''
Create or upd ate an account on the ACME server . For ACME v1 ,
Detect or cre ate an account on the ACME server . For ACME v1 ,
as the only way ( without knowing an account URI ) to test if an
as the only way ( without knowing an account URI ) to test if an
account exists is to try and create one with the provided account
account exists is to try and create one with the provided account
key , this method will always result in an account being present
key , this method will always result in an account being present
( except on error situations ) . For ACME v2 , a new account will
( except on error situations ) . For ACME v2 , a new account will
only be created if allow_creation is set to True .
only be created if ` ` allow_creation ` ` is set to True .
For ACME v2 , check_mode is fully respected . For ACME v1 , the account
For ACME v2 , ` ` check_mode ` ` is fully respected . For ACME v1 , the
might be created if it does not yet exist .
account might be created if it does not yet exist .
If the account already exists and if update_contact is set to
Return a pair ` ` ( created , account_data ) ` ` . Here , ` ` created ` ` will
True , this method will update the contact information .
be ` ` True ` ` in case the account was created or would be created
( check mode ) . ` ` account_data ` ` will be the current account data ,
or ` ` None ` ` if the account does not exist .
Return True in case something changed ( account was created , contact
The account URI will be stored in ` ` self . uri ` ` ; if it is ` ` None ` ` ,
info updated ) or would be changed ( check_mode ) . The account URI
the account does not exist .
will be stored in self . uri ; if it is None , the account does not
exist .
https : / / tools . ietf . org / html / draft - ietf - acme - acme - 14 #section-7.3
https : / / tools . ietf . org / html / draft - ietf - acme - acme - 14 #section-7.3
'''
'''
new_account = True
changed = False
if self . uri is not None :
if self . uri is not None :
new_account = False
created = False
if not update_contact :
# Verify that the account key belongs to the URI.
# Verify that the account key belongs to the URI.
# (If update_contact is True, this will be done below.)
# (If update_contact is True, this will be done below. )
account_data = self . get_account_data ( )
if self . get_ account_data( ) is None :
if account_data is None :
if remove_account_uri_if_not_exists and not allow_creation :
if remove_account_uri_if_not_exists and not allow_creation :
self . uri = None
self . uri = None
r eturn Fa lse
else:
raise ModuleFailException ( " Account is deactivated or does not exist! " )
raise ModuleFailException ( " Account is deactivated or does not exist! " )
else :
else :
new_account = self . _new_reg (
created, account_data = self . _new_reg (
contact ,
contact ,
agreement = agreement ,
agreement = agreement ,
terms_agreed = terms_agreed ,
terms_agreed = terms_agreed ,
allow_creation = allow_creation and not self . module . check_mode
allow_creation = allow_creation and not self . module . check_mode
)
)
if self . module . check_mode and self . uri is None and allow_creation :
if self . module . check_mode and self . uri is None and allow_creation :
return True
created = True
if not new_account and self . uri and update_contact :
account_data = {
result = self . get_account_data ( )
' contact ' : contact or [ ]
if result is None :
}
if not allow_creation :
return created , account_data
self . uri = None
return False
def update_account ( self , account_data , contact = None ) :
raise ModuleFailException ( " Account is deactivated or does not exist! " )
'''
Update an account on the ACME server . Check mode is fully respected .
# ...and check if update is necessary
if result . get ( ' contact ' , [ ] ) != contact :
The current account data must be provided as ` ` account_data ` ` .
if not self . module . check_mode :
upd_reg = result
Return a pair ` ` ( updated , account_data ) ` ` , where ` ` updated ` ` is
upd_reg [ ' contact ' ] = contact
` ` True ` ` in case something changed ( contact info updated ) or
result , dummy = self . send_signed_request ( self . uri , upd_reg )
would be changed ( check mode ) , and ` ` account_data ` ` the updated
changed = True
account data .
return new_account or changed
https : / / tools . ietf . org / html / draft - ietf - acme - acme - 14 #section-7.3.2
'''
# Create request
update_request = { }
if contact is not None and account_data . get ( ' contact ' , [ ] ) != contact :
update_request [ ' contact ' ] = list ( contact )
# No change?
if not update_request :
return False , dict ( account_data )
# Apply change
if self . module . check_mode :
account_data = dict ( account_data )
account_data . update ( update_request )
else :
account_data , dummy = self . send_signed_request ( self . uri , update_request )
return True , account_data
def cryptography_get_csr_domains ( module , csr_filename ) :
def cryptography_get_csr_domains ( module , csr_filename ) :