acme_account_info: retrieve orders (#59697)
* Add retrieve_orders option. * Run acme_certificate tests also for acme_account_info; use acme_account_info to get list of orders. * Doing some quoting. * Improve returned description.
This commit is contained in:
parent
14974f5fc2
commit
039123ec6b
4 changed files with 220 additions and 2 deletions
|
@ -28,6 +28,21 @@ notes:
|
|||
- "The M(acme_account) module allows to modify, create and delete ACME accounts."
|
||||
- "This module was called C(acme_account_facts) before Ansible 2.8. The usage
|
||||
did not change."
|
||||
options:
|
||||
retrieve_orders:
|
||||
description:
|
||||
- "Whether to retrieve the list of order URLs or order objects, if provided
|
||||
by the ACME server."
|
||||
- "A value of C(ignore) will not fetch the list of orders."
|
||||
- "Currently, Let's Encrypt does not return orders, so the C(orders) result
|
||||
will always be empty."
|
||||
type: str
|
||||
choices:
|
||||
- ignore
|
||||
- url_list
|
||||
- object_list
|
||||
default: ignore
|
||||
version_added: "2.9"
|
||||
seealso:
|
||||
- module: acme_account
|
||||
description: Allows to create, modify or delete an ACME account.
|
||||
|
@ -90,7 +105,10 @@ account:
|
|||
choices: ['valid', 'deactivated', 'revoked']
|
||||
sample: valid
|
||||
orders:
|
||||
description: a URL where a list of orders can be retrieved for this account
|
||||
description:
|
||||
- A URL where a list of orders can be retrieved for this account.
|
||||
- Use the I(retrieve_orders) option to query this URL and retrieve the
|
||||
complete list of orders.
|
||||
returned: always
|
||||
type: str
|
||||
sample: https://example.ca/account/1/orders
|
||||
|
@ -99,15 +117,126 @@ account:
|
|||
returned: always
|
||||
type: str
|
||||
sample: https://example.ca/account/1/orders
|
||||
|
||||
orders:
|
||||
description:
|
||||
- "The list of orders."
|
||||
- "If I(retrieve_orders) is C(url_list), this will be a list of URLs."
|
||||
- "If I(retrieve_orders) is C(object_list), this will be a list of objects."
|
||||
type: list
|
||||
returned: if account exists, I(retrieve_orders) is not C(ignore), and server supports order listing
|
||||
contains:
|
||||
status:
|
||||
description: The order's status.
|
||||
type: str
|
||||
choices:
|
||||
- pending
|
||||
- ready
|
||||
- processing
|
||||
- valid
|
||||
- invalid
|
||||
expires:
|
||||
description:
|
||||
- When the order expires.
|
||||
- Timestamp should be formatted as described in RFC3339.
|
||||
- Only required to be included in result when I(status) is C(pending) or C(valid).
|
||||
type: str
|
||||
returned: when server gives expiry date
|
||||
identifiers:
|
||||
description:
|
||||
- List of identifiers this order is for.
|
||||
type: list
|
||||
contains:
|
||||
type:
|
||||
description: Type of identifier. C(dns) or C(ip).
|
||||
type: str
|
||||
value:
|
||||
description: Name of identifier. Hostname or IP address.
|
||||
type: str
|
||||
wildcard:
|
||||
description: "Whether I(value) is actually a wildcard. The wildcard
|
||||
prefix C(*.) is not included in I(value) if this is C(true)."
|
||||
type: bool
|
||||
returned: required to be included if the identifier is wildcarded
|
||||
notBefore:
|
||||
description:
|
||||
- The requested value of the C(notBefore) field in the certificate.
|
||||
- Date should be formatted as described in RFC3339.
|
||||
- Server is not required to return this.
|
||||
type: str
|
||||
returned: when server returns this
|
||||
notAfter:
|
||||
description:
|
||||
- The requested value of the C(notAfter) field in the certificate.
|
||||
- Date should be formatted as described in RFC3339.
|
||||
- Server is not required to return this.
|
||||
type: str
|
||||
returned: when server returns this
|
||||
error:
|
||||
description:
|
||||
- In case an error occured during processing, this contains information about the error.
|
||||
- The field is structured as a problem document (RFC7807).
|
||||
type: complex
|
||||
returned: when an error occurred
|
||||
authorizations:
|
||||
description:
|
||||
- A list of URLs for authorizations for this order.
|
||||
type: list
|
||||
finalize:
|
||||
description:
|
||||
- A URL used for finalizing an ACME order.
|
||||
type: str
|
||||
certificate:
|
||||
description:
|
||||
- The URL for retrieving the certificate.
|
||||
type: str
|
||||
returned: when certificate was issued
|
||||
'''
|
||||
|
||||
from ansible.module_utils.acme import (
|
||||
ModuleFailException, ACMEAccount, set_crypto_backend,
|
||||
ModuleFailException, ACMEAccount, set_crypto_backend, process_links,
|
||||
)
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
def get_orders_list(module, account, orders_url):
|
||||
'''
|
||||
Retrieves orders list (handles pagination).
|
||||
'''
|
||||
orders = []
|
||||
while orders_url:
|
||||
# Get part of orders list
|
||||
res, info = account.get_request(orders_url, parse_json_result=True, fail_on_error=True)
|
||||
if not res.get('orders'):
|
||||
if orders:
|
||||
module.warn('When retrieving orders list part {0}, got empty result list'.format(orders_url))
|
||||
break
|
||||
# Add order URLs to result list
|
||||
orders.extend(res['orders'])
|
||||
# Extract URL of next part of results list
|
||||
new_orders_url = []
|
||||
|
||||
def f(link, relation):
|
||||
if relation == 'next':
|
||||
new_orders_url.append(link)
|
||||
|
||||
process_links(info, f)
|
||||
new_orders_url.append(None)
|
||||
previous_orders_url, orders_url = orders_url, new_orders_url.pop(0)
|
||||
if orders_url == previous_orders_url:
|
||||
# Prevent infinite loop
|
||||
orders_url = None
|
||||
return orders
|
||||
|
||||
|
||||
def get_order(account, order_url):
|
||||
'''
|
||||
Retrieve order data.
|
||||
'''
|
||||
return account.get_request(order_url, parse_json_result=True, fail_on_error=True)[0]
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
|
@ -118,6 +247,7 @@ def main():
|
|||
acme_version=dict(type='int', default=1, choices=[1, 2]),
|
||||
validate_certs=dict(type='bool', default=True),
|
||||
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'openssl', 'cryptography']),
|
||||
retrieve_orders=dict(type='str', default='ignore', choices=['ignore', 'url_list', 'object_list']),
|
||||
),
|
||||
required_one_of=(
|
||||
['account_key_src', 'account_key_content'],
|
||||
|
@ -159,6 +289,13 @@ def main():
|
|||
account_data['contact'] = []
|
||||
account_data['public_account_key'] = account.key_data['jwk']
|
||||
result['account'] = account_data
|
||||
# Retrieve orders list
|
||||
if account_data.get('orders') and module.params['retrieve_orders'] != 'ignore':
|
||||
orders = get_orders_list(module, account, account_data['orders'])
|
||||
if module.params['retrieve_orders'] == 'url_list':
|
||||
result['orders'] = orders
|
||||
else:
|
||||
result['orders'] = [get_order(account, order) for order in orders]
|
||||
module.exit_json(**result)
|
||||
except ModuleFailException as e:
|
||||
e.do_fail(module)
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
shippable/cloud/group1
|
||||
cloud/acme
|
||||
acme_account_info
|
||||
|
|
|
@ -299,3 +299,49 @@
|
|||
- name: Dumping cert 8
|
||||
command: openssl x509 -in "{{ output_dir }}/cert-8.pem" -noout -text
|
||||
register: cert_8_text
|
||||
## GET ACCOUNT ORDERS #########################################################################
|
||||
- name: Don't retrieve orders
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
retrieve_orders: ignore
|
||||
register: account_orders_not
|
||||
- name: Retrieve orders as URL list (1/2)
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
retrieve_orders: url_list
|
||||
register: account_orders_urls
|
||||
- name: Retrieve orders as URL list (2/2)
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec384.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
retrieve_orders: url_list
|
||||
register: account_orders_urls2
|
||||
- name: Retrieve orders as object list (1/2)
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec256.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
retrieve_orders: object_list
|
||||
register: account_orders_full
|
||||
- name: Retrieve orders as object list (2/2)
|
||||
acme_account_info:
|
||||
select_crypto_backend: "{{ select_crypto_backend }}"
|
||||
account_key_src: "{{ output_dir }}/account-ec384.pem"
|
||||
acme_version: 2
|
||||
acme_directory: https://{{ acme_host }}:14000/dir
|
||||
validate_certs: no
|
||||
retrieve_orders: object_list
|
||||
register: account_orders_full2
|
||||
|
|
|
@ -83,3 +83,37 @@
|
|||
assert:
|
||||
that:
|
||||
- "'DNS:example.org' in cert_6_text.stdout"
|
||||
|
||||
- name: Validate that orders were not retrieved
|
||||
assert:
|
||||
that:
|
||||
- "'account' in account_orders_not"
|
||||
- "'orders' not in account_orders_not"
|
||||
|
||||
- name: Validate that orders were retrieved as list of URLs (1/2)
|
||||
assert:
|
||||
that:
|
||||
- "'account' in account_orders_urls"
|
||||
- "'orders' in account_orders_urls"
|
||||
- "account_orders_urls.orders[0] is string"
|
||||
|
||||
- name: Validate that orders were retrieved as list of URLs (2/2)
|
||||
assert:
|
||||
that:
|
||||
- "'account' in account_orders_urls2"
|
||||
- "'orders' in account_orders_urls2"
|
||||
- "account_orders_urls2.orders[0] is string"
|
||||
|
||||
- name: Validate that orders were retrieved as list of objects (1/2)
|
||||
assert:
|
||||
that:
|
||||
- "'account' in account_orders_full"
|
||||
- "'orders' in account_orders_full"
|
||||
- "account_orders_full.orders[0].status is string"
|
||||
|
||||
- name: Validate that orders were retrieved as list of objects (2/2)
|
||||
assert:
|
||||
that:
|
||||
- "'account' in account_orders_full2"
|
||||
- "'orders' in account_orders_full2"
|
||||
- "account_orders_full2.orders[0].status is string"
|
||||
|
|
Loading…
Reference in a new issue